diff --git a/plugins/action/__init__.py b/plugins/action/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/action/aireos.py b/plugins/action/aireos.py
deleted file mode 100644
index 84daba2724..0000000000
--- a/plugins/action/aireos.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#
-# (c) 2016 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import sys
-import copy
-
-from ansible import constants as C
-from ansible_collections.ansible.netcommon.plugins.action.network import ActionModule as ActionNetworkModule
-from ansible_collections.community.general.plugins.module_utils.network.aireos.aireos import aireos_provider_spec
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import load_provider
-from ansible.utils.display import Display
-
-display = Display()
-
-
-class ActionModule(ActionNetworkModule):
-
- def run(self, tmp=None, task_vars=None):
- del tmp # tmp no longer has any effect
-
- module_name = self._task.action.split('.')[-1]
- self._config_module = True if module_name == 'aireos_config' else False
-
- if self._play_context.connection != 'local':
- return dict(
- failed=True,
- msg='invalid connection specified, expected connection=local, '
- 'got %s' % self._play_context.connection
- )
-
- provider = load_provider(aireos_provider_spec, self._task.args)
-
- pc = copy.deepcopy(self._play_context)
- pc.connection = 'network_cli'
- pc.network_os = 'aireos'
- pc.remote_addr = provider['host'] or self._play_context.remote_addr
- pc.port = int(provider['port'] or self._play_context.port or 22)
- pc.remote_user = provider['username'] or self._play_context.connection_user
- pc.password = provider['password'] or self._play_context.password
- command_timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
-
- display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
- connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin, task_uuid=self._task._uuid)
- connection.set_options(direct={'persistent_command_timeout': command_timeout})
-
- socket_path = connection.run()
- display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)
- if not socket_path:
- return {'failed': True,
- 'msg': 'unable to open shell. Please see: ' +
- 'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell'}
-
- task_vars['ansible_socket'] = socket_path
-
- if self._play_context.become_method == 'enable':
- self._play_context.become = False
- self._play_context.become_method = None
-
- result = super(ActionModule, self).run(task_vars=task_vars)
-
- return result
diff --git a/plugins/action/aruba.py b/plugins/action/aruba.py
deleted file mode 100644
index 7ea03c8726..0000000000
--- a/plugins/action/aruba.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#
-# (c) 2016 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import sys
-import copy
-
-from ansible import constants as C
-from ansible_collections.ansible.netcommon.plugins.action.network import ActionModule as ActionNetworkModule
-from ansible_collections.community.general.plugins.module_utils.network.aruba.aruba import aruba_provider_spec
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import load_provider
-from ansible.utils.display import Display
-
-display = Display()
-
-
-class ActionModule(ActionNetworkModule):
-
- def run(self, tmp=None, task_vars=None):
- del tmp # tmp no longer has any effect
-
- module_name = self._task.action.split('.')[-1]
- self._config_module = True if module_name == 'aruba_config' else False
-
- if self._play_context.connection != 'local':
- return dict(
- failed=True,
- msg='invalid connection specified, expected connection=local, '
- 'got %s' % self._play_context.connection
- )
-
- provider = load_provider(aruba_provider_spec, self._task.args)
-
- pc = copy.deepcopy(self._play_context)
- pc.connection = 'network_cli'
- pc.network_os = 'aruba'
- pc.remote_addr = provider['host'] or self._play_context.remote_addr
- pc.port = int(provider['port'] or self._play_context.port or 22)
- pc.remote_user = provider['username'] or self._play_context.connection_user
- pc.password = provider['password'] or self._play_context.password
- pc.private_key_file = provider['ssh_keyfile'] or self._play_context.private_key_file
- command_timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
-
- display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
- connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin, task_uuid=self._task._uuid)
- connection.set_options(direct={'persistent_command_timeout': command_timeout})
-
- socket_path = connection.run()
- display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)
- if not socket_path:
- return {'failed': True,
- 'msg': 'unable to open shell. Please see: ' +
- 'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell'}
-
- task_vars['ansible_socket'] = socket_path
-
- if self._play_context.become_method == 'enable':
- self._play_context.become = False
- self._play_context.become_method = None
-
- result = super(ActionModule, self).run(task_vars=task_vars)
- return result
diff --git a/plugins/action/ce.py b/plugins/action/ce.py
deleted file mode 100644
index 31cf3b4e6d..0000000000
--- a/plugins/action/ce.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#
-# Copyright: (c) 2016, Red Hat Inc.
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import sys
-import copy
-
-from ansible import constants as C
-from ansible_collections.ansible.netcommon.plugins.action.network import ActionModule as ActionNetworkModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_provider_spec
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import load_provider
-from ansible.utils.display import Display
-
-display = Display()
-
-CLI_SUPPORTED_MODULES = ['ce_rollback', 'ce_mlag_interface', 'ce_startup', 'ce_config',
- 'ce_command', 'ce_facts', 'ce_evpn_global', 'ce_evpn_bgp_rr',
- 'ce_mtu', 'ce_evpn_bgp', 'ce_snmp_location', 'ce_snmp_contact',
- 'ce_snmp_traps', 'ce_netstream_global', 'ce_netstream_aging',
- 'ce_netstream_export', 'ce_netstream_template', 'ce_ntp_auth',
- 'ce_stp', 'ce_vxlan_global', 'ce_vxlan_arp', 'ce_vxlan_gateway',
- 'ce_acl_interface']
-
-
-class ActionModule(ActionNetworkModule):
-
- def run(self, tmp=None, task_vars=None):
- del tmp # tmp no longer has any effect
-
- module_name = self._task.action.split('.')[-1]
- self._config_module = True if module_name == 'ce_config' else False
- socket_path = None
- persistent_connection = self._play_context.connection.split('.')[-1]
-
- if self._play_context.connection == 'local':
- provider = load_provider(ce_provider_spec, self._task.args)
- transport = provider['transport'] or 'cli'
-
- display.vvvv('connection transport is %s' % transport, self._play_context.remote_addr)
-
- if transport == 'cli':
- pc = copy.deepcopy(self._play_context)
- pc.connection = 'network_cli'
- pc.network_os = 'ce'
- pc.remote_addr = provider['host'] or self._play_context.remote_addr
- pc.port = int(provider['port'] or self._play_context.port or 22)
- pc.remote_user = provider['username'] or self._play_context.connection_user
- pc.password = provider['password'] or self._play_context.password
- command_timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
- self._task.args['provider'] = provider.update(
- host=pc.remote_addr,
- port=pc.port,
- username=pc.remote_user,
- password=pc.password
- )
- if module_name in ['ce_netconf'] or module_name not in CLI_SUPPORTED_MODULES:
- pc.connection = 'netconf'
- display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
- connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin, task_uuid=self._task._uuid)
- connection.set_options(direct={'persistent_command_timeout': command_timeout})
-
- socket_path = connection.run()
- display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)
- if not socket_path:
- return {'failed': True,
- 'msg': 'unable to open shell. Please see: ' +
- 'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell'}
-
- task_vars['ansible_socket'] = socket_path
- # make sure a transport value is set in args
- self._task.args['transport'] = transport
- self._task.args['provider'] = provider
- elif persistent_connection in ('netconf', 'network_cli'):
- provider = self._task.args.get('provider', {})
- if any(provider.values()):
- display.warning('provider is unnecessary when using %s and will be ignored' % self._play_context.connection)
- del self._task.args['provider']
-
- if (persistent_connection == 'network_cli' and module_name not in CLI_SUPPORTED_MODULES) or \
- (persistent_connection == 'netconf' and module_name in CLI_SUPPORTED_MODULES):
- return {'failed': True, 'msg': "Connection type '%s' is not valid for '%s' module."
- % (self._play_context.connection, self._task.action)}
-
- result = super(ActionModule, self).run(task_vars=task_vars)
- return result
diff --git a/plugins/action/ce_template.py b/plugins/action/ce_template.py
deleted file mode 100644
index aaacf42b6b..0000000000
--- a/plugins/action/ce_template.py
+++ /dev/null
@@ -1,104 +0,0 @@
-#
-# Copyright 2015 Peter Sprygada
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import os
-import time
-import glob
-from ansible.module_utils.six.moves.urllib.parse import urlsplit
-
-from ansible.module_utils._text import to_text
-from ansible_collections.community.general.plugins.action.ce import ActionModule as _ActionModule
-
-
-class ActionModule(_ActionModule):
-
- def run(self, tmp=None, task_vars=None):
-
- try:
- self._handle_template()
- except (ValueError, AttributeError) as exc:
- return dict(failed=True, msg=exc.message)
-
- result = super(ActionModule, self).run(tmp, task_vars)
- del tmp # tmp no longer has any effect
-
- if self._task.args.get('backup') and result.get('__backup__'):
- # User requested backup and no error occurred in module.
- # NOTE: If there is a parameter error, __backup__ key may not be in results.
- self._write_backup(task_vars['inventory_hostname'], result['__backup__'])
-
- if '__backup__' in result:
- del result['__backup__']
-
- return result
-
- def _get_working_path(self):
- cwd = self._loader.get_basedir()
- if self._task._role is not None:
- cwd = self._task._role._role_path
- return cwd
-
- def _write_backup(self, host, contents):
- backup_path = self._get_working_path() + '/backup'
- if not os.path.exists(backup_path):
- os.mkdir(backup_path)
- for fn in glob.glob('%s/%s*' % (backup_path, host)):
- os.remove(fn)
- tstamp = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time()))
- filename = '%s/%s_config.%s' % (backup_path, host, tstamp)
- open(filename, 'w').write(contents)
-
- def _handle_template(self):
- src = self._task.args.get('src')
- if not src:
- raise ValueError('missing required arguments: src')
-
- working_path = self._get_working_path()
-
- if os.path.isabs(src) or urlsplit(src).scheme:
- source = src
- else:
- source = self._loader.path_dwim_relative(working_path, 'templates', src)
- if not source:
- source = self._loader.path_dwim_relative(working_path, src)
-
- if not os.path.exists(source):
- return
-
- try:
- with open(source, 'r') as f:
- template_data = to_text(f.read())
- except IOError:
- return dict(failed=True, msg='unable to load src file')
-
- # Create a template search path in the following order:
- # [working_path, self_role_path, dependent_role_paths, dirname(source)]
- searchpath = [working_path]
- if self._task._role is not None:
- searchpath.append(self._task._role._role_path)
- if hasattr(self._task, "_block:"):
- dep_chain = self._task._block.get_dep_chain()
- if dep_chain is not None:
- for role in dep_chain:
- searchpath.append(role._role_path)
- searchpath.append(os.path.dirname(source))
- with self._templar.set_temporary_context(searchpath=searchpath):
- self._task.args['src'] = self._templar.template(template_data)
diff --git a/plugins/action/cnos.py b/plugins/action/cnos.py
deleted file mode 100644
index fa0332da5e..0000000000
--- a/plugins/action/cnos.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# (C) 2017 Red Hat Inc.
-# Copyright (C) 2017 Lenovo.
-#
-# GNU General Public License v3.0+
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-# Contains Action Plugin methods for CNOS Config Module
-# Lenovo Networking
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import sys
-import copy
-
-from ansible import constants as C
-from ansible_collections.ansible.netcommon.plugins.action.network import ActionModule as ActionNetworkModule
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import cnos_provider_spec
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import load_provider
-from ansible.utils.display import Display
-
-display = Display()
-
-
-class ActionModule(ActionNetworkModule):
-
- def run(self, tmp=None, task_vars=None):
- del tmp # tmp no longer has any effect
-
- module_name = self._task.action.split('.')[-1]
- self._config_module = True if module_name == 'cnos_config' else False
-
- if self._play_context.connection == 'local':
- provider = load_provider(cnos_provider_spec, self._task.args)
- pc = copy.deepcopy(self._play_context)
- pc.connection = 'network_cli'
- pc.network_os = 'cnos'
- pc.remote_addr = provider['host'] or self._play_context.remote_addr
- pc.port = provider['port'] or self._play_context.port or 22
- pc.remote_user = provider['username'] or self._play_context.connection_user
- pc.password = provider['password'] or self._play_context.password
- pc.private_key_file = provider['ssh_keyfile'] or self._play_context.private_key_file
- command_timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
- pc.become = provider['authorize'] or True
- pc.become_pass = provider['auth_pass']
- pc.become_method = 'enable'
-
- display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
- connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin, task_uuid=self._task._uuid)
- connection.set_options(direct={'persistent_command_timeout': command_timeout})
-
- socket_path = connection.run()
- display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)
- if not socket_path:
- return {'failed': True,
- 'msg': 'unable to open shell. Please see: ' +
- 'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell'}
-
- task_vars['ansible_socket'] = socket_path
-
- result = super(ActionModule, self).run(task_vars=task_vars)
- return result
diff --git a/plugins/action/edgeos_config.py b/plugins/action/edgeos_config.py
deleted file mode 100644
index e1145da6b8..0000000000
--- a/plugins/action/edgeos_config.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Copyright 2018 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-from ansible_collections.ansible.netcommon.plugins.action.network import ActionModule as ActionNetworkModule
-
-
-class ActionModule(ActionNetworkModule):
-
- def run(self, tmp=None, task_vars=None):
- del tmp # tmp no longer has any effect
-
- self._config_module = True
-
- if self._play_context.connection.split('.')[-1] != 'network_cli':
- return {'failed': True, 'msg': 'Connection type %s is not valid for this module. Must use fully qualified'
- ' name of network_cli connection type.' % self._play_context.connection}
-
- return super(ActionModule, self).run(task_vars=task_vars)
diff --git a/plugins/action/enos.py b/plugins/action/enos.py
deleted file mode 100644
index 5097d95749..0000000000
--- a/plugins/action/enos.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# (C) 2017 Red Hat Inc.
-# Copyright (C) 2017 Lenovo.
-#
-# GNU General Public License v3.0+
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-# Contains Action Plugin methods for ENOS Config Module
-# Lenovo Networking
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import sys
-import copy
-
-from ansible import constants as C
-from ansible_collections.ansible.netcommon.plugins.action.network import ActionModule as ActionNetworkModule
-from ansible_collections.community.general.plugins.module_utils.network.enos.enos import enos_provider_spec
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import load_provider
-from ansible.utils.display import Display
-
-display = Display()
-
-
-class ActionModule(ActionNetworkModule):
-
- def run(self, tmp=None, task_vars=None):
- del tmp # tmp no longer has any effect
-
- module_name = self._task.action.split('.')[-1]
- self._config_module = True if module_name == 'enos_config' else False
-
- if self._play_context.connection == 'local':
- provider = load_provider(enos_provider_spec, self._task.args)
- pc = copy.deepcopy(self._play_context)
- pc.connection = 'network_cli'
- pc.network_os = 'enos'
- pc.remote_addr = provider['host'] or self._play_context.remote_addr
- pc.port = provider['port'] or self._play_context.port or 22
- pc.remote_user = provider['username'] or self._play_context.connection_user
- pc.password = provider['password'] or self._play_context.password
- pc.private_key_file = provider['ssh_keyfile'] or self._play_context.private_key_file
- command_timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
- pc.become = provider['authorize'] or True
- pc.become_pass = provider['auth_pass']
- pc.become_method = 'enable'
-
- display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
- connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin, task_uuid=self._task._uuid)
- connection.set_options(direct={'persistent_command_timeout': command_timeout})
-
- socket_path = connection.run()
- display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)
- if not socket_path:
- return {'failed': True,
- 'msg': 'unable to open shell. Please see: ' +
- 'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell'}
-
- task_vars['ansible_socket'] = socket_path
-
- result = super(ActionModule, self).run(task_vars=task_vars)
- return result
diff --git a/plugins/action/exos.py b/plugins/action/exos.py
deleted file mode 100644
index 5d91155c12..0000000000
--- a/plugins/action/exos.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Copyright 2015 Peter Sprygada
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-from ansible_collections.ansible.netcommon.plugins.action.network import ActionModule as ActionNetworkModule
-
-
-class ActionModule(ActionNetworkModule):
-
- EXOS_NETWORK_CLI_MODULES = (
- 'exos_facts',
- 'exos_config',
- 'exos_command')
-
- def run(self, tmp=None, task_vars=None):
- del tmp # tmp no longer has any effect
-
- module_name = self._task.action.split('.')[-1]
- self._config_module = True if module_name == 'exos_config' else False
- persistent_connection = self._play_context.connection.split('.')[-1]
-
- if persistent_connection not in ('network_cli', 'httpapi'):
- return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
-
- if persistent_connection == 'network_cli' and module_name not in self.EXOS_NETWORK_CLI_MODULES:
- return {'failed': True, 'msg': "Connection type %s is not valid for this module" % self._play_context.connection}
-
- return super(ActionModule, self).run(task_vars=task_vars)
diff --git a/plugins/action/ironware.py b/plugins/action/ironware.py
deleted file mode 100644
index 0a75a2f365..0000000000
--- a/plugins/action/ironware.py
+++ /dev/null
@@ -1,80 +0,0 @@
-#
-# (c) 2016 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import sys
-import copy
-
-from ansible_collections.ansible.netcommon.plugins.action.network import ActionModule as ActionNetworkModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import load_provider
-from ansible_collections.community.general.plugins.module_utils.network.ironware.ironware import ironware_provider_spec
-from ansible.utils.display import Display
-
-display = Display()
-
-
-class ActionModule(ActionNetworkModule):
-
- def run(self, tmp=None, task_vars=None):
- del tmp # tmp no longer has any effect
-
- module_name = self._task.action.split('.')[-1]
- self._config_module = True if module_name == 'ironware_config' else False
- persistent_connection = self._play_context.connection.split('.')[-1]
-
- if persistent_connection == 'network_cli':
- provider = self._task.args.get('provider', {})
- if any(provider.values()):
- display.warning('provider is unnecessary when using network_cli and will be ignored')
- del self._task.args['provider']
- elif self._play_context.connection == 'local':
- provider = load_provider(ironware_provider_spec, self._task.args)
- pc = copy.deepcopy(self._play_context)
- pc.connection = 'network_cli'
- pc.network_os = 'ironware'
- pc.remote_addr = provider['host'] or self._play_context.remote_addr
- pc.port = int(provider['port'] or self._play_context.port or 22)
- pc.remote_user = provider['username'] or self._play_context.connection_user
- pc.password = provider['password'] or self._play_context.password
- pc.private_key_file = provider['ssh_keyfile'] or self._play_context.private_key_file
- pc.become = provider['authorize'] or False
- if pc.become:
- pc.become_method = 'enable'
- pc.become_pass = provider['auth_pass']
-
- display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
- connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin, task_uuid=self._task._uuid)
-
- command_timeout = int(provider['timeout']) if provider['timeout'] else connection.get_option('persistent_command_timeout')
- connection.set_options(direct={'persistent_command_timeout': command_timeout})
-
- socket_path = connection.run()
- display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)
- if not socket_path:
- return {'failed': True,
- 'msg': 'unable to open shell. Please see: ' +
- 'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell'}
-
- task_vars['ansible_socket'] = socket_path
- else:
- return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
-
- result = super(ActionModule, self).run(task_vars=task_vars)
- return result
diff --git a/plugins/action/nos_config.py b/plugins/action/nos_config.py
deleted file mode 100644
index 3f49e1afab..0000000000
--- a/plugins/action/nos_config.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# (c) 2018 Extreme Networks Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-from ansible_collections.ansible.netcommon.plugins.action.network import ActionModule as ActionNetworkModule
-
-
-class ActionModule(ActionNetworkModule):
-
- def run(self, tmp=None, task_vars=None):
- del tmp # tmp no longer has any effect
-
- self._config_module = True
- return super(ActionModule, self).run(task_vars=task_vars)
diff --git a/plugins/action/onyx_config.py b/plugins/action/onyx_config.py
deleted file mode 100644
index b1c9089b49..0000000000
--- a/plugins/action/onyx_config.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# (c) 2017, Red Hat, Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-from ansible_collections.ansible.netcommon.plugins.action.network import ActionModule as ActionNetworkModule
-
-
-class ActionModule(ActionNetworkModule):
-
- def run(self, tmp=None, task_vars=None):
- del tmp # tmp no longer has any effect
-
- self._config_module = True
- return super(ActionModule, self).run(task_vars=task_vars)
diff --git a/plugins/action/slxos.py b/plugins/action/slxos.py
deleted file mode 100644
index cb0478ce87..0000000000
--- a/plugins/action/slxos.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# (c) 2018 Extreme Networks Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import re
-
-from ansible_collections.ansible.netcommon.plugins.action.network import ActionModule as ActionNetworkModule
-
-PRIVATE_KEYS_RE = re.compile('__.+__')
-
-
-class ActionModule(ActionNetworkModule):
-
- def run(self, tmp=None, task_vars=None):
- del tmp # tmp no longer has any effect
-
- module_name = self._task.action.split('.')[-1]
- self._config_module = True if module_name == 'slxos_config' else False
- persistent_connection = self._play_context.connection.split('.')[-1]
-
- if persistent_connection not in ('network_cli'):
- return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
- return super(ActionModule, self).run(task_vars=task_vars)
diff --git a/plugins/action/sros.py b/plugins/action/sros.py
deleted file mode 100644
index 0de5947a71..0000000000
--- a/plugins/action/sros.py
+++ /dev/null
@@ -1,77 +0,0 @@
-#
-# (c) 2016 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import sys
-import copy
-
-from ansible import constants as C
-from ansible_collections.ansible.netcommon.plugins.action.network import ActionModule as ActionNetworkModule
-from ansible_collections.community.general.plugins.module_utils.network.sros.sros import sros_provider_spec
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import load_provider
-from ansible.utils.display import Display
-
-display = Display()
-
-
-class ActionModule(ActionNetworkModule):
-
- def run(self, tmp=None, task_vars=None):
- del tmp # tmp no longer has any effect
-
- module_name = self._task.action.split('.')[-1]
- persistent_connection = self._play_context.connection.split('.')[-1]
-
- self._config_module = True if module_name == 'sros_config' else False
- if persistent_connection == 'network_cli':
- provider = self._task.args.get('provider', {})
- if any(provider.values()):
- display.warning('provider is unnecessary when using network_cli and will be ignored')
- del self._task.args['provider']
- elif self._play_context.connection == 'local':
- provider = load_provider(sros_provider_spec, self._task.args)
-
- pc = copy.deepcopy(self._play_context)
- pc.connection = 'network_cli'
- pc.network_os = 'sros'
- pc.remote_addr = provider['host'] or self._play_context.remote_addr
- pc.port = int(provider['port'] or self._play_context.port or 22)
- pc.remote_user = provider['username'] or self._play_context.connection_user
- pc.password = provider['password'] or self._play_context.password
- pc.private_key_file = provider['ssh_keyfile'] or self._play_context.private_key_file
- command_timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
-
- display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
- connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin, task_uuid=self._task._uuid)
- connection.set_options(direct={'persistent_command_timeout': command_timeout})
-
- socket_path = connection.run()
- display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)
- if not socket_path:
- return {'failed': True,
- 'msg': 'unable to open shell. Please see: ' +
- 'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell'}
-
- task_vars['ansible_socket'] = socket_path
- else:
- return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
-
- result = super(ActionModule, self).run(task_vars=task_vars)
- return result
diff --git a/plugins/action/voss.py b/plugins/action/voss.py
deleted file mode 100644
index e7e2ca452c..0000000000
--- a/plugins/action/voss.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# (c) 2018 Extreme Networks Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-from ansible_collections.ansible.netcommon.plugins.action.network import ActionModule as ActionNetworkModule
-
-
-class ActionModule(ActionNetworkModule):
-
- def run(self, tmp=None, task_vars=None):
- del tmp # tmp no longer has any effect
-
- module_name = self._task.action.split('.')[-1]
- self._config_module = True if module_name == 'voss_config' else False
- persistent_connection = self._play_context.connection.split('.')[-1]
-
- if persistent_connection not in ('network_cli'):
- return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
- return super(ActionModule, self).run(task_vars=task_vars)
diff --git a/plugins/cliconf/__init__.py b/plugins/cliconf/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/cliconf/aireos.py b/plugins/cliconf/aireos.py
deleted file mode 100644
index 438e4972cc..0000000000
--- a/plugins/cliconf/aireos.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# (c) 2017 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-cliconf: aireos
-short_description: Use aireos cliconf to run command on Cisco WLC platform
-description:
- - This aireos plugin provides low level abstraction apis for
- sending and receiving CLI commands from Cisco WLC network devices.
-'''
-
-import re
-import json
-
-from itertools import chain
-
-from ansible.errors import AnsibleConnectionFailure
-from ansible.module_utils._text import to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.cliconf import CliconfBase, enable_mode
-
-
-class Cliconf(CliconfBase):
-
- def get_device_info(self):
- device_info = {}
-
- device_info['network_os'] = 'aireos'
- reply = self.get('show sysinfo')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'Product Version\.* (.*)', data)
- if match:
- device_info['network_os_version'] = match.group(1)
-
- match = re.search(r'System Name\.* (.*)', data, re.M)
- if match:
- device_info['network_os_hostname'] = match.group(1)
-
- reply = self.get('show inventory')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'DESCR: \"(.*)\"', data, re.M)
- if match:
- device_info['network_os_model'] = match.group(1)
- return device_info
-
- @enable_mode
- def get_config(self, source='running', format='text', flags=None):
- if source not in ('running', 'startup'):
- return self.invalid_params("fetching configuration from %s is not supported" % source)
- if source == 'running':
- cmd = 'show run-config commands'
- else:
- cmd = 'show run-config startup-commands'
- return self.send_command(cmd)
-
- @enable_mode
- def edit_config(self, command):
- for cmd in chain(['config'], to_list(command), ['end']):
- self.send_command(cmd)
-
- def get(self, command, prompt=None, answer=None, sendonly=False, newline=True, check_all=False):
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def get_capabilities(self):
- result = super(Cliconf, self).get_capabilities()
- return json.dumps(result)
-
- def set_cli_prompt_context(self):
- """
- Make sure we are in the operational cli mode
- :return: None
- """
- if self._connection.connected:
- self._update_cli_prompt_context(config_context=')#')
diff --git a/plugins/cliconf/apconos.py b/plugins/cliconf/apconos.py
deleted file mode 100644
index 03c7e7a1de..0000000000
--- a/plugins/cliconf/apconos.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# (C) 2018 Red Hat Inc.
-# Copyright (C) 2019 APCON.
-#
-# GNU General Public License v3.0+
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-# Contains CLIConf Plugin methods for apconos Modules
-# APCON Networking
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-author: "David Li (@davidlee-ap)"
-cliconf: apconos
-short_description: Use apconos cliconf to run command on APCON network devices
-description:
- - This apconos plugin provides low level abstraction apis for
- sending and receiving CLI commands from APCON network devices.
-'''
-
-import re
-import json
-
-from itertools import chain
-
-from ansible.module_utils._text import to_bytes, to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.cliconf import CliconfBase, enable_mode
-
-
-class Cliconf(CliconfBase):
-
- def get_device_info(self):
- device_info = {}
-
- device_info['network_os'] = 'apconos'
- reply = self.get(b'show version')
- data = to_text(reply, errors='surrogate_or_strict').strip()
- if data:
- device_info['network_os_version'] = self.parse_version(data)
- device_info['network_os_model'] = self.parse_model(data)
-
- return device_info
-
- def parse_version(self, data):
- return ""
-
- def parse_model(self, data):
- return ""
-
- @enable_mode
- def get_config(self, source='running', format='text'):
- pass
-
- @enable_mode
- def edit_config(self, command):
- for cmd in chain([b'configure terminal'], to_list(command), [b'end']):
- self.send_command(cmd)
-
- def get(self, command, prompt=None, answer=None, sendonly=False, check_all=False):
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, check_all=check_all)
-
- def get_capabilities(self):
- return json.dumps(self.get_device_info())
diff --git a/plugins/cliconf/aruba.py b/plugins/cliconf/aruba.py
deleted file mode 100644
index 52c0a974a4..0000000000
--- a/plugins/cliconf/aruba.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# (c) 2017 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-cliconf: aruba
-short_description: Use aruba cliconf to run command on Aruba platform
-description:
- - This aruba plugin provides low level abstraction apis for
- sending and receiving CLI commands from Aruba network devices.
-'''
-
-import re
-import json
-
-from itertools import chain
-
-from ansible.module_utils._text import to_bytes, to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.cliconf import CliconfBase, enable_mode
-
-
-class Cliconf(CliconfBase):
-
- def get_device_info(self):
- device_info = {}
-
- device_info['network_os'] = 'aruba'
- reply = self.get('show version')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'Version (\S+)', data)
- if match:
- device_info['network_os_version'] = match.group(1)
-
- match = re.search(r'^MODEL: (\S+)\),', data, re.M)
- if match:
- device_info['network_os_model'] = match.group(1)
-
- reply = self.get('show hostname')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'^Hostname is (.+)', data, re.M)
- if match:
- device_info['network_os_hostname'] = match.group(1)
-
- return device_info
-
- @enable_mode
- def get_config(self, source='running', format='text', flags=None):
- if source not in ('running', 'startup'):
- return self.invalid_params("fetching configuration from %s is not supported" % source)
- if source == 'running':
- cmd = 'show running-config all'
- else:
- cmd = 'show configuration'
- return self.send_command(cmd)
-
- @enable_mode
- def edit_config(self, command):
- for cmd in chain(['configure terminal'], to_list(command), ['end']):
- self.send_command(cmd)
-
- def get(self, command, prompt=None, answer=None, sendonly=False, newline=True, check_all=False):
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def get_capabilities(self):
- result = super(Cliconf, self).get_capabilities()
- return json.dumps(result)
-
- def set_cli_prompt_context(self):
- """
- Make sure we are in the operational cli mode
- :return: None
- """
- if self._connection.connected:
- self._update_cli_prompt_context(config_context=')#')
diff --git a/plugins/cliconf/ce.py b/plugins/cliconf/ce.py
deleted file mode 100644
index 4af008c085..0000000000
--- a/plugins/cliconf/ce.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#
-# (c) 2017 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-cliconf: ce
-short_description: Use ce cliconf to run command on HUAWEI CloudEngine platform
-description:
- - This ce plugin provides low level abstraction apis for
- sending and receiving CLI commands from HUAWEI CloudEngine network devices.
-'''
-
-import re
-import json
-
-from itertools import chain
-
-from ansible.errors import AnsibleConnectionFailure
-from ansible.module_utils._text import to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.cliconf import CliconfBase, enable_mode
-
-
-class Cliconf(CliconfBase):
-
- def get_device_info(self):
- device_info = {}
-
- device_info['network_os'] = 'ce'
- reply = self.get('display version')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'^Huawei.+\n.+\Version\s+(\S+)', data)
- if match:
- device_info['network_os_version'] = match.group(1).strip(',')
-
- match = re.search(r'^Huawei(.+)\n.+\(\S+\s+\S+\)', data, re.M)
- if match:
- device_info['network_os_model'] = match.group(1)
-
- match = re.search(r'HUAWEI\s+(\S+)\s+uptime', data, re.M)
- if match:
- device_info['network_os_hostname'] = match.group(1)
-
- return device_info
-
- @enable_mode
- def get_config(self, source='running', format='text', flags=None):
- if source not in ('running'):
- return self.invalid_params("fetching configuration from %s is not supported" % source)
-
- if not flags:
- flags = []
-
- cmd = 'display current-configuration'
-
- return self.send_command(cmd)
-
- @enable_mode
- def edit_config(self, command):
- results = []
- for cmd in chain(['configure terminal'], to_list(command), ['end']):
- if isinstance(cmd, dict):
- command = cmd['command']
- prompt = cmd['prompt']
- answer = cmd['answer']
- newline = cmd.get('newline', True)
- else:
- command = cmd
- prompt = None
- answer = None
- newline = True
-
- results.append(self.send_command(command, prompt, answer, False, newline))
- return results[1:-1]
-
- def get(self, command, prompt=None, answer=None, sendonly=False, newline=True, check_all=False):
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def get_capabilities(self):
- result = super(Cliconf, self).get_capabilities()
- return json.dumps(result)
-
- def set_cli_prompt_context(self):
- """
- Make sure we are in the operational cli mode
- :return: None
- """
- if self._connection.connected:
- out = self._connection.get_prompt()
-
- if out is None:
- raise AnsibleConnectionFailure(message=u'cli prompt is not identified from the last received'
- u' response window: %s' % self._connection._last_recv_window)
-
- prompt = to_text(out, errors='surrogate_then_replace').strip()
- while prompt.endswith(']'):
- self._connection.queue_message('vvvv', 'wrong context, sending return to device')
- if prompt.startswith('[*'):
- self._connection.exec_command('clear configuration candidate')
- self._connection.exec_command('return')
- out = self._connection.get_prompt()
- prompt = to_text(out, errors='surrogate_then_replace').strip()
diff --git a/plugins/cliconf/cnos.py b/plugins/cliconf/cnos.py
deleted file mode 100644
index 51541861c3..0000000000
--- a/plugins/cliconf/cnos.py
+++ /dev/null
@@ -1,135 +0,0 @@
-# (C) 2017 Red Hat Inc.
-# Copyright (C) 2017 Lenovo.
-#
-# GNU General Public License v3.0+
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-# Contains CLIConf Plugin methods for CNOS Modules
-# Lenovo Networking
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-cliconf: cnos
-short_description: Use cnos cliconf to run command on Lenovo CNOS platform
-description:
- - This cnos plugin provides low level abstraction apis for
- sending and receiving CLI commands from Lenovo CNOS network devices.
-'''
-
-import re
-import json
-
-from ansible.errors import AnsibleConnectionFailure
-from ansible.module_utils.common._collections_compat import Mapping
-from ansible.module_utils._text import to_bytes, to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.cliconf import CliconfBase, enable_mode
-
-
-class Cliconf(CliconfBase):
-
- def get_device_info(self):
- device_info = {}
-
- device_info['network_os'] = 'cnos'
- reply = self.get('show sys-info')
- data = to_text(reply, errors='surrogate_or_strict').strip()
- host = self.get('show hostname')
- hostname = to_text(host, errors='surrogate_or_strict').strip()
- if data:
- device_info['network_os_version'] = self.parse_version(data)
- device_info['network_os_model'] = self.parse_model(data)
- device_info['network_os_hostname'] = hostname
-
- return device_info
-
- def parse_version(self, data):
- for line in data.split('\n'):
- line = line.strip()
- match = re.match(r'System Software Revision (.*?)',
- line, re.M | re.I)
- if match:
- vers = line.split(':')
- ver = vers[1].strip()
- return ver
- return "NA"
-
- def parse_model(self, data):
- for line in data.split('\n'):
- line = line.strip()
- match = re.match(r'System Model (.*?)', line, re.M | re.I)
- if match:
- mdls = line.split(':')
- mdl = mdls[1].strip()
- return mdl
- return "NA"
-
- @enable_mode
- def get_config(self, source='running', format='text', flags=None):
- if source not in ('running', 'startup'):
- msg = "fetching configuration from %s is not supported"
- return self.invalid_params(msg % source)
- if source == 'running':
- cmd = 'show running-config'
- else:
- cmd = 'show startup-config'
- return self.send_command(cmd)
-
- @enable_mode
- def edit_config(self, candidate=None, commit=True,
- replace=None, comment=None):
- resp = {}
- results = []
- requests = []
- if commit:
- self.send_command('configure terminal')
- for line in to_list(candidate):
- if not isinstance(line, Mapping):
- line = {'command': line}
-
- cmd = line['command']
- if cmd != 'end' and cmd[0] != '!':
- results.append(self.send_command(**line))
- requests.append(cmd)
-
- self.send_command('end')
- else:
- raise ValueError('check mode is not supported')
-
- resp['request'] = requests
- resp['response'] = results
- return resp
-
- def get(self, command, prompt=None, answer=None, sendonly=False, newline=True, check_all=False):
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def get_capabilities(self):
- result = super(Cliconf, self).get_capabilities()
- return json.dumps(result)
-
- def set_cli_prompt_context(self):
- """
- Make sure we are in the operational cli mode
- :return: None
- """
- if self._connection.connected:
- out = self._connection.get_prompt()
-
- if out is None:
- raise AnsibleConnectionFailure(message=u'cli prompt is not identified from the last received'
- u' response window: %s' % self._connection._last_recv_window)
-
- if to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
- self._connection.queue_message('vvvv', 'In Config mode, sending exit to device')
- self._connection.send_command('exit')
- else:
- self._connection.send_command('enable')
diff --git a/plugins/cliconf/edgeos.py b/plugins/cliconf/edgeos.py
deleted file mode 100644
index ef55889046..0000000000
--- a/plugins/cliconf/edgeos.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# Copyright: (c) 2018, Ansible Project
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-cliconf: edgeos
-short_description: Use edgeos cliconf to run command on EdgeOS platform
-description:
- - This edgeos plugin provides low level abstraction apis for
- sending and receiving CLI commands from Ubiquiti EdgeOS network devices.
-'''
-
-import re
-import json
-
-from itertools import chain
-
-from ansible.errors import AnsibleConnectionFailure
-from ansible.module_utils._text import to_text
-from ansible.module_utils.common._collections_compat import Mapping
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.cliconf import CliconfBase
-
-
-class Cliconf(CliconfBase):
-
- def get_device_info(self):
- device_info = {}
-
- device_info['network_os'] = 'edgeos'
- reply = self.get('show version')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'Version:\s*v?(\S+)', data)
- if match:
- device_info['network_os_version'] = match.group(1)
-
- match = re.search(r'HW model:\s*(\S+)', data)
- if match:
- device_info['network_os_model'] = match.group(1)
-
- reply = self.get('show host name')
- device_info['network_os_hostname'] = to_text(reply, errors='surrogate_or_strict').strip()
-
- return device_info
-
- def get_config(self, source='running', format='text', flags=None):
- return self.send_command('show configuration commands')
-
- def edit_config(self, candidate=None, commit=True, replace=False, comment=None):
- for cmd in chain(['configure'], to_list(candidate)):
- self.send_command(cmd)
-
- def get(self, command, prompt=None, answer=None, sendonly=False, newline=True, check_all=False):
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def commit(self, comment=None):
- if comment:
- command = 'commit comment "{0}"'.format(comment)
- else:
- command = 'commit'
- self.send_command(command)
-
- def discard_changes(self, *args, **kwargs):
- self.send_command('discard')
-
- def run_commands(self, commands=None, check_rc=True):
- if commands is None:
- raise ValueError("'commands' value is required")
-
- responses = list()
- for cmd in to_list(commands):
- if not isinstance(cmd, Mapping):
- cmd = {'command': cmd}
-
- output = cmd.pop('output', None)
- if output:
- raise ValueError("'output' value %s is not supported for run_commands" % output)
-
- try:
- out = self.send_command(**cmd)
- except AnsibleConnectionFailure as e:
- if check_rc:
- raise
- out = getattr(e, 'err', e)
-
- responses.append(out)
-
- return responses
-
- def get_device_operations(self):
- return {
- 'supports_diff_replace': False,
- 'supports_commit': True,
- 'supports_rollback': False,
- 'supports_defaults': False,
- 'supports_onbox_diff': False,
- 'supports_commit_comment': True,
- 'supports_multiline_delimiter': False,
- 'supports_diff_match': False,
- 'supports_diff_ignore_lines': False,
- 'supports_generate_diff': False,
- 'supports_replace': False
- }
-
- def get_capabilities(self):
- result = super(Cliconf, self).get_capabilities()
- result['rpc'] += ['commit', 'discard_changes', 'run_commands']
- result['device_operations'] = self.get_device_operations()
- return json.dumps(result)
diff --git a/plugins/cliconf/edgeswitch.py b/plugins/cliconf/edgeswitch.py
deleted file mode 100644
index eb99f23674..0000000000
--- a/plugins/cliconf/edgeswitch.py
+++ /dev/null
@@ -1,141 +0,0 @@
-#
-# (c) 2018 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-cliconf: edgeswitch
-short_description: Use edgeswitch cliconf to run command on EdgeSwitch platform
-description:
- - This edgeswitch plugin provides low level abstraction apis for
- sending and receiving CLI commands from Ubiquiti EdgeSwitch network devices.
-'''
-
-import re
-import time
-import json
-
-from itertools import chain
-
-from ansible.errors import AnsibleConnectionFailure
-from ansible.module_utils._text import to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import dumps
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.cliconf import CliconfBase, enable_mode
-from ansible.module_utils.common._collections_compat import Mapping
-
-
-class Cliconf(CliconfBase):
-
- def get_device_info(self):
- device_info = {}
-
- device_info['network_os'] = 'edgeswitch'
- reply = self.get(command='show version')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'Software Version\.+ (.*)', data)
- if match:
- device_info['network_os_version'] = match.group(1).strip(',')
-
- match = re.search(r'^Machine Model\.+ (.*)', data, re.M)
- if match:
- device_info['network_os_model'] = match.group(1)
-
- match = re.search(r'System Name\.+ (.*)', data, re.M)
- if match:
- device_info['network_os_hostname'] = match.group(1)
-
- return device_info
-
- @enable_mode
- def get_config(self, source='running', flags=None):
- if source not in ('running', 'startup'):
- raise ValueError("fetching configuration from %s is not supported" % source)
-
- if source == 'running':
- cmd = 'show running-config '
- else:
- cmd = 'show startup-config '
-
- if flags:
- cmd += ' '.join(to_list(flags))
- cmd = cmd.strip()
-
- return self.send_command(cmd)
-
- @enable_mode
- def edit_config(self, commands):
- resp = {}
-
- results = []
- requests = []
- self.send_command('configure')
- for line in to_list(commands):
- if not isinstance(line, Mapping):
- line = {'command': line}
-
- cmd = line['command']
- if cmd != 'end' and cmd[0] != '!':
- results.append(self.send_command(**line))
- requests.append(cmd)
-
- self.send_command('end')
-
- resp['request'] = requests
- resp['response'] = results
- return resp
-
- def get(self, command=None, prompt=None, answer=None, sendonly=False, output=None, newline=True, check_all=False):
- if not command:
- raise ValueError('must provide value of command to execute')
- if output:
- raise ValueError("'output' value %s is not supported for get" % output)
-
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def get_capabilities(self):
- result = super(Cliconf, self).get_capabilities()
- result['rpc'] += ['run_commands']
- return json.dumps(result)
-
- def run_commands(self, commands=None, check_rc=True):
- if commands is None:
- raise ValueError("'commands' value is required")
-
- responses = list()
- for cmd in to_list(commands):
- if not isinstance(cmd, Mapping):
- cmd = {'command': cmd}
-
- output = cmd.pop('output', None)
- if output:
- raise ValueError("'output' value %s is not supported for run_commands" % output)
-
- try:
- out = self.send_command(**cmd)
- except AnsibleConnectionFailure as e:
- if check_rc:
- raise
- out = getattr(e, 'err', e)
-
- responses.append(out)
-
- return responses
diff --git a/plugins/cliconf/enos.py b/plugins/cliconf/enos.py
deleted file mode 100644
index 225409f5cd..0000000000
--- a/plugins/cliconf/enos.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# (C) 2017 Red Hat Inc.
-# Copyright (C) 2017 Lenovo.
-#
-# GNU General Public License v3.0+
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-# Contains CLIConf Plugin methods for ENOS Modules
-# Lenovo Networking
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-cliconf: enos
-short_description: Use enos cliconf to run command on Lenovo ENOS platform
-description:
- - This enos plugin provides low level abstraction apis for
- sending and receiving CLI commands from Lenovo ENOS network devices.
-'''
-
-import re
-import json
-
-from itertools import chain
-
-from ansible.errors import AnsibleConnectionFailure
-from ansible.module_utils._text import to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.cliconf import CliconfBase, enable_mode
-
-
-class Cliconf(CliconfBase):
-
- def get_device_info(self):
- device_info = {}
-
- device_info['network_os'] = 'enos'
- reply = self.get('show version')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'^Software Version (.*?) ', data, re.M | re.I)
- if match:
- device_info['network_os_version'] = match.group(1)
-
- match = re.search(r'^Lenovo RackSwitch (\S+)', data, re.M | re.I)
- if match:
- device_info['network_os_model'] = match.group(1)
-
- match = re.search(r'^(.+) uptime', data, re.M)
- if match:
- device_info['network_os_hostname'] = match.group(1)
- else:
- device_info['network_os_hostname'] = "NA"
-
- return device_info
-
- @enable_mode
- def get_config(self, source='running', format='text', flags=None):
- if source not in ('running', 'startup'):
- msg = "fetching configuration from %s is not supported"
- return self.invalid_params(msg % source)
- if source == 'running':
- cmd = 'show running-config'
- else:
- cmd = 'show startup-config'
- return self.send_command(cmd)
-
- @enable_mode
- def edit_config(self, command):
- for cmd in chain(['configure terminal'], to_list(command), ['end']):
- self.send_command(cmd)
-
- def get(self, command, prompt=None, answer=None, sendonly=False, newline=True, check_all=False):
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def get_capabilities(self):
- result = super(Cliconf, self).get_capabilities()
- return json.dumps(result)
-
- def set_cli_prompt_context(self):
- """
- Make sure we are in the operational cli mode
- :return: None
- """
- if self._connection.connected:
- out = self._connection.get_prompt()
-
- if out is None:
- raise AnsibleConnectionFailure(message=u'cli prompt is not identified from the last received'
- u' response window: %s' % self._connection._last_recv_window)
-
- if to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
- self._connection.queue_message('vvvv', 'In Config mode, sending exit to device')
- self._connection.send_command('exit')
- else:
- self._connection.send_command('enable')
diff --git a/plugins/cliconf/eric_eccli.py b/plugins/cliconf/eric_eccli.py
deleted file mode 100644
index 13c5f9edc3..0000000000
--- a/plugins/cliconf/eric_eccli.py
+++ /dev/null
@@ -1,97 +0,0 @@
-#
-# Copyright (c) 2019 Ericsson AB.
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-author: Ericsson IPOS OAM team
-cliconf: eccli
-short_description: Use eccli cliconf to run command on Ericsson ECCLI platform
-description:
- - This eccli plugin provides low level abstraction APIs for
- sending and receiving CLI commands from Ericsson ECCLI network devices.
-'''
-
-from ansible.module_utils.common._collections_compat import Mapping
-import collections
-import re
-import time
-import json
-
-from itertools import chain
-
-from ansible.errors import AnsibleConnectionFailure
-from ansible.module_utils._text import to_text
-from ansible.module_utils.six import iteritems
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, dumps
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.cliconf import CliconfBase, enable_mode
-
-
-class Cliconf(CliconfBase):
-
- def get_config(self, source='running', flags=None, format=None):
- return
-
- def edit_config(self, candidate=None, commit=True, replace=None, comment=None):
- return
-
- def get(self, command=None, prompt=None, answer=None, sendonly=False, output=None, newline=True, check_all=False):
- if not command:
- raise ValueError('must provide value of command to execute')
- if output:
- raise ValueError("'output' value %s is not supported for get" % output)
-
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def get_device_info(self):
- device_info = {}
- device_info['network_os'] = 'eric_eccli'
- return device_info
-
- def get_capabilities(self):
- result = dict()
- result['rpc'] = self.get_base_rpc() + ['run_commands']
- result['network_api'] = 'cliconf'
- result['device_info'] = self.get_device_info()
- return json.dumps(result)
-
- def run_commands(self, commands=None, check_rc=True):
- if commands is None:
- raise ValueError("'commands' value is required")
-
- responses = list()
- for cmd in to_list(commands):
- if not isinstance(cmd, Mapping):
- cmd = {'command': cmd}
-
- output = cmd.pop('output', None)
- if output:
- raise ValueError("'output' value %s is not supported for run_commands" % output)
- try:
- out = self.send_command(**cmd)
- except AnsibleConnectionFailure as e:
- if check_rc:
- raise
- out = getattr(e, 'err', e)
-
- responses.append(out)
-
- return responses
diff --git a/plugins/cliconf/exos.py b/plugins/cliconf/exos.py
deleted file mode 100644
index c9ca494688..0000000000
--- a/plugins/cliconf/exos.py
+++ /dev/null
@@ -1,229 +0,0 @@
-#
-# (c) 2017 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-cliconf: exos
-short_description: Use exos cliconf to run command on Extreme EXOS platform
-description:
- - This exos plugin provides low level abstraction apis for
- sending and receiving CLI commands from Extreme EXOS network devices.
-'''
-
-import re
-import json
-
-from ansible.errors import AnsibleConnectionFailure
-from ansible.module_utils._text import to_bytes, to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.module_utils.connection import ConnectionError
-from ansible.module_utils.common._collections_compat import Mapping
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, dumps
-from ansible.plugins.cliconf import CliconfBase
-
-
-class Cliconf(CliconfBase):
-
- def get_diff(self, candidate=None, running=None, diff_match='line', diff_ignore_lines=None, path=None, diff_replace='line'):
- diff = {}
- device_operations = self.get_device_operations()
- option_values = self.get_option_values()
-
- if candidate is None and device_operations['supports_generate_diff']:
- raise ValueError("candidate configuration is required to generate diff")
-
- if diff_match not in option_values['diff_match']:
- raise ValueError("'match' value %s in invalid, valid values are %s" % (diff_match, ', '.join(option_values['diff_match'])))
-
- if diff_replace not in option_values['diff_replace']:
- raise ValueError("'replace' value %s in invalid, valid values are %s" % (diff_replace, ', '.join(option_values['diff_replace'])))
-
- # prepare candidate configuration
- candidate_obj = NetworkConfig(indent=1)
- candidate_obj.load(candidate)
-
- if running and diff_match != 'none' and diff_replace != 'config':
- # running configuration
- running_obj = NetworkConfig(indent=1, contents=running, ignore_lines=diff_ignore_lines)
- configdiffobjs = candidate_obj.difference(running_obj, path=path, match=diff_match, replace=diff_replace)
-
- else:
- configdiffobjs = candidate_obj.items
-
- diff['config_diff'] = dumps(configdiffobjs, 'commands') if configdiffobjs else ''
- return diff
-
- def get_device_info(self):
- device_info = {}
- device_info['network_os'] = 'exos'
-
- reply = self.run_commands({'command': 'show switch detail', 'output': 'text'})
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'ExtremeXOS version (\S+)', data)
- if match:
- device_info['network_os_version'] = match.group(1)
-
- match = re.search(r'System Type: +(\S+)', data)
- if match:
- device_info['network_os_model'] = match.group(1)
-
- match = re.search(r'SysName: +(\S+)', data)
- if match:
- device_info['network_os_hostname'] = match.group(1)
-
- return device_info
-
- def get_default_flag(self):
- # The flag to modify the command to collect configuration with defaults
- return 'detail'
-
- def get_config(self, source='running', format='text', flags=None):
- options_values = self.get_option_values()
- if format not in options_values['format']:
- raise ValueError("'format' value %s is invalid. Valid values are %s" % (format, ','.join(options_values['format'])))
-
- lookup = {'running': 'show configuration', 'startup': 'debug cfgmgr show configuration file'}
- if source not in lookup:
- raise ValueError("fetching configuration from %s is not supported" % source)
-
- cmd = {'command': lookup[source], 'output': 'text'}
-
- if source == 'startup':
- reply = self.run_commands({'command': 'show switch', 'format': 'text'})
- data = to_text(reply, errors='surrogate_or_strict').strip()
- match = re.search(r'Config Selected: +(\S+)\.cfg', data, re.MULTILINE)
- if match:
- cmd['command'] += match.group(1)
- else:
- # No Startup(/Selected) Config
- return {}
-
- cmd['command'] += ' '.join(to_list(flags))
- cmd['command'] = cmd['command'].strip()
-
- return self.run_commands(cmd)[0]
-
- def edit_config(self, candidate=None, commit=True, replace=None, diff=False, comment=None):
- resp = {}
- operations = self.get_device_operations()
- self.check_edit_config_capability(operations, candidate, commit, replace, comment)
- results = []
- requests = []
-
- if commit:
- for line in to_list(candidate):
- if not isinstance(line, Mapping):
- line = {'command': line}
- results.append(self.send_command(**line))
- requests.append(line['command'])
- else:
- raise ValueError('check mode is not supported')
-
- resp['request'] = requests
- resp['response'] = results
- return resp
-
- def get(self, command, prompt=None, answer=None, sendonly=False, output=None, newline=True, check_all=False):
- if output:
- command = self._get_command_with_output(command, output)
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def run_commands(self, commands=None, check_rc=True):
- if commands is None:
- raise ValueError("'commands' value is required")
-
- responses = list()
- for cmd in to_list(commands):
- if not isinstance(cmd, Mapping):
- cmd = {'command': cmd}
-
- output = cmd.pop('output', None)
- if output:
- cmd['command'] = self._get_command_with_output(cmd['command'], output)
-
- try:
- out = self.send_command(**cmd)
- except AnsibleConnectionFailure as e:
- if check_rc is True:
- raise
- out = getattr(e, 'err', e)
-
- if out is not None:
- try:
- out = to_text(out, errors='surrogate_or_strict').strip()
- except UnicodeError:
- raise ConnectionError(message=u'Failed to decode output from %s: %s' % (cmd, to_text(out)))
-
- if output and output == 'json':
- try:
- out = json.loads(out)
- except ValueError:
- raise ConnectionError('Response was not valid JSON, got {0}'.format(
- to_text(out)
- ))
- responses.append(out)
-
- return responses
-
- def get_device_operations(self):
- return {
- 'supports_diff_replace': False, # identify if config should be merged or replaced is supported
- 'supports_commit': False, # identify if commit is supported by device or not
- 'supports_rollback': False, # identify if rollback is supported or not
- 'supports_defaults': True, # identify if fetching running config with default is supported
- 'supports_commit_comment': False, # identify if adding comment to commit is supported of not
- 'supports_onbox_diff': False, # identify if on box diff capability is supported or not
- 'supports_generate_diff': True, # identify if diff capability is supported within plugin
- 'supports_multiline_delimiter': False, # identify if multiline delimiter is supported within config
- 'supports_diff_match': True, # identify if match is supported
- 'supports_diff_ignore_lines': True, # identify if ignore line in diff is supported
- 'supports_config_replace': False, # identify if running config replace with candidate config is supported
- 'supports_admin': False, # identify if admin configure mode is supported or not
- 'supports_commit_label': False, # identify if commit label is supported or not
- 'supports_replace': False
- }
-
- def get_option_values(self):
- return {
- 'format': ['text', 'json'],
- 'diff_match': ['line', 'strict', 'exact', 'none'],
- 'diff_replace': ['line', 'block'],
- 'output': ['text', 'json']
- }
-
- def get_capabilities(self):
- result = super(Cliconf, self).get_capabilities()
- result['rpc'] += ['run_commmands', 'get_default_flag', 'get_diff']
- result['device_operations'] = self.get_device_operations()
- result['device_info'] = self.get_device_info()
- result.update(self.get_option_values())
- return json.dumps(result)
-
- def _get_command_with_output(self, command, output):
- if output not in self.get_option_values().get('output'):
- raise ValueError("'output' value is %s is invalid. Valid values are %s" % (output, ','.join(self.get_option_values().get('output'))))
-
- if output == 'json' and not command.startswith('run script cli2json.py'):
- cmd = 'run script cli2json.py %s' % command
- else:
- cmd = command
- return cmd
diff --git a/plugins/cliconf/icx.py b/plugins/cliconf/icx.py
deleted file mode 100644
index 4ce6e5d130..0000000000
--- a/plugins/cliconf/icx.py
+++ /dev/null
@@ -1,314 +0,0 @@
-# Copyright: (c) 2019, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-author: Ruckus Wireless (@Commscope)
-cliconf: icx
-short_description: Use icx cliconf to run command on Ruckus ICX platform
-description:
- - This icx plugin provides low level abstraction APIs for
- sending and receiving CLI commands from Ruckus ICX network devices.
-'''
-
-
-import re
-import time
-import json
-import os
-
-from itertools import chain
-from ansible.errors import AnsibleConnectionFailure
-from ansible.module_utils._text import to_text
-from ansible.module_utils.six import iteritems
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, dumps
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.cliconf import CliconfBase, enable_mode
-from ansible.module_utils.common._collections_compat import Mapping
-
-
-class Cliconf(CliconfBase):
-
- @enable_mode
- def get_config(self, source='running', flags=None, format=None, compare=None):
- if source not in ('running', 'startup'):
- raise ValueError("fetching configuration from %s is not supported" % source)
-
- if format:
- raise ValueError("'format' value %s is not supported for get_config" % format)
-
- if not flags:
- flags = []
-
- if compare is False:
- return ''
- else:
- if source == 'running':
- cmd = 'show running-config '
- else:
- cmd = 'show configuration '
-
- cmd += ' '.join(to_list(flags))
- cmd = cmd.strip()
-
- return self.send_command(cmd)
-
- def get_diff(self, candidate=None, running=None, diff_match='line', diff_ignore_lines=None, path=None, diff_replace='line'):
- """
- Generate diff between candidate and running configuration. If the
- remote host supports onbox diff capabilities ie. supports_onbox_diff in that case
- candidate and running configurations are not required to be passed as argument.
- In case if onbox diff capability is not supported candidate argument is mandatory
- and running argument is optional.
- :param candidate: The configuration which is expected to be present on remote host.
- :param running: The base configuration which is used to generate diff.
- :param diff_match: Instructs how to match the candidate configuration with current device configuration
- Valid values are 'line', 'strict', 'exact', 'none'.
- 'line' - commands are matched line by line
- 'strict' - command lines are matched with respect to position
- 'exact' - command lines must be an equal match
- 'none' - will not compare the candidate configuration with the running configuration
- :param diff_ignore_lines: Use this argument to specify one or more lines that should be
- ignored during the diff. This is used for lines in the configuration
- that are automatically updated by the system. This argument takes
- a list of regular expressions or exact line matches.
- :param path: The ordered set of parents that uniquely identify the section or hierarchy
- the commands should be checked against. If the parents argument
- is omitted, the commands are checked against the set of top
- level or global commands.
- :param diff_replace: Instructs on the way to perform the configuration on the device.
- If the replace argument is set to I(line) then the modified lines are
- pushed to the device in configuration mode. If the replace argument is
- set to I(block) then the entire command block is pushed to the device in
- configuration mode if any line is not correct.
- :return: Configuration diff in json format.
- {
- 'config_diff': '',
- 'banner_diff': {}
- }
-
- """
- diff = {}
- device_operations = self.get_device_operations()
- option_values = self.get_option_values()
-
- if candidate is None and device_operations['supports_generate_diff']:
- raise ValueError("candidate configuration is required to generate diff")
-
- if diff_match not in option_values['diff_match']:
- raise ValueError("'match' value %s in invalid, valid values are %s" % (diff_match, ', '.join(option_values['diff_match'])))
-
- if diff_replace not in option_values['diff_replace']:
- raise ValueError("'replace' value %s in invalid, valid values are %s" % (diff_replace, ', '.join(option_values['diff_replace'])))
-
- # prepare candidate configuration
- candidate_obj = NetworkConfig(indent=1)
- want_src, want_banners = self._extract_banners(candidate)
- candidate_obj.load(want_src)
-
- if running and diff_match != 'none':
- # running configuration
- have_src, have_banners = self._extract_banners(running)
-
- running_obj = NetworkConfig(indent=1, contents=have_src, ignore_lines=diff_ignore_lines)
- configdiffobjs = candidate_obj.difference(running_obj, path=path, match=diff_match, replace=diff_replace)
-
- else:
- configdiffobjs = candidate_obj.items
- have_banners = {}
-
- diff['config_diff'] = dumps(configdiffobjs, 'commands') if configdiffobjs else ''
-
- banners = self._diff_banners(want_banners, have_banners)
- diff['banner_diff'] = banners if banners else {}
- return diff
-
- @enable_mode
- def edit_config(self, candidate=None, commit=True, replace=None, comment=None):
- resp = {}
- operations = self.get_device_operations()
- self.check_edit_config_capability(operations, candidate, commit, replace, comment)
-
- results = []
- requests = []
- if commit:
- prompt = self._connection.get_prompt()
- if (b'(config-if' in prompt) or (b'(config' in prompt) or (b'(config-lag-if' in prompt):
- self.send_command('end')
-
- self.send_command('configure terminal')
-
- for line in to_list(candidate):
- if not isinstance(line, Mapping):
- line = {'command': line}
-
- cmd = line['command']
- if cmd != 'end' and cmd[0] != '!':
- results.append(self.send_command(**line))
- requests.append(cmd)
-
- self.send_command('end')
- else:
- raise ValueError('check mode is not supported')
-
- resp['request'] = requests
- resp['response'] = results
- return resp
-
- def get(self, command=None, prompt=None, answer=None, sendonly=False, output=None, check_all=False):
- if not command:
- raise ValueError('must provide value of command to execute')
- if output:
- raise ValueError("'output' value %s is not supported for get" % output)
-
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, check_all=check_all)
-
- def scp(self, command=None, scp_user=None, scp_pass=None):
- if not command:
- raise ValueError('must provide value of command to execute')
- prompt = ["User name:", "Password:"]
- if(scp_pass is None):
- answer = [scp_user, self._connection._play_context.password]
- else:
- answer = [scp_user, scp_pass]
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=False, check_all=True)
-
- def get_device_info(self):
- device_info = {}
-
- device_info['network_os'] = 'icx'
- reply = self.get(command='show version')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'Version (\S+)', data)
- if match:
- device_info['network_os_version'] = match.group(1).strip(',')
-
- match = re.search(r'^Cisco (.+) \(revision', data, re.M)
- if match:
- device_info['network_os_model'] = match.group(1)
-
- match = re.search(r'^(.+) uptime', data, re.M)
- if match:
- device_info['network_os_hostname'] = match.group(1)
-
- return device_info
-
- def get_device_operations(self):
- return {
- 'supports_diff_replace': True,
- 'supports_commit': False,
- 'supports_rollback': False,
- 'supports_defaults': True,
- 'supports_onbox_diff': False,
- 'supports_commit_comment': False,
- 'supports_multiline_delimiter': True,
- 'supports_diff_match': True,
- 'supports_diff_ignore_lines': True,
- 'supports_generate_diff': True,
- 'supports_replace': False
- }
-
- def get_option_values(self):
- return {
- 'format': ['text'],
- 'diff_match': ['line', 'strict', 'exact', 'none'],
- 'diff_replace': ['line', 'block'],
- 'output': []
- }
-
- def get_capabilities(self):
- result = dict()
- result['rpc'] = self.get_base_rpc() + ['edit_banner', 'get_diff', 'run_commands', 'get_defaults_flag']
- result['network_api'] = 'cliconf'
- result['device_operations'] = self.get_device_operations()
- result.update(self.get_option_values())
- return json.dumps(result)
-
- def edit_banner(self, candidate=None, multiline_delimiter="@", commit=True):
- """
- Edit banner on remote device
- :param banners: Banners to be loaded in json format
- :param multiline_delimiter: Line delimiter for banner
- :param commit: Boolean value that indicates if the device candidate
- configuration should be pushed in the running configuration or discarded.
- :param diff: Boolean flag to indicate if configuration that is applied on remote host should
- generated and returned in response or not
- :return: Returns response of executing the configuration command received
- from remote host
- """
- resp = {}
- banners_obj = json.loads(candidate)
- results = []
- requests = []
- if commit:
- for key, value in iteritems(banners_obj):
- key += ' %s' % multiline_delimiter
- self.send_command('config terminal', sendonly=True)
- for cmd in [key, value, multiline_delimiter]:
- obj = {'command': cmd, 'sendonly': True}
- results.append(self.send_command(**obj))
- requests.append(cmd)
-
- self.send_command('end', sendonly=True)
- time.sleep(0.1)
- results.append(self.send_command('\n'))
- requests.append('\n')
-
- resp['request'] = requests
- resp['response'] = results
-
- return resp
-
- def run_commands(self, commands=None, check_rc=True):
- if commands is None:
- raise ValueError("'commands' value is required")
-
- responses = list()
- for cmd in to_list(commands):
- if not isinstance(cmd, Mapping):
- cmd = {'command': cmd}
-
- output = cmd.pop('output', None)
- if output:
- raise ValueError("'output' value %s is not supported for run_commands" % output)
-
- try:
- out = self.send_command(**cmd)
- except AnsibleConnectionFailure as e:
- if check_rc:
- raise
- out = getattr(e, 'err', to_text(e))
-
- responses.append(out)
-
- return responses
-
- def _extract_banners(self, config):
- banners = {}
- banner_cmds = re.findall(r'^banner (\w+)', config, re.M)
- for cmd in banner_cmds:
- regex = r'banner %s \$(.+?)(?=\$)' % cmd
- match = re.search(regex, config, re.S)
- if match:
- key = 'banner %s' % cmd
- banners[key] = match.group(1).strip()
-
- for cmd in banner_cmds:
- regex = r'banner %s \$(.+?)(?=\$)' % cmd
- match = re.search(regex, config, re.S)
- if match:
- config = config.replace(str(match.group(1)), '')
-
- config = re.sub(r'banner \w+ \$\$', '!! banner removed', config)
- return config, banners
-
- def _diff_banners(self, want, have):
- candidate = {}
- for key, value in iteritems(want):
- if value != have.get(key):
- candidate[key] = value
- return candidate
diff --git a/plugins/cliconf/ironware.py b/plugins/cliconf/ironware.py
deleted file mode 100644
index cb476f924d..0000000000
--- a/plugins/cliconf/ironware.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# (c) 2017 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-cliconf: ironware
-short_description: Use ironware cliconf to run command on Extreme Ironware platform
-description:
- - This ironware plugin provides low level abstraction apis for
- sending and receiving CLI commands from Extreme Ironware network devices.
-'''
-
-import re
-import json
-
-from itertools import chain
-
-from ansible.module_utils._text import to_bytes, to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.cliconf import CliconfBase, enable_mode
-
-
-class Cliconf(CliconfBase):
-
- def get_device_info(self):
- device_info = {}
-
- device_info['network_os'] = 'ironware'
- reply = self.send_command('show version')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'IronWare : Version (\S+),', data)
- if match:
- device_info['network_os_version'] = match.group(1)
-
- match = re.search(r'^(?:System Mode\:|System\:) (CES|CER|MLX|XMR)', data, re.M)
- if match:
- device_info['network_os_model'] = match.group(1)
-
- return device_info
-
- @enable_mode
- def get_config(self, source='running', format='text', flags=None):
- if source not in ('running', 'startup'):
- raise ValueError("fetching configuration from %s is not supported" % source)
-
- if source == 'running':
- cmd = 'show running-config'
- if flags is not None:
- cmd += ' ' + ' '.join(flags)
-
- else:
- cmd = 'show configuration'
- if flags is not None:
- raise ValueError("flags are only supported with running-config")
-
- return self.send_command(cmd)
-
- @enable_mode
- def edit_config(self, command):
- for cmd in chain(['configure terminal'], to_list(command), ['end']):
- self.send_command(cmd)
-
- def get(self, command, prompt=None, answer=None, sendonly=False, newline=True, check_all=False):
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def get_capabilities(self):
- result = super(Cliconf, self).get_capabilities()
- return json.dumps(result)
-
- def set_cli_prompt_context(self):
- """
- Make sure we are in the operational cli mode
- :return: None
- """
- if self._connection.connected:
- self._update_cli_prompt_context(config_context=')#')
diff --git a/plugins/cliconf/netvisor.py b/plugins/cliconf/netvisor.py
deleted file mode 100644
index 51301531ce..0000000000
--- a/plugins/cliconf/netvisor.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#
-# (c) 2016 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-cliconf: netvisor
-short_description: Use netvisor cliconf to run command on Pluribus netvisor platform
-description:
- - This netvisor plugin provides low level abstraction apis for
- sending and receiving CLI commands from Pluribus netvisor devices.
-'''
-
-import json
-from ansible.plugins.cliconf import CliconfBase
-
-
-class Cliconf(CliconfBase):
-
- def get_config(self, source='running', format='text', flags=None):
- if source not in ('running'):
- return self.invalid_params("fetching configuration from %s is not supported" % source)
- cmd = 'show running-config'
- return self.send_command(cmd)
-
- def edit_config(self, command):
- return
-
- def get(self, command=None, prompt=None, answer=None, sendonly=False, output=None, newline=True, check_all=False):
- if not command:
- raise ValueError('must provide value of command to execute')
- if output:
- raise ValueError("'output' value %s is not supported for get" % output)
-
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def get_option_values(self):
- return {
- 'format': ['text'],
- 'diff_match': ['line', 'strict', 'exact', 'none'],
- 'diff_replace': ['line', 'block'],
- 'output': []
- }
-
- def get_capabilities(self):
- result = dict()
- result['rpc'] = self.get_base_rpc()
- result['network_api'] = 'cliconf'
- result['device_info'] = self.get_device_info()
- result.update(self.get_option_values())
- return json.dumps(result)
-
- def get_device_info(self):
- device_info = {}
- device_info['network_os'] = 'netvisor'
-
- return device_info
diff --git a/plugins/cliconf/nos.py b/plugins/cliconf/nos.py
deleted file mode 100644
index b1f922ac55..0000000000
--- a/plugins/cliconf/nos.py
+++ /dev/null
@@ -1,112 +0,0 @@
-#
-# (c) 2018 Extreme Networks Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-cliconf: nos
-short_description: Use nos cliconf to run command on Extreme NOS platform
-description:
- - This nos plugin provides low level abstraction apis for
- sending and receiving CLI commands from Extreme NOS network devices.
-'''
-
-import re
-import json
-
-from ansible.module_utils._text import to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.cliconf import CliconfBase
-
-
-class Cliconf(CliconfBase):
-
- def get_device_info(self):
- device_info = {}
-
- device_info['network_os'] = 'nos'
- reply = self.get('show version')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'Network Operating System Version: (\S+)', data)
- if match:
- device_info['network_os_version'] = match.group(1)
-
- reply = self.get('show chassis')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'^Chassis Name:(\s+)(\S+)', data, re.M)
- if match:
- device_info['network_os_model'] = match.group(2)
-
- reply = self.get('show running-config | inc "switch-attributes host-name"')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'switch-attributes host-name (\S+)', data, re.M)
- if match:
- device_info['network_os_hostname'] = match.group(1)
-
- return device_info
-
- def get_config(self, source='running', flags=None):
- if source not in 'running':
- raise ValueError("fetching configuration from %s is not supported" % source)
- if source == 'running':
- cmd = 'show running-config'
-
- flags = [] if flags is None else flags
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- return self.send_command(cmd)
-
- def edit_config(self, command):
- resp = {}
- results = []
- requests = []
- self.send_command('configure terminal')
- for cmd in to_list(command):
- if isinstance(cmd, dict):
- command = cmd['command']
- prompt = cmd['prompt']
- answer = cmd['answer']
- newline = cmd.get('newline', True)
- else:
- command = cmd
- prompt = None
- answer = None
- newline = True
-
- if cmd != 'end' and cmd[0] != '!':
- results.append(self.send_command(command, prompt, answer, False, newline))
- requests.append(cmd)
-
- self.send_command('end')
-
- resp['request'] = requests
- resp['response'] = results
- return resp
-
- def get(self, command, prompt=None, answer=None, sendonly=False, newline=True, check_all=False):
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def get_capabilities(self):
- result = super(Cliconf, self).get_capabilities()
- return json.dumps(result)
diff --git a/plugins/cliconf/onyx.py b/plugins/cliconf/onyx.py
deleted file mode 100644
index af7690efb5..0000000000
--- a/plugins/cliconf/onyx.py
+++ /dev/null
@@ -1,77 +0,0 @@
-#
-# (c) 2017 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-cliconf: onyx
-short_description: Use onyx cliconf to run command on Mellanox ONYX platform
-description:
- - This onyx plugin provides low level abstraction apis for
- sending and receiving CLI commands from Mellanox ONYX network devices.
-'''
-
-import json
-
-from itertools import chain
-
-from ansible.module_utils._text import to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.cliconf import CliconfBase, enable_mode
-
-
-class Cliconf(CliconfBase):
-
- def get_device_info(self):
- device_info = {}
-
- reply = self.get('show version | json-print')
- data = json.loads(reply)
- device_info['network_os'] = data['Product name']
- device_info['network_os_version'] = data['Product release']
- device_info['network_os_version_summary'] = data['Version summary']
- device_info['network_os_model'] = data['Product model']
-
- reply = self.get('show hosts | include Hostname')
- data = to_text(reply, errors='surrogate_or_strict').strip()
- hostname = data.split(':')[1]
- hostname = hostname.strip()
- device_info['network_os_hostname'] = hostname
-
- return device_info
-
- @enable_mode
- def get_config(self, source='running', format='text', flags=None):
- if source not in ('running',):
- return self.invalid_params("fetching configuration from %s is not supported" % source)
- cmd = 'show running-config'
- return self.send_command(cmd)
-
- @enable_mode
- def edit_config(self, command):
- for cmd in chain(['configure terminal'], to_list(command), ['exit']):
- self.send_command(cmd)
-
- def get(self, command, prompt=None, answer=None, sendonly=False, newline=True, check_all=False):
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def get_capabilities(self):
- result = super(Cliconf, self).get_capabilities()
- return json.dumps(result)
diff --git a/plugins/cliconf/routeros.py b/plugins/cliconf/routeros.py
deleted file mode 100644
index 9e020a1b03..0000000000
--- a/plugins/cliconf/routeros.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#
-# (c) 2017 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-cliconf: routeros
-short_description: Use routeros cliconf to run command on MikroTik RouterOS platform
-description:
- - This routeros plugin provides low level abstraction apis for
- sending and receiving CLI commands from MikroTik RouterOS network devices.
-'''
-
-import re
-import json
-
-from itertools import chain
-
-from ansible.module_utils._text import to_bytes, to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.cliconf import CliconfBase, enable_mode
-
-
-class Cliconf(CliconfBase):
-
- def get_device_info(self):
- device_info = {}
- device_info['network_os'] = 'RouterOS'
-
- resource = self.get('/system resource print')
- data = to_text(resource, errors='surrogate_or_strict').strip()
- match = re.search(r'version: (\S+)', data)
- if match:
- device_info['network_os_version'] = match.group(1)
-
- routerboard = self.get('/system routerboard print')
- data = to_text(routerboard, errors='surrogate_or_strict').strip()
- match = re.search(r'model: (.+)$', data, re.M)
- if match:
- device_info['network_os_model'] = match.group(1)
-
- identity = self.get('/system identity print')
- data = to_text(identity, errors='surrogate_or_strict').strip()
- match = re.search(r'name: (.+)$', data, re.M)
- if match:
- device_info['network_os_hostname'] = match.group(1)
-
- return device_info
-
- def get_config(self, source='running', format='text', flags=None):
- return
-
- def edit_config(self, command):
- return
-
- def get(self, command, prompt=None, answer=None, sendonly=False, newline=True, check_all=False):
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def get_capabilities(self):
- result = super(Cliconf, self).get_capabilities()
- return json.dumps(result)
diff --git a/plugins/cliconf/slxos.py b/plugins/cliconf/slxos.py
deleted file mode 100644
index a7809a3b95..0000000000
--- a/plugins/cliconf/slxos.py
+++ /dev/null
@@ -1,104 +0,0 @@
-#
-# (c) 2018 Extreme Networks Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-cliconf: slxos
-short_description: Use slxos cliconf to run command on Extreme SLX-OS platform
-description:
- - This slxos plugin provides low level abstraction apis for
- sending and receiving CLI commands from Extreme SLX-OS network devices.
-'''
-
-import re
-import json
-
-from itertools import chain
-
-from ansible.module_utils._text import to_bytes, to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.cliconf import CliconfBase
-
-
-class Cliconf(CliconfBase):
-
- def get_device_info(self):
- device_info = {}
-
- device_info['network_os'] = 'slxos'
- reply = self.get('show version')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'SLX\-OS Operating System Version: (\S+)', data)
- if match:
- device_info['network_os_version'] = match.group(1)
-
- reply = self.get('show chassis')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'^Chassis Name:(\s+)(\S+)', data, re.M)
- if match:
- device_info['network_os_model'] = match.group(2)
-
- reply = self.get('show running-config | inc "switch-attributes host-name"')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'switch-attributes host-name (\S+)', data, re.M)
- if match:
- device_info['network_os_hostname'] = match.group(1)
-
- return device_info
-
- def get_config(self, source='running', flags=None):
- if source not in ('running', 'startup'):
- raise ValueError("fetching configuration from %s is not supported" % source)
- if source == 'running':
- cmd = 'show running-config'
- else:
- cmd = 'show startup-config'
-
- flags = [] if flags is None else flags
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- return self.send_command(cmd)
-
- def edit_config(self, command):
- for cmd in chain(['configure terminal'], to_list(command), ['end']):
- if isinstance(cmd, dict):
- command = cmd['command']
- prompt = cmd['prompt']
- answer = cmd['answer']
- newline = cmd.get('newline', True)
- else:
- command = cmd
- prompt = None
- answer = None
- newline = True
-
- self.send_command(command, prompt, answer, False, newline)
-
- def get(self, command, prompt=None, answer=None, sendonly=False, newline=True, check_all=False):
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def get_capabilities(self):
- result = super(Cliconf, self).get_capabilities()
- return json.dumps(result)
diff --git a/plugins/cliconf/voss.py b/plugins/cliconf/voss.py
deleted file mode 100644
index 7d3d26eb7d..0000000000
--- a/plugins/cliconf/voss.py
+++ /dev/null
@@ -1,235 +0,0 @@
-#
-# (c) 2018 Extreme Networks Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-cliconf: voss
-short_description: Use voss cliconf to run command on Extreme VOSS platform
-description:
- - This voss plugin provides low level abstraction apis for
- sending and receiving CLI commands from Extreme VOSS network devices.
-'''
-
-import re
-import json
-
-from ansible.errors import AnsibleConnectionFailure
-from ansible.module_utils._text import to_text
-from ansible.module_utils.common._collections_compat import Mapping
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, dumps
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible_collections.community.general.plugins.module_utils.network.voss.voss import VossNetworkConfig
-from ansible.plugins.cliconf import CliconfBase, enable_mode
-
-
-class Cliconf(CliconfBase):
-
- @enable_mode
- def get_config(self, source='running', flags=None, format=None):
- if source not in ('running', 'startup'):
- raise ValueError("fetching configuration from %s is not supported" % source)
-
- if format:
- raise ValueError("'format' value %s is not supported for get_config" % format)
-
- if not flags:
- flags = []
- if source == 'running':
- cmd = 'show running-config '
- cmd += ' '.join(to_list(flags))
- cmd = cmd.strip()
- else:
- cmd = 'more /intflash/config.cfg'
-
- return self.send_command(cmd)
-
- def get_diff(self, candidate=None, running=None, diff_match='line', diff_ignore_lines=None, path=None, diff_replace='line'):
- """
- Generate diff between candidate and running configuration. If the
- remote host supports onbox diff capabilities ie. supports_onbox_diff in that case
- candidate and running configurations are not required to be passed as argument.
- In case if onbox diff capability is not supported candidate argument is mandatory
- and running argument is optional.
- :param candidate: The configuration which is expected to be present on remote host.
- :param running: The base configuration which is used to generate diff.
- :param diff_match: Instructs how to match the candidate configuration with current device configuration
- Valid values are 'line', 'strict', 'exact', 'none'.
- 'line' - commands are matched line by line
- 'strict' - command lines are matched with respect to position
- 'exact' - command lines must be an equal match
- 'none' - will not compare the candidate configuration with the running configuration
- :param diff_ignore_lines: Use this argument to specify one or more lines that should be
- ignored during the diff. This is used for lines in the configuration
- that are automatically updated by the system. This argument takes
- a list of regular expressions or exact line matches.
- :param path: The ordered set of parents that uniquely identify the section or hierarchy
- the commands should be checked against. If the parents argument
- is omitted, the commands are checked against the set of top
- level or global commands.
- :param diff_replace: Instructs on the way to perform the configuration on the device.
- If the replace argument is set to I(line) then the modified lines are
- pushed to the device in configuration mode. If the replace argument is
- set to I(block) then the entire command block is pushed to the device in
- configuration mode if any line is not correct.
- :return: Configuration diff in json format.
- {
- 'config_diff': '',
- }
-
- """
- diff = {}
-
- device_operations = self.get_device_operations()
- option_values = self.get_option_values()
-
- if candidate is None and device_operations['supports_generate_diff']:
- raise ValueError("candidate configuration is required to generate diff")
-
- if diff_match not in option_values['diff_match']:
- raise ValueError("'match' value %s in invalid, valid values are %s" % (diff_match, ', '.join(option_values['diff_match'])))
-
- if diff_replace not in option_values['diff_replace']:
- raise ValueError("'replace' value %s in invalid, valid values are %s" % (diff_replace, ', '.join(option_values['diff_replace'])))
-
- # prepare candidate configuration
- candidate_obj = VossNetworkConfig(indent=0, ignore_lines=diff_ignore_lines)
- candidate_obj.load(candidate)
-
- if running and diff_match != 'none':
- # running configuration
- running_obj = VossNetworkConfig(indent=0, contents=running, ignore_lines=diff_ignore_lines)
- configdiffobjs = candidate_obj.difference(running_obj, path=path, match=diff_match, replace=diff_replace)
-
- else:
- configdiffobjs = candidate_obj.items
-
- diff['config_diff'] = dumps(configdiffobjs, 'commands') if configdiffobjs else ''
- diff['diff_path'] = path
- diff['diff_replace'] = diff_replace
- return diff
-
- @enable_mode
- def edit_config(self, candidate=None, commit=True, replace=None, comment=None):
- resp = {}
- operations = self.get_device_operations()
- self.check_edit_config_capability(operations, candidate, commit, replace, comment)
-
- results = []
- requests = []
- if commit:
- self.send_command('configure terminal')
- for line in to_list(candidate):
- if not isinstance(line, Mapping):
- line = {'command': line}
-
- cmd = line['command']
- if cmd != 'end' and cmd[0] != '!':
- results.append(self.send_command(**line))
- requests.append(cmd)
-
- self.send_command('end')
- else:
- raise ValueError('check mode is not supported')
-
- resp['request'] = requests
- resp['response'] = results
- return resp
-
- def get(self, command, prompt=None, answer=None, sendonly=False, newline=True, check_all=False):
- return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
-
- def get_device_info(self):
- device_info = {}
-
- device_info['network_os'] = 'voss'
- reply = self.get(command='show sys-info')
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'SysDescr\s+: \S+ \((\S+)\)', data)
- if match:
- device_info['network_os_version'] = match.group(1)
-
- match = re.search(r'Chassis\s+: (\S+)', data)
- if match:
- device_info['network_os_model'] = match.group(1)
-
- match = re.search(r'SysName\s+: (\S+)', data)
- if match:
- device_info['network_os_hostname'] = match.group(1)
-
- return device_info
-
- def get_device_operations(self):
- return {
- 'supports_diff_replace': True,
- 'supports_commit': False,
- 'supports_rollback': False,
- 'supports_defaults': True,
- 'supports_onbox_diff': False,
- 'supports_commit_comment': False,
- 'supports_multiline_delimiter': False,
- 'supports_diff_match': True,
- 'supports_diff_ignore_lines': True,
- 'supports_generate_diff': True,
- 'supports_replace': False
- }
-
- def get_option_values(self):
- return {
- 'format': ['text'],
- 'diff_match': ['line', 'strict', 'exact', 'none'],
- 'diff_replace': ['line', 'block'],
- 'output': []
- }
-
- def get_capabilities(self):
- result = super(Cliconf, self).get_capabilities()
- result['rpc'] += ['get_diff', 'run_commands', 'get_defaults_flag']
- result['device_operations'] = self.get_device_operations()
- result.update(self.get_option_values())
- return json.dumps(result)
-
- def run_commands(self, commands=None, check_rc=True):
- if commands is None:
- raise ValueError("'commands' value is required")
-
- responses = list()
- for cmd in to_list(commands):
- if not isinstance(cmd, Mapping):
- cmd = {'command': cmd}
-
- output = cmd.pop('output', None)
- if output:
- raise ValueError("'output' value %s is not supported for run_commands" % output)
-
- try:
- out = self.send_command(**cmd)
- except AnsibleConnectionFailure as e:
- if check_rc:
- raise
- out = getattr(e, 'err', e)
-
- responses.append(out)
-
- return responses
-
- def get_defaults_flag(self):
- return 'verbose'
diff --git a/plugins/doc_fragments/a10.py b/plugins/doc_fragments/a10.py
deleted file mode 100644
index d2d6cb502f..0000000000
--- a/plugins/doc_fragments/a10.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2016, John Barker
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
-
- # Standard files documentation fragment
- DOCUMENTATION = r'''
-options:
- host:
- description:
- - Hostname or IP of the A10 Networks device.
- type: str
- required: true
- username:
- description:
- - An account with administrator privileges.
- type: str
- required: true
- aliases: [ admin, user ]
- password:
- description:
- - Password for the C(username) account.
- type: str
- required: true
- aliases: [ pass, pwd ]
- write_config:
- description:
- - If C(yes), any changes will cause a write of the running configuration
- to non-volatile memory. This will save I(all) configuration changes,
- including those that may have been made manually or through other modules,
- so care should be taken when specifying C(yes).
- type: bool
- default: no
- validate_certs:
- description:
- - If C(no), SSL certificates will not be validated.
- - This should only be used on personally controlled devices using self-signed certificates.
- type: bool
- default: yes
-notes:
- - Requires A10 Networks aXAPI 2.1.
-'''
diff --git a/plugins/doc_fragments/aireos.py b/plugins/doc_fragments/aireos.py
deleted file mode 100644
index b3e734a06c..0000000000
--- a/plugins/doc_fragments/aireos.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, James Mighion <@jmighion>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
-
- # Standard files documentation fragment
- DOCUMENTATION = r'''
-options:
- provider:
- description:
- - A dict object containing connection details.
- suboptions:
- host:
- description:
- - Specifies the DNS host name or address for connecting to the remote device over the specified transport.
- - The value of host is used as the destination address for the transport.
- type: str
- required: true
- port:
- description:
- - Specifies the port to use when building the connection to the remote device.
- type: int
- default: 22
- username:
- description:
- - Configures the username to use to authenticate the connection to the remote device.
- - This value is used to authenticate the SSH session.
- - If the value is not specified in the task, the value of environment variable
- C(ANSIBLE_NET_USERNAME) will be used instead.
- type: str
- password:
- description:
- - Specifies the password to use to authenticate the connection to the remote device.
- - This value is used to authenticate the SSH session.
- - If the value is not specified in the task, the value of environment variable
- C(ANSIBLE_NET_PASSWORD) will be used instead.
- type: str
- timeout:
- description:
- - Specifies the timeout in seconds for communicating with the network device
- for either connecting or sending commands.
- - If the timeout is exceeded before the operation is completed, the module will error.
- type: int
- default: 10
- ssh_keyfile:
- description:
- - Specifies the SSH key to use to authenticate the connection to the remote device.
- - This value is the path to the key used to authenticate the SSH session.
- - If the value is not specified in the task, the value of environment variable
- C(ANSIBLE_NET_SSH_KEYFILE) will be used instead.
- type: path
-'''
diff --git a/plugins/doc_fragments/aruba.py b/plugins/doc_fragments/aruba.py
deleted file mode 100644
index 6bd49ddf9f..0000000000
--- a/plugins/doc_fragments/aruba.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, James Mighion <@jmighion>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
-
- # Standard files documentation fragment
- DOCUMENTATION = r'''
-options:
- provider:
- description:
- - A dict object containing connection details.
- suboptions:
- host:
- description:
- - Specifies the DNS host name or address for connecting to the remote
- device over the specified transport. The value of host is used as
- the destination address for the transport.
- type: str
- required: true
- port:
- description:
- - Specifies the port to use when building the connection to the remote.
- device.
- type: int
- default: 22
- username:
- description:
- - Configures the username to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_USERNAME) will be used instead.
- type: str
- password:
- description:
- - Specifies the password to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_PASSWORD) will be used instead.
- type: str
- timeout:
- description:
- - Specifies the timeout in seconds for communicating with the network device
- for either connecting or sending commands. If the timeout is
- exceeded before the operation is completed, the module will error.
- type: int
- default: 10
- ssh_keyfile:
- description:
- - Specifies the SSH key to use to authenticate the connection to
- the remote device. This value is the path to the
- key used to authenticate the SSH session. If the value is not specified
- in the task, the value of environment variable C(ANSIBLE_NET_SSH_KEYFILE)
- will be used instead.
- type: path
-'''
diff --git a/plugins/doc_fragments/avi.py b/plugins/doc_fragments/avi.py
deleted file mode 100644
index 2692e11888..0000000000
--- a/plugins/doc_fragments/avi.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Created on December 12, 2016
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Avi Version: 16.3.4
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
- # Avi common documentation fragment
- DOCUMENTATION = r'''
-options:
- controller:
- description:
- - IP address or hostname of the controller. The default value is the environment variable C(AVI_CONTROLLER).
- type: str
- default: ''
- username:
- description:
- - Username used for accessing Avi controller. The default value is the environment variable C(AVI_USERNAME).
- type: str
- default: ''
- password:
- description:
- - Password of Avi user in Avi controller. The default value is the environment variable C(AVI_PASSWORD).
- type: str
- default: ''
- tenant:
- description:
- - Name of tenant used for all Avi API calls and context of object.
- type: str
- default: admin
- tenant_uuid:
- description:
- - UUID of tenant used for all Avi API calls and context of object.
- type: str
- default: ''
- api_version:
- description:
- - Avi API version of to use for Avi API and objects.
- type: str
- default: 16.4.4
- avi_credentials:
- description:
- - Avi Credentials dictionary which can be used in lieu of enumerating Avi Controller login details.
- suboptions:
- controller:
- description:
- - Avi controller IP or SQDN
- username:
- description:
- - Avi controller username
- password:
- description:
- - Avi controller password
- api_version:
- description:
- - Avi controller version
- default: 16.4.4
- tenant:
- description:
- - Avi controller tenant
- default: admin
- tenant_uuid:
- description:
- - Avi controller tenant UUID
- port:
- description:
- - Avi controller port
- token:
- description:
- - Avi controller API token
- timeout:
- description:
- - Avi controller request timeout
- default: 300
- session_id:
- description:
- - Avi controller API session id to reuse existing session with csrftoken
- csrftoken:
- description:
- - Avi controller API csrftoken to reuse existing session with session id
- type: dict
- api_context:
- description:
- - Avi API context that includes current session ID and CSRF Token.
- - This allows user to perform single login and re-use the session.
- type: dict
- avi_disable_session_cache_as_fact:
- description:
- - It disables avi session information to be cached as a fact.
- type: bool
-
-notes:
- - For more information on using Ansible to manage Avi Network devices see U(https://www.ansible.com/ansible-avi-networks).
-'''
diff --git a/plugins/doc_fragments/ce.py b/plugins/doc_fragments/ce.py
deleted file mode 100644
index 0709ab26e5..0000000000
--- a/plugins/doc_fragments/ce.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
-
- # Standard files documentation fragment
- DOCUMENTATION = r'''
-options:
- provider:
- description:
- - A dict object containing connection details.
- suboptions:
- host:
- description:
- - Specifies the DNS host name or address for connecting to the remote
- device over the specified transport. The value of host is used as
- the destination address for the transport.
- type: str
- required: true
- port:
- description:
- - Specifies the port to use when building the connection to the remote
- device. This value applies to either I(cli) or I(netconf). The port
- value will default to the appropriate transport common port if
- none is provided in the task. (cli=22, netconf=22).
- type: int
- default: 0 (use common port)
- username:
- description:
- - Configures the username to use to authenticate the connection to
- the remote device. This value is used to authenticate the CLI login.
- If the value is not specified in the task, the value of environment
- variable C(ANSIBLE_NET_USERNAME) will be used instead.
- type: str
- password:
- description:
- - Specifies the password to use to authenticate the connection to
- the remote device. This is a common argument used for cli
- transports. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_PASSWORD) will be used instead.
- type: str
- ssh_keyfile:
- description:
- - Specifies the SSH key to use to authenticate the connection to
- the remote device. This argument is used for the I(cli)
- transport. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_SSH_KEYFILE) will be used instead.
- type: path
- transport:
- description:
- - Configures the transport connection to use when connecting to the
- remote device. The transport argument supports connectivity to the
- device over cli (ssh).
- type: str
- required: true
- choices: [ cli, netconf ]
- default: cli
-'''
diff --git a/plugins/doc_fragments/cnos.py b/plugins/doc_fragments/cnos.py
deleted file mode 100644
index 11f59e95de..0000000000
--- a/plugins/doc_fragments/cnos.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Lenovo, Inc.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
- # Standard CNOS documentation fragment
- DOCUMENTATION = r'''
-options:
- outputfile:
- description:
- - This specifies the file path where the output of each command
- execution is saved. Each command that is specified in the merged
- template file and each response from the device are saved here.
- Usually the location is the results folder, but you can
- choose another location based on your write permission.
- type: str
- required: true
- host:
- description:
- - This is the variable used to search the hosts file at
- /etc/ansible/hosts and identify the IP address of the device on
- which the template is going to be applied. Usually the Ansible
- keyword {{ inventory_hostname }} is specified in the playbook as
- an abstraction of the group of network elements that need to be
- configured.
- type: str
- required: true
- username:
- description:
- - Configures the username used to authenticate the connection to
- the remote device. The value of the username parameter is used to
- authenticate the SSH session. While generally the value should
- come from the inventory file, you can also specify it as a
- variable. This parameter is optional. If it is not specified, no
- default value will be used.
- type: str
- required: true
- password:
- description:
- - Configures the password used to authenticate the connection to
- the remote device. The value of the password parameter is used to
- authenticate the SSH session. While generally the value should
- come from the inventory file, you can also specify it as a
- variable. This parameter is optional. If it is not specified, no
- default value will be used.
- type: str
- required: true
- enablePassword:
- description:
- - Configures the password used to enter Global Configuration
- command mode on the switch. If the switch does not request this
- password, the parameter is ignored.While generally the value
- should come from the inventory file, you can also specify it as a
- variable. This parameter is optional. If it is not specified,
- no default value will be used.
- type: str
- deviceType:
- description:
- - This specifies the type of device where the method is executed.
- The choices NE1072T,NE1032,NE1032T,NE10032,NE2572 are added
- since Ansible 2.4. The choice NE0152T is added since 2.8
- type: str
- required: true
- choices:
- - g8272_cnos
- - g8296_cnos
- - g8332_cnos
- - NE0152T
- - NE1072T
- - NE1032
- - NE1032T
- - NE10032
- - NE2572
-notes:
- - For more information on using Ansible to manage Lenovo Network devices see U(https://www.ansible.com/ansible-lenovo).
-'''
diff --git a/plugins/doc_fragments/enos.py b/plugins/doc_fragments/enos.py
deleted file mode 100644
index 7b26c9056d..0000000000
--- a/plugins/doc_fragments/enos.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Red Hat Inc.
-# Copyright: (c) 2017, Lenovo.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
-
- # Standard files documentation fragment
- DOCUMENTATION = r'''
-options:
- authorize:
- description:
- - Instructs the module to enter privileged mode on the remote device
- before sending any commands. If not specified, the device will
- attempt to execute all commands in non-privileged mode. If the value
- is not specified in the task, the value of environment variable
- C(ANSIBLE_NET_AUTHORIZE) will be used instead.
- type: bool
- default: no
- auth_pass:
- description:
- - Specifies the password to use if required to enter privileged mode
- on the remote device. If I(authorize) is false, then this argument
- does nothing. If the value is not specified in the task, the value of
- environment variable C(ANSIBLE_NET_AUTH_PASS) will be used instead.
- provider:
- description:
- - A dict object containing connection details.
- type: dict
- suboptions:
- host:
- description:
- - Specifies the DNS host name or address for connecting to the remote
- device over the specified transport. The value of host is used as
- the destination address for the transport.
- type: str
- required: true
- port:
- description:
- - Specifies the port to use when building the connection to the remote device.
- type: int
- default: 22
- username:
- description:
- - Configures the username to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_USERNAME) will be used instead.
- type: str
- password:
- description:
- - Specifies the password to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_PASSWORD) will be used instead.
- type: str
- timeout:
- description:
- - Specifies the timeout in seconds for communicating with the network device
- for either connecting or sending commands. If the timeout is
- exceeded before the operation is completed, the module will error.
- type: int
- default: 10
- ssh_keyfile:
- description:
- - Specifies the SSH key to use to authenticate the connection to
- the remote device. This value is the path to the
- key used to authenticate the SSH session. If the value is not specified
- in the task, the value of environment variable C(ANSIBLE_NET_SSH_KEYFILE)
- will be used instead.
- type: path
- authorize:
- description:
- - Instructs the module to enter privileged mode on the remote device
- before sending any commands. If not specified, the device will
- attempt to execute all commands in non-privileged mode. If the value
- is not specified in the task, the value of environment variable
- C(ANSIBLE_NET_AUTHORIZE) will be used instead.
- type: bool
- default: no
- auth_pass:
- description:
- - Specifies the password to use if required to enter privileged mode
- on the remote device. If I(authorize) is false, then this argument
- does nothing. If the value is not specified in the task, the value of
- environment variable C(ANSIBLE_NET_AUTH_PASS) will be used instead.
- type: str
-'''
diff --git a/plugins/doc_fragments/ingate.py b/plugins/doc_fragments/ingate.py
deleted file mode 100644
index ed1882d5c1..0000000000
--- a/plugins/doc_fragments/ingate.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Ingate Systems AB
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
- DOCUMENTATION = r'''
-options:
- client:
- description:
- - A dict object containing connection details.
- suboptions:
- version:
- description:
- - REST API version.
- type: str
- choices: [ v1 ]
- default: v1
- scheme:
- description:
- - Which HTTP protocol to use.
- type: str
- required: true
- choices: [ http, https ]
- address:
- description:
- - The hostname or IP address to the unit.
- type: str
- required: true
- username:
- description:
- - The username of the REST API user.
- type: str
- required: true
- password:
- description:
- - The password for the REST API user.
- type: str
- required: true
- port:
- description:
- - Which HTTP(S) port to connect to.
- type: int
- timeout:
- description:
- - The timeout (in seconds) for REST API requests.
- type: int
- validate_certs:
- description:
- - Verify the unit's HTTPS certificate.
- type: bool
- default: yes
- aliases: [ verify_ssl ]
-notes:
- - This module requires that the Ingate Python SDK is installed on the
- host. To install the SDK use the pip command from your shell
- C(pip install ingatesdk).
-requirements:
- - ingatesdk >= 1.0.6
-'''
diff --git a/plugins/doc_fragments/ironware.py b/plugins/doc_fragments/ironware.py
deleted file mode 100644
index afdc431038..0000000000
--- a/plugins/doc_fragments/ironware.py
+++ /dev/null
@@ -1,93 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Paul Baker <@paulquack>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
-
- # Standard files documentation fragment
- DOCUMENTATION = r'''
-options:
- authorize:
- description:
- - B(Deprecated)
- - "Starting with Ansible 2.7 we recommend using C(connection: network_cli) and C(become: yes)."
- - For more information please see the L(IronWare Platform Options guide, ../network/user_guide/platform_ironware.html).
- - HORIZONTALLINE
- - Instructs the module to enter privileged mode on the remote device
- before sending any commands. If not specified, the device will
- attempt to execute all commands in non-privileged mode. If the value
- is not specified in the task, the value of environment variable
- C(ANSIBLE_NET_AUTHORIZE) will be used instead.
- type: bool
- default: no
- provider:
- description:
- - B(Deprecated)
- - "Starting with Ansible 2.7 we recommend using C(connection: network_cli) and C(become: yes)."
- - For more information please see the L(IronWare Platform Options guide, ../network/user_guide/platform_ironware.html).
- - HORIZONTALLINE
- - A dict object containing connection details.
- type: dict
- suboptions:
- host:
- description:
- - Specifies the DNS host name or address for connecting to the remote
- device over the specified transport. The value of host is used as
- the destination address for the transport.
- type: str
- port:
- description:
- - Specifies the port to use when building the connection to the remote
- device.
- type: int
- default: 22
- username:
- description:
- - Configures the username to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_USERNAME) will be used instead.
- type: str
- password:
- description:
- - Specifies the password to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_PASSWORD) will be used instead.
- type: str
- ssh_keyfile:
- description:
- - Specifies the SSH key to use to authenticate the connection to
- the remote device. This value is the path to the
- key used to authenticate the SSH session. If the value is not specified
- in the task, the value of environment variable C(ANSIBLE_NET_SSH_KEYFILE)
- will be used instead.
- type: path
- authorize:
- description:
- - Instructs the module to enter privileged mode on the remote device
- before sending any commands. If not specified, the device will
- attempt to execute all commands in non-privileged mode. If the value
- is not specified in the task, the value of environment variable
- C(ANSIBLE_NET_AUTHORIZE) will be used instead.
- type: bool
- default: no
- auth_pass:
- description:
- - Specifies the password to use if required to enter privileged mode
- on the remote device. If I(authorize) is false, then this argument
- does nothing. If the value is not specified in the task, the value of
- environment variable C(ANSIBLE_NET_AUTH_PASS) will be used instead.
- type: str
- timeout:
- description:
- - Specifies idle timeout in seconds for the connection, in seconds. Useful
- if the console freezes before continuing. For example when saving
- configurations.
- type: int
- default: 10
-notes:
- - For more information on using Ansible to manage network devices see the :ref:`Ansible Network Guide `
-'''
diff --git a/plugins/doc_fragments/netscaler.py b/plugins/doc_fragments/netscaler.py
deleted file mode 100644
index 98d464e36f..0000000000
--- a/plugins/doc_fragments/netscaler.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
- DOCUMENTATION = r'''
-
-options:
- nsip:
- description:
- - The ip address of the netscaler appliance where the nitro API calls will be made.
- - "The port can be specified with the colon (:). E.g. 192.168.1.1:555."
- type: str
- required: True
-
- nitro_user:
- description:
- - The username with which to authenticate to the netscaler node.
- type: str
- required: True
-
- nitro_pass:
- description:
- - The password with which to authenticate to the netscaler node.
- type: str
- required: True
-
- nitro_protocol:
- description:
- - Which protocol to use when accessing the nitro API objects.
- type: str
- choices: [ http, https ]
- default: http
-
- validate_certs:
- description:
- - If C(no), SSL certificates will not be validated. This should only be used on personally controlled sites using self-signed certificates.
- type: bool
- default: yes
-
- nitro_timeout:
- description:
- - Time in seconds until a timeout error is thrown when establishing a new session with Netscaler
- type: float
- default: 310
-
- state:
- description:
- - The state of the resource being configured by the module on the netscaler node.
- - When present the resource will be created if needed and configured according to the module's parameters.
- - When absent the resource will be deleted from the netscaler node.
- type: str
- choices: [ absent, present ]
- default: present
-
- save_config:
- description:
- - If C(yes) the module will save the configuration on the netscaler node if it makes any changes.
- - The module will not save the configuration on the netscaler node if it made no changes.
- type: bool
- default: yes
-notes:
- - For more information on using Ansible to manage Citrix NetScaler Network devices see U(https://www.ansible.com/ansible-netscaler).
-'''
diff --git a/plugins/doc_fragments/nso.py b/plugins/doc_fragments/nso.py
deleted file mode 100644
index 47e9acf2db..0000000000
--- a/plugins/doc_fragments/nso.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Cisco and/or its affiliates.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
-
- DOCUMENTATION = r'''
-options:
- url:
- description: NSO JSON-RPC URL, http://localhost:8080/jsonrpc
- type: str
- required: true
- username:
- description: NSO username
- type: str
- required: true
- password:
- description: NSO password
- type: str
- required: true
- timeout:
- description: JSON-RPC request timeout in seconds
- type: int
- default: 300
- validate_certs:
- description: When set to true, validates the SSL certificate of NSO when
- using SSL
- type: bool
- required: false
- default: false
-'''
diff --git a/plugins/doc_fragments/onyx.py b/plugins/doc_fragments/onyx.py
deleted file mode 100644
index 86bc543530..0000000000
--- a/plugins/doc_fragments/onyx.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
-
- # Standard files documentation fragment
- DOCUMENTATION = r'''
-options:
- provider:
- description:
- - A dict object containing connection details.
- type: dict
- suboptions:
- host:
- description:
- - Specifies the DNS host name or address for connecting to the remote
- device over the specified transport. The value of host is used as
- the destination address for the transport.
- type: str
- required: true
- port:
- description:
- - Specifies the port to use when building the connection to the remote device.
- type: int
- default: 22
- username:
- description:
- - Configures the username to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_USERNAME) will be used instead.
- type: str
- password:
- description:
- - Specifies the password to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_PASSWORD) will be used instead.
- type: str
- timeout:
- description:
- - Specifies the timeout in seconds for communicating with the network device
- for either connecting or sending commands. If the timeout is
- exceeded before the operation is completed, the module will error.
- type: int
- default: 10
- ssh_keyfile:
- description:
- - Specifies the SSH key to use to authenticate the connection to
- the remote device. This value is the path to the
- key used to authenticate the SSH session. If the value is not specified
- in the task, the value of environment variable C(ANSIBLE_NET_SSH_KEYFILE)
- will be used instead.
- type: path
- authorize:
- description:
- - Instructs the module to enter privileged mode on the remote device
- before sending any commands. If not specified, the device will
- attempt to execute all commands in non-privileged mode. If the value
- is not specified in the task, the value of environment variable
- C(ANSIBLE_NET_AUTHORIZE) will be used instead.
- type: bool
- default: no
- auth_pass:
- description:
- - Specifies the password to use if required to enter privileged mode
- on the remote device. If I(authorize) is false, then this argument
- does nothing. If the value is not specified in the task, the value of
- environment variable C(ANSIBLE_NET_AUTH_PASS) will be used instead.
- type: str
-'''
diff --git a/plugins/doc_fragments/panos.py b/plugins/doc_fragments/panos.py
deleted file mode 100644
index 857f02d677..0000000000
--- a/plugins/doc_fragments/panos.py
+++ /dev/null
@@ -1,245 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2016, techbizdev
-# Copyright: (c) 2018, Kevin Breit (@kbreit)
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
- # Standard files documentation fragment
- DOCUMENTATION = r'''
-options:
- ip_address:
- description:
- - IP address (or hostname) of PAN-OS device.
- type: str
- required: true
- password:
- description:
- - Password for authentication.
- type: str
- required: true
- username:
- description:
- - Username for authentication.
- type: str
- default: admin
-'''
-
- PROVIDER = r'''
-options:
- provider:
- description:
- - A dict object containing connection details.
- version_added: '2.8'
- required: true
- suboptions:
- ip_address:
- description:
- - The IP address or hostname of the PAN-OS device being configured.
- type: str
- required: true
- username:
- description:
- - The username to use for authentication. This is ignored if
- I(api_key) is specified.
- type: str
- default: 'admin'
- password:
- description:
- - The password to use for authentication. This is ignored if
- I(api_key) is specified.
- type: str
- api_key:
- description:
- - The API key to use instead of generating it using
- I(username) / I(password).
- type: str
- port:
- description:
- - The port number to connect to the PAN-OS device on.
- type: int
- default: 443
- serial_number:
- description:
- - The serial number of a firewall to use for targeted commands.
- If I(ip_address) is not a Panorama PAN-OS device, then
- this param is ignored.
- type: str
-'''
-
- TRANSITIONAL_PROVIDER = r'''
-options:
- provider:
- description:
- - A dict object containing connection details.
- version_added: '2.8'
- suboptions:
- ip_address:
- description:
- - The IP address or hostname of the PAN-OS device being configured.
- type: str
- username:
- description:
- - The username to use for authentication. This is ignored if
- I(api_key) is specified.
- type: str
- default: 'admin'
- password:
- description:
- - The password to use for authentication. This is ignored if
- I(api_key) is specified.
- type: str
- api_key:
- description:
- - The API key to use instead of generating it using
- I(username) / I(password).
- type: str
- port:
- description:
- - The port number to connect to the PAN-OS device on.
- type: int
- default: 443
- serial_number:
- description:
- - The serial number of a firewall to use for targeted commands.
- If I(ip_address) is not a Panorama PAN-OS device, then
- this param is ignored.
- type: str
- ip_address:
- description:
- - B(Deprecated)
- - Use I(provider) to specify PAN-OS connectivity instead.
- - HORIZONTALLINE
- - The IP address or hostname of the PAN-OS device being configured.
- type: str
- username:
- description:
- - B(Deprecated)
- - Use I(provider) to specify PAN-OS connectivity instead.
- - HORIZONTALLINE
- - The username to use for authentication. This is ignored if
- I(api_key) is specified.
- type: str
- default: 'admin'
- password:
- description:
- - B(Deprecated)
- - Use I(provider) to specify PAN-OS connectivity instead.
- - HORIZONTALLINE
- - The password to use for authentication. This is ignored if
- I(api_key) is specified.
- type: str
- api_key:
- description:
- - B(Deprecated)
- - Use I(provider) to specify PAN-OS connectivity instead.
- - HORIZONTALLINE
- - The API key to use instead of generating it using
- I(username) / I(password).
- type: str
- port:
- description:
- - B(Deprecated)
- - Use I(provider) to specify PAN-OS connectivity instead.
- - HORIZONTALLINE
- - The port number to connect to the PAN-OS device on.
- type: int
- default: 443
-notes:
- - PAN-OS connectivity should be specified using I(provider) or the
- classic PAN-OS connectivity params (I(ip_address), I(username),
- I(password), I(api_key), and I(port)). If both are present, then the
- classic params are ignored.
-'''
-
- STATE = r'''
-options:
- state:
- description:
- - The state.
- type: str
- default: present
- choices:
- - present
- - absent
-'''
-
- RULEBASE = r'''
-options:
- rulebase:
- description:
- - The rulebase in which the rule is to exist. If left unspecified,
- this defaults to I(rulebase=pre-rulebase) for Panorama. For
- NGFW, this is always set to be I(rulebase=rulebase).
- type: str
- choices:
- - pre-rulebase
- - rulebase
- - post-rulebase
-'''
-
- VSYS_DG = r'''
-options:
- vsys_dg:
- description:
- - The vsys (for NGFW) or device group (for Panorama) this
- operation should target. If left unspecified, this defaults to
- I(vsys_dg=vsys1) for NGFW or I(vsys_dg=shared) for Panorama.
- type: str
-'''
-
- DEVICE_GROUP = r'''
-options:
- device_group:
- description:
- - (Panorama only) The device group the operation should target.
- type: str
- default: shared
-'''
-
- VSYS_IMPORT = r'''
-options:
- vsys:
- description:
- - The vsys this object should be imported into. Objects that are
- imported include interfaces, virtual routers, virtual wires, and
- VLANs. Interfaces are typically imported into vsys1 if no vsys
- is specified.
- type: str
-'''
-
- VSYS = r'''
-options:
- vsys:
- description:
- - The vsys this object belongs to.
- type: str
- default: vsys1
-'''
-
- TEMPLATE_ONLY = r'''
-options:
- template:
- description:
- - (Panorama only) The template this operation should target. This
- param is required if the PAN-OS device is Panorama.
- type: str
-'''
-
- FULL_TEMPLATE_SUPPORT = r'''
-options:
- template:
- description:
- - (Panorama only) The template this operation should target.
- Mutually exclusive with I(template_stack).
- type: str
- template_stack:
- description:
- - (Panorama only) The template stack this operation should target.
- Mutually exclusive with I(template).
- type: str
-notes:
- - If the PAN-OS to be configured is Panorama, either I(template) or
- I(template_stack) must be specified.
-'''
diff --git a/plugins/doc_fragments/sros.py b/plugins/doc_fragments/sros.py
deleted file mode 100644
index be66404368..0000000000
--- a/plugins/doc_fragments/sros.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2015, Peter Sprygada
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
-
- # Standard files documentation fragment
- DOCUMENTATION = r'''
-options:
- provider:
- description:
- - A dict object containing connection details.
- type: dict
- suboptions:
- host:
- description:
- - Specifies the DNS host name or address for connecting to the remote
- device over the specified transport. The value of host is used as
- the destination address for the transport.
- type: str
- required: true
- port:
- description:
- - Specifies the port to use when building the connection to the remote
- device.
- type: int
- default: 22
- username:
- description:
- - Configures the username to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_USERNAME) will be used instead.
- type: str
- password:
- description:
- - Specifies the password to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_PASSWORD) will be used instead.
- type: str
- timeout:
- description:
- - Specifies the timeout in seconds for communicating with the network device
- for either connecting or sending commands. If the timeout is
- exceeded before the operation is completed, the module will error.
- type: int
- default: 10
- ssh_keyfile:
- description:
- - Specifies the SSH key to use to authenticate the connection to
- the remote device. This value is the path to the
- key used to authenticate the SSH session. If the value is not specified
- in the task, the value of environment variable C(ANSIBLE_NET_SSH_KEYFILE)
- will be used instead.
- type: path
-notes:
- - For more information on using Ansible to manage Nokia SR OS Network devices see U(https://www.ansible.com/ansible-nokia).
-'''
diff --git a/plugins/httpapi/__init__.py b/plugins/httpapi/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/httpapi/exos.py b/plugins/httpapi/exos.py
deleted file mode 100644
index 10d25dd4e9..0000000000
--- a/plugins/httpapi/exos.py
+++ /dev/null
@@ -1,252 +0,0 @@
-# Copyright (c) 2019 Extreme Networks.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-author:
- - "Ujwal Komarla (@ujwalkomarla)"
-httpapi: exos
-short_description: Use EXOS REST APIs to communicate with EXOS platform
-description:
- - This plugin provides low level abstraction api's to send REST API
- requests to EXOS network devices and receive JSON responses.
-'''
-
-import json
-import re
-from ansible.module_utils._text import to_text
-from ansible.module_utils.connection import ConnectionError
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.plugins.httpapi import HttpApiBase
-import ansible.module_utils.six.moves.http_cookiejar as cookiejar
-from ansible.module_utils.common._collections_compat import Mapping
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, dumps
-
-
-class HttpApi(HttpApiBase):
-
- def __init__(self, *args, **kwargs):
- super(HttpApi, self).__init__(*args, **kwargs)
- self._device_info = None
- self._auth_token = cookiejar.CookieJar()
-
- def login(self, username, password):
- auth_path = '/auth/token'
- credentials = {'username': username, 'password': password}
- self.send_request(path=auth_path, data=json.dumps(credentials), method='POST')
-
- def logout(self):
- pass
-
- def handle_httperror(self, exc):
- return False
-
- def send_request(self, path, data=None, method='GET', **message_kwargs):
- headers = {'Content-Type': 'application/json'}
- response, response_data = self.connection.send(path, data, method=method, cookies=self._auth_token, headers=headers, **message_kwargs)
- try:
- if response.status == 204:
- response_data = {}
- else:
- response_data = json.loads(to_text(response_data.getvalue()))
- except ValueError:
- raise ConnectionError('Response was not valid JSON, got {0}'.format(
- to_text(response_data.getvalue())
- ))
- return response_data
-
- def run_commands(self, commands, check_rc=True):
- if commands is None:
- raise ValueError("'commands' value is required")
-
- headers = {'Content-Type': 'application/json'}
- responses = list()
- for cmd in to_list(commands):
- if not isinstance(cmd, Mapping):
- cmd = {'command': cmd}
-
- cmd['command'] = strip_run_script_cli2json(cmd['command'])
-
- output = cmd.pop('output', None)
- if output and output not in self.get_option_values().get('output'):
- raise ValueError("'output' value is %s is invalid. Valid values are %s" % (output, ','.join(self.get_option_values().get('output'))))
-
- data = request_builder(cmd['command'])
-
- response, response_data = self.connection.send('/jsonrpc', data, cookies=self._auth_token, headers=headers, method='POST')
- try:
- response_data = json.loads(to_text(response_data.getvalue()))
- except ValueError:
- raise ConnectionError('Response was not valid JSON, got {0}'.format(
- to_text(response_data.getvalue())
- ))
-
- if response_data.get('error', None):
- raise ConnectionError("Request Error, got {0}".format(response_data['error']))
- if not response_data.get('result', None):
- raise ConnectionError("Request Error, got {0}".format(response_data))
-
- response_data = response_data['result']
-
- if output and output == 'text':
- statusOut = getKeyInResponse(response_data, 'status')
- cliOut = getKeyInResponse(response_data, 'CLIoutput')
- if statusOut == "ERROR":
- raise ConnectionError("Command error({1}) for request {0}".format(cmd['command'], cliOut))
- if cliOut is None:
- raise ValueError("Response for request {0} doesn't have the CLIoutput field, got {1}".format(cmd['command'], response_data))
- response_data = cliOut
-
- responses.append(response_data)
- return responses
-
- def get_device_info(self):
- device_info = {}
- device_info['network_os'] = 'exos'
-
- reply = self.run_commands({'command': 'show switch detail', 'output': 'text'})
- data = to_text(reply, errors='surrogate_or_strict').strip()
-
- match = re.search(r'ExtremeXOS version (\S+)', data)
- if match:
- device_info['network_os_version'] = match.group(1)
-
- match = re.search(r'System Type: +(\S+)', data)
- if match:
- device_info['network_os_model'] = match.group(1)
-
- match = re.search(r'SysName: +(\S+)', data)
- if match:
- device_info['network_os_hostname'] = match.group(1)
-
- return device_info
-
- def get_device_operations(self):
- return {
- 'supports_diff_replace': False, # identify if config should be merged or replaced is supported
- 'supports_commit': False, # identify if commit is supported by device or not
- 'supports_rollback': False, # identify if rollback is supported or not
- 'supports_defaults': True, # identify if fetching running config with default is supported
- 'supports_commit_comment': False, # identify if adding comment to commit is supported of not
- 'supports_onbox_diff': False, # identify if on box diff capability is supported or not
- 'supports_generate_diff': True, # identify if diff capability is supported within plugin
- 'supports_multiline_delimiter': False, # identify if multiline demiliter is supported within config
- 'supports_diff_match': True, # identify if match is supported
- 'supports_diff_ignore_lines': True, # identify if ignore line in diff is supported
- 'supports_config_replace': False, # identify if running config replace with candidate config is supported
- 'supports_admin': False, # identify if admin configure mode is supported or not
- 'supports_commit_label': False # identify if commit label is supported or not
- }
-
- def get_option_values(self):
- return {
- 'format': ['text', 'json'],
- 'diff_match': ['line', 'strict', 'exact', 'none'],
- 'diff_replace': ['line', 'block'],
- 'output': ['text', 'json']
- }
-
- def get_capabilities(self):
- result = {}
- result['rpc'] = ['get_default_flag', 'run_commands', 'get_config', 'send_request', 'get_capabilities', 'get_diff']
- result['device_info'] = self.get_device_info()
- result['device_operations'] = self.get_device_operations()
- result.update(self.get_option_values())
- result['network_api'] = 'exosapi'
- return json.dumps(result)
-
- def get_default_flag(self):
- # The flag to modify the command to collect configuration with defaults
- return 'detail'
-
- def get_diff(self, candidate=None, running=None, diff_match='line', diff_ignore_lines=None, path=None, diff_replace='line'):
- diff = {}
- device_operations = self.get_device_operations()
- option_values = self.get_option_values()
-
- if candidate is None and device_operations['supports_generate_diff']:
- raise ValueError("candidate configuration is required to generate diff")
-
- if diff_match not in option_values['diff_match']:
- raise ValueError("'match' value %s in invalid, valid values are %s" % (diff_match, ', '.join(option_values['diff_match'])))
-
- if diff_replace not in option_values['diff_replace']:
- raise ValueError("'replace' value %s in invalid, valid values are %s" % (diff_replace, ', '.join(option_values['diff_replace'])))
-
- # prepare candidate configuration
- candidate_obj = NetworkConfig(indent=1)
- candidate_obj.load(candidate)
-
- if running and diff_match != 'none' and diff_replace != 'config':
- # running configuration
- running_obj = NetworkConfig(indent=1, contents=running, ignore_lines=diff_ignore_lines)
- configdiffobjs = candidate_obj.difference(running_obj, path=path, match=diff_match, replace=diff_replace)
-
- else:
- configdiffobjs = candidate_obj.items
-
- diff['config_diff'] = dumps(configdiffobjs, 'commands') if configdiffobjs else ''
- return diff
-
- def get_config(self, source='running', format='text', flags=None):
- options_values = self.get_option_values()
- if format not in options_values['format']:
- raise ValueError("'format' value %s is invalid. Valid values are %s" % (format, ','.join(options_values['format'])))
-
- lookup = {'running': 'show configuration', 'startup': 'debug cfgmgr show configuration file'}
- if source not in lookup:
- raise ValueError("fetching configuration from %s is not supported" % source)
-
- cmd = {'command': lookup[source], 'output': 'text'}
-
- if source == 'startup':
- reply = self.run_commands({'command': 'show switch', 'format': 'text'})
- data = to_text(reply, errors='surrogate_or_strict').strip()
- match = re.search(r'Config Selected: +(\S+)\.cfg', data, re.MULTILINE)
- if match:
- cmd['command'] += match.group(1)
- else:
- # No Startup(/Selected) Config
- return {}
-
- cmd['command'] += ' '.join(to_list(flags))
- cmd['command'] = cmd['command'].strip()
-
- return self.run_commands(cmd)[0]
-
-
-def request_builder(command, reqid=""):
- return json.dumps(dict(jsonrpc='2.0', id=reqid, method='cli', params=to_list(command)))
-
-
-def strip_run_script_cli2json(command):
- if to_text(command, errors="surrogate_then_replace").startswith('run script cli2json.py'):
- command = str(command).replace('run script cli2json.py', '')
- return command
-
-
-def getKeyInResponse(response, key):
- keyOut = None
- for item in response:
- if key in item:
- keyOut = item[key]
- break
- return keyOut
diff --git a/plugins/httpapi/fortianalyzer.py b/plugins/httpapi/fortianalyzer.py
deleted file mode 100644
index 1e870140a2..0000000000
--- a/plugins/httpapi/fortianalyzer.py
+++ /dev/null
@@ -1,453 +0,0 @@
-# Copyright (c) 2018 Fortinet and/or its affiliates.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-httpapi : fortianalyzer
-short_description: HttpApi Plugin for Fortinet FortiAnalyzer Appliance or VM.
-description:
- - This HttpApi plugin provides methods to connect to Fortinet FortiAnalyzer Appliance or VM via JSON RPC API.
-
-'''
-
-import json
-from ansible.plugins.httpapi import HttpApiBase
-from ansible.module_utils.basic import to_text
-from ansible_collections.community.general.plugins.module_utils.network.fortianalyzer.common import BASE_HEADERS
-from ansible_collections.community.general.plugins.module_utils.network.fortianalyzer.common import FAZBaseException
-from ansible_collections.community.general.plugins.module_utils.network.fortianalyzer.common import FAZCommon
-from ansible_collections.community.general.plugins.module_utils.network.fortianalyzer.common import FAZMethods
-
-
-class HttpApi(HttpApiBase):
- def __init__(self, connection):
- super(HttpApi, self).__init__(connection)
- self._req_id = 0
- self._sid = None
- self._url = "/jsonrpc"
- self._host = None
- self._tools = FAZCommon
- self._debug = False
- self._connected_faz = None
- self._last_response_msg = None
- self._last_response_code = None
- self._last_data_payload = None
- self._last_url = None
- self._last_response_raw = None
- self._locked_adom_list = list()
- self._locked_adoms_by_user = list()
- self._uses_workspace = False
- self._uses_adoms = False
- self._adom_list = list()
- self._logged_in_user = None
-
- def set_become(self, become_context):
- """
- ELEVATION IS NOT REQUIRED ON FORTINET DEVICES - SKIPPED
- :param become_context: Unused input.
- :return: None
- """
- return None
-
- def update_auth(self, response, response_data):
- """
- TOKENS ARE NOT USED SO NO NEED TO UPDATE AUTH
- :param response: Unused input.
- :param response_data Unused_input.
- :return: None
- """
- return None
-
- def login(self, username, password):
- """
- This function will log the plugin into FortiAnalyzer, and return the results.
- :param username: Username of FortiAnalyzer Admin
- :param password: Password of FortiAnalyzer Admin
-
- :return: Dictionary of status if it logged in or not.
- """
-
- self._logged_in_user = username
- self.send_request(FAZMethods.EXEC, self._tools.format_request(FAZMethods.EXEC, "sys/login/user",
- passwd=password, user=username,))
-
- if "FortiAnalyzer object connected to FortiAnalyzer" in self.__str__():
- # If Login worked then inspect the FortiAnalyzer for Workspace Mode, and it's system information.
- self.inspect_faz()
- return
- else:
- raise FAZBaseException(msg="Unknown error while logging in...connection was lost during login operation..."
- " Exiting")
-
- def inspect_faz(self):
- # CHECK FOR WORKSPACE MODE TO SEE IF WE HAVE TO ENABLE ADOM LOCKS
- status = self.get_system_status()
- if status[0] == -11:
- # THE CONNECTION GOT LOST SOMEHOW, REMOVE THE SID AND REPORT BAD LOGIN
- self.logout()
- raise FAZBaseException(msg="Error -11 -- the Session ID was likely malformed somehow. Contact authors."
- " Exiting")
- elif status[0] == 0:
- try:
- self.check_mode()
- if self._uses_adoms:
- self.get_adom_list()
- if self._uses_workspace:
- self.get_locked_adom_list()
- self._connected_faz = status[1]
- self._host = self._connected_faz["Hostname"]
- except Exception:
- pass
- return
-
- def logout(self):
- """
- This function will logout of the FortiAnalyzer.
- """
- if self.sid is not None:
- # IF WE WERE USING WORKSPACES, THEN CLEAN UP OUR LOCKS IF THEY STILL EXIST
- if self.uses_workspace:
- self.get_lock_info()
- self.run_unlock()
- ret_code, response = self.send_request(FAZMethods.EXEC,
- self._tools.format_request(FAZMethods.EXEC, "sys/logout"))
- self.sid = None
- return ret_code, response
-
- def send_request(self, method, params):
- """
- Responsible for actual sending of data to the connection httpapi base plugin. Does some formatting as well.
- :param params: A formatted dictionary that was returned by self.common_datagram_params()
- before being called here.
- :param method: The preferred API Request method (GET, ADD, POST, etc....)
- :type method: basestring
-
- :return: Dictionary of status if it logged in or not.
- """
-
- try:
- if self.sid is None and params[0]["url"] != "sys/login/user":
- try:
- self.connection._connect()
- except Exception as err:
- raise FAZBaseException(
- msg="An problem happened with the httpapi plugin self-init connection process. "
- "Error: " + to_text(err))
- except IndexError:
- raise FAZBaseException("An attempt was made at communicating with a FAZ with "
- "no valid session and an incorrectly formatted request.")
- except Exception:
- raise FAZBaseException("An attempt was made at communicating with a FAZ with "
- "no valid session and an unexpected error was discovered.")
-
- self._update_request_id()
- json_request = {
- "method": method,
- "params": params,
- "session": self.sid,
- "id": self.req_id,
- "verbose": 1
- }
- data = json.dumps(json_request, ensure_ascii=False).replace('\\\\', '\\')
- try:
- # Sending URL and Data in Unicode, per Ansible Specifications for Connection Plugins
- response, response_data = self.connection.send(path=to_text(self._url), data=to_text(data),
- headers=BASE_HEADERS)
- # Get Unicode Response - Must convert from StringIO to unicode first so we can do a replace function below
- result = json.loads(to_text(response_data.getvalue()))
- self._update_self_from_response(result, self._url, data)
- return self._handle_response(result)
- except Exception as err:
- raise FAZBaseException(err)
-
- def _handle_response(self, response):
- self._set_sid(response)
- if isinstance(response["result"], list):
- result = response["result"][0]
- else:
- result = response["result"]
- if "data" in result:
- return result["status"]["code"], result["data"]
- else:
- return result["status"]["code"], result
-
- def _update_self_from_response(self, response, url, data):
- self._last_response_raw = response
- if isinstance(response["result"], list):
- result = response["result"][0]
- else:
- result = response["result"]
- if "status" in result:
- self._last_response_code = result["status"]["code"]
- self._last_response_msg = result["status"]["message"]
- self._last_url = url
- self._last_data_payload = data
-
- def _set_sid(self, response):
- if self.sid is None and "session" in response:
- self.sid = response["session"]
-
- def return_connected_faz(self):
- """
- Returns the data stored under self._connected_faz
-
- :return: dict
- """
- try:
- if self._connected_faz:
- return self._connected_faz
- except Exception:
- raise FAZBaseException("Couldn't Retrieve Connected FAZ Stats")
-
- def get_system_status(self):
- """
- Returns the system status page from the FortiAnalyzer, for logging and other uses.
- return: status
- """
- status = self.send_request(FAZMethods.GET, self._tools.format_request(FAZMethods.GET, "sys/status"))
- return status
-
- @property
- def debug(self):
- return self._debug
-
- @debug.setter
- def debug(self, val):
- self._debug = val
-
- @property
- def req_id(self):
- return self._req_id
-
- @req_id.setter
- def req_id(self, val):
- self._req_id = val
-
- def _update_request_id(self, reqid=0):
- self.req_id = reqid if reqid != 0 else self.req_id + 1
-
- @property
- def sid(self):
- return self._sid
-
- @sid.setter
- def sid(self, val):
- self._sid = val
-
- def __str__(self):
- if self.sid is not None and self.connection._url is not None:
- return "FortiAnalyzer object connected to FortiAnalyzer: " + to_text(self.connection._url)
- return "FortiAnalyzer object with no valid connection to a FortiAnalyzer appliance."
-
- ##################################
- # BEGIN DATABASE LOCK CONTEXT CODE
- ##################################
-
- @property
- def uses_workspace(self):
- return self._uses_workspace
-
- @uses_workspace.setter
- def uses_workspace(self, val):
- self._uses_workspace = val
-
- @property
- def uses_adoms(self):
- return self._uses_adoms
-
- @uses_adoms.setter
- def uses_adoms(self, val):
- self._uses_adoms = val
-
- def add_adom_to_lock_list(self, adom):
- if adom not in self._locked_adom_list:
- self._locked_adom_list.append(adom)
-
- def remove_adom_from_lock_list(self, adom):
- if adom in self._locked_adom_list:
- self._locked_adom_list.remove(adom)
-
- def check_mode(self):
- """
- Checks FortiAnalyzer for the use of Workspace mode
- """
- url = "/cli/global/system/global"
- code, resp_obj = self.send_request(FAZMethods.GET,
- self._tools.format_request(FAZMethods.GET,
- url,
- fields=["workspace-mode", "adom-status"]))
- try:
- if resp_obj["workspace-mode"] == "workflow":
- self.uses_workspace = True
- elif resp_obj["workspace-mode"] == "disabled":
- self.uses_workspace = False
- except KeyError:
- self.uses_workspace = False
- except Exception:
- raise FAZBaseException(msg="Couldn't determine workspace-mode in the plugin")
- try:
- if resp_obj["adom-status"] in [1, "enable"]:
- self.uses_adoms = True
- else:
- self.uses_adoms = False
- except KeyError:
- self.uses_adoms = False
- except Exception:
- raise FAZBaseException(msg="Couldn't determine adom-status in the plugin")
-
- def run_unlock(self):
- """
- Checks for ADOM status, if locked, it will unlock
- """
- for adom_locked in self._locked_adoms_by_user:
- adom = adom_locked["adom"]
- self.unlock_adom(adom)
-
- def lock_adom(self, adom=None, *args, **kwargs):
- """
- Locks an ADOM for changes
- """
- if adom:
- if adom.lower() == "global":
- url = "/dvmdb/global/workspace/lock/"
- else:
- url = "/dvmdb/adom/{adom}/workspace/lock/".format(adom=adom)
- else:
- url = "/dvmdb/adom/root/workspace/lock"
- code, respobj = self.send_request(FAZMethods.EXEC, self._tools.format_request(FAZMethods.EXEC, url))
- if code == 0 and respobj["status"]["message"].lower() == "ok":
- self.add_adom_to_lock_list(adom)
- return code, respobj
-
- def unlock_adom(self, adom=None, *args, **kwargs):
- """
- Unlocks an ADOM after changes
- """
- if adom:
- if adom.lower() == "global":
- url = "/dvmdb/global/workspace/unlock/"
- else:
- url = "/dvmdb/adom/{adom}/workspace/unlock/".format(adom=adom)
- else:
- url = "/dvmdb/adom/root/workspace/unlock"
- code, respobj = self.send_request(FAZMethods.EXEC, self._tools.format_request(FAZMethods.EXEC, url))
- if code == 0 and respobj["status"]["message"].lower() == "ok":
- self.remove_adom_from_lock_list(adom)
- return code, respobj
-
- def commit_changes(self, adom=None, aux=False, *args, **kwargs):
- """
- Commits changes to an ADOM
- """
- if adom:
- if aux:
- url = "/pm/config/adom/{adom}/workspace/commit".format(adom=adom)
- else:
- if adom.lower() == "global":
- url = "/dvmdb/global/workspace/commit/"
- else:
- url = "/dvmdb/adom/{adom}/workspace/commit".format(adom=adom)
- else:
- url = "/dvmdb/adom/root/workspace/commit"
- return self.send_request(FAZMethods.EXEC, self._tools.format_request(FAZMethods.EXEC, url))
-
- def get_lock_info(self, adom=None):
- """
- Gets ADOM lock info so it can be displayed with the error messages. Or if determined to be locked by ansible
- for some reason, then unlock it.
- """
- if not adom or adom == "root":
- url = "/dvmdb/adom/root/workspace/lockinfo"
- else:
- if adom.lower() == "global":
- url = "/dvmdb/global/workspace/lockinfo/"
- else:
- url = "/dvmdb/adom/{adom}/workspace/lockinfo/".format(adom=adom)
- datagram = {}
- data = self._tools.format_request(FAZMethods.GET, url, **datagram)
- resp_obj = self.send_request(FAZMethods.GET, data)
- code = resp_obj[0]
- if code != 0:
- self._module.fail_json(msg=("An error occurred trying to get the ADOM Lock Info. Error: " + to_text(resp_obj)))
- elif code == 0:
- try:
- if resp_obj[1]["status"]["message"] == "OK":
- self._lock_info = None
- except Exception:
- self._lock_info = resp_obj[1]
- return resp_obj
-
- def get_adom_list(self):
- """
- Gets the list of ADOMs for the FortiAnalyzer
- """
- if self.uses_adoms:
- url = "/dvmdb/adom"
- datagram = {}
- data = self._tools.format_request(FAZMethods.GET, url, **datagram)
- resp_obj = self.send_request(FAZMethods.GET, data)
- code = resp_obj[0]
- if code != 0:
- self._module.fail_json(msg=("An error occurred trying to get the ADOM Info. Error: " + to_text(resp_obj)))
- elif code == 0:
- num_of_adoms = len(resp_obj[1])
- append_list = ['root', ]
- for adom in resp_obj[1]:
- if adom["tab_status"] != "":
- append_list.append(to_text(adom["name"]))
- self._adom_list = append_list
- return resp_obj
-
- def get_locked_adom_list(self):
- """
- Gets the list of locked adoms
- """
- try:
- locked_list = list()
- locked_by_user_list = list()
- for adom in self._adom_list:
- adom_lock_info = self.get_lock_info(adom=adom)
- try:
- if adom_lock_info[1]["status"]["message"] == "OK":
- continue
- except Exception:
- pass
- try:
- if adom_lock_info[1][0]["lock_user"]:
- locked_list.append(to_text(adom))
- if adom_lock_info[1][0]["lock_user"] == self._logged_in_user:
- locked_by_user_list.append({"adom": to_text(adom), "user": to_text(adom_lock_info[1][0]["lock_user"])})
- except Exception as err:
- raise FAZBaseException(err)
- self._locked_adom_list = locked_list
- self._locked_adoms_by_user = locked_by_user_list
-
- except Exception as err:
- raise FAZBaseException(msg=("An error occurred while trying to get the locked adom list. Error: "
- + to_text(err)))
-
- #################################
- # END DATABASE LOCK CONTEXT CODE
- #################################
diff --git a/plugins/httpapi/fortimanager.py b/plugins/httpapi/fortimanager.py
deleted file mode 100644
index 1c80c2808e..0000000000
--- a/plugins/httpapi/fortimanager.py
+++ /dev/null
@@ -1,451 +0,0 @@
-# Copyright (c) 2018 Fortinet and/or its affiliates.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-httpapi : fortimanager
-short_description: HttpApi Plugin for Fortinet FortiManager Appliance or VM.
-description:
- - This HttpApi plugin provides methods to connect to Fortinet FortiManager Appliance or VM via JSON RPC API.
-'''
-
-import json
-from ansible.plugins.httpapi import HttpApiBase
-from ansible.module_utils.basic import to_text
-from ansible_collections.fortinet.fortios.plugins.module_utils.network.fortimanager.common import BASE_HEADERS
-from ansible_collections.fortinet.fortios.plugins.module_utils.network.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.network.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.network.fortimanager.common import FMGRMethods
-
-
-class HttpApi(HttpApiBase):
- def __init__(self, connection):
- super(HttpApi, self).__init__(connection)
- self._req_id = 0
- self._sid = None
- self._url = "/jsonrpc"
- self._host = None
- self._tools = FMGRCommon
- self._debug = False
- self._connected_fmgr = None
- self._last_response_msg = None
- self._last_response_code = None
- self._last_data_payload = None
- self._last_url = None
- self._last_response_raw = None
- self._locked_adom_list = list()
- self._locked_adoms_by_user = list()
- self._uses_workspace = False
- self._uses_adoms = False
- self._adom_list = list()
- self._logged_in_user = None
-
- def set_become(self, become_context):
- """
- ELEVATION IS NOT REQUIRED ON FORTINET DEVICES - SKIPPED.
- :param become_context: Unused input.
- :return: None
- """
- return None
-
- def update_auth(self, response, response_data):
- """
- TOKENS ARE NOT USED SO NO NEED TO UPDATE AUTH.
- :param response: Unused input.
- :param response_data Unused_input.
- :return: None
- """
- return None
-
- def login(self, username, password):
-
- """
- This function will log the plugin into FortiManager, and return the results.
- :param username: Username of FortiManager Admin
- :param password: Password of FortiManager Admin
-
- :return: Dictionary of status if it logged in or not.
- """
- self._logged_in_user = username
- self.send_request(FMGRMethods.EXEC, self._tools.format_request(FMGRMethods.EXEC, "sys/login/user",
- passwd=password, user=username, ))
-
- if "FortiManager object connected to FortiManager" in self.__str__():
- # If Login worked, then inspect the FortiManager for Workspace Mode, and it's system information.
- self.inspect_fmgr()
- return
- else:
- raise FMGBaseException(msg="Unknown error while logging in...connection was lost during login operation...."
- " Exiting")
-
- def inspect_fmgr(self):
- # CHECK FOR WORKSPACE MODE TO SEE IF WE HAVE TO ENABLE ADOM LOCKS
- status = self.get_system_status()
- if status[0] == -11:
- # THE CONNECTION GOT LOST SOMEHOW, REMOVE THE SID AND REPORT BAD LOGIN
- self.logout()
- raise FMGBaseException(msg="Error -11 -- the Session ID was likely malformed somehow. Contact authors."
- " Exiting")
- elif status[0] == 0:
- try:
- self.check_mode()
- if self._uses_adoms:
- self.get_adom_list()
- if self._uses_workspace:
- self.get_locked_adom_list()
- self._connected_fmgr = status[1]
- self._host = self._connected_fmgr["Hostname"]
- except BaseException:
- pass
- return
-
- def logout(self):
- """
- This function will logout of the FortiManager.
- """
- if self.sid is not None:
- # IF WE WERE USING WORKSPACES, THEN CLEAN UP OUR LOCKS IF THEY STILL EXIST
- if self.uses_workspace:
- self.get_lock_info()
- self.run_unlock()
- ret_code, response = self.send_request(FMGRMethods.EXEC,
- self._tools.format_request(FMGRMethods.EXEC, "sys/logout"))
- self.sid = None
- return ret_code, response
-
- def send_request(self, method, params):
- """
- Responsible for actual sending of data to the connection httpapi base plugin. Does some formatting too.
- :param params: A formatted dictionary that was returned by self.common_datagram_params()
- before being called here.
- :param method: The preferred API Request method (GET, ADD, POST, etc....)
- :type method: basestring
-
- :return: Dictionary of status, if it logged in or not.
- """
- try:
- if self.sid is None and params[0]["url"] != "sys/login/user":
- try:
- self.connection._connect()
- except Exception as err:
- raise FMGBaseException(
- msg="An problem happened with the httpapi plugin self-init connection process. "
- "Error: " + to_text(err))
- except IndexError:
- raise FMGBaseException("An attempt was made at communicating with a FMG with "
- "no valid session and an incorrectly formatted request.")
- except Exception as err:
- raise FMGBaseException("An attempt was made at communicating with a FMG with "
- "no valid session and an unexpected error was discovered. \n Error: " + to_text(err))
-
- self._update_request_id()
- json_request = {
- "method": method,
- "params": params,
- "session": self.sid,
- "id": self.req_id,
- "verbose": 1
- }
- data = json.dumps(json_request, ensure_ascii=False).replace('\\\\', '\\')
- try:
- # Sending URL and Data in Unicode, per Ansible Specifications for Connection Plugins
- response, response_data = self.connection.send(path=to_text(self._url), data=to_text(data),
- headers=BASE_HEADERS)
- # Get Unicode Response - Must convert from StringIO to unicode first so we can do a replace function below
- result = json.loads(to_text(response_data.getvalue()))
- self._update_self_from_response(result, self._url, data)
- return self._handle_response(result)
- except Exception as err:
- raise FMGBaseException(err)
-
- def _handle_response(self, response):
- self._set_sid(response)
- if isinstance(response["result"], list):
- result = response["result"][0]
- else:
- result = response["result"]
- if "data" in result:
- return result["status"]["code"], result["data"]
- else:
- return result["status"]["code"], result
-
- def _update_self_from_response(self, response, url, data):
- self._last_response_raw = response
- if isinstance(response["result"], list):
- result = response["result"][0]
- else:
- result = response["result"]
- if "status" in result:
- self._last_response_code = result["status"]["code"]
- self._last_response_msg = result["status"]["message"]
- self._last_url = url
- self._last_data_payload = data
-
- def _set_sid(self, response):
- if self.sid is None and "session" in response:
- self.sid = response["session"]
-
- def return_connected_fmgr(self):
- """
- Returns the data stored under self._connected_fmgr
-
- :return: dict
- """
- try:
- if self._connected_fmgr:
- return self._connected_fmgr
- except Exception:
- raise FMGBaseException("Couldn't Retrieve Connected FMGR Stats")
-
- def get_system_status(self):
- """
- Returns the system status page from the FortiManager, for logging and other uses.
- return: status
- """
- status = self.send_request(FMGRMethods.GET, self._tools.format_request(FMGRMethods.GET, "sys/status"))
- return status
-
- @property
- def debug(self):
- return self._debug
-
- @debug.setter
- def debug(self, val):
- self._debug = val
-
- @property
- def req_id(self):
- return self._req_id
-
- @req_id.setter
- def req_id(self, val):
- self._req_id = val
-
- def _update_request_id(self, reqid=0):
- self.req_id = reqid if reqid != 0 else self.req_id + 1
-
- @property
- def sid(self):
- return self._sid
-
- @sid.setter
- def sid(self, val):
- self._sid = val
-
- def __str__(self):
- if self.sid is not None and self.connection._url is not None:
- return "FortiManager object connected to FortiManager: " + to_text(self.connection._url)
- return "FortiManager object with no valid connection to a FortiManager appliance."
-
- ##################################
- # BEGIN DATABASE LOCK CONTEXT CODE
- ##################################
-
- @property
- def uses_workspace(self):
- return self._uses_workspace
-
- @uses_workspace.setter
- def uses_workspace(self, val):
- self._uses_workspace = val
-
- @property
- def uses_adoms(self):
- return self._uses_adoms
-
- @uses_adoms.setter
- def uses_adoms(self, val):
- self._uses_adoms = val
-
- def add_adom_to_lock_list(self, adom):
- if adom not in self._locked_adom_list:
- self._locked_adom_list.append(adom)
-
- def remove_adom_from_lock_list(self, adom):
- if adom in self._locked_adom_list:
- self._locked_adom_list.remove(adom)
-
- def check_mode(self):
- """
- Checks FortiManager for the use of Workspace mode
- """
- url = "/cli/global/system/global"
- code, resp_obj = self.send_request(FMGRMethods.GET,
- self._tools.format_request(FMGRMethods.GET,
- url,
- fields=["workspace-mode", "adom-status"]))
- try:
- if resp_obj["workspace-mode"] == "workflow":
- self.uses_workspace = True
- elif resp_obj["workspace-mode"] == "disabled":
- self.uses_workspace = False
- except KeyError:
- raise FMGBaseException(msg="Couldn't determine workspace-mode in the plugin")
- try:
- if resp_obj["adom-status"] in [1, "enable"]:
- self.uses_adoms = True
- else:
- self.uses_adoms = False
- except KeyError:
- raise FMGBaseException(msg="Couldn't determine adom-status in the plugin")
-
- def run_unlock(self):
- """
- Checks for ADOM status, if locked, it will unlock
- """
- for adom_locked in self._locked_adoms_by_user:
- adom = adom_locked["adom"]
- self.unlock_adom(adom)
-
- def lock_adom(self, adom=None, *args, **kwargs):
- """
- Locks an ADOM for changes
- """
- if adom:
- if adom.lower() == "global":
- url = "/dvmdb/global/workspace/lock/"
- else:
- url = "/dvmdb/adom/{adom}/workspace/lock/".format(adom=adom)
- else:
- url = "/dvmdb/adom/root/workspace/lock"
- code, respobj = self.send_request(FMGRMethods.EXEC, self._tools.format_request(FMGRMethods.EXEC, url))
- if code == 0 and respobj["status"]["message"].lower() == "ok":
- self.add_adom_to_lock_list(adom)
- return code, respobj
-
- def unlock_adom(self, adom=None, *args, **kwargs):
- """
- Unlocks an ADOM after changes
- """
- if adom:
- if adom.lower() == "global":
- url = "/dvmdb/global/workspace/unlock/"
- else:
- url = "/dvmdb/adom/{adom}/workspace/unlock/".format(adom=adom)
- else:
- url = "/dvmdb/adom/root/workspace/unlock"
- code, respobj = self.send_request(FMGRMethods.EXEC, self._tools.format_request(FMGRMethods.EXEC, url))
- if code == 0 and respobj["status"]["message"].lower() == "ok":
- self.remove_adom_from_lock_list(adom)
- return code, respobj
-
- def commit_changes(self, adom=None, aux=False, *args, **kwargs):
- """
- Commits changes to an ADOM
- """
- if adom:
- if aux:
- url = "/pm/config/adom/{adom}/workspace/commit".format(adom=adom)
- else:
- if adom.lower() == "global":
- url = "/dvmdb/global/workspace/commit/"
- else:
- url = "/dvmdb/adom/{adom}/workspace/commit".format(adom=adom)
- else:
- url = "/dvmdb/adom/root/workspace/commit"
- return self.send_request(FMGRMethods.EXEC, self._tools.format_request(FMGRMethods.EXEC, url))
-
- def get_lock_info(self, adom=None):
- """
- Gets ADOM lock info so it can be displayed with the error messages. Or if determined to be locked by ansible
- for some reason, then unlock it.
- """
- if not adom or adom == "root":
- url = "/dvmdb/adom/root/workspace/lockinfo"
- else:
- if adom.lower() == "global":
- url = "/dvmdb/global/workspace/lockinfo/"
- else:
- url = "/dvmdb/adom/{adom}/workspace/lockinfo/".format(adom=adom)
- datagram = {}
- data = self._tools.format_request(FMGRMethods.GET, url, **datagram)
- resp_obj = self.send_request(FMGRMethods.GET, data)
- code = resp_obj[0]
- if code != 0:
- self._module.fail_json(msg=("An error occurred trying to get the ADOM Lock Info. "
- "Error: " + to_text(resp_obj)))
- elif code == 0:
- try:
- if resp_obj[1]["status"]["message"] == "OK":
- self._lock_info = None
- except Exception:
- self._lock_info = resp_obj[1]
- return resp_obj
-
- def get_adom_list(self):
- """
- Gets the list of ADOMs for the FortiManager
- """
- if self.uses_adoms:
- url = "/dvmdb/adom"
- datagram = {}
- data = self._tools.format_request(FMGRMethods.GET, url, **datagram)
- resp_obj = self.send_request(FMGRMethods.GET, data)
- code = resp_obj[0]
- if code != 0:
- self._module.fail_json(msg=("An error occurred trying to get the ADOM Info. "
- "Error: " + to_text(resp_obj)))
- elif code == 0:
- num_of_adoms = len(resp_obj[1])
- append_list = ['root', ]
- for adom in resp_obj[1]:
- if adom["tab_status"] != "":
- append_list.append(to_text(adom["name"]))
- self._adom_list = append_list
- return resp_obj
-
- def get_locked_adom_list(self):
- """
- Gets the list of locked adoms
- """
- try:
- locked_list = list()
- locked_by_user_list = list()
- for adom in self._adom_list:
- adom_lock_info = self.get_lock_info(adom=adom)
- try:
- if adom_lock_info[1]["status"]["message"] == "OK":
- continue
- except IndexError as err:
- pass
- try:
- if adom_lock_info[1][0]["lock_user"]:
- locked_list.append(to_text(adom))
- if adom_lock_info[1][0]["lock_user"] == self._logged_in_user:
- locked_by_user_list.append({"adom": to_text(adom),
- "user": to_text(adom_lock_info[1][0]["lock_user"])})
- except Exception as err:
- raise FMGBaseException(err)
- self._locked_adom_list = locked_list
- self._locked_adoms_by_user = locked_by_user_list
-
- except Exception as err:
- raise FMGBaseException(msg=("An error occurred while trying to get the locked adom list. Error: "
- + to_text(err)))
-
- ################################
- # END DATABASE LOCK CONTEXT CODE
- ################################
diff --git a/plugins/httpapi/ftd.py b/plugins/httpapi/ftd.py
deleted file mode 100644
index 73db5ef79d..0000000000
--- a/plugins/httpapi/ftd.py
+++ /dev/null
@@ -1,386 +0,0 @@
-# Copyright (c) 2018 Cisco and/or its affiliates.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-
-__metaclass__ = type
-
-DOCUMENTATION = '''
----
-author: Ansible Networking Team
-httpapi : ftd
-short_description: HttpApi Plugin for Cisco ASA Firepower device
-description:
- - This HttpApi plugin provides methods to connect to Cisco ASA firepower
- devices over a HTTP(S)-based api.
-options:
- token_path:
- type: str
- description:
- - Specifies the api token path of the FTD device
- vars:
- - name: ansible_httpapi_ftd_token_path
- spec_path:
- type: str
- description:
- - Specifies the api spec path of the FTD device
- default: '/apispec/ngfw.json'
- vars:
- - name: ansible_httpapi_ftd_spec_path
-'''
-
-import json
-import os
-import re
-
-from ansible import __version__ as ansible_version
-
-from ansible.module_utils.basic import to_text
-from ansible.errors import AnsibleConnectionFailure
-from ansible_collections.community.general.plugins.module_utils.network.ftd.fdm_swagger_client import FdmSwaggerParser, SpecProp, FdmSwaggerValidator
-from ansible_collections.community.general.plugins.module_utils.network.ftd.common import HTTPMethod, ResponseParams
-from ansible.module_utils.six.moves.urllib.error import HTTPError
-from ansible.module_utils.six.moves.urllib.parse import urlencode
-from ansible.plugins.httpapi import HttpApiBase
-from urllib3 import encode_multipart_formdata
-from urllib3.fields import RequestField
-from ansible.module_utils.connection import ConnectionError
-
-BASE_HEADERS = {
- 'Content-Type': 'application/json',
- 'Accept': 'application/json',
- 'User-Agent': 'FTD Ansible/%s' % ansible_version
-}
-
-TOKEN_EXPIRATION_STATUS_CODE = 408
-UNAUTHORIZED_STATUS_CODE = 401
-API_TOKEN_PATH_OPTION_NAME = 'token_path'
-TOKEN_PATH_TEMPLATE = '/api/fdm/{0}/fdm/token'
-GET_API_VERSIONS_PATH = '/api/versions'
-DEFAULT_API_VERSIONS = ['v2', 'v1']
-
-INVALID_API_TOKEN_PATH_MSG = ('The API token path is incorrect. Please, check correctness of '
- 'the `ansible_httpapi_ftd_token_path` variable in the inventory file.')
-MISSING_API_TOKEN_PATH_MSG = ('Ansible could not determine the API token path automatically. Please, '
- 'specify the `ansible_httpapi_ftd_token_path` variable in the inventory file.')
-
-
-class HttpApi(HttpApiBase):
- def __init__(self, connection):
- super(HttpApi, self).__init__(connection)
- self.connection = connection
- self.access_token = None
- self.refresh_token = None
- self._api_spec = None
- self._api_validator = None
- self._ignore_http_errors = False
-
- def login(self, username, password):
- def request_token_payload(username, password):
- return {
- 'grant_type': 'password',
- 'username': username,
- 'password': password
- }
-
- def refresh_token_payload(refresh_token):
- return {
- 'grant_type': 'refresh_token',
- 'refresh_token': refresh_token
- }
-
- if self.refresh_token:
- payload = refresh_token_payload(self.refresh_token)
- elif username and password:
- payload = request_token_payload(username, password)
- else:
- raise AnsibleConnectionFailure('Username and password are required for login in absence of refresh token')
-
- response = self._lookup_login_url(payload)
-
- try:
- self.refresh_token = response['refresh_token']
- self.access_token = response['access_token']
- self.connection._auth = {'Authorization': 'Bearer %s' % self.access_token}
- except KeyError:
- raise ConnectionError(
- 'Server returned response without token info during connection authentication: %s' % response)
-
- def _lookup_login_url(self, payload):
- """ Try to find correct login URL and get api token using this URL.
-
- :param payload: Token request payload
- :type payload: dict
- :return: token generation response
- """
- preconfigured_token_path = self._get_api_token_path()
- if preconfigured_token_path:
- token_paths = [preconfigured_token_path]
- else:
- token_paths = self._get_known_token_paths()
-
- for url in token_paths:
- try:
- response = self._send_login_request(payload, url)
-
- except ConnectionError as e:
- self.connection.queue_message('vvvv', 'REST:request to %s failed because of connection error: %s ' % (
- url, e))
- # In the case of ConnectionError caused by HTTPError we should check response code.
- # Response code 400 returned in case of invalid credentials so we should stop attempts to log in and
- # inform the user.
- if hasattr(e, 'http_code') and e.http_code == 400:
- raise
- else:
- if not preconfigured_token_path:
- self._set_api_token_path(url)
- return response
-
- raise ConnectionError(INVALID_API_TOKEN_PATH_MSG if preconfigured_token_path else MISSING_API_TOKEN_PATH_MSG)
-
- def _send_login_request(self, payload, url):
- self._display(HTTPMethod.POST, 'login', url)
- response, response_data = self._send_auth_request(
- url, json.dumps(payload), method=HTTPMethod.POST, headers=BASE_HEADERS
- )
- self._display(HTTPMethod.POST, 'login:status_code', response.getcode())
-
- response = self._response_to_json(self._get_response_value(response_data))
- return response
-
- def logout(self):
- auth_payload = {
- 'grant_type': 'revoke_token',
- 'access_token': self.access_token,
- 'token_to_revoke': self.refresh_token
- }
-
- url = self._get_api_token_path()
-
- self._display(HTTPMethod.POST, 'logout', url)
- response, dummy = self._send_auth_request(url, json.dumps(auth_payload), method=HTTPMethod.POST,
- headers=BASE_HEADERS)
- self._display(HTTPMethod.POST, 'logout:status_code', response.getcode())
-
- self.refresh_token = None
- self.access_token = None
-
- def _send_auth_request(self, path, data, **kwargs):
- error_msg_prefix = 'Server returned an error during authentication request'
- return self._send_service_request(path, error_msg_prefix, data=data, **kwargs)
-
- def _send_service_request(self, path, error_msg_prefix, data=None, **kwargs):
- try:
- self._ignore_http_errors = True
- return self.connection.send(path, data, **kwargs)
- except HTTPError as e:
- # HttpApi connection does not read the error response from HTTPError, so we do it here and wrap it up in
- # ConnectionError, so the actual error message is displayed to the user.
- error_msg = self._response_to_json(to_text(e.read()))
- raise ConnectionError('%s: %s' % (error_msg_prefix, error_msg), http_code=e.code)
- finally:
- self._ignore_http_errors = False
-
- def update_auth(self, response, response_data):
- # With tokens, authentication should not be checked and updated on each request
- return None
-
- def send_request(self, url_path, http_method, body_params=None, path_params=None, query_params=None):
- url = construct_url_path(url_path, path_params, query_params)
- data = json.dumps(body_params) if body_params else None
- try:
- self._display(http_method, 'url', url)
- if data:
- self._display(http_method, 'data', data)
-
- response, response_data = self.connection.send(url, data, method=http_method, headers=BASE_HEADERS)
-
- value = self._get_response_value(response_data)
- self._display(http_method, 'response', value)
-
- return {
- ResponseParams.SUCCESS: True,
- ResponseParams.STATUS_CODE: response.getcode(),
- ResponseParams.RESPONSE: self._response_to_json(value)
- }
- # Being invoked via JSON-RPC, this method does not serialize and pass HTTPError correctly to the method caller.
- # Thus, in order to handle non-200 responses, we need to wrap them into a simple structure and pass explicitly.
- except HTTPError as e:
- error_msg = to_text(e.read())
- self._display(http_method, 'error', error_msg)
- return {
- ResponseParams.SUCCESS: False,
- ResponseParams.STATUS_CODE: e.code,
- ResponseParams.RESPONSE: self._response_to_json(error_msg)
- }
-
- def upload_file(self, from_path, to_url):
- url = construct_url_path(to_url)
- self._display(HTTPMethod.POST, 'upload', url)
- with open(from_path, 'rb') as src_file:
- rf = RequestField('fileToUpload', src_file.read(), os.path.basename(src_file.name))
- rf.make_multipart()
- body, content_type = encode_multipart_formdata([rf])
-
- headers = dict(BASE_HEADERS)
- headers['Content-Type'] = content_type
- headers['Content-Length'] = len(body)
-
- dummy, response_data = self.connection.send(url, data=body, method=HTTPMethod.POST, headers=headers)
- value = self._get_response_value(response_data)
- self._display(HTTPMethod.POST, 'upload:response', value)
- return self._response_to_json(value)
-
- def download_file(self, from_url, to_path, path_params=None):
- url = construct_url_path(from_url, path_params=path_params)
- self._display(HTTPMethod.GET, 'download', url)
- response, response_data = self.connection.send(url, data=None, method=HTTPMethod.GET, headers=BASE_HEADERS)
-
- if os.path.isdir(to_path):
- filename = extract_filename_from_headers(response.info())
- to_path = os.path.join(to_path, filename)
-
- with open(to_path, "wb") as output_file:
- output_file.write(response_data.getvalue())
- self._display(HTTPMethod.GET, 'downloaded', to_path)
-
- def handle_httperror(self, exc):
- is_auth_related_code = exc.code == TOKEN_EXPIRATION_STATUS_CODE or exc.code == UNAUTHORIZED_STATUS_CODE
- if not self._ignore_http_errors and is_auth_related_code:
- self.connection._auth = None
- self.login(self.connection.get_option('remote_user'), self.connection.get_option('password'))
- return True
- # False means that the exception will be passed further to the caller
- return False
-
- def _display(self, http_method, title, msg=''):
- self.connection.queue_message('vvvv', 'REST:%s:%s:%s\n%s' % (http_method, self.connection._url, title, msg))
-
- @staticmethod
- def _get_response_value(response_data):
- return to_text(response_data.getvalue())
-
- def _get_api_spec_path(self):
- return self.get_option('spec_path')
-
- def _get_known_token_paths(self):
- """Generate list of token generation urls based on list of versions supported by device(if exposed via API) or
- default list of API versions.
-
- :returns: list of token generation urls
- :rtype: generator
- """
- try:
- api_versions = self._get_supported_api_versions()
- except ConnectionError:
- # API versions API is not supported we need to check all known version
- api_versions = DEFAULT_API_VERSIONS
-
- return [TOKEN_PATH_TEMPLATE.format(version) for version in api_versions]
-
- def _get_supported_api_versions(self):
- """
- Fetch list of API versions supported by device.
-
- :return: list of API versions suitable for device
- :rtype: list
- """
- # Try to fetch supported API version
- http_method = HTTPMethod.GET
- response, response_data = self._send_service_request(
- path=GET_API_VERSIONS_PATH,
- error_msg_prefix="Can't fetch list of supported api versions",
- method=http_method,
- headers=BASE_HEADERS
- )
-
- value = self._get_response_value(response_data)
- self._display(http_method, 'response', value)
- api_versions_info = self._response_to_json(value)
- return api_versions_info["supportedVersions"]
-
- def _get_api_token_path(self):
- return self.get_option(API_TOKEN_PATH_OPTION_NAME)
-
- def _set_api_token_path(self, url):
- return self.set_option(API_TOKEN_PATH_OPTION_NAME, url)
-
- @staticmethod
- def _response_to_json(response_text):
- try:
- return json.loads(response_text) if response_text else {}
- # JSONDecodeError only available on Python 3.5+
- except getattr(json.decoder, 'JSONDecodeError', ValueError):
- raise ConnectionError('Invalid JSON response: %s' % response_text)
-
- def get_operation_spec(self, operation_name):
- return self.api_spec[SpecProp.OPERATIONS].get(operation_name, None)
-
- def get_operation_specs_by_model_name(self, model_name):
- if model_name:
- return self.api_spec[SpecProp.MODEL_OPERATIONS].get(model_name, None)
- else:
- return None
-
- def get_model_spec(self, model_name):
- return self.api_spec[SpecProp.MODELS].get(model_name, None)
-
- def validate_data(self, operation_name, data):
- return self.api_validator.validate_data(operation_name, data)
-
- def validate_query_params(self, operation_name, params):
- return self.api_validator.validate_query_params(operation_name, params)
-
- def validate_path_params(self, operation_name, params):
- return self.api_validator.validate_path_params(operation_name, params)
-
- @property
- def api_spec(self):
- if self._api_spec is None:
- spec_path_url = self._get_api_spec_path()
- response = self.send_request(url_path=spec_path_url, http_method=HTTPMethod.GET)
- if response[ResponseParams.SUCCESS]:
- self._api_spec = FdmSwaggerParser().parse_spec(response[ResponseParams.RESPONSE])
- else:
- raise ConnectionError('Failed to download API specification. Status code: %s. Response: %s' % (
- response[ResponseParams.STATUS_CODE], response[ResponseParams.RESPONSE]))
- return self._api_spec
-
- @property
- def api_validator(self):
- if self._api_validator is None:
- self._api_validator = FdmSwaggerValidator(self.api_spec)
- return self._api_validator
-
-
-def construct_url_path(path, path_params=None, query_params=None):
- url = path
- if path_params:
- url = url.format(**path_params)
- if query_params:
- url += "?" + urlencode(query_params)
- return url
-
-
-def extract_filename_from_headers(response_info):
- content_header_regex = r'attachment; ?filename="?([^"]+)'
- match = re.match(content_header_regex, response_info.get('Content-Disposition'))
- if match:
- return match.group(1)
- else:
- raise ValueError("No appropriate Content-Disposition header is specified.")
diff --git a/plugins/lookup/avi.py b/plugins/lookup/avi.py
deleted file mode 100644
index f19c036a28..0000000000
--- a/plugins/lookup/avi.py
+++ /dev/null
@@ -1,127 +0,0 @@
-# python 3 headers, required if submitting to Ansible
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
-lookup: avi
-author: Sandeep Bandi
-short_description: Look up ``Avi`` objects.
-description:
- - Given an object_type, fetch all the objects of that type or fetch
- the specific object that matches the name/uuid given via options.
- - For single object lookup. If you want the output to be a list, you may
- want to pass option wantlist=True to the plugin.
-
-options:
- obj_type:
- description:
- - type of object to query
- required: True
- obj_name:
- description:
- - name of the object to query
- obj_uuid:
- description:
- - UUID of the object to query
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-# Lookup query for all the objects of a specific type.
-- debug: msg="{{ lookup('avi', avi_credentials=avi_credentials, obj_type='virtualservice') }}"
-# Lookup query for an object with the given name and type.
-- debug: msg="{{ lookup('avi', avi_credentials=avi_credentials, obj_name='vs1', obj_type='virtualservice', wantlist=True) }}"
-# Lookup query for an object with the given UUID and type.
-- debug: msg="{{ lookup('avi', obj_uuid='virtualservice-5c0e183a-690a-45d8-8d6f-88c30a52550d', obj_type='virtualservice') }}"
-# We can replace lookup with query function to always the get the output as list.
-# This is helpful for looping.
-- debug: msg="{{ query('avi', obj_uuid='virtualservice-5c0e183a-690a-45d8-8d6f-88c30a52550d', obj_type='virtualservice') }}"
-"""
-
-RETURN = """
- _raw:
- description:
- - One ore more objects returned from ``Avi`` API.
- type: list
- elements: dictionary
-"""
-
-from ansible.module_utils._text import to_native
-from ansible.errors import AnsibleError, AnsibleParserError
-from ansible.plugins.lookup import LookupBase
-from ansible.utils.display import Display
-from ansible_collections.community.general.plugins.module_utils.network.avi.avi_api import (ApiSession,
- AviCredentials,
- AviServerError,
- ObjectNotFound,
- APIError)
-
-display = Display()
-
-
-def _api(avi_session, path, **kwargs):
- '''
- Generic function to handle both // and /
- API resource endpoints.
- '''
- rsp = []
- try:
- rsp_data = avi_session.get(path, **kwargs).json()
- if 'results' in rsp_data:
- rsp = rsp_data['results']
- else:
- rsp.append(rsp_data)
- except ObjectNotFound as e:
- display.warning('Resource not found. Please check obj_name/'
- 'obj_uuid/obj_type are spelled correctly.')
- display.v(to_native(e))
- except (AviServerError, APIError) as e:
- raise AnsibleError(to_native(e))
- except Exception as e:
- # Generic excption handling for connection failures
- raise AnsibleError('Unable to communicate with controller'
- 'due to error: %s' % to_native(e))
-
- return rsp
-
-
-class LookupModule(LookupBase):
- def run(self, terms, variables=None, avi_credentials=None, **kwargs):
-
- api_creds = AviCredentials(**avi_credentials)
- # Create the session using avi_credentials
- try:
- avi = ApiSession(avi_credentials=api_creds)
- except Exception as e:
- raise AnsibleError(to_native(e))
-
- # Return an empty list if the object is not found
- rsp = []
- try:
- path = kwargs.pop('obj_type')
- except KeyError:
- raise AnsibleError("Please pass the obj_type for lookup")
-
- if kwargs.get('obj_name', None):
- name = kwargs.pop('obj_name')
- try:
- display.v("Fetching obj: %s of type: %s" % (name, path))
- rsp_data = avi.get_object_by_name(path, name, **kwargs)
- if rsp_data:
- # Append the return data only if it is not None. i.e object
- # with specified name is present
- rsp.append(rsp_data)
- except AviServerError as e:
- raise AnsibleError(to_native(e))
- elif kwargs.get('obj_uuid', None):
- obj_uuid = kwargs.pop('obj_uuid')
- obj_path = "%s/%s" % (path, obj_uuid)
- display.v("Fetching obj: %s of type: %s" % (obj_uuid, path))
- rsp = _api(avi, obj_path, **kwargs)
- else:
- display.v("Fetching all objects of type: %s" % path)
- rsp = _api(avi, path, **kwargs)
-
- return rsp
diff --git a/plugins/module_utils/f5_utils.py b/plugins/module_utils/f5_utils.py
deleted file mode 100644
index 17994f99cf..0000000000
--- a/plugins/module_utils/f5_utils.py
+++ /dev/null
@@ -1,383 +0,0 @@
-#
-# Copyright 2016 F5 Networks Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-
-
-# Legacy
-
-try:
- import bigsuds
- bigsuds_found = True
-except ImportError:
- bigsuds_found = False
-
-
-from ansible.module_utils.basic import env_fallback
-
-
-def f5_argument_spec():
- return dict(
- server=dict(
- type='str',
- required=True,
- fallback=(env_fallback, ['F5_SERVER'])
- ),
- user=dict(
- type='str',
- required=True,
- fallback=(env_fallback, ['F5_USER'])
- ),
- password=dict(
- type='str',
- aliases=['pass', 'pwd'],
- required=True,
- no_log=True,
- fallback=(env_fallback, ['F5_PASSWORD'])
- ),
- validate_certs=dict(
- default='yes',
- type='bool',
- fallback=(env_fallback, ['F5_VALIDATE_CERTS'])
- ),
- server_port=dict(
- type='int',
- default=443,
- fallback=(env_fallback, ['F5_SERVER_PORT'])
- ),
- state=dict(
- type='str',
- default='present',
- choices=['present', 'absent']
- ),
- partition=dict(
- type='str',
- default='Common',
- fallback=(env_fallback, ['F5_PARTITION'])
- )
- )
-
-
-def f5_parse_arguments(module):
- if not bigsuds_found:
- module.fail_json(msg="the python bigsuds module is required")
-
- if module.params['validate_certs']:
- import ssl
- if not hasattr(ssl, 'SSLContext'):
- module.fail_json(
- msg="bigsuds does not support verifying certificates with python < 2.7.9."
- "Either update python or set validate_certs=False on the task'")
-
- return (
- module.params['server'],
- module.params['user'],
- module.params['password'],
- module.params['state'],
- module.params['partition'],
- module.params['validate_certs'],
- module.params['server_port']
- )
-
-
-def bigip_api(bigip, user, password, validate_certs, port=443):
- try:
- if bigsuds.__version__ >= '1.0.4':
- api = bigsuds.BIGIP(hostname=bigip, username=user, password=password, verify=validate_certs, port=port)
- elif bigsuds.__version__ == '1.0.3':
- api = bigsuds.BIGIP(hostname=bigip, username=user, password=password, verify=validate_certs)
- else:
- api = bigsuds.BIGIP(hostname=bigip, username=user, password=password)
- except TypeError:
- # bigsuds < 1.0.3, no verify param
- if validate_certs:
- # Note: verified we have SSLContext when we parsed params
- api = bigsuds.BIGIP(hostname=bigip, username=user, password=password)
- else:
- import ssl
- if hasattr(ssl, 'SSLContext'):
- # Really, you should never do this. It disables certificate
- # verification *globally*. But since older bigip libraries
- # don't give us a way to toggle verification we need to
- # disable it at the global level.
- # From https://www.python.org/dev/peps/pep-0476/#id29
- ssl._create_default_https_context = ssl._create_unverified_context
- api = bigsuds.BIGIP(hostname=bigip, username=user, password=password)
-
- return api
-
-
-# Fully Qualified name (with the partition)
-def fq_name(partition, name):
- if name is not None and not name.startswith('/'):
- return '/%s/%s' % (partition, name)
- return name
-
-
-# Fully Qualified name (with partition) for a list
-def fq_list_names(partition, list_names):
- if list_names is None:
- return None
- return map(lambda x: fq_name(partition, x), list_names)
-
-
-def to_commands(module, commands):
- spec = {
- 'command': dict(key=True),
- 'prompt': dict(),
- 'answer': dict()
- }
- transform = ComplexList(spec, module)
- return transform(commands)
-
-
-def run_commands(module, commands, check_rc=True):
- responses = list()
- commands = to_commands(module, to_list(commands))
- for cmd in commands:
- cmd = module.jsonify(cmd)
- rc, out, err = exec_command(module, cmd)
- if check_rc and rc != 0:
- module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), rc=rc)
- responses.append(to_text(out, errors='surrogate_then_replace'))
- return responses
-
-
-# New style
-
-from abc import ABCMeta, abstractproperty
-from collections import defaultdict
-
-try:
- from f5.bigip import ManagementRoot as BigIpMgmt
- from f5.bigip.contexts import TransactionContextManager as BigIpTxContext
-
- from f5.bigiq import ManagementRoot as BigIqMgmt
-
- from f5.iworkflow import ManagementRoot as iWorkflowMgmt
- from icontrol.exceptions import iControlUnexpectedHTTPError
- HAS_F5SDK = True
-except ImportError:
- HAS_F5SDK = False
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.six import iteritems, with_metaclass
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList
-from ansible.module_utils.connection import exec_command
-from ansible.module_utils._text import to_text
-
-
-F5_COMMON_ARGS = dict(
- server=dict(
- type='str',
- required=True,
- fallback=(env_fallback, ['F5_SERVER'])
- ),
- user=dict(
- type='str',
- required=True,
- fallback=(env_fallback, ['F5_USER'])
- ),
- password=dict(
- type='str',
- aliases=['pass', 'pwd'],
- required=True,
- no_log=True,
- fallback=(env_fallback, ['F5_PASSWORD'])
- ),
- validate_certs=dict(
- default='yes',
- type='bool',
- fallback=(env_fallback, ['F5_VALIDATE_CERTS'])
- ),
- server_port=dict(
- type='int',
- default=443,
- fallback=(env_fallback, ['F5_SERVER_PORT'])
- ),
- state=dict(
- type='str',
- default='present',
- choices=['present', 'absent']
- ),
- partition=dict(
- type='str',
- default='Common',
- fallback=(env_fallback, ['F5_PARTITION'])
- )
-)
-
-
-class AnsibleF5Client(object):
- def __init__(self, argument_spec=None, supports_check_mode=False,
- mutually_exclusive=None, required_together=None,
- required_if=None, required_one_of=None, add_file_common_args=False,
- f5_product_name='bigip', sans_state=False, sans_partition=False):
-
- self.f5_product_name = f5_product_name
-
- merged_arg_spec = dict()
- merged_arg_spec.update(F5_COMMON_ARGS)
- if argument_spec:
- merged_arg_spec.update(argument_spec)
- if sans_state:
- del merged_arg_spec['state']
- if sans_partition:
- del merged_arg_spec['partition']
- self.arg_spec = merged_arg_spec
-
- mutually_exclusive_params = []
- if mutually_exclusive:
- mutually_exclusive_params += mutually_exclusive
-
- required_together_params = []
- if required_together:
- required_together_params += required_together
-
- self.module = AnsibleModule(
- argument_spec=merged_arg_spec,
- supports_check_mode=supports_check_mode,
- mutually_exclusive=mutually_exclusive_params,
- required_together=required_together_params,
- required_if=required_if,
- required_one_of=required_one_of,
- add_file_common_args=add_file_common_args
- )
-
- self.check_mode = self.module.check_mode
- self._connect_params = self._get_connect_params()
-
- if 'transport' not in self.module.params or self.module.params['transport'] != 'cli':
- try:
- self.api = self._get_mgmt_root(
- f5_product_name, **self._connect_params
- )
- except iControlUnexpectedHTTPError as exc:
- self.fail(str(exc))
-
- def fail(self, msg):
- self.module.fail_json(msg=msg)
-
- def _get_connect_params(self):
- params = dict(
- user=self.module.params['user'],
- password=self.module.params['password'],
- server=self.module.params['server'],
- server_port=self.module.params['server_port'],
- validate_certs=self.module.params['validate_certs']
- )
- return params
-
- def _get_mgmt_root(self, type, **kwargs):
- if type == 'bigip':
- return BigIpMgmt(
- kwargs['server'],
- kwargs['user'],
- kwargs['password'],
- port=kwargs['server_port'],
- token='tmos'
- )
- elif type == 'iworkflow':
- return iWorkflowMgmt(
- kwargs['server'],
- kwargs['user'],
- kwargs['password'],
- port=kwargs['server_port'],
- token='local'
- )
- elif type == 'bigiq':
- return BigIqMgmt(
- kwargs['server'],
- kwargs['user'],
- kwargs['password'],
- port=kwargs['server_port'],
- auth_provider='local'
- )
-
- def reconnect(self):
- """Attempts to reconnect to a device
-
- The existing token from a ManagementRoot can become invalid if you,
- for example, upgrade the device (such as is done in the *_software
- module.
-
- This method can be used to reconnect to a remote device without
- having to re-instantiate the ArgumentSpec and AnsibleF5Client classes
- it will use the same values that were initially provided to those
- classes
-
- :return:
- :raises iControlUnexpectedHTTPError
- """
- self.api = self._get_mgmt_root(
- self.f5_product_name, **self._connect_params
- )
-
-
-class AnsibleF5Parameters(object):
- def __init__(self, params=None):
- self._values = defaultdict(lambda: None)
- self._values['__warnings'] = []
- if params:
- self.update(params=params)
-
- def update(self, params=None):
- if params:
- for k, v in iteritems(params):
- if self.api_map is not None and k in self.api_map:
- dict_to_use = self.api_map
- map_key = self.api_map[k]
- else:
- dict_to_use = self._values
- map_key = k
-
- # Handle weird API parameters like `dns.proxy.__iter__` by
- # using a map provided by the module developer
- class_attr = getattr(type(self), map_key, None)
- if isinstance(class_attr, property):
- # There is a mapped value for the api_map key
- if class_attr.fset is None:
- # If the mapped value does not have an associated setter
- self._values[map_key] = v
- else:
- # The mapped value has a setter
- setattr(self, map_key, v)
- else:
- # If the mapped value is not a @property
- self._values[map_key] = v
-
- def __getattr__(self, item):
- # Ensures that properties that weren't defined, and therefore stashed
- # in the `_values` dict, will be retrievable.
- return self._values[item]
-
- @property
- def partition(self):
- if self._values['partition'] is None:
- return 'Common'
- return self._values['partition'].strip('/')
-
- @partition.setter
- def partition(self, value):
- self._values['partition'] = value
-
- def _filter_params(self, params):
- return dict((k, v) for k, v in iteritems(params) if v is not None)
-
-
-class F5ModuleError(Exception):
- pass
diff --git a/plugins/module_utils/network/__init__.py b/plugins/module_utils/network/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/a10/__init__.py b/plugins/module_utils/network/a10/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/a10/a10.py b/plugins/module_utils/network/a10/a10.py
deleted file mode 100644
index bf713702e4..0000000000
--- a/plugins/module_utils/network/a10/a10.py
+++ /dev/null
@@ -1,153 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# Copyright (c), Michael DeHaan , 2012-2013
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import json
-
-from ansible.module_utils.urls import fetch_url
-
-
-AXAPI_PORT_PROTOCOLS = {
- 'tcp': 2,
- 'udp': 3,
-}
-
-AXAPI_VPORT_PROTOCOLS = {
- 'tcp': 2,
- 'udp': 3,
- 'fast-http': 9,
- 'http': 11,
- 'https': 12,
-}
-
-
-def a10_argument_spec():
- return dict(
- host=dict(type='str', required=True),
- username=dict(type='str', aliases=['user', 'admin'], required=True),
- password=dict(type='str', aliases=['pass', 'pwd'], required=True, no_log=True),
- write_config=dict(type='bool', default=False)
- )
-
-
-def axapi_failure(result):
- if 'response' in result and result['response'].get('status') == 'fail':
- return True
- return False
-
-
-def axapi_call(module, url, post=None):
- '''
- Returns a datastructure based on the result of the API call
- '''
- rsp, info = fetch_url(module, url, data=post)
- if not rsp or info['status'] >= 400:
- module.fail_json(msg="failed to connect (status code %s), error was %s" % (info['status'], info.get('msg', 'no error given')))
- try:
- raw_data = rsp.read()
- data = json.loads(raw_data)
- except ValueError:
- # at least one API call (system.action.write_config) returns
- # XML even when JSON is requested, so do some minimal handling
- # here to prevent failing even when the call succeeded
- if 'status="ok"' in raw_data.lower():
- data = {"response": {"status": "OK"}}
- else:
- data = {"response": {"status": "fail", "err": {"msg": raw_data}}}
- except Exception:
- module.fail_json(msg="could not read the result from the host")
- finally:
- rsp.close()
- return data
-
-
-def axapi_authenticate(module, base_url, username, password):
- url = '%s&method=authenticate&username=%s&password=%s' % (base_url, username, password)
- result = axapi_call(module, url)
- if axapi_failure(result):
- return module.fail_json(msg=result['response']['err']['msg'])
- sessid = result['session_id']
- return base_url + '&session_id=' + sessid
-
-
-def axapi_authenticate_v3(module, base_url, username, password):
- url = base_url
- auth_payload = {"credentials": {"username": username, "password": password}}
- result = axapi_call_v3(module, url, method='POST', body=json.dumps(auth_payload))
- if axapi_failure(result):
- return module.fail_json(msg=result['response']['err']['msg'])
- signature = result['authresponse']['signature']
- return signature
-
-
-def axapi_call_v3(module, url, method=None, body=None, signature=None):
- '''
- Returns a datastructure based on the result of the API call
- '''
- if signature:
- headers = {'content-type': 'application/json', 'Authorization': 'A10 %s' % signature}
- else:
- headers = {'content-type': 'application/json'}
- rsp, info = fetch_url(module, url, method=method, data=body, headers=headers)
- if not rsp or info['status'] >= 400:
- module.fail_json(msg="failed to connect (status code %s), error was %s" % (info['status'], info.get('msg', 'no error given')))
- try:
- raw_data = rsp.read()
- data = json.loads(raw_data)
- except ValueError:
- # at least one API call (system.action.write_config) returns
- # XML even when JSON is requested, so do some minimal handling
- # here to prevent failing even when the call succeeded
- if 'status="ok"' in raw_data.lower():
- data = {"response": {"status": "OK"}}
- else:
- data = {"response": {"status": "fail", "err": {"msg": raw_data}}}
- except Exception:
- module.fail_json(msg="could not read the result from the host")
- finally:
- rsp.close()
- return data
-
-
-def axapi_enabled_disabled(flag):
- '''
- The axapi uses 0/1 integer values for flags, rather than strings
- or booleans, so convert the given flag to a 0 or 1. For now, params
- are specified as strings only so thats what we check.
- '''
- if flag == 'enabled':
- return 1
- else:
- return 0
-
-
-def axapi_get_port_protocol(protocol):
- return AXAPI_PORT_PROTOCOLS.get(protocol.lower(), None)
-
-
-def axapi_get_vport_protocol(protocol):
- return AXAPI_VPORT_PROTOCOLS.get(protocol.lower(), None)
diff --git a/plugins/module_utils/network/aci/__init__.py b/plugins/module_utils/network/aci/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/aireos/__init__.py b/plugins/module_utils/network/aireos/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/aireos/aireos.py b/plugins/module_utils/network/aireos/aireos.py
deleted file mode 100644
index e5db446ad9..0000000000
--- a/plugins/module_utils/network/aireos/aireos.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# (c) 2016 Red Hat Inc.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import env_fallback
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList
-from ansible.module_utils.connection import exec_command
-
-_DEVICE_CONFIGS = {}
-
-aireos_provider_spec = {
- 'host': dict(),
- 'port': dict(type='int'),
- 'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
- 'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True),
- 'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
- 'timeout': dict(type='int'),
-}
-aireos_argument_spec = {
- 'provider': dict(type='dict', options=aireos_provider_spec)
-}
-
-aireos_top_spec = {
- 'host': dict(removed_in_version=2.9),
- 'port': dict(removed_in_version=2.9, type='int'),
- 'username': dict(removed_in_version=2.9),
- 'password': dict(removed_in_version=2.9, no_log=True),
- 'ssh_keyfile': dict(removed_in_version=2.9, type='path'),
- 'timeout': dict(removed_in_version=2.9, type='int'),
-}
-aireos_argument_spec.update(aireos_top_spec)
-
-
-def sanitize(resp):
- # Takes response from device and strips whitespace from all lines
- # Aireos adds in extra preceding whitespace which netcfg parses as children/parents, which Aireos does not do
- # Aireos also adds in trailing whitespace that is unused
- cleaned = []
- for line in resp.splitlines():
- cleaned.append(line.strip())
- return '\n'.join(cleaned).strip()
-
-
-def get_provider_argspec():
- return aireos_provider_spec
-
-
-def check_args(module, warnings):
- pass
-
-
-def get_config(module, flags=None):
- flags = [] if flags is None else flags
-
- cmd = 'show run-config commands '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- try:
- return _DEVICE_CONFIGS[cmd]
- except KeyError:
- rc, out, err = exec_command(module, cmd)
- if rc != 0:
- module.fail_json(msg='unable to retrieve current config', stderr=to_text(err, errors='surrogate_then_replace'))
- cfg = sanitize(to_text(out, errors='surrogate_then_replace').strip())
- _DEVICE_CONFIGS[cmd] = cfg
- return cfg
-
-
-def to_commands(module, commands):
- spec = {
- 'command': dict(key=True),
- 'prompt': dict(),
- 'answer': dict()
- }
- transform = ComplexList(spec, module)
- return transform(commands)
-
-
-def run_commands(module, commands, check_rc=True):
- responses = list()
- commands = to_commands(module, to_list(commands))
- for cmd in commands:
- cmd = module.jsonify(cmd)
- rc, out, err = exec_command(module, cmd)
- if check_rc and rc != 0:
- module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), rc=rc)
- responses.append(sanitize(to_text(out, errors='surrogate_then_replace')))
- return responses
-
-
-def load_config(module, commands):
-
- rc, out, err = exec_command(module, 'config')
- if rc != 0:
- module.fail_json(msg='unable to enter configuration mode', err=to_text(out, errors='surrogate_then_replace'))
-
- for command in to_list(commands):
- if command == 'end':
- continue
- rc, out, err = exec_command(module, command)
- if rc != 0:
- module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc)
-
- exec_command(module, 'end')
diff --git a/plugins/module_utils/network/aos/__init__.py b/plugins/module_utils/network/aos/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/aos/aos.py b/plugins/module_utils/network/aos/aos.py
deleted file mode 100644
index 092bbf5b4a..0000000000
--- a/plugins/module_utils/network/aos/aos.py
+++ /dev/null
@@ -1,180 +0,0 @@
-#
-# Copyright (c) 2017 Apstra Inc,
-#
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-"""
-This module adds shared support for Apstra AOS modules
-
-In order to use this module, include it as part of your module
-
-from ansible.module_utils.network.aos.aos import (check_aos_version, get_aos_session, find_collection_item,
- content_to_dict, do_load_resource)
-
-"""
-import json
-
-from distutils.version import LooseVersion
-
-try:
- import yaml
- HAS_YAML = True
-except ImportError:
- HAS_YAML = False
-
-try:
- from apstra.aosom.session import Session
-
- HAS_AOS_PYEZ = True
-except ImportError:
- HAS_AOS_PYEZ = False
-
-from ansible.module_utils._text import to_native
-
-
-def check_aos_version(module, min=False):
- """
- Check if the library aos-pyez is present.
- If provided, also check if the minimum version requirement is met
- """
- if not HAS_AOS_PYEZ:
- module.fail_json(msg='aos-pyez is not installed. Please see details '
- 'here: https://github.com/Apstra/aos-pyez')
-
- elif min:
- import apstra.aosom
- AOS_PYEZ_VERSION = apstra.aosom.__version__
-
- if LooseVersion(AOS_PYEZ_VERSION) < LooseVersion(min):
- module.fail_json(msg='aos-pyez >= %s is required for this module' % min)
-
- return True
-
-
-def get_aos_session(module, auth):
- """
- Resume an existing session and return an AOS object.
-
- Args:
- auth (dict): An AOS session as obtained by aos_login module blocks::
-
- dict( token=,
- server=,
- port=
- )
-
- Return:
- Aos object
- """
-
- check_aos_version(module)
-
- aos = Session()
- aos.session = auth
-
- return aos
-
-
-def find_collection_item(collection, item_name=False, item_id=False):
- """
- Find collection_item based on name or id from a collection object
- Both Collection_item and Collection Objects are provided by aos-pyez library
-
- Return
- collection_item: object corresponding to the collection type
- """
- my_dict = None
-
- if item_name:
- my_dict = collection.find(label=item_name)
- elif item_id:
- my_dict = collection.find(uid=item_id)
-
- if my_dict is None:
- return collection['']
- else:
- return my_dict
-
-
-def content_to_dict(module, content):
- """
- Convert 'content' into a Python Dict based on 'content_format'
- """
-
- # if not HAS_YAML:
- # module.fail_json(msg="Python Library Yaml is not present, mandatory to use 'content'")
-
- content_dict = None
-
- # try:
- # content_dict = json.loads(content.replace("\'", '"'))
- # except:
- # module.fail_json(msg="Unable to convert 'content' from JSON, please check if valid")
- #
- # elif format in ['yaml', 'var']:
-
- try:
- content_dict = yaml.safe_load(content)
-
- if not isinstance(content_dict, dict):
- raise Exception()
-
- # Check if dict is empty and return an error if it's
- if not content_dict:
- raise Exception()
-
- except Exception:
- module.fail_json(msg="Unable to convert 'content' to a dict, please check if valid")
-
- # replace the string with the dict
- module.params['content'] = content_dict
-
- return content_dict
-
-
-def do_load_resource(module, collection, name):
- """
- Create a new object (collection.item) by loading a datastructure directly
- """
-
- try:
- item = find_collection_item(collection, name, '')
- except Exception:
- module.fail_json(msg="An error occurred while running 'find_collection_item'")
-
- if item.exists:
- module.exit_json(changed=False, name=item.name, id=item.id, value=item.value)
-
- # If not in check mode, apply the changes
- if not module.check_mode:
- try:
- item.datum = module.params['content']
- item.write()
- except Exception as e:
- module.fail_json(msg="Unable to write item content : %r" % to_native(e))
-
- module.exit_json(changed=True, name=item.name, id=item.id, value=item.value)
diff --git a/plugins/module_utils/network/apconos/__init__.py b/plugins/module_utils/network/apconos/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/apconos/apconos.py b/plugins/module_utils/network/apconos/apconos.py
deleted file mode 100644
index 1b9eebcda8..0000000000
--- a/plugins/module_utils/network/apconos/apconos.py
+++ /dev/null
@@ -1,113 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by
-# Ansible still belong to the author of the module, and may assign their own
-# license to the complete work.
-#
-# Copyright (C) 2019 APCON, Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# Contains utility methods
-# APCON Networking
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-from ansible.module_utils._text import to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import EntityCollection
-from ansible.module_utils.connection import Connection, exec_command
-from ansible.module_utils.connection import ConnectionError
-
-_DEVICE_CONFIGS = {}
-_CONNECTION = None
-
-
-command_spec = {
- 'command': dict(key=True),
-}
-
-
-def check_args(module, warnings):
- pass
-
-
-def get_connection(module):
- global _CONNECTION
- if _CONNECTION:
- return _CONNECTION
- _CONNECTION = Connection(module._socket_path)
-
- return _CONNECTION
-
-
-def get_config(module, flags=None):
- flags = [] if flags is None else flags
-
- cmd = ' '.join(flags).strip()
-
- try:
- return _DEVICE_CONFIGS[cmd]
- except KeyError:
- conn = get_connection(module)
- out = conn.get(cmd)
- cfg = to_text(out, errors='surrogate_then_replace').strip()
- _DEVICE_CONFIGS[cmd] = cfg
- return cfg
-
-
-def run_commands(module, commands, check_rc=True):
- connection = get_connection(module)
- transform = EntityCollection(module, command_spec)
- commands = transform(commands)
-
- responses = list()
-
- for cmd in commands:
- out = connection.get(**cmd)
- responses.append(to_text(out, errors='surrogate_then_replace'))
-
- return responses
-
-
-def load_config(module, config):
- try:
- conn = get_connection(module)
- conn.edit_config(config)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
-
-
-def get_defaults_flag(module):
- rc, out, err = exec_command(module, 'display running-config ?')
- out = to_text(out, errors='surrogate_then_replace')
-
- commands = set()
- for line in out.splitlines():
- if line:
- commands.add(line.strip().split()[0])
-
- if 'all' in commands:
- return 'all'
- else:
- return 'full'
diff --git a/plugins/module_utils/network/aruba/__init__.py b/plugins/module_utils/network/aruba/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/aruba/aruba.py b/plugins/module_utils/network/aruba/aruba.py
deleted file mode 100644
index 0499a44315..0000000000
--- a/plugins/module_utils/network/aruba/aruba.py
+++ /dev/null
@@ -1,131 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# (c) 2016 Red Hat Inc.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-import re
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import env_fallback
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList
-from ansible.module_utils.connection import exec_command
-
-_DEVICE_CONFIGS = {}
-
-aruba_provider_spec = {
- 'host': dict(),
- 'port': dict(type='int'),
- 'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
- 'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True),
- 'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
- 'timeout': dict(type='int'),
-}
-aruba_argument_spec = {
- 'provider': dict(type='dict', options=aruba_provider_spec)
-}
-
-aruba_top_spec = {
- 'host': dict(removed_in_version=2.9),
- 'port': dict(removed_in_version=2.9, type='int'),
- 'username': dict(removed_in_version=2.9),
- 'password': dict(removed_in_version=2.9, no_log=True),
- 'ssh_keyfile': dict(removed_in_version=2.9, type='path'),
- 'timeout': dict(removed_in_version=2.9, type='int'),
-}
-
-aruba_argument_spec.update(aruba_top_spec)
-
-
-def get_provider_argspec():
- return aruba_provider_spec
-
-
-def check_args(module, warnings):
- pass
-
-
-def get_config(module, flags=None):
- flags = [] if flags is None else flags
-
- cmd = 'show running-config '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- try:
- return _DEVICE_CONFIGS[cmd]
- except KeyError:
- rc, out, err = exec_command(module, cmd)
- if rc != 0:
- module.fail_json(msg='unable to retrieve current config', stderr=to_text(err, errors='surrogate_then_replace'))
- cfg = sanitize(to_text(out, errors='surrogate_then_replace').strip())
- _DEVICE_CONFIGS[cmd] = cfg
- return cfg
-
-
-def sanitize(resp):
- # Takes response from device and adjusts leading whitespace to just 1 space
- cleaned = []
- for line in resp.splitlines():
- cleaned.append(re.sub(r"^\s+", " ", line))
- return '\n'.join(cleaned).strip()
-
-
-def to_commands(module, commands):
- spec = {
- 'command': dict(key=True),
- 'prompt': dict(),
- 'answer': dict()
- }
- transform = ComplexList(spec, module)
- return transform(commands)
-
-
-def run_commands(module, commands, check_rc=True):
- responses = list()
- commands = to_commands(module, to_list(commands))
- for cmd in commands:
- cmd = module.jsonify(cmd)
- rc, out, err = exec_command(module, cmd)
- if check_rc and rc != 0:
- module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), rc=rc)
- responses.append(to_text(out, errors='surrogate_then_replace'))
- return responses
-
-
-def load_config(module, commands):
-
- rc, out, err = exec_command(module, 'configure terminal')
- if rc != 0:
- module.fail_json(msg='unable to enter configuration mode', err=to_text(out, errors='surrogate_then_replace'))
-
- for command in to_list(commands):
- if command == 'end':
- continue
- rc, out, err = exec_command(module, command)
- if rc != 0:
- module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc)
-
- exec_command(module, 'end')
diff --git a/plugins/module_utils/network/avi/__init__.py b/plugins/module_utils/network/avi/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/avi/ansible_utils.py b/plugins/module_utils/network/avi/ansible_utils.py
deleted file mode 100644
index 2dea53319a..0000000000
--- a/plugins/module_utils/network/avi/ansible_utils.py
+++ /dev/null
@@ -1,572 +0,0 @@
-from __future__ import absolute_import
-
-"""
-Created on Aug 16, 2016
-
-@author: Gaurav Rastogi (grastogi@avinetworks.com)
-"""
-import os
-import re
-import logging
-import sys
-from copy import deepcopy
-from ansible.module_utils.basic import env_fallback
-
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi_api import (
- ApiSession, ObjectNotFound, avi_sdk_syslog_logger, AviCredentials, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-if os.environ.get('AVI_LOG_HANDLER', '') != 'syslog':
- log = logging.getLogger(__name__)
-else:
- # Ansible does not allow logging from the modules.
- log = avi_sdk_syslog_logger()
-
-
-def _check_type_string(x):
- """
- :param x:
- :return: True if it is of type string
- """
- if isinstance(x, str):
- return True
- if sys.version_info[0] < 3:
- try:
- return isinstance(x, unicode)
- except NameError:
- return False
-
-
-class AviCheckModeResponse(object):
- """
- Class to support ansible check mode.
- """
-
- def __init__(self, obj, status_code=200):
- self.obj = obj
- self.status_code = status_code
-
- def json(self):
- return self.obj
-
-
-def ansible_return(module, rsp, changed, req=None, existing_obj=None,
- api_context=None):
- """
- :param module: AnsibleModule
- :param rsp: ApiResponse from avi_api
- :param changed: boolean
- :param req: ApiRequest to avi_api
- :param existing_obj: object to be passed debug output
- :param api_context: api login context
-
- helper function to return the right ansible based on the error code and
- changed
- Returns: specific ansible module exit function
- """
-
- if rsp is not None and rsp.status_code > 299:
- return module.fail_json(
- msg='Error %d Msg %s req: %s api_context:%s ' % (
- rsp.status_code, rsp.text, req, api_context))
- api_creds = AviCredentials()
- api_creds.update_from_ansible_module(module)
- key = '%s:%s:%s' % (api_creds.controller, api_creds.username,
- api_creds.port)
- disable_fact = module.params.get('avi_disable_session_cache_as_fact')
-
- fact_context = None
- if not disable_fact:
- fact_context = module.params.get('api_context', {})
- if fact_context:
- fact_context.update({key: api_context})
- else:
- fact_context = {key: api_context}
-
- obj_val = rsp.json() if rsp else existing_obj
-
- if (obj_val and module.params.get("obj_username", None) and
- "username" in obj_val):
- obj_val["obj_username"] = obj_val["username"]
- if (obj_val and module.params.get("obj_password", None) and
- "password" in obj_val):
- obj_val["obj_password"] = obj_val["password"]
- old_obj_val = existing_obj if changed and existing_obj else None
- api_context_val = api_context if disable_fact else None
- ansible_facts_val = dict(
- avi_api_context=fact_context) if not disable_fact else {}
-
- return module.exit_json(
- changed=changed, obj=obj_val, old_obj=old_obj_val,
- ansible_facts=ansible_facts_val, api_context=api_context_val)
-
-
-def purge_optional_fields(obj, module):
- """
- It purges the optional arguments to be sent to the controller.
- :param obj: dictionary of the ansible object passed as argument.
- :param module: AnsibleModule
- return modified obj
- """
- purge_fields = []
- for param, spec in module.argument_spec.items():
- if not spec.get('required', False):
- if param not in obj:
- # these are ansible common items
- continue
- if obj[param] is None:
- purge_fields.append(param)
- log.debug('purging fields %s', purge_fields)
- for param in purge_fields:
- obj.pop(param, None)
- return obj
-
-
-def cleanup_absent_fields(obj):
- """
- cleans up any field that is marked as state: absent. It needs to be removed
- from the object if it is present.
- :param obj:
- :return: Purged object
- """
- if type(obj) != dict:
- return obj
- cleanup_keys = []
- for k, v in obj.items():
- if type(v) == dict:
- if (('state' in v and v['state'] == 'absent') or
- (v == "{'state': 'absent'}")):
- cleanup_keys.append(k)
- else:
- cleanup_absent_fields(v)
- if not v:
- cleanup_keys.append(k)
- elif type(v) == list:
- new_list = []
- for elem in v:
- elem = cleanup_absent_fields(elem)
- if elem:
- # remove the item from list
- new_list.append(elem)
- if new_list:
- obj[k] = new_list
- else:
- cleanup_keys.append(k)
- elif isinstance(v, str) or isinstance(v, str):
- if v == "{'state': 'absent'}":
- cleanup_keys.append(k)
- for k in cleanup_keys:
- del obj[k]
- return obj
-
-
-RE_REF_MATCH = re.compile(r'^/api/[\w/]+\?name\=[\w]+[^#<>]*$')
-# if HTTP ref match then strip out the #name
-HTTP_REF_MATCH = re.compile(r'https://[\w.0-9:-]+/api/.+')
-HTTP_REF_W_NAME_MATCH = re.compile(r'https://[\w.0-9:-]+/api/.*#.+')
-
-
-def ref_n_str_cmp(x, y):
- """
- compares two references
- 1. check for exact reference
- 2. check for obj_type/uuid
- 3. check for name
-
- if x is ref=name then extract uuid and name from y and use it.
- if x is http_ref then
- strip x and y
- compare them.
-
- if x and y are urls then match with split on #
- if x is a RE_REF_MATCH then extract name
- if y is a REF_MATCH then extract name
- :param x: first string
- :param y: second string from controller's object
-
- Returns
- True if they are equivalent else False
- """
- if type(y) in (int, float, bool, int, complex):
- y = str(y)
- x = str(x)
- if not (_check_type_string(x) and _check_type_string(y)):
- return False
- y_uuid = y_name = str(y)
- x = str(x)
- if RE_REF_MATCH.match(x):
- x = x.split('name=')[1]
- elif HTTP_REF_MATCH.match(x):
- x = x.rsplit('#', 1)[0]
- y = y.rsplit('#', 1)[0]
- elif RE_REF_MATCH.match(y):
- y = y.split('name=')[1]
-
- if HTTP_REF_W_NAME_MATCH.match(y):
- path = y.split('api/', 1)[1]
- # Fetching name or uuid from path /xxxx_xx/xx/xx_x/uuid_or_name
- uuid_or_name = path.split('/')[-1]
- parts = uuid_or_name.rsplit('#', 1)
- y_uuid = parts[0]
- y_name = parts[1] if len(parts) > 1 else ''
- # is just string but y is a url so match either uuid or name
- result = (x in (y, y_name, y_uuid))
- if not result:
- log.debug('x: %s y: %s y_name %s y_uuid %s',
- x, y, y_name, y_uuid)
- return result
-
-
-def avi_obj_cmp(x, y, sensitive_fields=None):
- """
- compares whether x is fully contained in y. The comparision is different
- from a simple dictionary compare for following reasons
- 1. Some fields could be references. The object in controller returns the
- full URL for those references. However, the ansible script would have
- it specified as /api/pool?name=blah. So, the reference fields need
- to match uuid, relative reference based on name and actual reference.
-
- 2. Optional fields with defaults: In case there are optional fields with
- defaults then controller automatically fills it up. This would
- cause the comparison with Ansible object specification to always return
- changed.
-
- 3. Optional fields without defaults: This is most tricky. The issue is
- how to specify deletion of such objects from ansible script. If the
- ansible playbook has object specified as Null then Avi controller will
- reject for non Message(dict) type fields. In addition, to deal with the
- defaults=null issue all the fields that are set with None are purged
- out before comparing with Avi controller's version
-
- So, the solution is to pass state: absent if any optional field needs
- to be deleted from the configuration. The script would return changed
- =true if it finds a key in the controller version and it is marked with
- state: absent in ansible playbook. Alternatively, it would return
- false if key is not present in the controller object. Before, doing
- put or post it would purge the fields that are marked state: absent.
-
- :param x: first string
- :param y: second string from controller's object
- :param sensitive_fields: sensitive fields to ignore for diff
-
- Returns:
- True if x is subset of y else False
- """
- if not sensitive_fields:
- sensitive_fields = set()
- if isinstance(x, str) or isinstance(x, str):
- # Special handling for strings as they can be references.
- return ref_n_str_cmp(x, y)
- if type(x) not in [list, dict]:
- # if it is not list or dict or string then simply compare the values
- return x == y
- if type(x) == list:
- # should compare each item in the list and that should match
- if len(x) != len(y):
- log.debug('x has %d items y has %d', len(x), len(y))
- return False
- for i in zip(x, y):
- if not avi_obj_cmp(i[0], i[1], sensitive_fields=sensitive_fields):
- # no need to continue
- return False
-
- if type(x) == dict:
- x.pop('_last_modified', None)
- x.pop('tenant', None)
- y.pop('_last_modified', None)
- x.pop('api_version', None)
- y.pop('api_verison', None)
- d_xks = [k for k in x.keys() if k in sensitive_fields]
-
- if d_xks:
- # if there is sensitive field then always return changed
- return False
- # pop the keys that are marked deleted but not present in y
- # return false if item is marked absent and is present in y
- d_x_absent_ks = []
- for k, v in x.items():
- if v is None:
- d_x_absent_ks.append(k)
- continue
- if isinstance(v, dict):
- if ('state' in v) and (v['state'] == 'absent'):
- if type(y) == dict and k not in y:
- d_x_absent_ks.append(k)
- else:
- return False
- elif not v:
- d_x_absent_ks.append(k)
- elif isinstance(v, list) and not v:
- d_x_absent_ks.append(k)
- # Added condition to check key in dict.
- elif isinstance(v, str) or (k in y and isinstance(y[k], str)):
- # this is the case when ansible converts the dictionary into a
- # string.
- if v == "{'state': 'absent'}" and k not in y:
- d_x_absent_ks.append(k)
- elif not v and k not in y:
- # this is the case when x has set the value that qualifies
- # as not but y does not have that value
- d_x_absent_ks.append(k)
- for k in d_x_absent_ks:
- x.pop(k)
- x_keys = set(x.keys())
- y_keys = set(y.keys())
- if not x_keys.issubset(y_keys):
- # log.debug('x has %s and y has %s keys', len(x_keys), len(y_keys))
- return False
- for k, v in x.items():
- if k not in y:
- # log.debug('k %s is not in y %s', k, y)
- return False
- if not avi_obj_cmp(v, y[k], sensitive_fields=sensitive_fields):
- # log.debug('k %s v %s did not match in y %s', k, v, y[k])
- return False
- return True
-
-
-POP_FIELDS = ['state', 'controller', 'username', 'password', 'api_version',
- 'avi_credentials', 'avi_api_update_method', 'avi_api_patch_op',
- 'api_context', 'tenant', 'tenant_uuid', 'avi_disable_session_cache_as_fact']
-
-
-def get_api_context(module, api_creds):
- api_context = module.params.get('api_context')
- if api_context and module.params.get('avi_disable_session_cache_as_fact'):
- return api_context
- elif api_context and not module.params.get(
- 'avi_disable_session_cache_as_fact'):
- key = '%s:%s:%s' % (api_creds.controller, api_creds.username,
- api_creds.port)
- return api_context.get(key)
- else:
- return None
-
-
-def avi_ansible_api(module, obj_type, sensitive_fields):
- """
- This converts the Ansible module into AVI object and invokes APIs
- :param module: Ansible module
- :param obj_type: string representing Avi object type
- :param sensitive_fields: sensitive fields to be excluded for comparison
- purposes.
- Returns:
- success: module.exit_json with obj=avi object
- faliure: module.fail_json
- """
-
- api_creds = AviCredentials()
- api_creds.update_from_ansible_module(module)
- api_context = get_api_context(module, api_creds)
- if api_context:
- api = ApiSession.get_session(
- api_creds.controller,
- api_creds.username,
- password=api_creds.password,
- timeout=api_creds.timeout,
- tenant=api_creds.tenant,
- tenant_uuid=api_creds.tenant_uuid,
- token=api_context['csrftoken'],
- port=api_creds.port,
- session_id=api_context['session_id'],
- csrftoken=api_context['csrftoken'])
- else:
- api = ApiSession.get_session(
- api_creds.controller,
- api_creds.username,
- password=api_creds.password,
- timeout=api_creds.timeout,
- tenant=api_creds.tenant,
- tenant_uuid=api_creds.tenant_uuid,
- token=api_creds.token,
- port=api_creds.port)
- state = module.params['state']
- # Get the api version.
- avi_update_method = module.params.get('avi_api_update_method', 'put')
- avi_patch_op = module.params.get('avi_api_patch_op', 'add')
-
- api_version = api_creds.api_version
- name = module.params.get('name', None)
- # Added Support to get uuid
- uuid = module.params.get('uuid', None)
- check_mode = module.check_mode
- if uuid and obj_type != 'cluster':
- obj_path = '%s/%s' % (obj_type, uuid)
- else:
- obj_path = '%s/' % obj_type
- obj = deepcopy(module.params)
- tenant = obj.pop('tenant', '')
- tenant_uuid = obj.pop('tenant_uuid', '')
- # obj.pop('cloud_ref', None)
- for k in POP_FIELDS:
- obj.pop(k, None)
- purge_optional_fields(obj, module)
-
- # Special code to handle situation where object has a field
- # named username. This is used in case of api/user
- # The following code copies the username and password
- # from the obj_username and obj_password fields.
- if 'obj_username' in obj:
- obj['username'] = obj['obj_username']
- obj.pop('obj_username')
- if 'obj_password' in obj:
- obj['password'] = obj['obj_password']
- obj.pop('obj_password')
- if 'full_name' not in obj and 'name' in obj and obj_type == "user":
- obj['full_name'] = obj['name']
- # Special case as name represent full_name in user module
- # As per API response, name is always same as username regardless of full_name
- obj['name'] = obj['username']
-
- log.info('passed object %s ', obj)
-
- if uuid:
- # Get the object based on uuid.
- try:
- existing_obj = api.get(
- obj_path, tenant=tenant, tenant_uuid=tenant_uuid,
- params={'include_refs': '', 'include_name': ''},
- api_version=api_version)
- existing_obj = existing_obj.json()
- except ObjectNotFound:
- existing_obj = None
- elif name:
- params = {'include_refs': '', 'include_name': ''}
- if obj.get('cloud_ref', None):
- # this is the case when gets have to be scoped with cloud
- cloud = obj['cloud_ref'].split('name=')[1]
- params['cloud_ref.name'] = cloud
- existing_obj = api.get_object_by_name(
- obj_type, name, tenant=tenant, tenant_uuid=tenant_uuid,
- params=params, api_version=api_version)
-
- # Need to check if tenant_ref was provided and the object returned
- # is actually in admin tenant.
- if existing_obj and 'tenant_ref' in obj and 'tenant_ref' in existing_obj:
- # https://10.10.25.42/api/tenant/admin#admin
- existing_obj_tenant = existing_obj['tenant_ref'].split('#')[1]
- obj_tenant = obj['tenant_ref'].split('name=')[1]
- if obj_tenant != existing_obj_tenant:
- existing_obj = None
- else:
- # added api version to avi api call.
- existing_obj = api.get(obj_path, tenant=tenant, tenant_uuid=tenant_uuid,
- params={'include_refs': '', 'include_name': ''},
- api_version=api_version).json()
-
- if state == 'absent':
- rsp = None
- changed = False
- err = False
- if not check_mode and existing_obj:
- try:
- if name is not None:
- # added api version to avi api call.
- rsp = api.delete_by_name(
- obj_type, name, tenant=tenant, tenant_uuid=tenant_uuid,
- api_version=api_version)
- else:
- # added api version to avi api call.
- rsp = api.delete(
- obj_path, tenant=tenant, tenant_uuid=tenant_uuid,
- api_version=api_version)
- except ObjectNotFound:
- pass
- if check_mode and existing_obj:
- changed = True
-
- if rsp:
- if rsp.status_code == 204:
- changed = True
- else:
- err = True
- if not err:
- return ansible_return(
- module, rsp, changed, existing_obj=existing_obj,
- api_context=api.get_context())
- elif rsp:
- return module.fail_json(msg=rsp.text)
-
- rsp = None
- req = None
- if existing_obj:
- # this is case of modify as object exists. should find out
- # if changed is true or not
- if name is not None and obj_type != 'cluster':
- obj_uuid = existing_obj['uuid']
- obj_path = '%s/%s' % (obj_type, obj_uuid)
- if avi_update_method == 'put':
- changed = not avi_obj_cmp(obj, existing_obj, sensitive_fields)
- obj = cleanup_absent_fields(obj)
- if changed:
- req = obj
- if check_mode:
- # No need to process any further.
- rsp = AviCheckModeResponse(obj=existing_obj)
- else:
- rsp = api.put(
- obj_path, data=req, tenant=tenant,
- tenant_uuid=tenant_uuid, api_version=api_version)
- elif check_mode:
- rsp = AviCheckModeResponse(obj=existing_obj)
- else:
- if check_mode:
- # No need to process any further.
- rsp = AviCheckModeResponse(obj=existing_obj)
- changed = True
- else:
- obj.pop('name', None)
- patch_data = {avi_patch_op: obj}
- rsp = api.patch(
- obj_path, data=patch_data, tenant=tenant,
- tenant_uuid=tenant_uuid, api_version=api_version)
- obj = rsp.json()
- changed = not avi_obj_cmp(obj, existing_obj)
- if changed:
- log.debug('EXISTING OBJ %s', existing_obj)
- log.debug('NEW OBJ %s', obj)
- else:
- changed = True
- req = obj
- if check_mode:
- rsp = AviCheckModeResponse(obj=None)
- else:
- rsp = api.post(obj_type, data=obj, tenant=tenant,
- tenant_uuid=tenant_uuid, api_version=api_version)
- return ansible_return(module, rsp, changed, req, existing_obj=existing_obj,
- api_context=api.get_context())
-
-
-def avi_common_argument_spec():
- """
- Returns common arguments for all Avi modules
- :return: dict
- """
- credentials_spec = dict(
- controller=dict(fallback=(env_fallback, ['AVI_CONTROLLER'])),
- username=dict(fallback=(env_fallback, ['AVI_USERNAME'])),
- password=dict(fallback=(env_fallback, ['AVI_PASSWORD']), no_log=True),
- api_version=dict(default='16.4.4', type='str'),
- tenant=dict(default='admin'),
- tenant_uuid=dict(default='', type='str'),
- port=dict(type='int'),
- timeout=dict(default=300, type='int'),
- token=dict(default='', type='str', no_log=True),
- session_id=dict(default='', type='str', no_log=True),
- csrftoken=dict(default='', type='str', no_log=True)
- )
-
- return dict(
- controller=dict(fallback=(env_fallback, ['AVI_CONTROLLER'])),
- username=dict(fallback=(env_fallback, ['AVI_USERNAME'])),
- password=dict(fallback=(env_fallback, ['AVI_PASSWORD']), no_log=True),
- tenant=dict(default='admin'),
- tenant_uuid=dict(default=''),
- api_version=dict(default='16.4.4', type='str'),
- avi_credentials=dict(default=None, type='dict',
- options=credentials_spec),
- api_context=dict(type='dict'),
- avi_disable_session_cache_as_fact=dict(default=False, type='bool'))
diff --git a/plugins/module_utils/network/avi/avi.py b/plugins/module_utils/network/avi/avi.py
deleted file mode 100644
index 04cb4157f4..0000000000
--- a/plugins/module_utils/network/avi/avi.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# Copyright (c), Gaurav Rastogi , 2017
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# This module initially matched the namespace of network module avi. However,
-# that causes namespace import error when other modules from avi namespaces
-# are imported. Added import of absolute_import to avoid import collisions for
-# avi.sdk.
-
-from __future__ import absolute_import
-
-from ansible_collections.community.general.plugins.module_utils.network.avi.ansible_utils import (
- avi_ansible_api, avi_common_argument_spec, ansible_return,
- avi_obj_cmp, cleanup_absent_fields, AviCheckModeResponse, HAS_AVI)
diff --git a/plugins/module_utils/network/avi/avi_api.py b/plugins/module_utils/network/avi/avi_api.py
deleted file mode 100644
index 817f909dd0..0000000000
--- a/plugins/module_utils/network/avi/avi_api.py
+++ /dev/null
@@ -1,972 +0,0 @@
-from __future__ import absolute_import
-import os
-import sys
-import copy
-import json
-import logging
-import time
-from datetime import datetime, timedelta
-from ssl import SSLError
-
-
-class MockResponse(object):
- def __init__(self, *args, **kwargs):
- raise Exception("Requests library Response object not found. Using fake one.")
-
-
-class MockRequestsConnectionError(Exception):
- pass
-
-
-class MockSession(object):
- def __init__(self, *args, **kwargs):
- raise Exception("Requests library Session object not found. Using fake one.")
-
-
-HAS_AVI = True
-try:
- from requests import ConnectionError as RequestsConnectionError
- from requests import Response
- from requests.sessions import Session
-except ImportError:
- HAS_AVI = False
- Response = MockResponse
- RequestsConnectionError = MockRequestsConnectionError
- Session = MockSession
-
-
-logger = logging.getLogger(__name__)
-
-sessionDict = {}
-
-
-def avi_timedelta(td):
- '''
- This is a wrapper class to workaround python 2.6 builtin datetime.timedelta
- does not have total_seconds method
- :param timedelta object
- '''
- if type(td) != timedelta:
- raise TypeError()
- if sys.version_info >= (2, 7):
- ts = td.total_seconds()
- else:
- ts = td.seconds + (24 * 3600 * td.days)
- return ts
-
-
-def avi_sdk_syslog_logger(logger_name='avi.sdk'):
- # The following sets up syslog module to log underlying avi SDK messages
- # based on the environment variables:
- # AVI_LOG_HANDLER: names the logging handler to use. Only syslog is
- # supported.
- # AVI_LOG_LEVEL: Logging level used for the avi SDK. Default is DEBUG
- # AVI_SYSLOG_ADDRESS: Destination address for the syslog handler.
- # Default is /dev/log
- from logging.handlers import SysLogHandler
- lf = '[%(asctime)s] %(levelname)s [%(module)s.%(funcName)s:%(lineno)d] %(message)s'
- log = logging.getLogger(logger_name)
- log_level = os.environ.get('AVI_LOG_LEVEL', 'DEBUG')
- if log_level:
- log.setLevel(getattr(logging, log_level))
- formatter = logging.Formatter(lf)
- sh = SysLogHandler(address=os.environ.get('AVI_SYSLOG_ADDRESS', '/dev/log'))
- sh.setFormatter(formatter)
- log.addHandler(sh)
- return log
-
-
-class ObjectNotFound(Exception):
- pass
-
-
-class APIError(Exception):
- def __init__(self, arg, rsp=None):
- self.args = [arg, rsp]
- self.rsp = rsp
-
-
-class AviServerError(APIError):
- def __init__(self, arg, rsp=None):
- super(AviServerError, self).__init__(arg, rsp)
-
-
-class APINotImplemented(Exception):
- pass
-
-
-class ApiResponse(Response):
- """
- Returns copy of the requests.Response object provides additional helper
- routines
- 1. obj: returns dictionary of Avi Object
- """
- def __init__(self, rsp):
- super(ApiResponse, self).__init__()
- for k, v in list(rsp.__dict__.items()):
- setattr(self, k, v)
-
- def json(self):
- """
- Extends the session default json interface to handle special errors
- and raise Exceptions
- returns the Avi object as a dictionary from rsp.text
- """
- if self.status_code in (200, 201):
- if not self.text:
- # In cases like status_code == 201 the response text could be
- # empty string.
- return None
- return super(ApiResponse, self).json()
- elif self.status_code == 204:
- # No response needed; e.g., delete operation
- return None
- elif self.status_code == 404:
- raise ObjectNotFound('HTTP Error: %s Error Msg %s' % (
- self.status_code, self.text), self)
- elif self.status_code >= 500:
- raise AviServerError('HTTP Error: %s Error Msg %s' % (
- self.status_code, self.text), self)
- else:
- raise APIError('HTTP Error: %s Error Msg %s' % (
- self.status_code, self.text), self)
-
- def count(self):
- """
- return the number of objects in the collection response. If it is not
- a collection response then it would simply return 1.
- """
- obj = self.json()
- if 'count' in obj:
- # this was a resposne to collection
- return obj['count']
- return 1
-
- @staticmethod
- def to_avi_response(resp):
- if type(resp) == Response:
- return ApiResponse(resp)
- return resp
-
-
-class AviCredentials(object):
- controller = ''
- username = ''
- password = ''
- api_version = '16.4.4'
- tenant = None
- tenant_uuid = None
- token = None
- port = None
- timeout = 300
- session_id = None
- csrftoken = None
-
- def __init__(self, **kwargs):
- for k, v in kwargs.items():
- setattr(self, k, v)
-
- def update_from_ansible_module(self, m):
- """
- :param m: ansible module
- :return:
- """
- if m.params.get('avi_credentials'):
- for k, v in m.params['avi_credentials'].items():
- if hasattr(self, k):
- setattr(self, k, v)
- if m.params['controller']:
- self.controller = m.params['controller']
- if m.params['username']:
- self.username = m.params['username']
- if m.params['password']:
- self.password = m.params['password']
- if (m.params['api_version'] and
- (m.params['api_version'] != '16.4.4')):
- self.api_version = m.params['api_version']
- if m.params['tenant']:
- self.tenant = m.params['tenant']
- if m.params['tenant_uuid']:
- self.tenant_uuid = m.params['tenant_uuid']
- if m.params.get('session_id'):
- self.session_id = m.params['session_id']
- if m.params.get('csrftoken'):
- self.csrftoken = m.params['csrftoken']
-
- def __str__(self):
- return 'controller %s user %s api %s tenant %s' % (
- self.controller, self.username, self.api_version, self.tenant)
-
-
-class ApiSession(Session):
- """
- Extends the Request library's session object to provide helper
- utilities to work with Avi Controller like authentication, api massaging
- etc.
- """
-
- # This keeps track of the process which created the cache.
- # At anytime the pid of the process changes then it would create
- # a new cache for that process.
- AVI_SLUG = 'Slug'
- SESSION_CACHE_EXPIRY = 20 * 60
- SHARED_USER_HDRS = ['X-CSRFToken', 'Session-Id', 'Referer', 'Content-Type']
- MAX_API_RETRIES = 3
-
- def __init__(self, controller_ip=None, username=None, password=None,
- token=None, tenant=None, tenant_uuid=None, verify=False,
- port=None, timeout=60, api_version=None,
- retry_conxn_errors=True, data_log=False,
- avi_credentials=None, session_id=None, csrftoken=None,
- lazy_authentication=False, max_api_retries=None):
- """
- ApiSession takes ownership of avi_credentials and may update the
- information inside it.
-
- Initialize new session object with authenticated token from login api.
- It also keeps a cache of user sessions that are cleaned up if inactive
- for more than 20 mins.
-
- Notes:
- 01. If mode is https and port is none or 443, we don't embed the
- port in the prefix. The prefix would be 'https://ip'. If port
- is a non-default value then we concatenate https://ip:port
- in the prefix.
- 02. If mode is http and the port is none or 80, we don't embed the
- port in the prefix. The prefix would be 'http://ip'. If port is
- a non-default value, then we concatenate http://ip:port in
- the prefix.
- """
- super(ApiSession, self).__init__()
- if not avi_credentials:
- tenant = tenant if tenant else "admin"
- self.avi_credentials = AviCredentials(
- controller=controller_ip, username=username, password=password,
- api_version=api_version, tenant=tenant, tenant_uuid=tenant_uuid,
- token=token, port=port, timeout=timeout,
- session_id=session_id, csrftoken=csrftoken)
- else:
- self.avi_credentials = avi_credentials
- self.headers = {}
- self.verify = verify
- self.retry_conxn_errors = retry_conxn_errors
- self.remote_api_version = {}
- self.session_cookie_name = ''
- self.user_hdrs = {}
- self.data_log = data_log
- self.num_session_retries = 0
- self.retry_wait_time = 0
- self.max_session_retries = (
- self.MAX_API_RETRIES if max_api_retries is None
- else int(max_api_retries))
- # Refer Notes 01 and 02
- k_port = port if port else 443
- if self.avi_credentials.controller.startswith('http'):
- k_port = 80 if not self.avi_credentials.port else k_port
- if self.avi_credentials.port is None or self.avi_credentials.port\
- == 80:
- self.prefix = self.avi_credentials.controller
- else:
- self.prefix = '{x}:{y}'.format(
- x=self.avi_credentials.controller,
- y=self.avi_credentials.port)
- else:
- if port is None or port == 443:
- self.prefix = 'https://{x}'.format(
- x=self.avi_credentials.controller)
- else:
- self.prefix = 'https://{x}:{y}'.format(
- x=self.avi_credentials.controller,
- y=self.avi_credentials.port)
- self.timeout = timeout
- self.key = '%s:%s:%s' % (self.avi_credentials.controller,
- self.avi_credentials.username, k_port)
- # Added api token and session id to sessionDict for handle single
- # session
- if self.avi_credentials.csrftoken:
- sessionDict[self.key] = {
- 'api': self,
- "csrftoken": self.avi_credentials.csrftoken,
- "session_id": self.avi_credentials.session_id,
- "last_used": datetime.utcnow()
- }
- elif lazy_authentication:
- sessionDict.get(self.key, {}).update(
- {'api': self, "last_used": datetime.utcnow()})
- else:
- self.authenticate_session()
-
- self.num_session_retries = 0
- self.pid = os.getpid()
- ApiSession._clean_inactive_sessions()
- return
-
- @property
- def controller_ip(self):
- return self.avi_credentials.controller
-
- @controller_ip.setter
- def controller_ip(self, controller_ip):
- self.avi_credentials.controller = controller_ip
-
- @property
- def username(self):
- return self.avi_credentials.username
-
- @property
- def connected(self):
- return sessionDict.get(self.key, {}).get('connected', False)
-
- @username.setter
- def username(self, username):
- self.avi_credentials.username = username
-
- @property
- def password(self):
- return self.avi_credentials.password
-
- @password.setter
- def password(self, password):
- self.avi_credentials.password = password
-
- @property
- def keystone_token(self):
- return sessionDict.get(self.key, {}).get('csrftoken', None)
-
- @keystone_token.setter
- def keystone_token(self, token):
- sessionDict[self.key]['csrftoken'] = token
-
- @property
- def tenant_uuid(self):
- self.avi_credentials.tenant_uuid
-
- @tenant_uuid.setter
- def tenant_uuid(self, tenant_uuid):
- self.avi_credentials.tenant_uuid = tenant_uuid
-
- @property
- def tenant(self):
- return self.avi_credentials.tenant
-
- @tenant.setter
- def tenant(self, tenant):
- if tenant:
- self.avi_credentials.tenant = tenant
- else:
- self.avi_credentials.tenant = 'admin'
-
- @property
- def port(self):
- self.avi_credentials.port
-
- @port.setter
- def port(self, port):
- self.avi_credentials.port = port
-
- @property
- def api_version(self):
- return self.avi_credentials.api_version
-
- @api_version.setter
- def api_version(self, api_version):
- self.avi_credentials.api_version = api_version
-
- @property
- def session_id(self):
- return sessionDict[self.key]['session_id']
-
- def get_context(self):
- return {
- 'session_id': sessionDict[self.key]['session_id'],
- 'csrftoken': sessionDict[self.key]['csrftoken']
- }
-
- @staticmethod
- def clear_cached_sessions():
- global sessionDict
- sessionDict = {}
-
- @staticmethod
- def get_session(
- controller_ip=None, username=None, password=None, token=None, tenant=None,
- tenant_uuid=None, verify=False, port=None, timeout=60,
- retry_conxn_errors=True, api_version=None, data_log=False,
- avi_credentials=None, session_id=None, csrftoken=None,
- lazy_authentication=False, max_api_retries=None):
- """
- returns the session object for same user and tenant
- calls init if session dose not exist and adds it to session cache
- :param controller_ip: controller IP address
- :param username:
- :param password:
- :param token: Token to use; example, a valid keystone token
- :param tenant: Name of the tenant on Avi Controller
- :param tenant_uuid: Don't specify tenant when using tenant_id
- :param port: Rest-API may use a different port other than 443
- :param timeout: timeout for API calls; Default value is 60 seconds
- :param retry_conxn_errors: retry on connection errors
- :param api_version: Controller API version
- """
- if not avi_credentials:
- tenant = tenant if tenant else "admin"
- avi_credentials = AviCredentials(
- controller=controller_ip, username=username, password=password,
- api_version=api_version, tenant=tenant, tenant_uuid=tenant_uuid,
- token=token, port=port, timeout=timeout,
- session_id=session_id, csrftoken=csrftoken)
-
- k_port = avi_credentials.port if avi_credentials.port else 443
- if avi_credentials.controller.startswith('http'):
- k_port = 80 if not avi_credentials.port else k_port
- key = '%s:%s:%s' % (avi_credentials.controller,
- avi_credentials.username, k_port)
- cached_session = sessionDict.get(key)
- if cached_session:
- user_session = cached_session['api']
- if not (user_session.avi_credentials.csrftoken or
- lazy_authentication):
- user_session.authenticate_session()
- else:
- user_session = ApiSession(
- controller_ip, username, password, token=token, tenant=tenant,
- tenant_uuid=tenant_uuid, verify=verify, port=port,
- timeout=timeout, retry_conxn_errors=retry_conxn_errors,
- api_version=api_version, data_log=data_log,
- avi_credentials=avi_credentials,
- lazy_authentication=lazy_authentication,
- max_api_retries=max_api_retries)
- ApiSession._clean_inactive_sessions()
- return user_session
-
- def reset_session(self):
- """
- resets and re-authenticates the current session.
- """
- sessionDict[self.key]['connected'] = False
- logger.info('resetting session for %s', self.key)
- self.user_hdrs = {}
- for k, v in self.headers.items():
- if k not in self.SHARED_USER_HDRS:
- self.user_hdrs[k] = v
- self.headers = {}
- self.authenticate_session()
-
- def authenticate_session(self):
- """
- Performs session authentication with Avi controller and stores
- session cookies and sets header options like tenant.
- """
- body = {"username": self.avi_credentials.username}
- if self.avi_credentials.password:
- body["password"] = self.avi_credentials.password
- elif self.avi_credentials.token:
- body["token"] = self.avi_credentials.token
- else:
- raise APIError("Neither user password or token provided")
- logger.debug('authenticating user %s prefix %s',
- self.avi_credentials.username, self.prefix)
- self.cookies.clear()
- err = None
- try:
- rsp = super(ApiSession, self).post(
- self.prefix + "/login", body, timeout=self.timeout, verify=self.verify)
-
- if rsp.status_code == 200:
- self.num_session_retries = 0
- self.remote_api_version = rsp.json().get('version', {})
- self.session_cookie_name = rsp.json().get('session_cookie_name', 'sessionid')
- self.headers.update(self.user_hdrs)
- if rsp.cookies and 'csrftoken' in rsp.cookies:
- csrftoken = rsp.cookies['csrftoken']
- sessionDict[self.key] = {
- 'csrftoken': csrftoken,
- 'session_id': rsp.cookies[self.session_cookie_name],
- 'last_used': datetime.utcnow(),
- 'api': self,
- 'connected': True
- }
- logger.debug("authentication success for user %s",
- self.avi_credentials.username)
- return
- # Check for bad request and invalid credentials response code
- elif rsp.status_code in [401, 403]:
- logger.error('Status Code %s msg %s', rsp.status_code, rsp.text)
- err = APIError('Status Code %s msg %s' % (
- rsp.status_code, rsp.text), rsp)
- raise err
- else:
- logger.error("Error status code %s msg %s", rsp.status_code,
- rsp.text)
- err = APIError('Status Code %s msg %s' % (
- rsp.status_code, rsp.text), rsp)
- except (RequestsConnectionError, SSLError) as e:
- if not self.retry_conxn_errors:
- raise
- logger.warning('Connection error retrying %s', e)
- err = e
- # comes here only if there was either exception or login was not
- # successful
- if self.retry_wait_time:
- time.sleep(self.retry_wait_time)
- self.num_session_retries += 1
- if self.num_session_retries > self.max_session_retries:
- self.num_session_retries = 0
- logger.error("giving up after %d retries connection failure %s",
- self.max_session_retries, True)
- ret_err = (
- err if err else APIError("giving up after %d retries connection failure %s" %
- (self.max_session_retries, True)))
- raise ret_err
- self.authenticate_session()
- return
-
- def _get_api_headers(self, tenant, tenant_uuid, timeout, headers,
- api_version):
- """
- returns the headers that are passed to the requests.Session api calls.
- """
- api_hdrs = copy.deepcopy(self.headers)
- api_hdrs.update({
- "Referer": self.prefix,
- "Content-Type": "application/json"
- })
- api_hdrs['timeout'] = str(timeout)
- if self.key in sessionDict and 'csrftoken' in sessionDict.get(self.key):
- api_hdrs['X-CSRFToken'] = sessionDict.get(self.key)['csrftoken']
- else:
- self.authenticate_session()
- api_hdrs['X-CSRFToken'] = sessionDict.get(self.key)['csrftoken']
- if api_version:
- api_hdrs['X-Avi-Version'] = api_version
- elif self.avi_credentials.api_version:
- api_hdrs['X-Avi-Version'] = self.avi_credentials.api_version
- if tenant:
- tenant_uuid = None
- elif tenant_uuid:
- tenant = None
- else:
- tenant = self.avi_credentials.tenant
- tenant_uuid = self.avi_credentials.tenant_uuid
- if tenant_uuid:
- api_hdrs.update({"X-Avi-Tenant-UUID": "%s" % tenant_uuid})
- api_hdrs.pop("X-Avi-Tenant", None)
- elif tenant:
- api_hdrs.update({"X-Avi-Tenant": "%s" % tenant})
- api_hdrs.pop("X-Avi-Tenant-UUID", None)
- # Override any user headers that were passed by users. We don't know
- # when the user had updated the user_hdrs
- if self.user_hdrs:
- api_hdrs.update(self.user_hdrs)
- if headers:
- # overwrite the headers passed via the API calls.
- api_hdrs.update(headers)
- return api_hdrs
-
- def _api(self, api_name, path, tenant, tenant_uuid, data=None,
- headers=None, timeout=None, api_version=None, **kwargs):
- """
- It calls the requests.Session APIs and handles session expiry
- and other situations where session needs to be reset.
- returns ApiResponse object
- :param path: takes relative path to the AVI api.
- :param tenant: overrides the tenant used during session creation
- :param tenant_uuid: overrides the tenant or tenant_uuid during session
- creation
- :param timeout: timeout for API calls; Default value is 60 seconds
- :param headers: dictionary of headers that override the session
- headers.
- """
- if self.pid != os.getpid():
- logger.info('pid %d change detected new %d. Closing session',
- self.pid, os.getpid())
- self.close()
- self.pid = os.getpid()
- if timeout is None:
- timeout = self.timeout
- fullpath = self._get_api_path(path)
- fn = getattr(super(ApiSession, self), api_name)
- api_hdrs = self._get_api_headers(tenant, tenant_uuid, timeout, headers,
- api_version)
- connection_error = False
- err = None
- cookies = {
- 'csrftoken': api_hdrs['X-CSRFToken'],
- }
- try:
- if self.session_cookie_name:
- cookies[self.session_cookie_name] = sessionDict[self.key]['session_id']
- except KeyError:
- pass
- try:
- if (data is not None) and (type(data) == dict):
- resp = fn(fullpath, data=json.dumps(data), headers=api_hdrs,
- timeout=timeout, cookies=cookies, **kwargs)
- else:
- resp = fn(fullpath, data=data, headers=api_hdrs,
- timeout=timeout, cookies=cookies, **kwargs)
- except (RequestsConnectionError, SSLError) as e:
- logger.warning('Connection error retrying %s', e)
- if not self.retry_conxn_errors:
- raise
- connection_error = True
- err = e
- except Exception as e:
- logger.error('Error in Requests library %s', e)
- raise
- if not connection_error:
- logger.debug('path: %s http_method: %s hdrs: %s params: '
- '%s data: %s rsp: %s', fullpath, api_name.upper(),
- api_hdrs, kwargs, data,
- (resp.text if self.data_log else 'None'))
- if connection_error or resp.status_code in (401, 419):
- if connection_error:
- try:
- self.close()
- except Exception:
- # ignoring exception in cleanup path
- pass
- logger.warning('Connection failed, retrying.')
- # Adding sleep before retrying
- if self.retry_wait_time:
- time.sleep(self.retry_wait_time)
- else:
- logger.info('received error %d %s so resetting connection',
- resp.status_code, resp.text)
- ApiSession.reset_session(self)
- self.num_session_retries += 1
- if self.num_session_retries > self.max_session_retries:
- # Added this such that any code which re-tries can succeed
- # eventually.
- self.num_session_retries = 0
- if not connection_error:
- err = APIError('Status Code %s msg %s' % (
- resp.status_code, resp.text), resp)
- logger.error(
- "giving up after %d retries conn failure %s err %s",
- self.max_session_retries, connection_error, err)
- ret_err = (
- err if err else APIError("giving up after %d retries connection failure %s" %
- (self.max_session_retries, True)))
- raise ret_err
- # should restore the updated_hdrs to one passed down
- resp = self._api(api_name, path, tenant, tenant_uuid, data,
- headers=headers, api_version=api_version,
- timeout=timeout, **kwargs)
- self.num_session_retries = 0
-
- if resp.cookies and 'csrftoken' in resp.cookies:
- csrftoken = resp.cookies['csrftoken']
- self.headers.update({"X-CSRFToken": csrftoken})
- self._update_session_last_used()
- return ApiResponse.to_avi_response(resp)
-
- def get_controller_details(self):
- result = {
- "controller_ip": self.controller_ip,
- "controller_api_version": self.remote_api_version
- }
- return result
-
- def get(self, path, tenant='', tenant_uuid='', timeout=None, params=None,
- api_version=None, **kwargs):
- """
- It extends the Session Library interface to add AVI API prefixes,
- handle session exceptions related to authentication and update
- the global user session cache.
- :param path: takes relative path to the AVI api.
- :param tenant: overrides the tenant used during session creation
- :param tenant_uuid: overrides the tenant or tenant_uuid during session
- creation
- :param timeout: timeout for API calls; Default value is 60 seconds
- :param params: dictionary of key value pairs to be sent as query
- parameters
- :param api_version: overrides x-avi-header in request header during
- session creation
- get method takes relative path to service and kwargs as per Session
- class get method
- returns session's response object
- """
- return self._api('get', path, tenant, tenant_uuid, timeout=timeout,
- params=params, api_version=api_version, **kwargs)
-
- def get_object_by_name(self, path, name, tenant='', tenant_uuid='',
- timeout=None, params=None, api_version=None,
- **kwargs):
- """
- Helper function to access Avi REST Objects using object
- type and name. It behaves like python dictionary interface where it
- returns None when the object is not present in the AviController.
- Internally, it transforms the request to api/path?name=...
- :param path: relative path to service
- :param name: name of the object
- :param tenant: overrides the tenant used during session creation
- :param tenant_uuid: overrides the tenant or tenant_uuid during session
- creation
- :param timeout: timeout for API calls; Default value is 60 seconds
- :param params: dictionary of key value pairs to be sent as query
- parameters
- :param api_version: overrides x-avi-header in request header during
- session creation
- returns dictionary object if successful else None
- """
- obj = None
- if not params:
- params = {}
- params['name'] = name
- resp = self.get(path, tenant=tenant, tenant_uuid=tenant_uuid,
- timeout=timeout,
- params=params, api_version=api_version, **kwargs)
- if resp.status_code in (401, 419):
- ApiSession.reset_session(self)
- resp = self.get_object_by_name(
- path, name, tenant, tenant_uuid, timeout=timeout,
- params=params, **kwargs)
- if resp.status_code > 499 or 'Invalid version' in resp.text:
- logger.error('Error in get object by name for %s named %s. '
- 'Error: %s', path, name, resp.text)
- raise AviServerError(resp.text, rsp=resp)
- elif resp.status_code > 299:
- return obj
- try:
- if 'results' in resp.json():
- obj = resp.json()['results'][0]
- else:
- # For apis returning single object eg. api/cluster
- obj = resp.json()
- except IndexError:
- logger.warning('Warning: Object Not found for %s named %s',
- path, name)
- obj = None
- self._update_session_last_used()
- return obj
-
- def post(self, path, data=None, tenant='', tenant_uuid='', timeout=None,
- force_uuid=None, params=None, api_version=None, **kwargs):
- """
- It extends the Session Library interface to add AVI API prefixes,
- handle session exceptions related to authentication and update
- the global user session cache.
- :param path: takes relative path to the AVI api.It is modified by
- the library to conform to AVI Controller's REST API interface
- :param data: dictionary of the data. Support for json string
- is deprecated
- :param tenant: overrides the tenant used during session creation
- :param tenant_uuid: overrides the tenant or tenant_uuid during session
- creation
- :param timeout: timeout for API calls; Default value is 60 seconds
- :param params: dictionary of key value pairs to be sent as query
- parameters
- :param api_version: overrides x-avi-header in request header during
- session creation
- returns session's response object
- """
- if force_uuid is not None:
- headers = kwargs.get('headers', {})
- headers[self.AVI_SLUG] = force_uuid
- kwargs['headers'] = headers
- return self._api('post', path, tenant, tenant_uuid, data=data,
- timeout=timeout, params=params,
- api_version=api_version, **kwargs)
-
- def put(self, path, data=None, tenant='', tenant_uuid='',
- timeout=None, params=None, api_version=None, **kwargs):
- """
- It extends the Session Library interface to add AVI API prefixes,
- handle session exceptions related to authentication and update
- the global user session cache.
- :param path: takes relative path to the AVI api.It is modified by
- the library to conform to AVI Controller's REST API interface
- :param data: dictionary of the data. Support for json string
- is deprecated
- :param tenant: overrides the tenant used during session creation
- :param tenant_uuid: overrides the tenant or tenant_uuid during session
- creation
- :param timeout: timeout for API calls; Default value is 60 seconds
- :param params: dictionary of key value pairs to be sent as query
- parameters
- :param api_version: overrides x-avi-header in request header during
- session creation
- returns session's response object
- """
- return self._api('put', path, tenant, tenant_uuid, data=data,
- timeout=timeout, params=params,
- api_version=api_version, **kwargs)
-
- def patch(self, path, data=None, tenant='', tenant_uuid='',
- timeout=None, params=None, api_version=None, **kwargs):
- """
- It extends the Session Library interface to add AVI API prefixes,
- handle session exceptions related to authentication and update
- the global user session cache.
- :param path: takes relative path to the AVI api.It is modified by
- the library to conform to AVI Controller's REST API interface
- :param data: dictionary of the data. Support for json string
- is deprecated
- :param tenant: overrides the tenant used during session creation
- :param tenant_uuid: overrides the tenant or tenant_uuid during session
- creation
- :param timeout: timeout for API calls; Default value is 60 seconds
- :param params: dictionary of key value pairs to be sent as query
- parameters
- :param api_version: overrides x-avi-header in request header during
- session creation
- returns session's response object
- """
- return self._api('patch', path, tenant, tenant_uuid, data=data,
- timeout=timeout, params=params,
- api_version=api_version, **kwargs)
-
- def put_by_name(self, path, name, data=None, tenant='',
- tenant_uuid='', timeout=None, params=None,
- api_version=None, **kwargs):
- """
- Helper function to perform HTTP PUT on Avi REST Objects using object
- type and name.
- Internally, it transforms the request to api/path?name=...
- :param path: relative path to service
- :param name: name of the object
- :param data: dictionary of the data. Support for json string
- is deprecated
- :param tenant: overrides the tenant used during session creation
- :param tenant_uuid: overrides the tenant or tenant_uuid during session
- creation
- :param timeout: timeout for API calls; Default value is 60 seconds
- :param params: dictionary of key value pairs to be sent as query
- parameters
- :param api_version: overrides x-avi-header in request header during
- session creation
- returns session's response object
- """
- uuid = self._get_uuid_by_name(
- path, name, tenant, tenant_uuid, api_version=api_version)
- path = '%s/%s' % (path, uuid)
- return self.put(path, data, tenant, tenant_uuid, timeout=timeout,
- params=params, api_version=api_version, **kwargs)
-
- def delete(self, path, tenant='', tenant_uuid='', timeout=None, params=None,
- data=None, api_version=None, **kwargs):
- """
- It extends the Session Library interface to add AVI API prefixes,
- handle session exceptions related to authentication and update
- the global user session cache.
- :param path: takes relative path to the AVI api.It is modified by
- the library to conform to AVI Controller's REST API interface
- :param tenant: overrides the tenant used during session creation
- :param tenant_uuid: overrides the tenant or tenant_uuid during session
- creation
- :param timeout: timeout for API calls; Default value is 60 seconds
- :param params: dictionary of key value pairs to be sent as query
- parameters
- :param data: dictionary of the data. Support for json string
- is deprecated
- :param api_version: overrides x-avi-header in request header during
- session creation
- returns session's response object
- """
- return self._api('delete', path, tenant, tenant_uuid, data=data,
- timeout=timeout, params=params,
- api_version=api_version, **kwargs)
-
- def delete_by_name(self, path, name, tenant='', tenant_uuid='',
- timeout=None, params=None, api_version=None, **kwargs):
- """
- Helper function to perform HTTP DELETE on Avi REST Objects using object
- type and name.Internally, it transforms the request to
- api/path?name=...
- :param path: relative path to service
- :param name: name of the object
- :param tenant: overrides the tenant used during session creation
- :param tenant_uuid: overrides the tenant or tenant_uuid during session
- creation
- :param timeout: timeout for API calls; Default value is 60 seconds
- :param params: dictionary of key value pairs to be sent as query
- parameters
- :param api_version: overrides x-avi-header in request header during
- session creation
- returns session's response object
- """
- uuid = self._get_uuid_by_name(path, name, tenant, tenant_uuid,
- api_version=api_version)
- if not uuid:
- raise ObjectNotFound("%s/?name=%s" % (path, name))
- path = '%s/%s' % (path, uuid)
- return self.delete(path, tenant, tenant_uuid, timeout=timeout,
- params=params, api_version=api_version, **kwargs)
-
- def get_obj_ref(self, obj):
- """returns reference url from dict object"""
- if not obj:
- return None
- if isinstance(obj, Response):
- obj = json.loads(obj.text)
- if obj.get(0, None):
- return obj[0]['url']
- elif obj.get('url', None):
- return obj['url']
- elif obj.get('results', None):
- return obj['results'][0]['url']
- else:
- return None
-
- def get_obj_uuid(self, obj):
- """returns uuid from dict object"""
- if not obj:
- raise ObjectNotFound('Object %s Not found' % (obj))
- if isinstance(obj, Response):
- obj = json.loads(obj.text)
- if obj.get(0, None):
- return obj[0]['uuid']
- elif obj.get('uuid', None):
- return obj['uuid']
- elif obj.get('results', None):
- return obj['results'][0]['uuid']
- else:
- return None
-
- def _get_api_path(self, path, uuid=None):
- """
- This function returns the full url from relative path and uuid.
- """
- if path == 'logout':
- return self.prefix + '/' + path
- elif uuid:
- return self.prefix + '/api/' + path + '/' + uuid
- else:
- return self.prefix + '/api/' + path
-
- def _get_uuid_by_name(self, path, name, tenant='admin',
- tenant_uuid='', api_version=None):
- """gets object by name and service path and returns uuid"""
- resp = self.get_object_by_name(
- path, name, tenant, tenant_uuid, api_version=api_version)
- if not resp:
- raise ObjectNotFound("%s/%s" % (path, name))
- return self.get_obj_uuid(resp)
-
- def _update_session_last_used(self):
- if self.key in sessionDict:
- sessionDict[self.key]["last_used"] = datetime.utcnow()
-
- @staticmethod
- def _clean_inactive_sessions():
- """Removes sessions which are inactive more than 20 min"""
- session_cache = sessionDict
- logger.debug("cleaning inactive sessions in pid %d num elem %d",
- os.getpid(), len(session_cache))
- keys_to_delete = []
- for key, session in list(session_cache.items()):
- tdiff = avi_timedelta(datetime.utcnow() - session["last_used"])
- if tdiff < ApiSession.SESSION_CACHE_EXPIRY:
- continue
- keys_to_delete.append(key)
- for key in keys_to_delete:
- del session_cache[key]
- logger.debug("Removed session for : %s", key)
-
- def delete_session(self):
- """ Removes the session for cleanup"""
- logger.debug("Removed session for : %s", self.key)
- sessionDict.pop(self.key, None)
- return
-# End of file
diff --git a/plugins/module_utils/network/bigswitch/__init__.py b/plugins/module_utils/network/bigswitch/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/bigswitch/bigswitch.py b/plugins/module_utils/network/bigswitch/bigswitch.py
deleted file mode 100644
index 299fcd3310..0000000000
--- a/plugins/module_utils/network/bigswitch/bigswitch.py
+++ /dev/null
@@ -1,91 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# (c) 2016, Ted Elhourani
-#
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import json
-
-from ansible.module_utils.urls import fetch_url
-
-
-class Response(object):
-
- def __init__(self, resp, info):
- self.body = None
- if resp:
- self.body = resp.read()
- self.info = info
-
- @property
- def json(self):
- if not self.body:
- if "body" in self.info:
- return json.loads(self.info["body"])
- return None
- try:
- return json.loads(self.body)
- except ValueError:
- return None
-
- @property
- def status_code(self):
- return self.info["status"]
-
-
-class Rest(object):
-
- def __init__(self, module, headers, baseurl):
- self.module = module
- self.headers = headers
- self.baseurl = baseurl
-
- def _url_builder(self, path):
- if path[0] == '/':
- path = path[1:]
- return '%s/%s' % (self.baseurl, path)
-
- def send(self, method, path, data=None, headers=None):
- url = self._url_builder(path)
- data = self.module.jsonify(data)
-
- resp, info = fetch_url(self.module, url, data=data, headers=self.headers, method=method)
-
- return Response(resp, info)
-
- def get(self, path, data=None, headers=None):
- return self.send('GET', path, data, headers)
-
- def put(self, path, data=None, headers=None):
- return self.send('PUT', path, data, headers)
-
- def post(self, path, data=None, headers=None):
- return self.send('POST', path, data, headers)
-
- def patch(self, path, data=None, headers=None):
- return self.send('PATCH', path, data, headers)
-
- def delete(self, path, data=None, headers=None):
- return self.send('DELETE', path, data, headers)
diff --git a/plugins/module_utils/network/checkpoint/__init__.py b/plugins/module_utils/network/checkpoint/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/cloudengine/__init__.py b/plugins/module_utils/network/cloudengine/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/cloudengine/ce.py b/plugins/module_utils/network/cloudengine/ce.py
deleted file mode 100644
index b9fe91ff3c..0000000000
--- a/plugins/module_utils/network/cloudengine/ce.py
+++ /dev/null
@@ -1,421 +0,0 @@
-#
-# This code is part of Ansible, but is an independent component.
-#
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# (c) 2017 Red Hat, Inc.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-import re
-import socket
-import sys
-import traceback
-
-from ansible.module_utils.basic import env_fallback
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList
-from ansible.module_utils.connection import exec_command, ConnectionError
-from ansible.module_utils.six import iteritems
-from ansible.module_utils._text import to_native
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.netconf import NetconfConnection
-
-
-try:
- from ncclient.xml_ import to_xml, new_ele_ns
- HAS_NCCLIENT = True
-except ImportError:
- HAS_NCCLIENT = False
-
-
-try:
- from lxml import etree
-except ImportError:
- from xml.etree import ElementTree as etree
-
-_DEVICE_CLI_CONNECTION = None
-_DEVICE_NC_CONNECTION = None
-
-ce_provider_spec = {
- 'host': dict(),
- 'port': dict(type='int'),
- 'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
- 'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True),
- 'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
- 'use_ssl': dict(type='bool'),
- 'validate_certs': dict(type='bool'),
- 'timeout': dict(type='int'),
- 'transport': dict(default='cli', choices=['cli', 'netconf']),
-}
-ce_argument_spec = {
- 'provider': dict(type='dict', options=ce_provider_spec),
-}
-ce_top_spec = {
- 'host': dict(removed_in_version=2.9),
- 'port': dict(removed_in_version=2.9, type='int'),
- 'username': dict(removed_in_version=2.9),
- 'password': dict(removed_in_version=2.9, no_log=True),
- 'ssh_keyfile': dict(removed_in_version=2.9, type='path'),
- 'use_ssl': dict(removed_in_version=2.9, type='bool'),
- 'validate_certs': dict(removed_in_version=2.9, type='bool'),
- 'timeout': dict(removed_in_version=2.9, type='int'),
- 'transport': dict(removed_in_version=2.9, choices=['cli', 'netconf']),
-}
-ce_argument_spec.update(ce_top_spec)
-
-
-def to_string(data):
- return re.sub(r'|>)', r' 2 and err[0] in ["<", "["] and err[-1] in [">", "]"]:
- continue
- err.strip('.,\r\n\t ')
- if err:
- msg.append(err)
-
- if cmd:
- msg.insert(0, "Command: %s" % cmd)
-
- return ", ".join(msg).capitalize() + "."
-
-
-def to_command(module, commands):
- default_output = 'text'
- transform = ComplexList(dict(
- command=dict(key=True),
- output=dict(default=default_output),
- prompt=dict(),
- answer=dict()
- ), module)
-
- commands = transform(to_list(commands))
-
- return commands
-
-
-def get_config(module, flags=None):
- flags = [] if flags is None else flags
-
- conn = get_connection(module)
- return conn.get_config(flags)
-
-
-def run_commands(module, commands, check_rc=True):
- conn = get_connection(module)
- return conn.run_commands(to_command(module, commands), check_rc)
-
-
-def load_config(module, config):
- """load_config"""
- conn = get_connection(module)
- return conn.load_config(config)
-
-
-def ce_unknown_host_cb(host, fingerprint):
- """ ce_unknown_host_cb """
-
- return True
-
-
-def get_nc_set_id(xml_str):
- """get netconf set-id value"""
-
- result = re.findall(r'= 0 and index >= len(xml_list):
- return None
- if index < 0 and abs(index) > len(xml_list):
- return None
-
- ele = xml_list[index]
- if not ele.replace(" ", ""):
- xml_list.pop(index)
- ele = None
- return ele
-
-
-def merge_nc_xml(xml1, xml2):
- """merge xml1 and xml2"""
-
- xml1_list = xml1.split("")[0].split("\n")
- xml2_list = xml2.split("")[1].split("\n")
-
- while True:
- xml1_ele1 = get_xml_line(xml1_list, -1)
- xml1_ele2 = get_xml_line(xml1_list, -2)
- xml2_ele1 = get_xml_line(xml2_list, 0)
- xml2_ele2 = get_xml_line(xml2_list, 1)
- if not xml1_ele1 or not xml1_ele2 or not xml2_ele1 or not xml2_ele2:
- return xml1
-
- if "xmlns" in xml2_ele1:
- xml2_ele1 = xml2_ele1.lstrip().split(" ")[0] + ">"
- if "xmlns" in xml2_ele2:
- xml2_ele2 = xml2_ele2.lstrip().split(" ")[0] + ">"
- if xml1_ele1.replace(" ", "").replace("/", "") == xml2_ele1.replace(" ", "").replace("/", ""):
- if xml1_ele2.replace(" ", "").replace("/", "") == xml2_ele2.replace(" ", "").replace("/", ""):
- xml1_list.pop()
- xml2_list.pop(0)
- else:
- break
- else:
- break
-
- return "\n".join(xml1_list + xml2_list)
-
-
-def get_nc_connection(module):
- global _DEVICE_NC_CONNECTION
- if not _DEVICE_NC_CONNECTION:
- load_params(module)
- conn = NetconfConnection(module._socket_path)
- _DEVICE_NC_CONNECTION = conn
- return _DEVICE_NC_CONNECTION
-
-
-def set_nc_config(module, xml_str):
- """ set_config """
-
- conn = get_nc_connection(module)
- try:
- out = conn.edit_config(target='running', config=xml_str, default_operation='merge',
- error_option='rollback-on-error')
- finally:
- # conn.unlock(target = 'candidate')
- pass
- return to_string(to_xml(out))
-
-
-def get_nc_next(module, xml_str):
- """ get_nc_next for exchange capability """
-
- conn = get_nc_connection(module)
- result = None
- if xml_str is not None:
- response = conn.get(xml_str, if_rpc_reply=True)
- result = response.find('./*')
- set_id = response.get('set-id')
- while True and set_id is not None:
- try:
- fetch_node = new_ele_ns('get-next', 'http://www.huawei.com/netconf/capability/base/1.0', {'set-id': set_id})
- next_xml = conn.dispatch_rpc(etree.tostring(fetch_node))
- if next_xml is not None:
- result.extend(next_xml.find('./*'))
- set_id = next_xml.get('set-id')
- except ConnectionError:
- break
- if result is not None:
- return etree.tostring(result)
- return result
-
-
-def get_nc_config(module, xml_str):
- """ get_config """
-
- conn = get_nc_connection(module)
- if xml_str is not None:
- response = conn.get(xml_str)
- else:
- return None
-
- return to_string(to_xml(response))
-
-
-def execute_nc_action(module, xml_str):
- """ huawei execute-action """
-
- conn = get_nc_connection(module)
- response = conn.execute_action(xml_str)
- return to_string(to_xml(response))
-
-
-def execute_nc_cli(module, xml_str):
- """ huawei execute-cli """
-
- if xml_str is not None:
- try:
- conn = get_nc_connection(module)
- out = conn.execute_nc_cli(command=xml_str)
- return to_string(to_xml(out))
- except Exception as exc:
- raise Exception(exc)
-
-
-def check_ip_addr(ipaddr):
- """ check ip address, Supports IPv4 and IPv6 """
-
- if not ipaddr or '\x00' in ipaddr:
- return False
-
- try:
- res = socket.getaddrinfo(ipaddr, 0, socket.AF_UNSPEC,
- socket.SOCK_STREAM,
- 0, socket.AI_NUMERICHOST)
- return bool(res)
- except socket.gaierror:
- err = sys.exc_info()[1]
- if err.args[0] == socket.EAI_NONAME:
- return False
- raise
diff --git a/plugins/module_utils/network/cnos/__init__.py b/plugins/module_utils/network/cnos/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/cnos/cnos.py b/plugins/module_utils/network/cnos/cnos.py
deleted file mode 100644
index ae12a9a22d..0000000000
--- a/plugins/module_utils/network/cnos/cnos.py
+++ /dev/null
@@ -1,660 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by
-# Ansible still belong to the author of the module, and may assign their own
-# license to the complete work.
-#
-# Copyright (C) 2017 Lenovo, Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# Contains utility methods
-# Lenovo Networking
-
-import time
-import socket
-import re
-import json
-try:
- from ansible_collections.community.general.plugins.module_utils.network.cnos import cnos_errorcodes
- from ansible_collections.community.general.plugins.module_utils.network.cnos import cnos_devicerules
- HAS_LIB = True
-except Exception:
- HAS_LIB = False
-from distutils.cmd import Command
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import env_fallback
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, EntityCollection
-from ansible.module_utils.connection import Connection, exec_command
-from ansible.module_utils.connection import ConnectionError
-
-_DEVICE_CONFIGS = {}
-_CONNECTION = None
-_VALID_USER_ROLES = ['network-admin', 'network-operator']
-
-cnos_provider_spec = {
- 'host': dict(),
- 'port': dict(type='int'),
- 'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
- 'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']),
- no_log=True),
- 'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']),
- type='path'),
- 'authorize': dict(fallback=(env_fallback, ['ANSIBLE_NET_AUTHORIZE']),
- type='bool'),
- 'auth_pass': dict(fallback=(env_fallback, ['ANSIBLE_NET_AUTH_PASS']),
- no_log=True),
- 'timeout': dict(type='int'),
- 'context': dict(),
- 'passwords': dict()
-}
-
-cnos_argument_spec = {
- 'provider': dict(type='dict', options=cnos_provider_spec),
-}
-
-command_spec = {
- 'command': dict(key=True),
- 'prompt': dict(),
- 'answer': dict(),
- 'check_all': dict()
-}
-
-
-def get_provider_argspec():
- return cnos_provider_spec
-
-
-def check_args(module, warnings):
- pass
-
-
-def get_user_roles():
- return _VALID_USER_ROLES
-
-
-def get_connection(module):
- global _CONNECTION
- if _CONNECTION:
- return _CONNECTION
- _CONNECTION = Connection(module._socket_path)
-
- context = None
- try:
- context = module.params['context']
- except KeyError:
- context = None
-
- if context:
- if context == 'system':
- command = 'changeto system'
- else:
- command = 'changeto context %s' % context
- _CONNECTION.get(command)
-
- return _CONNECTION
-
-
-def get_config(module, flags=None):
- flags = [] if flags is None else flags
-
- passwords = None
- try:
- passwords = module.params['passwords']
- except KeyError:
- passwords = None
- if passwords:
- cmd = 'more system:running-config'
- else:
- cmd = 'display running-config '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- try:
- return _DEVICE_CONFIGS[cmd]
- except KeyError:
- conn = get_connection(module)
- out = conn.get(cmd)
- cfg = to_text(out, errors='surrogate_then_replace').strip()
- _DEVICE_CONFIGS[cmd] = cfg
- return cfg
-
-
-def to_commands(module, commands):
- if not isinstance(commands, list):
- raise AssertionError('argument must be of type ')
-
- transform = EntityCollection(module, command_spec)
- commands = transform(commands)
-
- for index, item in enumerate(commands):
- if module.check_mode and not item['command'].startswith('show'):
- module.warn('only show commands are supported when using check '
- 'mode, not executing `%s`' % item['command'])
-
- return commands
-
-
-def run_commands(module, commands, check_rc=True):
- connection = get_connection(module)
- connection.get('enable')
- commands = to_commands(module, to_list(commands))
-
- responses = list()
-
- for cmd in commands:
- out = connection.get(**cmd)
- responses.append(to_text(out, errors='surrogate_then_replace'))
-
- return responses
-
-
-def run_cnos_commands(module, commands, check_rc=True):
- retVal = ''
- enter_config = {'command': 'configure terminal', 'prompt': None,
- 'answer': None}
- exit_config = {'command': 'end', 'prompt': None, 'answer': None}
- commands.insert(0, enter_config)
- commands.append(exit_config)
- for cmd in commands:
- retVal = retVal + '>> ' + cmd['command'] + '\n'
- try:
- responses = run_commands(module, commands, check_rc)
- for response in responses:
- retVal = retVal + '<< ' + response + '\n'
- except Exception as e:
- errMsg = ''
- if hasattr(e, 'message'):
- errMsg = e.message
- else:
- errMsg = str(e)
- # Exception in Exceptions
- if 'VLAN_ACCESS_MAP' in errMsg:
- return retVal + '<<' + errMsg + '\n'
- if 'confederation identifier' in errMsg:
- return retVal + '<<' + errMsg + '\n'
- # Add more here if required
- retVal = retVal + '<< ' + 'Error-101 ' + errMsg + '\n'
- return str(retVal)
-
-
-def get_capabilities(module):
- if hasattr(module, '_cnos_capabilities'):
- return module._cnos_capabilities
- try:
- capabilities = Connection(module._socket_path).get_capabilities()
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- module._cnos_capabilities = json.loads(capabilities)
- return module._cnos_capabilities
-
-
-def load_config(module, config):
- try:
- conn = get_connection(module)
- conn.get('enable')
- resp = conn.edit_config(config)
- return resp.get('response')
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
-
-
-def get_defaults_flag(module):
- rc, out, err = exec_command(module, 'display running-config ?')
- out = to_text(out, errors='surrogate_then_replace')
-
- commands = set()
- for line in out.splitlines():
- if line:
- commands.add(line.strip().split()[0])
-
- if 'all' in commands:
- return 'all'
- else:
- return 'full'
-
-
-def enterEnableModeForDevice(enablePassword, timeout, obj):
- command = "enable\n"
- pwdPrompt = "password:"
- # debugOutput(enablePassword)
- # debugOutput('\n')
- obj.settimeout(int(timeout))
- # Executing enable
- obj.send(command)
- flag = False
- retVal = ""
- count = 5
- while not flag:
- # If wait time is execeeded.
- if(count == 0):
- flag = True
- else:
- count = count - 1
- # A delay of one second
- time.sleep(1)
- try:
- buffByte = obj.recv(9999)
- buff = buffByte.decode()
- retVal = retVal + buff
- # debugOutput(buff)
- gotit = buff.find(pwdPrompt)
- if(gotit != -1):
- time.sleep(1)
- if(enablePassword is None or enablePassword == ""):
- return "\n Error-106"
- obj.send(enablePassword)
- obj.send("\r")
- obj.send("\n")
- time.sleep(1)
- innerBuffByte = obj.recv(9999)
- innerBuff = innerBuffByte.decode()
- retVal = retVal + innerBuff
- # debugOutput(innerBuff)
- innerGotit = innerBuff.find("#")
- if(innerGotit != -1):
- return retVal
- else:
- gotit = buff.find("#")
- if(gotit != -1):
- return retVal
- except Exception:
- retVal = retVal + "\n Error-101"
- flag = True
- if(retVal == ""):
- retVal = "\n Error-101"
- return retVal
-# EOM
-
-
-def waitForDeviceResponse(command, prompt, timeout, obj):
- obj.settimeout(int(timeout))
- obj.send(command)
- flag = False
- retVal = ""
- while not flag:
- time.sleep(1)
- try:
- buffByte = obj.recv(9999)
- buff = buffByte.decode()
- retVal = retVal + buff
- # debugOutput(retVal)
- gotit = buff.find(prompt)
- if(gotit != -1):
- flag = True
- except Exception:
- # debugOutput(prompt)
- if prompt == "(yes/no)?":
- pass
- elif prompt == "Password:":
- pass
- else:
- retVal = retVal + "\n Error-101"
- flag = True
- return retVal
-# EOM
-
-
-def checkOutputForError(output):
- retVal = ""
- index = output.lower().find('error')
- startIndex = index + 6
- if(index == -1):
- index = output.lower().find('invalid')
- startIndex = index + 8
- if(index == -1):
- index = output.lower().find('cannot be enabled in l2 interface')
- startIndex = index + 34
- if(index == -1):
- index = output.lower().find('incorrect')
- startIndex = index + 10
- if(index == -1):
- index = output.lower().find('failure')
- startIndex = index + 8
- if(index == -1):
- return None
-
- endIndex = startIndex + 3
- errorCode = output[startIndex:endIndex]
- result = errorCode.isdigit()
- if(result is not True):
- return "Device returned an Error. Please check Results for more \
- information"
-
- errorFile = "dictionary/ErrorCodes.lvo"
- try:
- # with open(errorFile, 'r') as f:
- f = open(errorFile, 'r')
- for line in f:
- if('=' in line):
- data = line.split('=')
- if(data[0].strip() == errorCode):
- errorString = data[1].strip()
- return errorString
- except Exception:
- errorString = cnos_errorcodes.getErrorString(errorCode)
- errorString = errorString.strip()
- return errorString
- return "Error Code Not Found"
-# EOM
-
-
-def checkSanityofVariable(deviceType, variableId, variableValue):
- retVal = ""
- ruleFile = "dictionary/" + deviceType + "_rules.lvo"
- ruleString = getRuleStringForVariable(deviceType, ruleFile, variableId)
- retVal = validateValueAgainstRule(ruleString, variableValue)
- return retVal
-# EOM
-
-
-def getRuleStringForVariable(deviceType, ruleFile, variableId):
- retVal = ""
- try:
- # with open(ruleFile, 'r') as f:
- f = open(ruleFile, 'r')
- for line in f:
- # debugOutput(line)
- if(':' in line):
- data = line.split(':')
- # debugOutput(data[0])
- if(data[0].strip() == variableId):
- retVal = line
- except Exception:
- ruleString = cnos_devicerules.getRuleString(deviceType, variableId)
- retVal = ruleString.strip()
- return retVal
-# EOM
-
-
-def validateValueAgainstRule(ruleString, variableValue):
-
- retVal = ""
- if(ruleString == ""):
- return 1
- rules = ruleString.split(':')
- variableType = rules[1].strip()
- varRange = rules[2].strip()
- if(variableType == "INTEGER"):
- result = checkInteger(variableValue)
- if(result is True):
- return "ok"
- else:
- return "Error-111"
- elif(variableType == "FLOAT"):
- result = checkFloat(variableValue)
- if(result is True):
- return "ok"
- else:
- return "Error-112"
-
- elif(variableType == "INTEGER_VALUE"):
- int_range = varRange.split('-')
- r = range(int(int_range[0].strip()), int(int_range[1].strip()))
- if(checkInteger(variableValue) is not True):
- return "Error-111"
- result = int(variableValue) in r
- if(result is True):
- return "ok"
- else:
- return "Error-113"
-
- elif(variableType == "INTEGER_VALUE_RANGE"):
- int_range = varRange.split('-')
- varLower = int_range[0].strip()
- varHigher = int_range[1].strip()
- r = range(int(varLower), int(varHigher))
- val_range = variableValue.split('-')
- try:
- valLower = val_range[0].strip()
- valHigher = val_range[1].strip()
- except Exception:
- return "Error-113"
- if((checkInteger(valLower) is not True) or
- (checkInteger(valHigher) is not True)):
- # debugOutput("Error-114")
- return "Error-114"
- result = (int(valLower) in r) and (int(valHigher)in r) \
- and (int(valLower) < int(valHigher))
- if(result is True):
- return "ok"
- else:
- # debugOutput("Error-113")
- return "Error-113"
-
- elif(variableType == "INTEGER_OPTIONS"):
- int_options = varRange.split(',')
- if(checkInteger(variableValue) is not True):
- return "Error-111"
- for opt in int_options:
- if(opt.strip() is variableValue):
- result = True
- break
- if(result is True):
- return "ok"
- else:
- return "Error-115"
-
- elif(variableType == "LONG"):
- result = checkLong(variableValue)
- if(result is True):
- return "ok"
- else:
- return "Error-116"
-
- elif(variableType == "LONG_VALUE"):
- long_range = varRange.split('-')
- r = range(int(long_range[0].strip()), int(long_range[1].strip()))
- if(checkLong(variableValue) is not True):
- # debugOutput(variableValue)
- return "Error-116"
- result = int(variableValue) in r
- if(result is True):
- return "ok"
- else:
- return "Error-113"
-
- elif(variableType == "LONG_VALUE_RANGE"):
- long_range = varRange.split('-')
- r = range(int(long_range[0].strip()), int(long_range[1].strip()))
- val_range = variableValue.split('-')
- if((checkLong(val_range[0]) is not True) or
- (checkLong(val_range[1]) is not True)):
- return "Error-117"
- result = (val_range[0] in r) and (
- val_range[1] in r) and (val_range[0] < val_range[1])
- if(result is True):
- return "ok"
- else:
- return "Error-113"
- elif(variableType == "LONG_OPTIONS"):
- long_options = varRange.split(',')
- if(checkLong(variableValue) is not True):
- return "Error-116"
- for opt in long_options:
- if(opt.strip() == variableValue):
- result = True
- break
- if(result is True):
- return "ok"
- else:
- return "Error-115"
-
- elif(variableType == "TEXT"):
- if(variableValue == ""):
- return "Error-118"
- if(True is isinstance(variableValue, str)):
- return "ok"
- else:
- return "Error-119"
-
- elif(variableType == "NO_VALIDATION"):
- if(variableValue == ""):
- return "Error-118"
- else:
- return "ok"
-
- elif(variableType == "TEXT_OR_EMPTY"):
- if(variableValue is None or variableValue == ""):
- return "ok"
- if(result == isinstance(variableValue, str)):
- return "ok"
- else:
- return "Error-119"
-
- elif(variableType == "MATCH_TEXT"):
- if(variableValue == ""):
- return "Error-118"
- if(isinstance(variableValue, str)):
- if(varRange == variableValue):
- return "ok"
- else:
- return "Error-120"
- else:
- return "Error-119"
-
- elif(variableType == "MATCH_TEXT_OR_EMPTY"):
- if(variableValue is None or variableValue == ""):
- return "ok"
- if(isinstance(variableValue, str)):
- if(varRange == variableValue):
- return "ok"
- else:
- return "Error-120"
- else:
- return "Error-119"
-
- elif(variableType == "TEXT_OPTIONS"):
- str_options = varRange.split(',')
- if(isinstance(variableValue, str) is not True):
- return "Error-119"
- result = False
- for opt in str_options:
- if(opt.strip() == variableValue):
- result = True
- break
- if(result is True):
- return "ok"
- else:
- return "Error-115"
-
- elif(variableType == "TEXT_OPTIONS_OR_EMPTY"):
- if(variableValue is None or variableValue == ""):
- return "ok"
- str_options = varRange.split(',')
- if(isinstance(variableValue, str) is not True):
- return "Error-119"
- for opt in str_options:
- if(opt.strip() == variableValue):
- result = True
- break
- if(result is True):
- return "ok"
- else:
- return "Error-115"
-
- elif(variableType == "IPV4Address"):
- try:
- socket.inet_pton(socket.AF_INET, variableValue)
- result = True
- except socket.error:
- result = False
- if(result is True):
- return "ok"
- else:
- return "Error-121"
- elif(variableType == "IPV4AddressWithMask"):
- if(variableValue is None or variableValue == ""):
- return "Error-119"
- str_options = variableValue.split('/')
- ipaddr = str_options[0]
- mask = str_options[1]
- try:
- socket.inet_pton(socket.AF_INET, ipaddr)
- if(checkInteger(mask) is True):
- result = True
- else:
- result = False
- except socket.error:
- result = False
- if(result is True):
- return "ok"
- else:
- return "Error-121"
-
- elif(variableType == "IPV6Address"):
- try:
- socket.inet_pton(socket.AF_INET6, variableValue)
- result = True
- except socket.error:
- result = False
- if(result is True):
- return "ok"
- else:
- return "Error-122"
-
- return retVal
-# EOM
-
-
-def disablePaging(remote_conn):
- remote_conn.send("terminal length 0\n")
- time.sleep(1)
- # Clear the buffer on the screen
- outputByte = remote_conn.recv(1000)
- output = outputByte.decode()
- return output
-# EOM
-
-
-def checkInteger(s):
- try:
- int(s)
- return True
- except ValueError:
- return False
-# EOM
-
-
-def checkFloat(s):
- try:
- float(s)
- return True
- except ValueError:
- return False
-# EOM
-
-
-def checkLong(s):
- try:
- int(s)
- return True
- except ValueError:
- return False
-
-
-def debugOutput(command):
- f = open('debugOutput.txt', 'a')
- f.write(str(command)) # python will convert \n to os.linesep
- f.close() # you can omit in most cases as the destructor will call it
-# EOM
diff --git a/plugins/module_utils/network/cnos/cnos_devicerules.py b/plugins/module_utils/network/cnos/cnos_devicerules.py
deleted file mode 100644
index f6c8f24ea7..0000000000
--- a/plugins/module_utils/network/cnos/cnos_devicerules.py
+++ /dev/null
@@ -1,1921 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by
-# Ansible still belong to the author of the module, and may assign their
-# own license to the complete work.
-#
-# Copyright (C) 2017 Lenovo, Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# Contains device rule and methods
-# Lenovo Networking
-
-
-def getRuleString(deviceType, variableId):
- retVal = variableId + ":"
- if(deviceType == 'g8272_cnos'):
- if variableId in g8272_cnos:
- retVal = retVal + g8272_cnos[variableId]
- else:
- retVal = "The variable " + variableId + " is not supported"
- elif(deviceType == 'g8296_cnos'):
- if variableId in g8296_cnos:
- retVal = retVal + g8296_cnos[variableId]
- else:
- retVal = "The variable " + variableId + " is not supported"
- elif(deviceType == 'g8332_cnos'):
- if variableId in g8332_cnos:
- retVal = retVal + g8332_cnos[variableId]
- else:
- retVal = "The variable " + variableId + " is not supported"
- elif(deviceType == 'NE1072T'):
- if variableId in NE1072T:
- retVal = retVal + NE1072T[variableId]
- else:
- retVal = "The variable " + variableId + " is not supported"
- elif(deviceType == 'NE1032'):
- if variableId in NE1032:
- retVal = retVal + NE1032[variableId]
- else:
- retVal = "The variable " + variableId + " is not supported"
- elif(deviceType == 'NE1032T'):
- if variableId in NE1032T:
- retVal = retVal + NE1032T[variableId]
- else:
- retVal = "The variable " + variableId + " is not supported"
- elif(deviceType == 'NE10032'):
- if variableId in NE10032:
- retVal = retVal + NE10032[variableId]
- else:
- retVal = "The variable " + variableId + " is not supported"
- elif(deviceType == 'NE2572'):
- if variableId in NE2572:
- retVal = retVal + NE2572[variableId]
- else:
- retVal = "The variable " + variableId + " is not supported"
- elif(deviceType == 'NE0152T'):
- if variableId in NE0152T:
- retVal = retVal + NE0152T[variableId]
- else:
- retVal = "The variable " + variableId + " is not supported"
- else:
- if variableId in default_cnos:
- retVal = retVal + default_cnos[variableId]
- else:
- retVal = "The variable " + variableId + " is not supported"
- return retVal
-# EOM
-
-
-default_cnos = {
- 'vlan_id': 'INTEGER_VALUE:1-3999',
- 'vlan_id_range': 'INTEGER_VALUE_RANGE:1-3999',
- 'vlan_name': 'TEXT:',
- 'vlan_flood': 'TEXT_OPTIONS:ipv4,ipv6',
- 'vlan_state': 'TEXT_OPTIONS:active,suspend',
- 'vlan_last_member_query_interval': 'INTEGER_VALUE:1-25',
- 'vlan_querier': 'IPV4Address:',
- 'vlan_querier_timeout': 'INTEGER_VALUE:1-65535',
- 'vlan_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_query_max_response_time': 'INTEGER_VALUE:1-25',
- 'vlan_report_suppression': 'INTEGER_VALUE:1-25',
- 'vlan_robustness_variable': 'INTEGER_VALUE:1-7',
- 'vlan_startup_query_count': 'INTEGER_VALUE:1-10',
- 'vlan_startup_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_snooping_version': 'INTEGER_VALUE:2-3',
- 'vlan_access_map_name': 'TEXT: ',
- 'vlan_ethernet_interface': 'TEXT:',
- 'vlan_portagg_number': 'INTEGER_VALUE:1-4096',
- 'vlan_accessmap_action': 'TEXT_OPTIONS:drop,forward,redirect',
- 'vlan_dot1q_tag': 'MATCH_TEXT_OR_EMPTY:egress-only',
- 'vlan_filter_name': 'TEXT:',
- 'vlag_auto_recovery': 'INTEGER_VALUE:240-3600',
- 'vlag_config_consistency': 'TEXT_OPTIONS:disable,strict',
- 'vlag_instance': 'INTEGER_VALUE:1-64',
- 'vlag_port_aggregation': 'INTEGER_VALUE:1-4096',
- 'vlag_priority': 'INTEGER_VALUE:0-65535',
- 'vlag_startup_delay': 'INTEGER_VALUE:0-3600',
- 'vlag_tier_id': 'INTEGER_VALUE:1-512',
- 'vlag_hlthchk_options': 'TEXT_OPTIONS:keepalive-attempts,\
- keepalive-interval,peer-ip,retry-interval',
- 'vlag_keepalive_attempts': 'INTEGER_VALUE:1-24',
- 'vlag_keepalive_interval': 'INTEGER_VALUE:2-300',
- 'vlag_retry_interval': 'INTEGER_VALUE:1-300',
- 'vlag_peerip': 'IPV4Address:',
- 'vlag_peerip_vrf': 'TEXT_OPTIONS:default,management',
- 'bgp_as_number': 'NO_VALIDATION:1-4294967295',
- 'bgp_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_bgp_local_count': 'INTEGER_VALUE:2-64',
- 'cluster_id_as_ip': 'IPV4Address:',
- 'cluster_id_as_number': 'NO_VALIDATION:1-4294967295',
- 'confederation_identifier': 'INTEGER_VALUE:1-65535',
- 'condeferation_peers_as': 'INTEGER_VALUE:1-65535',
- 'stalepath_delay_value': 'INTEGER_VALUE:1-3600',
- 'maxas_limit_as': 'INTEGER_VALUE:1-2000',
- 'neighbor_ipaddress': 'IPV4Address:',
- 'neighbor_as': 'NO_VALIDATION:1-4294967295',
- 'router_id': 'IPV4Address:',
- 'bgp_keepalive_interval': 'INTEGER_VALUE:0-3600',
- 'bgp_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_aggregate_prefix': 'IPV4AddressWithMask:',
- 'addrfamily_routemap_name': 'TEXT:',
- 'reachability_half_life': 'INTEGER_VALUE:1-45',
- 'start_reuse_route_value': 'INTEGER_VALUE:1-20000',
- 'start_suppress_route_value': 'INTEGER_VALUE:1-20000',
- 'max_duration_to_suppress_route': 'INTEGER_VALUE:1-255',
- 'unreachability_halftime_for_penalty': 'INTEGER_VALUE:1-45',
- 'distance_external_AS': 'INTEGER_VALUE:1-255',
- 'distance_internal_AS': 'INTEGER_VALUE:1-255',
- 'distance_local_routes': 'INTEGER_VALUE:1-255',
- 'maxpath_option': 'TEXT_OPTIONS:ebgp,ibgp',
- 'maxpath_numbers': 'INTEGER_VALUE:2-32',
- 'network_ip_prefix_with_mask': 'IPV4AddressWithMask:',
- 'network_ip_prefix_value': 'IPV4Address:',
- 'network_ip_prefix_mask': 'IPV4Address:',
- 'nexthop_crtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'nexthop_noncrtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'addrfamily_redistribute_option': 'TEXT_OPTIONS:direct,ospf,\
- static',
- 'bgp_neighbor_af_occurances': 'INTEGER_VALUE:1-10',
- 'bgp_neighbor_af_filtername': 'TEXT:',
- 'bgp_neighbor_af_maxprefix': 'INTEGER_VALUE:1-15870',
- 'bgp_neighbor_af_prefixname': 'TEXT:',
- 'bgp_neighbor_af_routemap': 'TEXT:',
- 'bgp_neighbor_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_neighbor_connection_retrytime': 'INTEGER_VALUE:1-65535',
- 'bgp_neighbor_description': 'TEXT:',
- 'bgp_neighbor_maxhopcount': 'INTEGER_VALUE:1-255',
- 'bgp_neighbor_local_as': 'NO_VALIDATION:1-4294967295',
- 'bgp_neighbor_maxpeers': 'INTEGER_VALUE:1-96',
- 'bgp_neighbor_password': 'TEXT:',
- 'bgp_neighbor_timers_Keepalive': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_timers_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_ttl_hops': 'INTEGER_VALUE:1-254',
- 'bgp_neighbor_update_options': 'TEXT_OPTIONS:ethernet,loopback,\
- vlan',
- 'bgp_neighbor_update_ethernet': 'TEXT:',
- 'bgp_neighbor_update_loopback': 'INTEGER_VALUE:0-7',
- 'bgp_neighbor_update_vlan': 'INTEGER_VALUE:1-4094',
- 'bgp_neighbor_weight': 'INTEGER_VALUE:0-65535',
- 'ethernet_interface_value': 'INTEGER_VALUE:1-32',
- 'ethernet_interface_range': 'INTEGER_VALUE_RANGE:1-32',
- 'ethernet_interface_string': 'TEXT:',
- 'loopback_interface_value': 'INTEGER_VALUE:0-7',
- 'mgmt_interface_value': 'INTEGER_VALUE:0-0',
- 'vlan_interface_value': 'INTEGER_VALUE:1-4094',
- 'portchannel_interface_value': 'INTEGER_VALUE:1-4096',
- 'portchannel_interface_range': 'INTEGER_VALUE_RANGE:1-4096',
- 'portchannel_interface_string': 'TEXT:',
- 'aggregation_group_no': 'INTEGER_VALUE:1-4096',
- 'aggregation_group_mode': 'TEXT_OPTIONS:active,on,passive',
- 'bfd_options': 'TEXT_OPTIONS:authentication,echo,interval,ipv4,\
- ipv6,neighbor',
- 'bfd_interval': 'INTEGER_VALUE:50-999',
- 'bfd_minrx': 'INTEGER_VALUE:50-999',
- 'bfd_ multiplier': 'INTEGER_VALUE:3-50',
- 'bfd_ipv4_options': 'TEXT_OPTIONS:authentication,echo,\
- interval',
- 'bfd_auth_options': 'TEXT_OPTIONS:keyed-md5,keyed-sha1,\
- meticulous-keyed-md5,meticulous-keyed-sha1,simple',
- 'bfd_key_options': 'TEXT_OPTIONS:key-chain,key-id',
- 'bfd_key_chain': 'TEXT:',
- 'bfd_key_id': 'INTEGER_VALUE:0-255',
- 'bfd_key_name': 'TEXT:',
- 'bfd_neighbor_ip': 'TEXT:',
- 'bfd_neighbor_options': 'TEXT_OPTIONS:admin-down,multihop,\
- non-persistent',
- 'bfd_access_vlan': 'INTEGER_VALUE:1-3999',
- 'bfd_bridgeport_mode': 'TEXT_OPTIONS:access,dot1q-tunnel,\
- trunk',
- 'trunk_options': 'TEXT_OPTIONS:allowed,native',
- 'trunk_vlanid': 'INTEGER_VALUE:1-3999',
- 'portCh_description': 'TEXT:',
- 'duplex_option': 'TEXT_OPTIONS:auto,full,half',
- 'flowcontrol_options': 'TEXT_OPTIONS:receive,send',
- 'portchannel_ip_options': 'TEXT_OPTIONS:access-group,address,\
- arp,dhcp,ospf,port,port-unreachable,redirects,router,\
- unreachables',
- 'accessgroup_name': 'TEXT:',
- 'portchannel_ipv4': 'IPV4Address:',
- 'portchannel_ipv4_mask': 'TEXT:',
- 'arp_ipaddress': 'IPV4Address:',
- 'arp_macaddress': 'TEXT:',
- 'arp_timeout_value': 'INTEGER_VALUE:60-28800',
- 'relay_ipaddress': 'IPV4Address:',
- 'ip_ospf_options': 'TEXT_OPTIONS:authentication,\
- authentication-key,bfd,cost,database-filter,dead-interval,\
- hello-interval,message-digest-key,mtu,mtu-ignore,network,\
- passive-interface,priority,retransmit-interval,shutdown,\
- transmit-delay',
- 'ospf_id_decimal_value': 'NO_VALIDATION:1-4294967295',
- 'ospf_id_ipaddres_value': 'IPV4Address:',
- 'lacp_options': 'TEXT_OPTIONS:port-priority,suspend-individual,\
- timeout',
- 'port_priority': 'INTEGER_VALUE:1-65535',
- 'lldp_options': 'TEXT_OPTIONS:receive,tlv-select,transmit,\
- trap-notification',
- 'lldp_tlv_options': 'TEXT_OPTIONS:link-aggregation,\
- mac-phy-status,management-address,max-frame-size,\
- port-description,port-protocol-vlan,port-vlan,power-mdi,\
- protocol-identity,system-capabilities,system-description,\
- system-name,vid-management,vlan-name',
- 'load_interval_delay': 'INTEGER_VALUE:30-300',
- 'load_interval_counter': 'INTEGER_VALUE:1-3',
- 'mac_accessgroup_name': 'TEXT:',
- 'mac_address': 'TEXT:',
- 'microburst_threshold': 'NO_VALIDATION:1-4294967295',
- 'mtu_value': 'INTEGER_VALUE:64-9216',
- 'service_instance': 'NO_VALIDATION:1-4294967295',
- 'service_policy_options': 'TEXT_OPTIONS:copp-system-policy,\
- input,output,type',
- 'service_policy_name': 'TEXT:',
- 'spanning_tree_options': 'TEXT_OPTIONS:bpdufilter,bpduguard,\
- cost,disable,enable,guard,link-type,mst,port,port-priority,\
- vlan',
- 'spanning_tree_cost': 'NO_VALIDATION:1-200000000',
- 'spanning_tree_interfacerange': 'INTEGER_VALUE_RANGE:1-3999',
- 'spanning_tree_portpriority': 'TEXT_OPTIONS:0,32,64,96,128,160,\
- 192,224',
- 'portchannel_ipv6_neighbor_mac': 'TEXT:',
- 'portchannel_ipv6_neighbor_address': 'IPV6Address:',
- 'portchannel_ipv6_linklocal': 'IPV6Address:',
- 'portchannel_ipv6_dhcp_vlan': 'INTEGER_VALUE:1-4094',
- 'portchannel_ipv6_dhcp_ethernet': 'TEXT:',
- 'portchannel_ipv6_dhcp': 'IPV6Address:',
- 'portchannel_ipv6_address': 'IPV6Address:',
- 'portchannel_ipv6_options': 'TEXT_OPTIONS:address,dhcp,\
- link-local,nd,neighbor',
- 'interface_speed': 'TEXT_OPTIONS:1000,10000,100000,25000,40000,50000,auto',
- 'stormcontrol_options': 'TEXT_OPTIONS:broadcast,multicast,\
- unicast',
- 'stormcontrol_level': 'FLOAT:',
- 'portchannel_dot1q_tag': 'TEXT_OPTIONS:disable,enable,\
- egress-only',
- 'vrrp_id': 'INTEGER_VALUE:1-255',
-}
-NE0152T = {
- 'vlan_id': 'INTEGER_VALUE:1-3999',
- 'vlan_id_range': 'INTEGER_VALUE_RANGE:1-3999',
- 'vlan_name': 'TEXT:',
- 'vlan_flood': 'TEXT_OPTIONS:ipv4,ipv6',
- 'vlan_state': 'TEXT_OPTIONS:active,suspend',
- 'vlan_last_member_query_interval': 'INTEGER_VALUE:1-25',
- 'vlan_querier': 'IPV4Address:',
- 'vlan_querier_timeout': 'INTEGER_VALUE:1-65535',
- 'vlan_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_query_max_response_time': 'INTEGER_VALUE:1-25',
- 'vlan_report_suppression': 'INTEGER_VALUE:1-25',
- 'vlan_robustness_variable': 'INTEGER_VALUE:1-7',
- 'vlan_startup_query_count': 'INTEGER_VALUE:1-10',
- 'vlan_startup_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_snooping_version': 'INTEGER_VALUE:2-3',
- 'vlan_access_map_name': 'TEXT: ',
- 'vlan_ethernet_interface': 'TEXT:',
- 'vlan_portagg_number': 'INTEGER_VALUE:1-4096',
- 'vlan_accessmap_action': 'TEXT_OPTIONS:drop,forward,redirect',
- 'vlan_dot1q_tag': 'MATCH_TEXT_OR_EMPTY:egress-only',
- 'vlan_filter_name': 'TEXT:',
- 'vlag_auto_recovery': 'INTEGER_VALUE:240-3600',
- 'vlag_config_consistency': 'TEXT_OPTIONS:disable,strict',
- 'vlag_instance': 'INTEGER_VALUE:1-64',
- 'vlag_port_aggregation': 'INTEGER_VALUE:1-4096',
- 'vlag_priority': 'INTEGER_VALUE:0-65535',
- 'vlag_startup_delay': 'INTEGER_VALUE:0-3600',
- 'vlag_tier_id': 'INTEGER_VALUE:1-512',
- 'vlag_hlthchk_options': 'TEXT_OPTIONS:keepalive-attempts,\
- keepalive-interval,peer-ip,retry-interval',
- 'vlag_keepalive_attempts': 'INTEGER_VALUE:1-24',
- 'vlag_keepalive_interval': 'INTEGER_VALUE:2-300',
- 'vlag_retry_interval': 'INTEGER_VALUE:1-300',
- 'vlag_peerip': 'IPV4Address:',
- 'vlag_peerip_vrf': 'TEXT_OPTIONS:default,management',
- 'bgp_as_number': 'NO_VALIDATION:1-4294967295',
- 'bgp_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_bgp_local_count': 'INTEGER_VALUE:2-64',
- 'cluster_id_as_ip': 'IPV4Address:',
- 'cluster_id_as_number': 'NO_VALIDATION:1-4294967295',
- 'confederation_identifier': 'INTEGER_VALUE:1-65535',
- 'condeferation_peers_as': 'INTEGER_VALUE:1-65535',
- 'stalepath_delay_value': 'INTEGER_VALUE:1-3600',
- 'maxas_limit_as': 'INTEGER_VALUE:1-2000',
- 'neighbor_ipaddress': 'IPV4Address:',
- 'neighbor_as': 'NO_VALIDATION:1-4294967295',
- 'router_id': 'IPV4Address:',
- 'bgp_keepalive_interval': 'INTEGER_VALUE:0-3600',
- 'bgp_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_aggregate_prefix': 'IPV4AddressWithMask:',
- 'addrfamily_routemap_name': 'TEXT:',
- 'reachability_half_life': 'INTEGER_VALUE:1-45',
- 'start_reuse_route_value': 'INTEGER_VALUE:1-20000',
- 'start_suppress_route_value': 'INTEGER_VALUE:1-20000',
- 'max_duration_to_suppress_route': 'INTEGER_VALUE:1-255',
- 'unreachability_halftime_for_penalty': 'INTEGER_VALUE:1-45',
- 'distance_external_AS': 'INTEGER_VALUE:1-255',
- 'distance_internal_AS': 'INTEGER_VALUE:1-255',
- 'distance_local_routes': 'INTEGER_VALUE:1-255',
- 'maxpath_option': 'TEXT_OPTIONS:ebgp,ibgp',
- 'maxpath_numbers': 'INTEGER_VALUE:2-32',
- 'network_ip_prefix_with_mask': 'IPV4AddressWithMask:',
- 'network_ip_prefix_value': 'IPV4Address:',
- 'network_ip_prefix_mask': 'IPV4Address:',
- 'nexthop_crtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'nexthop_noncrtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'addrfamily_redistribute_option': 'TEXT_OPTIONS:direct,ospf,\
- static',
- 'bgp_neighbor_af_occurances': 'INTEGER_VALUE:1-10',
- 'bgp_neighbor_af_filtername': 'TEXT:',
- 'bgp_neighbor_af_maxprefix': 'INTEGER_VALUE:1-15870',
- 'bgp_neighbor_af_prefixname': 'TEXT:',
- 'bgp_neighbor_af_routemap': 'TEXT:',
- 'bgp_neighbor_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_neighbor_connection_retrytime': 'INTEGER_VALUE:1-65535',
- 'bgp_neighbor_description': 'TEXT:',
- 'bgp_neighbor_maxhopcount': 'INTEGER_VALUE:1-255',
- 'bgp_neighbor_local_as': 'NO_VALIDATION:1-4294967295',
- 'bgp_neighbor_maxpeers': 'INTEGER_VALUE:1-96',
- 'bgp_neighbor_password': 'TEXT:',
- 'bgp_neighbor_timers_Keepalive': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_timers_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_ttl_hops': 'INTEGER_VALUE:1-254',
- 'bgp_neighbor_update_options': 'TEXT_OPTIONS:ethernet,loopback,\
- vlan',
- 'bgp_neighbor_update_ethernet': 'TEXT:',
- 'bgp_neighbor_update_loopback': 'INTEGER_VALUE:0-7',
- 'bgp_neighbor_update_vlan': 'INTEGER_VALUE:1-4094',
- 'bgp_neighbor_weight': 'INTEGER_VALUE:0-65535',
- 'ethernet_interface_value': 'INTEGER_VALUE:1-52',
- 'ethernet_interface_range': 'INTEGER_VALUE_RANGE:1-52',
- 'ethernet_interface_string': 'TEXT:',
- 'loopback_interface_value': 'INTEGER_VALUE:0-7',
- 'mgmt_interface_value': 'INTEGER_VALUE:0-0',
- 'vlan_interface_value': 'INTEGER_VALUE:1-4094',
- 'portchannel_interface_value': 'INTEGER_VALUE:1-4096',
- 'portchannel_interface_range': 'INTEGER_VALUE_RANGE:1-4096',
- 'portchannel_interface_string': 'TEXT:',
- 'aggregation_group_no': 'INTEGER_VALUE:1-4096',
- 'aggregation_group_mode': 'TEXT_OPTIONS:active,on,passive',
- 'bfd_options': 'TEXT_OPTIONS:authentication,echo,interval,ipv4,\
- ipv6,neighbor',
- 'bfd_interval': 'INTEGER_VALUE:50-999',
- 'bfd_minrx': 'INTEGER_VALUE:50-999',
- 'bfd_ multiplier': 'INTEGER_VALUE:3-50',
- 'bfd_ipv4_options': 'TEXT_OPTIONS:authentication,echo,\
- interval',
- 'bfd_auth_options': 'TEXT_OPTIONS:keyed-md5,keyed-sha1,\
- meticulous-keyed-md5,meticulous-keyed-sha1,simple',
- 'bfd_key_options': 'TEXT_OPTIONS:key-chain,key-id',
- 'bfd_key_chain': 'TEXT:',
- 'bfd_key_id': 'INTEGER_VALUE:0-255',
- 'bfd_key_name': 'TEXT:',
- 'bfd_neighbor_ip': 'TEXT:',
- 'bfd_neighbor_options': 'TEXT_OPTIONS:admin-down,multihop,\
- non-persistent',
- 'bfd_access_vlan': 'INTEGER_VALUE:1-3999',
- 'bfd_bridgeport_mode': 'TEXT_OPTIONS:access,dot1q-tunnel,\
- trunk',
- 'trunk_options': 'TEXT_OPTIONS:allowed,native',
- 'trunk_vlanid': 'INTEGER_VALUE:1-3999',
- 'portCh_description': 'TEXT:',
- 'duplex_option': 'TEXT_OPTIONS:auto,full,half',
- 'flowcontrol_options': 'TEXT_OPTIONS:receive,send',
- 'portchannel_ip_options': 'TEXT_OPTIONS:access-group,address,\
- arp,dhcp,ospf,port,port-unreachable,redirects,router,\
- unreachables',
- 'accessgroup_name': 'TEXT:',
- 'portchannel_ipv4': 'IPV4Address:',
- 'portchannel_ipv4_mask': 'TEXT:',
- 'arp_ipaddress': 'IPV4Address:',
- 'arp_macaddress': 'TEXT:',
- 'arp_timeout_value': 'INTEGER_VALUE:60-28800',
- 'relay_ipaddress': 'IPV4Address:',
- 'ip_ospf_options': 'TEXT_OPTIONS:authentication,\
- authentication-key,bfd,cost,database-filter,dead-interval,\
- hello-interval,message-digest-key,mtu,mtu-ignore,network,\
- passive-interface,priority,retransmit-interval,shutdown,\
- transmit-delay',
- 'ospf_id_decimal_value': 'NO_VALIDATION:1-4294967295',
- 'ospf_id_ipaddres_value': 'IPV4Address:',
- 'lacp_options': 'TEXT_OPTIONS:port-priority,suspend-individual,\
- timeout',
- 'port_priority': 'INTEGER_VALUE:1-65535',
- 'lldp_options': 'TEXT_OPTIONS:receive,tlv-select,transmit,\
- trap-notification',
- 'lldp_tlv_options': 'TEXT_OPTIONS:link-aggregation,\
- mac-phy-status,management-address,max-frame-size,\
- port-description,port-protocol-vlan,port-vlan,power-mdi,\
- protocol-identity,system-capabilities,system-description,\
- system-name,vid-management,vlan-name',
- 'load_interval_delay': 'INTEGER_VALUE:30-300',
- 'load_interval_counter': 'INTEGER_VALUE:1-3',
- 'mac_accessgroup_name': 'TEXT:',
- 'mac_address': 'TEXT:',
- 'microburst_threshold': 'NO_VALIDATION:1-4294967295',
- 'mtu_value': 'INTEGER_VALUE:64-9216',
- 'service_instance': 'NO_VALIDATION:1-4294967295',
- 'service_policy_options': 'TEXT_OPTIONS:copp-system-policy,\
- input,output,type',
- 'service_policy_name': 'TEXT:',
- 'spanning_tree_options': 'TEXT_OPTIONS:bpdufilter,bpduguard,\
- cost,disable,enable,guard,link-type,mst,port,port-priority,\
- vlan',
- 'spanning_tree_cost': 'NO_VALIDATION:1-200000000',
- 'spanning_tree_interfacerange': 'INTEGER_VALUE_RANGE:1-3999',
- 'spanning_tree_portpriority': 'TEXT_OPTIONS:0,32,64,96,128,160,\
- 192,224',
- 'portchannel_ipv6_neighbor_mac': 'TEXT:',
- 'portchannel_ipv6_neighbor_address': 'IPV6Address:',
- 'portchannel_ipv6_linklocal': 'IPV6Address:',
- 'portchannel_ipv6_dhcp_vlan': 'INTEGER_VALUE:1-4094',
- 'portchannel_ipv6_dhcp_ethernet': 'TEXT:',
- 'portchannel_ipv6_dhcp': 'IPV6Address:',
- 'portchannel_ipv6_address': 'IPV6Address:',
- 'portchannel_ipv6_options': 'TEXT_OPTIONS:address,dhcp,\
- link-local,nd,neighbor',
- 'interface_speed': 'TEXT_OPTIONS:10,100,1000,10000,auto',
- 'stormcontrol_options': 'TEXT_OPTIONS:broadcast,multicast,\
- unicast',
- 'stormcontrol_level': 'FLOAT:',
- 'portchannel_dot1q_tag': 'TEXT_OPTIONS:disable,enable,\
- egress-only',
- 'vrrp_id': 'INTEGER_VALUE:1-255',
-}
-NE2572 = {
- 'vlan_id': 'INTEGER_VALUE:1-3999',
- 'vlan_id_range': 'INTEGER_VALUE_RANGE:1-3999',
- 'vlan_name': 'TEXT:',
- 'vlan_flood': 'TEXT_OPTIONS:ipv4,ipv6',
- 'vlan_state': 'TEXT_OPTIONS:active,suspend',
- 'vlan_last_member_query_interval': 'INTEGER_VALUE:1-25',
- 'vlan_querier': 'IPV4Address:',
- 'vlan_querier_timeout': 'INTEGER_VALUE:1-65535',
- 'vlan_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_query_max_response_time': 'INTEGER_VALUE:1-25',
- 'vlan_report_suppression': 'INTEGER_VALUE:1-25',
- 'vlan_robustness_variable': 'INTEGER_VALUE:1-7',
- 'vlan_startup_query_count': 'INTEGER_VALUE:1-10',
- 'vlan_startup_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_snooping_version': 'INTEGER_VALUE:2-3',
- 'vlan_access_map_name': 'TEXT: ',
- 'vlan_ethernet_interface': 'TEXT:',
- 'vlan_portagg_number': 'INTEGER_VALUE:1-4096',
- 'vlan_accessmap_action': 'TEXT_OPTIONS:drop,forward,redirect',
- 'vlan_dot1q_tag': 'MATCH_TEXT_OR_EMPTY:egress-only',
- 'vlan_filter_name': 'TEXT:',
- 'vlag_auto_recovery': 'INTEGER_VALUE:240-3600',
- 'vlag_config_consistency': 'TEXT_OPTIONS:disable,strict',
- 'vlag_instance': 'INTEGER_VALUE:1-64',
- 'vlag_port_aggregation': 'INTEGER_VALUE:1-4096',
- 'vlag_priority': 'INTEGER_VALUE:0-65535',
- 'vlag_startup_delay': 'INTEGER_VALUE:0-3600',
- 'vlag_tier_id': 'INTEGER_VALUE:1-512',
- 'vlag_hlthchk_options': 'TEXT_OPTIONS:keepalive-attempts,\
- keepalive-interval,peer-ip,retry-interval',
- 'vlag_keepalive_attempts': 'INTEGER_VALUE:1-24',
- 'vlag_keepalive_interval': 'INTEGER_VALUE:2-300',
- 'vlag_retry_interval': 'INTEGER_VALUE:1-300',
- 'vlag_peerip': 'IPV4Address:',
- 'vlag_peerip_vrf': 'TEXT_OPTIONS:default,management',
- 'bgp_as_number': 'NO_VALIDATION:1-4294967295',
- 'bgp_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_bgp_local_count': 'INTEGER_VALUE:2-64',
- 'cluster_id_as_ip': 'IPV4Address:',
- 'cluster_id_as_number': 'NO_VALIDATION:1-4294967295',
- 'confederation_identifier': 'INTEGER_VALUE:1-65535',
- 'condeferation_peers_as': 'INTEGER_VALUE:1-65535',
- 'stalepath_delay_value': 'INTEGER_VALUE:1-3600',
- 'maxas_limit_as': 'INTEGER_VALUE:1-2000',
- 'neighbor_ipaddress': 'IPV4Address:',
- 'neighbor_as': 'NO_VALIDATION:1-4294967295',
- 'router_id': 'IPV4Address:',
- 'bgp_keepalive_interval': 'INTEGER_VALUE:0-3600',
- 'bgp_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_aggregate_prefix': 'IPV4AddressWithMask:',
- 'addrfamily_routemap_name': 'TEXT:',
- 'reachability_half_life': 'INTEGER_VALUE:1-45',
- 'start_reuse_route_value': 'INTEGER_VALUE:1-20000',
- 'start_suppress_route_value': 'INTEGER_VALUE:1-20000',
- 'max_duration_to_suppress_route': 'INTEGER_VALUE:1-255',
- 'unreachability_halftime_for_penalty': 'INTEGER_VALUE:1-45',
- 'distance_external_AS': 'INTEGER_VALUE:1-255',
- 'distance_internal_AS': 'INTEGER_VALUE:1-255',
- 'distance_local_routes': 'INTEGER_VALUE:1-255',
- 'maxpath_option': 'TEXT_OPTIONS:ebgp,ibgp',
- 'maxpath_numbers': 'INTEGER_VALUE:2-32',
- 'network_ip_prefix_with_mask': 'IPV4AddressWithMask:',
- 'network_ip_prefix_value': 'IPV4Address:',
- 'network_ip_prefix_mask': 'IPV4Address:',
- 'nexthop_crtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'nexthop_noncrtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'addrfamily_redistribute_option': 'TEXT_OPTIONS:direct,ospf,\
- static',
- 'bgp_neighbor_af_occurances': 'INTEGER_VALUE:1-10',
- 'bgp_neighbor_af_filtername': 'TEXT:',
- 'bgp_neighbor_af_maxprefix': 'INTEGER_VALUE:1-15870',
- 'bgp_neighbor_af_prefixname': 'TEXT:',
- 'bgp_neighbor_af_routemap': 'TEXT:',
- 'bgp_neighbor_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_neighbor_connection_retrytime': 'INTEGER_VALUE:1-65535',
- 'bgp_neighbor_description': 'TEXT:',
- 'bgp_neighbor_maxhopcount': 'INTEGER_VALUE:1-255',
- 'bgp_neighbor_local_as': 'NO_VALIDATION:1-4294967295',
- 'bgp_neighbor_maxpeers': 'INTEGER_VALUE:1-96',
- 'bgp_neighbor_password': 'TEXT:',
- 'bgp_neighbor_timers_Keepalive': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_timers_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_ttl_hops': 'INTEGER_VALUE:1-254',
- 'bgp_neighbor_update_options': 'TEXT_OPTIONS:ethernet,loopback,\
- vlan',
- 'bgp_neighbor_update_ethernet': 'TEXT:',
- 'bgp_neighbor_update_loopback': 'INTEGER_VALUE:0-7',
- 'bgp_neighbor_update_vlan': 'INTEGER_VALUE:1-4094',
- 'bgp_neighbor_weight': 'INTEGER_VALUE:0-65535',
- 'ethernet_interface_value': 'INTEGER_VALUE:1-54',
- 'ethernet_interface_range': 'INTEGER_VALUE_RANGE:1-54',
- 'ethernet_interface_string': 'TEXT:',
- 'loopback_interface_value': 'INTEGER_VALUE:0-7',
- 'mgmt_interface_value': 'INTEGER_VALUE:0-0',
- 'vlan_interface_value': 'INTEGER_VALUE:1-4094',
- 'portchannel_interface_value': 'INTEGER_VALUE:1-4096',
- 'portchannel_interface_range': 'INTEGER_VALUE_RANGE:1-4096',
- 'portchannel_interface_string': 'TEXT:',
- 'aggregation_group_no': 'INTEGER_VALUE:1-4096',
- 'aggregation_group_mode': 'TEXT_OPTIONS:active,on,passive',
- 'bfd_options': 'TEXT_OPTIONS:authentication,echo,interval,ipv4,\
- ipv6,neighbor',
- 'bfd_interval': 'INTEGER_VALUE:50-999',
- 'bfd_minrx': 'INTEGER_VALUE:50-999',
- 'bfd_ multiplier': 'INTEGER_VALUE:3-50',
- 'bfd_ipv4_options': 'TEXT_OPTIONS:authentication,echo,interval',
- 'bfd_auth_options': 'TEXT_OPTIONS:keyed-md5,keyed-sha1,\
- meticulous-keyed-md5,meticulous-keyed-sha1,simple',
- 'bfd_key_options': 'TEXT_OPTIONS:key-chain,key-id',
- 'bfd_key_chain': 'TEXT:',
- 'bfd_key_id': 'INTEGER_VALUE:0-255',
- 'bfd_key_name': 'TEXT:',
- 'bfd_neighbor_ip': 'TEXT:',
- 'bfd_neighbor_options': 'TEXT_OPTIONS:admin-down,multihop,\
- non-persistent',
- 'bfd_access_vlan': 'INTEGER_VALUE:1-3999',
- 'bfd_bridgeport_mode': 'TEXT_OPTIONS:access,dot1q-tunnel,trunk',
- 'trunk_options': 'TEXT_OPTIONS:allowed,native',
- 'trunk_vlanid': 'INTEGER_VALUE:1-3999',
- 'portCh_description': 'TEXT:',
- 'duplex_option': 'TEXT_OPTIONS:auto,full,half',
- 'flowcontrol_options': 'TEXT_OPTIONS:receive,send',
- 'portchannel_ip_options': 'TEXT_OPTIONS:access-group,address,\
- arp,dhcp,ospf,port,port-unreachable,redirects,router,\
- unreachables',
- 'accessgroup_name': 'TEXT:',
- 'portchannel_ipv4': 'IPV4Address:',
- 'portchannel_ipv4_mask': 'TEXT:',
- 'arp_ipaddress': 'IPV4Address:',
- 'arp_macaddress': 'TEXT:',
- 'arp_timeout_value': 'INTEGER_VALUE:60-28800',
- 'relay_ipaddress': 'IPV4Address:',
- 'ip_ospf_options': 'TEXT_OPTIONS:authentication,\
- authentication-key,bfd,cost,database-filter,dead-interval,\
- hello-interval,message-digest-key,mtu,mtu-ignore,network,\
- passive-interface,priority,retransmit-interval,shutdown,\
- transmit-delay',
- 'ospf_id_decimal_value': 'NO_VALIDATION:1-4294967295',
- 'ospf_id_ipaddres_value': 'IPV4Address:',
- 'lacp_options': 'TEXT_OPTIONS:port-priority,suspend-individual,\
- timeout',
- 'port_priority': 'INTEGER_VALUE:1-65535',
- 'lldp_options': 'TEXT_OPTIONS:receive,tlv-select,transmit,\
- trap-notification',
- 'lldp_tlv_options': 'TEXT_OPTIONS:link-aggregation,\
- mac-phy-status,management-address,max-frame-size,\
- port-description,port-protocol-vlan,port-vlan,power-mdi,\
- protocol-identity,system-capabilities,system-description,\
- system-name,vid-management,vlan-name',
- 'load_interval_delay': 'INTEGER_VALUE:30-300',
- 'load_interval_counter': 'INTEGER_VALUE:1-3',
- 'mac_accessgroup_name': 'TEXT:',
- 'mac_address': 'TEXT:',
- 'microburst_threshold': 'NO_VALIDATION:1-4294967295',
- 'mtu_value': 'INTEGER_VALUE:64-9216',
- 'service_instance': 'NO_VALIDATION:1-4294967295',
- 'service_policy_options': 'TEXT_OPTIONS:copp-system-policy,input,\
- output,type',
- 'service_policy_name': 'TEXT:',
- 'spanning_tree_options': 'TEXT_OPTIONS:bpdufilter,bpduguard,\
- cost,disable,enable,guard,link-type,mst,port,port-priority,vlan',
- 'spanning_tree_cost': 'NO_VALIDATION:1-200000000',
- 'spanning_tree_interfacerange': 'INTEGER_VALUE_RANGE:1-3999',
- 'spanning_tree_portpriority': 'TEXT_OPTIONS:0,32,64,96,128,160,\
- 192,224',
- 'portchannel_ipv6_neighbor_mac': 'TEXT:',
- 'portchannel_ipv6_neighbor_address': 'IPV6Address:',
- 'portchannel_ipv6_linklocal': 'IPV6Address:',
- 'portchannel_ipv6_dhcp_vlan': 'INTEGER_VALUE:1-4094',
- 'portchannel_ipv6_dhcp_ethernet': 'TEXT:',
- 'portchannel_ipv6_dhcp': 'IPV6Address:',
- 'portchannel_ipv6_address': 'IPV6Address:',
- 'portchannel_ipv6_options': 'TEXT_OPTIONS:address,dhcp,\
- link-local,nd,neighbor',
- 'interface_speed': 'TEXT_OPTIONS:10000,100000,25000,40000,50000,auto',
- 'stormcontrol_options': 'TEXT_OPTIONS:broadcast,multicast,\
- unicast',
- 'stormcontrol_level': 'FLOAT:',
- 'portchannel_dot1q_tag': 'TEXT_OPTIONS:disable,enable,\
- egress-only',
- 'vrrp_id': 'INTEGER_VALUE:1-255',
-}
-NE1032T = {
- 'vlan_id': 'INTEGER_VALUE:1-3999',
- 'vlan_id_range': 'INTEGER_VALUE_RANGE:1-3999',
- 'vlan_name': 'TEXT:',
- 'vlan_flood': 'TEXT_OPTIONS:ipv4,ipv6',
- 'vlan_state': 'TEXT_OPTIONS:active,suspend',
- 'vlan_last_member_query_interval': 'INTEGER_VALUE:1-25',
- 'vlan_querier': 'IPV4Address:',
- 'vlan_querier_timeout': 'INTEGER_VALUE:1-65535',
- 'vlan_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_query_max_response_time': 'INTEGER_VALUE:1-25',
- 'vlan_report_suppression': 'INTEGER_VALUE:1-25',
- 'vlan_robustness_variable': 'INTEGER_VALUE:1-7',
- 'vlan_startup_query_count': 'INTEGER_VALUE:1-10',
- 'vlan_startup_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_snooping_version': 'INTEGER_VALUE:2-3',
- 'vlan_access_map_name': 'TEXT: ',
- 'vlan_ethernet_interface': 'TEXT:',
- 'vlan_portagg_number': 'INTEGER_VALUE:1-4096',
- 'vlan_accessmap_action': 'TEXT_OPTIONS:drop,forward,redirect',
- 'vlan_dot1q_tag': 'MATCH_TEXT_OR_EMPTY:egress-only',
- 'vlan_filter_name': 'TEXT:',
- 'vlag_auto_recovery': 'INTEGER_VALUE:240-3600',
- 'vlag_config_consistency': 'TEXT_OPTIONS:disable,strict',
- 'vlag_instance': 'INTEGER_VALUE:1-64',
- 'vlag_port_aggregation': 'INTEGER_VALUE:1-4096',
- 'vlag_priority': 'INTEGER_VALUE:0-65535',
- 'vlag_startup_delay': 'INTEGER_VALUE:0-3600',
- 'vlag_tier_id': 'INTEGER_VALUE:1-512',
- 'vlag_hlthchk_options': 'TEXT_OPTIONS:keepalive-attempts,\
- keepalive-interval,peer-ip,retry-interval',
- 'vlag_keepalive_attempts': 'INTEGER_VALUE:1-24',
- 'vlag_keepalive_interval': 'INTEGER_VALUE:2-300',
- 'vlag_retry_interval': 'INTEGER_VALUE:1-300',
- 'vlag_peerip': 'IPV4Address:',
- 'vlag_peerip_vrf': 'TEXT_OPTIONS:default,management',
- 'bgp_as_number': 'NO_VALIDATION:1-4294967295',
- 'bgp_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_bgp_local_count': 'INTEGER_VALUE:2-64',
- 'cluster_id_as_ip': 'IPV4Address:',
- 'cluster_id_as_number': 'NO_VALIDATION:1-4294967295',
- 'confederation_identifier': 'INTEGER_VALUE:1-65535',
- 'condeferation_peers_as': 'INTEGER_VALUE:1-65535',
- 'stalepath_delay_value': 'INTEGER_VALUE:1-3600',
- 'maxas_limit_as': 'INTEGER_VALUE:1-2000',
- 'neighbor_ipaddress': 'IPV4Address:',
- 'neighbor_as': 'NO_VALIDATION:1-4294967295',
- 'router_id': 'IPV4Address:',
- 'bgp_keepalive_interval': 'INTEGER_VALUE:0-3600',
- 'bgp_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_aggregate_prefix': 'IPV4AddressWithMask:',
- 'addrfamily_routemap_name': 'TEXT:',
- 'reachability_half_life': 'INTEGER_VALUE:1-45',
- 'start_reuse_route_value': 'INTEGER_VALUE:1-20000',
- 'start_suppress_route_value': 'INTEGER_VALUE:1-20000',
- 'max_duration_to_suppress_route': 'INTEGER_VALUE:1-255',
- 'unreachability_halftime_for_penalty': 'INTEGER_VALUE:1-45',
- 'distance_external_AS': 'INTEGER_VALUE:1-255',
- 'distance_internal_AS': 'INTEGER_VALUE:1-255',
- 'distance_local_routes': 'INTEGER_VALUE:1-255',
- 'maxpath_option': 'TEXT_OPTIONS:ebgp,ibgp',
- 'maxpath_numbers': 'INTEGER_VALUE:2-32',
- 'network_ip_prefix_with_mask': 'IPV4AddressWithMask:',
- 'network_ip_prefix_value': 'IPV4Address:',
- 'network_ip_prefix_mask': 'IPV4Address:',
- 'nexthop_crtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'nexthop_noncrtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'addrfamily_redistribute_option': 'TEXT_OPTIONS:direct,ospf,\
- static',
- 'bgp_neighbor_af_occurances': 'INTEGER_VALUE:1-10',
- 'bgp_neighbor_af_filtername': 'TEXT:',
- 'bgp_neighbor_af_maxprefix': 'INTEGER_VALUE:1-15870',
- 'bgp_neighbor_af_prefixname': 'TEXT:',
- 'bgp_neighbor_af_routemap': 'TEXT:',
- 'bgp_neighbor_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_neighbor_connection_retrytime': 'INTEGER_VALUE:1-65535',
- 'bgp_neighbor_description': 'TEXT:',
- 'bgp_neighbor_maxhopcount': 'INTEGER_VALUE:1-255',
- 'bgp_neighbor_local_as': 'NO_VALIDATION:1-4294967295',
- 'bgp_neighbor_maxpeers': 'INTEGER_VALUE:1-96',
- 'bgp_neighbor_password': 'TEXT:',
- 'bgp_neighbor_timers_Keepalive': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_timers_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_ttl_hops': 'INTEGER_VALUE:1-254',
- 'bgp_neighbor_update_options': 'TEXT_OPTIONS:ethernet,loopback,\
- vlan',
- 'bgp_neighbor_update_ethernet': 'TEXT:',
- 'bgp_neighbor_update_loopback': 'INTEGER_VALUE:0-7',
- 'bgp_neighbor_update_vlan': 'INTEGER_VALUE:1-4094',
- 'bgp_neighbor_weight': 'INTEGER_VALUE:0-65535',
- 'ethernet_interface_value': 'INTEGER_VALUE:1-32',
- 'ethernet_interface_range': 'INTEGER_VALUE_RANGE:1-32',
- 'ethernet_interface_string': 'TEXT:',
- 'loopback_interface_value': 'INTEGER_VALUE:0-7',
- 'mgmt_interface_value': 'INTEGER_VALUE:0-0',
- 'vlan_interface_value': 'INTEGER_VALUE:1-4094',
- 'portchannel_interface_value': 'INTEGER_VALUE:1-4096',
- 'portchannel_interface_range': 'INTEGER_VALUE_RANGE:1-4096',
- 'portchannel_interface_string': 'TEXT:',
- 'aggregation_group_no': 'INTEGER_VALUE:1-4096',
- 'aggregation_group_mode': 'TEXT_OPTIONS:active,on,passive',
- 'bfd_options': 'TEXT_OPTIONS:authentication,echo,interval,ipv4,\
- ipv6,neighbor',
- 'bfd_interval': 'INTEGER_VALUE:50-999',
- 'bfd_minrx': 'INTEGER_VALUE:50-999',
- 'bfd_ multiplier': 'INTEGER_VALUE:3-50',
- 'bfd_ipv4_options': 'TEXT_OPTIONS:authentication,echo,interval',
- 'bfd_auth_options': 'TEXT_OPTIONS:keyed-md5,keyed-sha1,\
- meticulous-keyed-md5,meticulous-keyed-sha1,simple',
- 'bfd_key_options': 'TEXT_OPTIONS:key-chain,key-id',
- 'bfd_key_chain': 'TEXT:',
- 'bfd_key_id': 'INTEGER_VALUE:0-255',
- 'bfd_key_name': 'TEXT:',
- 'bfd_neighbor_ip': 'TEXT:',
- 'bfd_neighbor_options': 'TEXT_OPTIONS:admin-down,multihop,\
- non-persistent',
- 'bfd_access_vlan': 'INTEGER_VALUE:1-3999',
- 'bfd_bridgeport_mode': 'TEXT_OPTIONS:access,dot1q-tunnel,trunk',
- 'trunk_options': 'TEXT_OPTIONS:allowed,native',
- 'trunk_vlanid': 'INTEGER_VALUE:1-3999',
- 'portCh_description': 'TEXT:',
- 'duplex_option': 'TEXT_OPTIONS:auto,full,half',
- 'flowcontrol_options': 'TEXT_OPTIONS:receive,send',
- 'portchannel_ip_options': 'TEXT_OPTIONS:access-group,address,\
- arp,dhcp,ospf,port,port-unreachable,redirects,router,\
- unreachables',
- 'accessgroup_name': 'TEXT:',
- 'portchannel_ipv4': 'IPV4Address:',
- 'portchannel_ipv4_mask': 'TEXT:',
- 'arp_ipaddress': 'IPV4Address:',
- 'arp_macaddress': 'TEXT:',
- 'arp_timeout_value': 'INTEGER_VALUE:60-28800',
- 'relay_ipaddress': 'IPV4Address:',
- 'ip_ospf_options': 'TEXT_OPTIONS:authentication,\
- authentication-key,bfd,cost,database-filter,dead-interval,\
- hello-interval,message-digest-key,mtu,mtu-ignore,network,\
- passive-interface,priority,retransmit-interval,shutdown,\
- transmit-delay',
- 'ospf_id_decimal_value': 'NO_VALIDATION:1-4294967295',
- 'ospf_id_ipaddres_value': 'IPV4Address:',
- 'lacp_options': 'TEXT_OPTIONS:port-priority,suspend-individual,\
- timeout',
- 'port_priority': 'INTEGER_VALUE:1-65535',
- 'lldp_options': 'TEXT_OPTIONS:receive,tlv-select,transmit,\
- trap-notification',
- 'lldp_tlv_options': 'TEXT_OPTIONS:link-aggregation,\
- mac-phy-status,management-address,max-frame-size,\
- port-description,port-protocol-vlan,port-vlan,power-mdi,\
- protocol-identity,system-capabilities,system-description,\
- system-name,vid-management,vlan-name',
- 'load_interval_delay': 'INTEGER_VALUE:30-300',
- 'load_interval_counter': 'INTEGER_VALUE:1-3',
- 'mac_accessgroup_name': 'TEXT:',
- 'mac_address': 'TEXT:',
- 'microburst_threshold': 'NO_VALIDATION:1-4294967295',
- 'mtu_value': 'INTEGER_VALUE:64-9216',
- 'service_instance': 'NO_VALIDATION:1-4294967295',
- 'service_policy_options': 'TEXT_OPTIONS:copp-system-policy,input,\
- output,type',
- 'service_policy_name': 'TEXT:',
- 'spanning_tree_options': 'TEXT_OPTIONS:bpdufilter,bpduguard,\
- cost,disable,enable,guard,link-type,mst,port,port-priority,vlan',
- 'spanning_tree_cost': 'NO_VALIDATION:1-200000000',
- 'spanning_tree_interfacerange': 'INTEGER_VALUE_RANGE:1-3999',
- 'spanning_tree_portpriority': 'TEXT_OPTIONS:0,32,64,96,128,160,\
- 192,224',
- 'portchannel_ipv6_neighbor_mac': 'TEXT:',
- 'portchannel_ipv6_neighbor_address': 'IPV6Address:',
- 'portchannel_ipv6_linklocal': 'IPV6Address:',
- 'portchannel_ipv6_dhcp_vlan': 'INTEGER_VALUE:1-4094',
- 'portchannel_ipv6_dhcp_ethernet': 'TEXT:',
- 'portchannel_ipv6_dhcp': 'IPV6Address:',
- 'portchannel_ipv6_address': 'IPV6Address:',
- 'portchannel_ipv6_options': 'TEXT_OPTIONS:address,dhcp,\
- link-local,nd,neighbor',
- 'interface_speed': 'TEXT_OPTIONS:1000,10000,100000,25000,40000,50000,auto',
- 'stormcontrol_options': 'TEXT_OPTIONS:broadcast,multicast,\
- unicast',
- 'stormcontrol_level': 'FLOAT:',
- 'portchannel_dot1q_tag': 'TEXT_OPTIONS:disable,enable,\
- egress-only',
- 'vrrp_id': 'INTEGER_VALUE:1-255',
-}
-NE1032 = {
- 'vlan_id': 'INTEGER_VALUE:1-3999',
- 'vlan_id_range': 'INTEGER_VALUE_RANGE:1-3999',
- 'vlan_name': 'TEXT:',
- 'vlan_flood': 'TEXT_OPTIONS:ipv4,ipv6',
- 'vlan_state': 'TEXT_OPTIONS:active,suspend',
- 'vlan_last_member_query_interval': 'INTEGER_VALUE:1-25',
- 'vlan_querier': 'IPV4Address:',
- 'vlan_querier_timeout': 'INTEGER_VALUE:1-65535',
- 'vlan_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_query_max_response_time': 'INTEGER_VALUE:1-25',
- 'vlan_report_suppression': 'INTEGER_VALUE:1-25',
- 'vlan_robustness_variable': 'INTEGER_VALUE:1-7',
- 'vlan_startup_query_count': 'INTEGER_VALUE:1-10',
- 'vlan_startup_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_snooping_version': 'INTEGER_VALUE:2-3',
- 'vlan_access_map_name': 'TEXT: ',
- 'vlan_ethernet_interface': 'TEXT:',
- 'vlan_portagg_number': 'INTEGER_VALUE:1-4096',
- 'vlan_accessmap_action': 'TEXT_OPTIONS:drop,forward,redirect',
- 'vlan_dot1q_tag': 'MATCH_TEXT_OR_EMPTY:egress-only',
- 'vlan_filter_name': 'TEXT:',
- 'vlag_auto_recovery': 'INTEGER_VALUE:240-3600',
- 'vlag_config_consistency': 'TEXT_OPTIONS:disable,strict',
- 'vlag_instance': 'INTEGER_VALUE:1-64',
- 'vlag_port_aggregation': 'INTEGER_VALUE:1-4096',
- 'vlag_priority': 'INTEGER_VALUE:0-65535',
- 'vlag_startup_delay': 'INTEGER_VALUE:0-3600',
- 'vlag_tier_id': 'INTEGER_VALUE:1-512',
- 'vlag_hlthchk_options': 'TEXT_OPTIONS:keepalive-attempts,\
- keepalive-interval,peer-ip,retry-interval',
- 'vlag_keepalive_attempts': 'INTEGER_VALUE:1-24',
- 'vlag_keepalive_interval': 'INTEGER_VALUE:2-300',
- 'vlag_retry_interval': 'INTEGER_VALUE:1-300',
- 'vlag_peerip': 'IPV4Address:',
- 'vlag_peerip_vrf': 'TEXT_OPTIONS:default,management',
- 'bgp_as_number': 'NO_VALIDATION:1-4294967295',
- 'bgp_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_bgp_local_count': 'INTEGER_VALUE:2-64',
- 'cluster_id_as_ip': 'IPV4Address:',
- 'cluster_id_as_number': 'NO_VALIDATION:1-4294967295',
- 'confederation_identifier': 'INTEGER_VALUE:1-65535',
- 'condeferation_peers_as': 'INTEGER_VALUE:1-65535',
- 'stalepath_delay_value': 'INTEGER_VALUE:1-3600',
- 'maxas_limit_as': 'INTEGER_VALUE:1-2000',
- 'neighbor_ipaddress': 'IPV4Address:',
- 'neighbor_as': 'NO_VALIDATION:1-4294967295',
- 'router_id': 'IPV4Address:',
- 'bgp_keepalive_interval': 'INTEGER_VALUE:0-3600',
- 'bgp_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_aggregate_prefix': 'IPV4AddressWithMask:',
- 'addrfamily_routemap_name': 'TEXT:',
- 'reachability_half_life': 'INTEGER_VALUE:1-45',
- 'start_reuse_route_value': 'INTEGER_VALUE:1-20000',
- 'start_suppress_route_value': 'INTEGER_VALUE:1-20000',
- 'max_duration_to_suppress_route': 'INTEGER_VALUE:1-255',
- 'unreachability_halftime_for_penalty': 'INTEGER_VALUE:1-45',
- 'distance_external_AS': 'INTEGER_VALUE:1-255',
- 'distance_internal_AS': 'INTEGER_VALUE:1-255',
- 'distance_local_routes': 'INTEGER_VALUE:1-255',
- 'maxpath_option': 'TEXT_OPTIONS:ebgp,ibgp',
- 'maxpath_numbers': 'INTEGER_VALUE:2-32',
- 'network_ip_prefix_with_mask': 'IPV4AddressWithMask:',
- 'network_ip_prefix_value': 'IPV4Address:',
- 'network_ip_prefix_mask': 'IPV4Address:',
- 'nexthop_crtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'nexthop_noncrtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'addrfamily_redistribute_option': 'TEXT_OPTIONS:direct,ospf,\
- static',
- 'bgp_neighbor_af_occurances': 'INTEGER_VALUE:1-10',
- 'bgp_neighbor_af_filtername': 'TEXT:',
- 'bgp_neighbor_af_maxprefix': 'INTEGER_VALUE:1-15870',
- 'bgp_neighbor_af_prefixname': 'TEXT:',
- 'bgp_neighbor_af_routemap': 'TEXT:',
- 'bgp_neighbor_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_neighbor_connection_retrytime': 'INTEGER_VALUE:1-65535',
- 'bgp_neighbor_description': 'TEXT:',
- 'bgp_neighbor_maxhopcount': 'INTEGER_VALUE:1-255',
- 'bgp_neighbor_local_as': 'NO_VALIDATION:1-4294967295',
- 'bgp_neighbor_maxpeers': 'INTEGER_VALUE:1-96',
- 'bgp_neighbor_password': 'TEXT:',
- 'bgp_neighbor_timers_Keepalive': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_timers_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_ttl_hops': 'INTEGER_VALUE:1-254',
- 'bgp_neighbor_update_options': 'TEXT_OPTIONS:ethernet,loopback,\
- vlan',
- 'bgp_neighbor_update_ethernet': 'TEXT:',
- 'bgp_neighbor_update_loopback': 'INTEGER_VALUE:0-7',
- 'bgp_neighbor_update_vlan': 'INTEGER_VALUE:1-4094',
- 'bgp_neighbor_weight': 'INTEGER_VALUE:0-65535',
- 'ethernet_interface_value': 'INTEGER_VALUE:1-32',
- 'ethernet_interface_range': 'INTEGER_VALUE_RANGE:1-32',
- 'ethernet_interface_string': 'TEXT:',
- 'loopback_interface_value': 'INTEGER_VALUE:0-7',
- 'mgmt_interface_value': 'INTEGER_VALUE:0-0',
- 'vlan_interface_value': 'INTEGER_VALUE:1-4094',
- 'portchannel_interface_value': 'INTEGER_VALUE:1-4096',
- 'portchannel_interface_range': 'INTEGER_VALUE_RANGE:1-4096',
- 'portchannel_interface_string': 'TEXT:',
- 'aggregation_group_no': 'INTEGER_VALUE:1-4096',
- 'aggregation_group_mode': 'TEXT_OPTIONS:active,on,passive',
- 'bfd_options': 'TEXT_OPTIONS:authentication,echo,interval,ipv4,\
- ipv6,neighbor',
- 'bfd_interval': 'INTEGER_VALUE:50-999',
- 'bfd_minrx': 'INTEGER_VALUE:50-999',
- 'bfd_ multiplier': 'INTEGER_VALUE:3-50',
- 'bfd_ipv4_options': 'TEXT_OPTIONS:authentication,echo,interval',
- 'bfd_auth_options': 'TEXT_OPTIONS:keyed-md5,keyed-sha1,\
- meticulous-keyed-md5,meticulous-keyed-sha1,simple',
- 'bfd_key_options': 'TEXT_OPTIONS:key-chain,key-id',
- 'bfd_key_chain': 'TEXT:',
- 'bfd_key_id': 'INTEGER_VALUE:0-255',
- 'bfd_key_name': 'TEXT:',
- 'bfd_neighbor_ip': 'TEXT:',
- 'bfd_neighbor_options': 'TEXT_OPTIONS:admin-down,multihop,\
- non-persistent',
- 'bfd_access_vlan': 'INTEGER_VALUE:1-3999',
- 'bfd_bridgeport_mode': 'TEXT_OPTIONS:access,dot1q-tunnel,trunk',
- 'trunk_options': 'TEXT_OPTIONS:allowed,native',
- 'trunk_vlanid': 'INTEGER_VALUE:1-3999',
- 'portCh_description': 'TEXT:',
- 'duplex_option': 'TEXT_OPTIONS:auto,full,half',
- 'flowcontrol_options': 'TEXT_OPTIONS:receive,send',
- 'portchannel_ip_options': 'TEXT_OPTIONS:access-group,address,\
- arp,dhcp,ospf,port,port-unreachable,redirects,router,\
- unreachables',
- 'accessgroup_name': 'TEXT:',
- 'portchannel_ipv4': 'IPV4Address:',
- 'portchannel_ipv4_mask': 'TEXT:',
- 'arp_ipaddress': 'IPV4Address:',
- 'arp_macaddress': 'TEXT:',
- 'arp_timeout_value': 'INTEGER_VALUE:60-28800',
- 'relay_ipaddress': 'IPV4Address:',
- 'ip_ospf_options': 'TEXT_OPTIONS:authentication,\
- authentication-key,bfd,cost,database-filter,dead-interval,\
- hello-interval,message-digest-key,mtu,mtu-ignore,network,\
- passive-interface,priority,retransmit-interval,shutdown,\
- transmit-delay',
- 'ospf_id_decimal_value': 'NO_VALIDATION:1-4294967295',
- 'ospf_id_ipaddres_value': 'IPV4Address:',
- 'lacp_options': 'TEXT_OPTIONS:port-priority,suspend-individual,\
- timeout',
- 'port_priority': 'INTEGER_VALUE:1-65535',
- 'lldp_options': 'TEXT_OPTIONS:receive,tlv-select,transmit,\
- trap-notification',
- 'lldp_tlv_options': 'TEXT_OPTIONS:link-aggregation,\
- mac-phy-status,management-address,max-frame-size,\
- port-description,port-protocol-vlan,port-vlan,power-mdi,\
- protocol-identity,system-capabilities,system-description,\
- system-name,vid-management,vlan-name',
- 'load_interval_delay': 'INTEGER_VALUE:30-300',
- 'load_interval_counter': 'INTEGER_VALUE:1-3',
- 'mac_accessgroup_name': 'TEXT:',
- 'mac_address': 'TEXT:',
- 'microburst_threshold': 'NO_VALIDATION:1-4294967295',
- 'mtu_value': 'INTEGER_VALUE:64-9216',
- 'service_instance': 'NO_VALIDATION:1-4294967295',
- 'service_policy_options': 'TEXT_OPTIONS:copp-system-policy,input,\
- output,type',
- 'service_policy_name': 'TEXT:',
- 'spanning_tree_options': 'TEXT_OPTIONS:bpdufilter,bpduguard,\
- cost,disable,enable,guard,link-type,mst,port,port-priority,vlan',
- 'spanning_tree_cost': 'NO_VALIDATION:1-200000000',
- 'spanning_tree_interfacerange': 'INTEGER_VALUE_RANGE:1-3999',
- 'spanning_tree_portpriority': 'TEXT_OPTIONS:0,32,64,96,128,160,\
- 192,224',
- 'portchannel_ipv6_neighbor_mac': 'TEXT:',
- 'portchannel_ipv6_neighbor_address': 'IPV6Address:',
- 'portchannel_ipv6_linklocal': 'IPV6Address:',
- 'portchannel_ipv6_dhcp_vlan': 'INTEGER_VALUE:1-4094',
- 'portchannel_ipv6_dhcp_ethernet': 'TEXT:',
- 'portchannel_ipv6_dhcp': 'IPV6Address:',
- 'portchannel_ipv6_address': 'IPV6Address:',
- 'portchannel_ipv6_options': 'TEXT_OPTIONS:address,dhcp,\
- link-local,nd,neighbor',
- 'interface_speed': 'TEXT_OPTIONS:1000,10000,100000,25000,40000,50000,auto',
- 'stormcontrol_options': 'TEXT_OPTIONS:broadcast,multicast,\
- unicast',
- 'stormcontrol_level': 'FLOAT:',
- 'portchannel_dot1q_tag': 'TEXT_OPTIONS:disable,enable,\
- egress-only',
- 'vrrp_id': 'INTEGER_VALUE:1-255',
-}
-NE1072T = {
- 'vlan_id': 'INTEGER_VALUE:1-3999',
- 'vlan_id_range': 'INTEGER_VALUE_RANGE:1-3999',
- 'vlan_name': 'TEXT:',
- 'vlan_flood': 'TEXT_OPTIONS:ipv4,ipv6',
- 'vlan_state': 'TEXT_OPTIONS:active,suspend',
- 'vlan_last_member_query_interval': 'INTEGER_VALUE:1-25',
- 'vlan_querier': 'IPV4Address:',
- 'vlan_querier_timeout': 'INTEGER_VALUE:1-65535',
- 'vlan_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_query_max_response_time': 'INTEGER_VALUE:1-25',
- 'vlan_report_suppression': 'INTEGER_VALUE:1-25',
- 'vlan_robustness_variable': 'INTEGER_VALUE:1-7',
- 'vlan_startup_query_count': 'INTEGER_VALUE:1-10',
- 'vlan_startup_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_snooping_version': 'INTEGER_VALUE:2-3',
- 'vlan_access_map_name': 'TEXT: ',
- 'vlan_ethernet_interface': 'TEXT:',
- 'vlan_portagg_number': 'INTEGER_VALUE:1-4096',
- 'vlan_accessmap_action': 'TEXT_OPTIONS:drop,forward,redirect',
- 'vlan_dot1q_tag': 'MATCH_TEXT_OR_EMPTY:egress-only',
- 'vlan_filter_name': 'TEXT:',
- 'vlag_auto_recovery': 'INTEGER_VALUE:240-3600',
- 'vlag_config_consistency': 'TEXT_OPTIONS:disable,strict',
- 'vlag_instance': 'INTEGER_VALUE:1-64',
- 'vlag_port_aggregation': 'INTEGER_VALUE:1-4096',
- 'vlag_priority': 'INTEGER_VALUE:0-65535',
- 'vlag_startup_delay': 'INTEGER_VALUE:0-3600',
- 'vlag_tier_id': 'INTEGER_VALUE:1-512',
- 'vlag_hlthchk_options': 'TEXT_OPTIONS:keepalive-attempts,\
- keepalive-interval,peer-ip,retry-interval',
- 'vlag_keepalive_attempts': 'INTEGER_VALUE:1-24',
- 'vlag_keepalive_interval': 'INTEGER_VALUE:2-300',
- 'vlag_retry_interval': 'INTEGER_VALUE:1-300',
- 'vlag_peerip': 'IPV4Address:',
- 'vlag_peerip_vrf': 'TEXT_OPTIONS:default,management',
- 'bgp_as_number': 'NO_VALIDATION:1-4294967295',
- 'bgp_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_bgp_local_count': 'INTEGER_VALUE:2-64',
- 'cluster_id_as_ip': 'IPV4Address:',
- 'cluster_id_as_number': 'NO_VALIDATION:1-4294967295',
- 'confederation_identifier': 'INTEGER_VALUE:1-65535',
- 'condeferation_peers_as': 'INTEGER_VALUE:1-65535',
- 'stalepath_delay_value': 'INTEGER_VALUE:1-3600',
- 'maxas_limit_as': 'INTEGER_VALUE:1-2000',
- 'neighbor_ipaddress': 'IPV4Address:',
- 'neighbor_as': 'NO_VALIDATION:1-4294967295',
- 'router_id': 'IPV4Address:',
- 'bgp_keepalive_interval': 'INTEGER_VALUE:0-3600',
- 'bgp_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_aggregate_prefix': 'IPV4AddressWithMask:',
- 'addrfamily_routemap_name': 'TEXT:',
- 'reachability_half_life': 'INTEGER_VALUE:1-45',
- 'start_reuse_route_value': 'INTEGER_VALUE:1-20000',
- 'start_suppress_route_value': 'INTEGER_VALUE:1-20000',
- 'max_duration_to_suppress_route': 'INTEGER_VALUE:1-255',
- 'unreachability_halftime_for_penalty': 'INTEGER_VALUE:1-45',
- 'distance_external_AS': 'INTEGER_VALUE:1-255',
- 'distance_internal_AS': 'INTEGER_VALUE:1-255',
- 'distance_local_routes': 'INTEGER_VALUE:1-255',
- 'maxpath_option': 'TEXT_OPTIONS:ebgp,ibgp',
- 'maxpath_numbers': 'INTEGER_VALUE:2-32',
- 'network_ip_prefix_with_mask': 'IPV4AddressWithMask:',
- 'network_ip_prefix_value': 'IPV4Address:',
- 'network_ip_prefix_mask': 'IPV4Address:',
- 'nexthop_crtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'nexthop_noncrtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'addrfamily_redistribute_option': 'TEXT_OPTIONS:direct,ospf,\
- static',
- 'bgp_neighbor_af_occurances': 'INTEGER_VALUE:1-10',
- 'bgp_neighbor_af_filtername': 'TEXT:',
- 'bgp_neighbor_af_maxprefix': 'INTEGER_VALUE:1-15870',
- 'bgp_neighbor_af_prefixname': 'TEXT:',
- 'bgp_neighbor_af_routemap': 'TEXT:',
- 'bgp_neighbor_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_neighbor_connection_retrytime': 'INTEGER_VALUE:1-65535',
- 'bgp_neighbor_description': 'TEXT:',
- 'bgp_neighbor_maxhopcount': 'INTEGER_VALUE:1-255',
- 'bgp_neighbor_local_as': 'NO_VALIDATION:1-4294967295',
- 'bgp_neighbor_maxpeers': 'INTEGER_VALUE:1-96',
- 'bgp_neighbor_password': 'TEXT:',
- 'bgp_neighbor_timers_Keepalive': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_timers_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_ttl_hops': 'INTEGER_VALUE:1-254',
- 'bgp_neighbor_update_options': 'TEXT_OPTIONS:ethernet,loopback,\
- vlan',
- 'bgp_neighbor_update_ethernet': 'TEXT:',
- 'bgp_neighbor_update_loopback': 'INTEGER_VALUE:0-7',
- 'bgp_neighbor_update_vlan': 'INTEGER_VALUE:1-4094',
- 'bgp_neighbor_weight': 'INTEGER_VALUE:0-65535',
- 'ethernet_interface_value': 'INTEGER_VALUE:1-54',
- 'ethernet_interface_range': 'INTEGER_VALUE_RANGE:1-54',
- 'ethernet_interface_string': 'TEXT:',
- 'loopback_interface_value': 'INTEGER_VALUE:0-7',
- 'mgmt_interface_value': 'INTEGER_VALUE:0-0',
- 'vlan_interface_value': 'INTEGER_VALUE:1-4094',
- 'portchannel_interface_value': 'INTEGER_VALUE:1-4096',
- 'portchannel_interface_range': 'INTEGER_VALUE_RANGE:1-4096',
- 'portchannel_interface_string': 'TEXT:',
- 'aggregation_group_no': 'INTEGER_VALUE:1-4096',
- 'aggregation_group_mode': 'TEXT_OPTIONS:active,on,passive',
- 'bfd_options': 'TEXT_OPTIONS:authentication,echo,interval,ipv4,\
- ipv6,neighbor',
- 'bfd_interval': 'INTEGER_VALUE:50-999',
- 'bfd_minrx': 'INTEGER_VALUE:50-999',
- 'bfd_ multiplier': 'INTEGER_VALUE:3-50',
- 'bfd_ipv4_options': 'TEXT_OPTIONS:authentication,echo,interval',
- 'bfd_auth_options': 'TEXT_OPTIONS:keyed-md5,keyed-sha1,\
- meticulous-keyed-md5,meticulous-keyed-sha1,simple',
- 'bfd_key_options': 'TEXT_OPTIONS:key-chain,key-id',
- 'bfd_key_chain': 'TEXT:',
- 'bfd_key_id': 'INTEGER_VALUE:0-255',
- 'bfd_key_name': 'TEXT:',
- 'bfd_neighbor_ip': 'TEXT:',
- 'bfd_neighbor_options': 'TEXT_OPTIONS:admin-down,multihop,\
- non-persistent',
- 'bfd_access_vlan': 'INTEGER_VALUE:1-3999',
- 'bfd_bridgeport_mode': 'TEXT_OPTIONS:access,dot1q-tunnel,trunk',
- 'trunk_options': 'TEXT_OPTIONS:allowed,native',
- 'trunk_vlanid': 'INTEGER_VALUE:1-3999',
- 'portCh_description': 'TEXT:',
- 'duplex_option': 'TEXT_OPTIONS:auto,full,half',
- 'flowcontrol_options': 'TEXT_OPTIONS:receive,send',
- 'portchannel_ip_options': 'TEXT_OPTIONS:access-group,address,\
- arp,dhcp,ospf,port,port-unreachable,redirects,router,\
- unreachables',
- 'accessgroup_name': 'TEXT:',
- 'portchannel_ipv4': 'IPV4Address:',
- 'portchannel_ipv4_mask': 'TEXT:',
- 'arp_ipaddress': 'IPV4Address:',
- 'arp_macaddress': 'TEXT:',
- 'arp_timeout_value': 'INTEGER_VALUE:60-28800',
- 'relay_ipaddress': 'IPV4Address:',
- 'ip_ospf_options': 'TEXT_OPTIONS:authentication,\
- authentication-key,bfd,cost,database-filter,dead-interval,\
- hello-interval,message-digest-key,mtu,mtu-ignore,network,\
- passive-interface,priority,retransmit-interval,shutdown,\
- transmit-delay',
- 'ospf_id_decimal_value': 'NO_VALIDATION:1-4294967295',
- 'ospf_id_ipaddres_value': 'IPV4Address:',
- 'lacp_options': 'TEXT_OPTIONS:port-priority,suspend-individual,\
- timeout',
- 'port_priority': 'INTEGER_VALUE:1-65535',
- 'lldp_options': 'TEXT_OPTIONS:receive,tlv-select,transmit,\
- trap-notification',
- 'lldp_tlv_options': 'TEXT_OPTIONS:link-aggregation,\
- mac-phy-status,management-address,max-frame-size,\
- port-description,port-protocol-vlan,port-vlan,power-mdi,\
- protocol-identity,system-capabilities,system-description,\
- system-name,vid-management,vlan-name',
- 'load_interval_delay': 'INTEGER_VALUE:30-300',
- 'load_interval_counter': 'INTEGER_VALUE:1-3',
- 'mac_accessgroup_name': 'TEXT:',
- 'mac_address': 'TEXT:',
- 'microburst_threshold': 'NO_VALIDATION:1-4294967295',
- 'mtu_value': 'INTEGER_VALUE:64-9216',
- 'service_instance': 'NO_VALIDATION:1-4294967295',
- 'service_policy_options': 'TEXT_OPTIONS:copp-system-policy,input,\
- output,type',
- 'service_policy_name': 'TEXT:',
- 'spanning_tree_options': 'TEXT_OPTIONS:bpdufilter,bpduguard,\
- cost,disable,enable,guard,link-type,mst,port,port-priority,vlan',
- 'spanning_tree_cost': 'NO_VALIDATION:1-200000000',
- 'spanning_tree_interfacerange': 'INTEGER_VALUE_RANGE:1-3999',
- 'spanning_tree_portpriority': 'TEXT_OPTIONS:0,32,64,96,128,160,\
- 192,224',
- 'portchannel_ipv6_neighbor_mac': 'TEXT:',
- 'portchannel_ipv6_neighbor_address': 'IPV6Address:',
- 'portchannel_ipv6_linklocal': 'IPV6Address:',
- 'portchannel_ipv6_dhcp_vlan': 'INTEGER_VALUE:1-4094',
- 'portchannel_ipv6_dhcp_ethernet': 'TEXT:',
- 'portchannel_ipv6_dhcp': 'IPV6Address:',
- 'portchannel_ipv6_address': 'IPV6Address:',
- 'portchannel_ipv6_options': 'TEXT_OPTIONS:address,dhcp,\
- link-local,nd,neighbor',
- 'interface_speed': 'TEXT_OPTIONS:1000,10000,100000,25000,40000,50000,auto',
- 'stormcontrol_options': 'TEXT_OPTIONS:broadcast,multicast,\
- unicast',
- 'stormcontrol_level': 'FLOAT:',
- 'portchannel_dot1q_tag': 'TEXT_OPTIONS:disable,enable,\
- egress-only',
- 'vrrp_id': 'INTEGER_VALUE:1-255',
-}
-NE10032 = {
- 'vlan_id': 'INTEGER_VALUE:1-3999',
- 'vlan_id_range': 'INTEGER_VALUE_RANGE:1-3999',
- 'vlan_name': 'TEXT:',
- 'vlan_flood': 'TEXT_OPTIONS:ipv4,ipv6',
- 'vlan_state': 'TEXT_OPTIONS:active,suspend',
- 'vlan_last_member_query_interval': 'INTEGER_VALUE:1-25',
- 'vlan_querier': 'IPV4Address:',
- 'vlan_querier_timeout': 'INTEGER_VALUE:1-65535',
- 'vlan_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_query_max_response_time': 'INTEGER_VALUE:1-25',
- 'vlan_report_suppression': 'INTEGER_VALUE:1-25',
- 'vlan_robustness_variable': 'INTEGER_VALUE:1-7',
- 'vlan_startup_query_count': 'INTEGER_VALUE:1-10',
- 'vlan_startup_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_snooping_version': 'INTEGER_VALUE:2-3',
- 'vlan_access_map_name': 'TEXT: ',
- 'vlan_ethernet_interface': 'TEXT:',
- 'vlan_portagg_number': 'INTEGER_VALUE:1-4096',
- 'vlan_accessmap_action': 'TEXT_OPTIONS:drop,forward,redirect',
- 'vlan_dot1q_tag': 'MATCH_TEXT_OR_EMPTY:egress-only',
- 'vlan_filter_name': 'TEXT:',
- 'vlag_auto_recovery': 'INTEGER_VALUE:240-3600',
- 'vlag_config_consistency': 'TEXT_OPTIONS:disable,strict',
- 'vlag_instance': 'INTEGER_VALUE:1-64',
- 'vlag_port_aggregation': 'INTEGER_VALUE:1-4096',
- 'vlag_priority': 'INTEGER_VALUE:0-65535',
- 'vlag_startup_delay': 'INTEGER_VALUE:0-3600',
- 'vlag_tier_id': 'INTEGER_VALUE:1-512',
- 'vlag_hlthchk_options': 'TEXT_OPTIONS:keepalive-attempts,\
- keepalive-interval,peer-ip,retry-interval',
- 'vlag_keepalive_attempts': 'INTEGER_VALUE:1-24',
- 'vlag_keepalive_interval': 'INTEGER_VALUE:2-300',
- 'vlag_retry_interval': 'INTEGER_VALUE:1-300',
- 'vlag_peerip': 'IPV4Address:',
- 'vlag_peerip_vrf': 'TEXT_OPTIONS:default,management',
- 'bgp_as_number': 'NO_VALIDATION:1-4294967295',
- 'bgp_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_bgp_local_count': 'INTEGER_VALUE:2-64',
- 'cluster_id_as_ip': 'IPV4Address:',
- 'cluster_id_as_number': 'NO_VALIDATION:1-4294967295',
- 'confederation_identifier': 'INTEGER_VALUE:1-65535',
- 'condeferation_peers_as': 'INTEGER_VALUE:1-65535',
- 'stalepath_delay_value': 'INTEGER_VALUE:1-3600',
- 'maxas_limit_as': 'INTEGER_VALUE:1-2000',
- 'neighbor_ipaddress': 'IPV4Address:',
- 'neighbor_as': 'NO_VALIDATION:1-4294967295',
- 'router_id': 'IPV4Address:',
- 'bgp_keepalive_interval': 'INTEGER_VALUE:0-3600',
- 'bgp_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_aggregate_prefix': 'IPV4AddressWithMask:',
- 'addrfamily_routemap_name': 'TEXT:',
- 'reachability_half_life': 'INTEGER_VALUE:1-45',
- 'start_reuse_route_value': 'INTEGER_VALUE:1-20000',
- 'start_suppress_route_value': 'INTEGER_VALUE:1-20000',
- 'max_duration_to_suppress_route': 'INTEGER_VALUE:1-255',
- 'unreachability_halftime_for_penalty': 'INTEGER_VALUE:1-45',
- 'distance_external_AS': 'INTEGER_VALUE:1-255',
- 'distance_internal_AS': 'INTEGER_VALUE:1-255',
- 'distance_local_routes': 'INTEGER_VALUE:1-255',
- 'maxpath_option': 'TEXT_OPTIONS:ebgp,ibgp',
- 'maxpath_numbers': 'INTEGER_VALUE:2-32',
- 'network_ip_prefix_with_mask': 'IPV4AddressWithMask:',
- 'network_ip_prefix_value': 'IPV4Address:',
- 'network_ip_prefix_mask': 'IPV4Address:',
- 'nexthop_crtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'nexthop_noncrtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'addrfamily_redistribute_option': 'TEXT_OPTIONS:direct,ospf,\
- static',
- 'bgp_neighbor_af_occurances': 'INTEGER_VALUE:1-10',
- 'bgp_neighbor_af_filtername': 'TEXT:',
- 'bgp_neighbor_af_maxprefix': 'INTEGER_VALUE:1-15870',
- 'bgp_neighbor_af_prefixname': 'TEXT:',
- 'bgp_neighbor_af_routemap': 'TEXT:',
- 'bgp_neighbor_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_neighbor_connection_retrytime': 'INTEGER_VALUE:1-65535',
- 'bgp_neighbor_description': 'TEXT:',
- 'bgp_neighbor_maxhopcount': 'INTEGER_VALUE:1-255',
- 'bgp_neighbor_local_as': 'NO_VALIDATION:1-4294967295',
- 'bgp_neighbor_maxpeers': 'INTEGER_VALUE:1-96',
- 'bgp_neighbor_password': 'TEXT:',
- 'bgp_neighbor_timers_Keepalive': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_timers_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_ttl_hops': 'INTEGER_VALUE:1-254',
- 'bgp_neighbor_update_options': 'TEXT_OPTIONS:ethernet,loopback,\
- vlan',
- 'bgp_neighbor_update_ethernet': 'TEXT:',
- 'bgp_neighbor_update_loopback': 'INTEGER_VALUE:0-7',
- 'bgp_neighbor_update_vlan': 'INTEGER_VALUE:1-4094',
- 'bgp_neighbor_weight': 'INTEGER_VALUE:0-65535',
- 'ethernet_interface_value': 'INTEGER_VALUE:1-32',
- 'ethernet_interface_range': 'INTEGER_VALUE_RANGE:1-32',
- 'ethernet_interface_string': 'TEXT:',
- 'loopback_interface_value': 'INTEGER_VALUE:0-7',
- 'mgmt_interface_value': 'INTEGER_VALUE:0-0',
- 'vlan_interface_value': 'INTEGER_VALUE:1-4094',
- 'portchannel_interface_value': 'INTEGER_VALUE:1-4096',
- 'portchannel_interface_range': 'INTEGER_VALUE_RANGE:1-4096',
- 'portchannel_interface_string': 'TEXT:',
- 'aggregation_group_no': 'INTEGER_VALUE:1-4096',
- 'aggregation_group_mode': 'TEXT_OPTIONS:active,on,passive',
- 'bfd_options': 'TEXT_OPTIONS:authentication,echo,interval,ipv4,\
- ipv6,neighbor',
- 'bfd_interval': 'INTEGER_VALUE:50-999',
- 'bfd_minrx': 'INTEGER_VALUE:50-999',
- 'bfd_ multiplier': 'INTEGER_VALUE:3-50',
- 'bfd_ipv4_options': 'TEXT_OPTIONS:authentication,echo,interval',
- 'bfd_auth_options': 'TEXT_OPTIONS:keyed-md5,keyed-sha1,\
- meticulous-keyed-md5,meticulous-keyed-sha1,simple',
- 'bfd_key_options': 'TEXT_OPTIONS:key-chain,key-id',
- 'bfd_key_chain': 'TEXT:',
- 'bfd_key_id': 'INTEGER_VALUE:0-255',
- 'bfd_key_name': 'TEXT:',
- 'bfd_neighbor_ip': 'TEXT:',
- 'bfd_neighbor_options': 'TEXT_OPTIONS:admin-down,multihop,\
- non-persistent',
- 'bfd_access_vlan': 'INTEGER_VALUE:1-3999',
- 'bfd_bridgeport_mode': 'TEXT_OPTIONS:access,dot1q-tunnel,trunk',
- 'trunk_options': 'TEXT_OPTIONS:allowed,native',
- 'trunk_vlanid': 'INTEGER_VALUE:1-3999',
- 'portCh_description': 'TEXT:',
- 'duplex_option': 'TEXT_OPTIONS:auto,full,half',
- 'flowcontrol_options': 'TEXT_OPTIONS:receive,send',
- 'portchannel_ip_options': 'TEXT_OPTIONS:access-group,address,\
- arp,dhcp,ospf,port,port-unreachable,redirects,router,\
- unreachables',
- 'accessgroup_name': 'TEXT:',
- 'portchannel_ipv4': 'IPV4Address:',
- 'portchannel_ipv4_mask': 'TEXT:',
- 'arp_ipaddress': 'IPV4Address:',
- 'arp_macaddress': 'TEXT:',
- 'arp_timeout_value': 'INTEGER_VALUE:60-28800',
- 'relay_ipaddress': 'IPV4Address:',
- 'ip_ospf_options': 'TEXT_OPTIONS:authentication,\
- authentication-key,bfd,cost,database-filter,dead-interval,\
- hello-interval,message-digest-key,mtu,mtu-ignore,network,\
- passive-interface,priority,retransmit-interval,shutdown,\
- transmit-delay',
- 'ospf_id_decimal_value': 'NO_VALIDATION:1-4294967295',
- 'ospf_id_ipaddres_value': 'IPV4Address:',
- 'lacp_options': 'TEXT_OPTIONS:port-priority,suspend-individual,\
- timeout',
- 'port_priority': 'INTEGER_VALUE:1-65535',
- 'lldp_options': 'TEXT_OPTIONS:receive,tlv-select,transmit,\
- trap-notification',
- 'lldp_tlv_options': 'TEXT_OPTIONS:link-aggregation,\
- mac-phy-status,management-address,max-frame-size,\
- port-description,port-protocol-vlan,port-vlan,power-mdi,\
- protocol-identity,system-capabilities,system-description,\
- system-name,vid-management,vlan-name',
- 'load_interval_delay': 'INTEGER_VALUE:30-300',
- 'load_interval_counter': 'INTEGER_VALUE:1-3',
- 'mac_accessgroup_name': 'TEXT:',
- 'mac_address': 'TEXT:',
- 'microburst_threshold': 'NO_VALIDATION:1-4294967295',
- 'mtu_value': 'INTEGER_VALUE:64-9216',
- 'service_instance': 'NO_VALIDATION:1-4294967295',
- 'service_policy_options': 'TEXT_OPTIONS:copp-system-policy,input,\
- output,type',
- 'service_policy_name': 'TEXT:',
- 'spanning_tree_options': 'TEXT_OPTIONS:bpdufilter,bpduguard,\
- cost,disable,enable,guard,link-type,mst,port,port-priority,vlan',
- 'spanning_tree_cost': 'NO_VALIDATION:1-200000000',
- 'spanning_tree_interfacerange': 'INTEGER_VALUE_RANGE:1-3999',
- 'spanning_tree_portpriority': 'TEXT_OPTIONS:0,32,64,96,128,160,\
- 192,224',
- 'portchannel_ipv6_neighbor_mac': 'TEXT:',
- 'portchannel_ipv6_neighbor_address': 'IPV6Address:',
- 'portchannel_ipv6_linklocal': 'IPV6Address:',
- 'portchannel_ipv6_dhcp_vlan': 'INTEGER_VALUE:1-4094',
- 'portchannel_ipv6_dhcp_ethernet': 'TEXT:',
- 'portchannel_ipv6_dhcp': 'IPV6Address:',
- 'portchannel_ipv6_address': 'IPV6Address:',
- 'portchannel_ipv6_options': 'TEXT_OPTIONS:address,dhcp,\
- link-local,nd,neighbor',
- 'interface_speed': 'TEXT_OPTIONS:10000,100000,25000,40000,50000,auto',
- 'stormcontrol_options': 'TEXT_OPTIONS:broadcast,multicast,\
- unicast',
- 'stormcontrol_level': 'FLOAT:',
- 'portchannel_dot1q_tag': 'TEXT_OPTIONS:disable,enable,\
- egress-only',
- 'vrrp_id': 'INTEGER_VALUE:1-255',
-}
-g8272_cnos = {'vlan_id': 'INTEGER_VALUE:1-3999',
- 'vlan_id_range': 'INTEGER_VALUE_RANGE:1-3999',
- 'vlan_name': 'TEXT:',
- 'vlan_flood': 'TEXT_OPTIONS:ipv4,ipv6',
- 'vlan_state': 'TEXT_OPTIONS:active,suspend',
- 'vlan_last_member_query_interval': 'INTEGER_VALUE:1-25',
- 'vlan_querier': 'IPV4Address:',
- 'vlan_querier_timeout': 'INTEGER_VALUE:1-65535',
- 'vlan_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_query_max_response_time': 'INTEGER_VALUE:1-25',
- 'vlan_report_suppression': 'INTEGER_VALUE:1-25',
- 'vlan_robustness_variable': 'INTEGER_VALUE:1-7',
- 'vlan_startup_query_count': 'INTEGER_VALUE:1-10',
- 'vlan_startup_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_snooping_version': 'INTEGER_VALUE:2-3',
- 'vlan_access_map_name': 'TEXT: ',
- 'vlan_ethernet_interface': 'TEXT:',
- 'vlan_portagg_number': 'INTEGER_VALUE:1-4096',
- 'vlan_accessmap_action': 'TEXT_OPTIONS:drop,forward,redirect',
- 'vlan_dot1q_tag': 'MATCH_TEXT_OR_EMPTY:egress-only',
- 'vlan_filter_name': 'TEXT:',
- 'vlag_auto_recovery': 'INTEGER_VALUE:240-3600',
- 'vlag_config_consistency': 'TEXT_OPTIONS:disable,strict',
- 'vlag_instance': 'INTEGER_VALUE:1-64',
- 'vlag_port_aggregation': 'INTEGER_VALUE:1-4096',
- 'vlag_priority': 'INTEGER_VALUE:0-65535',
- 'vlag_startup_delay': 'INTEGER_VALUE:0-3600',
- 'vlag_tier_id': 'INTEGER_VALUE:1-512',
- 'vlag_hlthchk_options': 'TEXT_OPTIONS:keepalive-attempts,\
- keepalive-interval,peer-ip,retry-interval',
- 'vlag_keepalive_attempts': 'INTEGER_VALUE:1-24',
- 'vlag_keepalive_interval': 'INTEGER_VALUE:2-300',
- 'vlag_retry_interval': 'INTEGER_VALUE:1-300',
- 'vlag_peerip': 'IPV4Address:',
- 'vlag_peerip_vrf': 'TEXT_OPTIONS:default,management',
- 'bgp_as_number': 'NO_VALIDATION:1-4294967295',
- 'bgp_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_bgp_local_count': 'INTEGER_VALUE:2-64',
- 'cluster_id_as_ip': 'IPV4Address:',
- 'cluster_id_as_number': 'NO_VALIDATION:1-4294967295',
- 'confederation_identifier': 'INTEGER_VALUE:1-65535',
- 'condeferation_peers_as': 'INTEGER_VALUE:1-65535',
- 'stalepath_delay_value': 'INTEGER_VALUE:1-3600',
- 'maxas_limit_as': 'INTEGER_VALUE:1-2000',
- 'neighbor_ipaddress': 'IPV4Address:',
- 'neighbor_as': 'NO_VALIDATION:1-4294967295',
- 'router_id': 'IPV4Address:',
- 'bgp_keepalive_interval': 'INTEGER_VALUE:0-3600',
- 'bgp_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_aggregate_prefix': 'IPV4AddressWithMask:',
- 'addrfamily_routemap_name': 'TEXT:',
- 'reachability_half_life': 'INTEGER_VALUE:1-45',
- 'start_reuse_route_value': 'INTEGER_VALUE:1-20000',
- 'start_suppress_route_value': 'INTEGER_VALUE:1-20000',
- 'max_duration_to_suppress_route': 'INTEGER_VALUE:1-255',
- 'unreachability_halftime_for_penalty': 'INTEGER_VALUE:1-45',
- 'distance_external_AS': 'INTEGER_VALUE:1-255',
- 'distance_internal_AS': 'INTEGER_VALUE:1-255',
- 'distance_local_routes': 'INTEGER_VALUE:1-255',
- 'maxpath_option': 'TEXT_OPTIONS:ebgp,ibgp',
- 'maxpath_numbers': 'INTEGER_VALUE:2-32',
- 'network_ip_prefix_with_mask': 'IPV4AddressWithMask:',
- 'network_ip_prefix_value': 'IPV4Address:',
- 'network_ip_prefix_mask': 'IPV4Address:',
- 'nexthop_crtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'nexthop_noncrtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'addrfamily_redistribute_option': 'TEXT_OPTIONS:direct,ospf,\
- static',
- 'bgp_neighbor_af_occurances': 'INTEGER_VALUE:1-10',
- 'bgp_neighbor_af_filtername': 'TEXT:',
- 'bgp_neighbor_af_maxprefix': 'INTEGER_VALUE:1-15870',
- 'bgp_neighbor_af_prefixname': 'TEXT:',
- 'bgp_neighbor_af_routemap': 'TEXT:',
- 'bgp_neighbor_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_neighbor_connection_retrytime': 'INTEGER_VALUE:1-65535',
- 'bgp_neighbor_description': 'TEXT:',
- 'bgp_neighbor_maxhopcount': 'INTEGER_VALUE:1-255',
- 'bgp_neighbor_local_as': 'NO_VALIDATION:1-4294967295',
- 'bgp_neighbor_maxpeers': 'INTEGER_VALUE:1-96',
- 'bgp_neighbor_password': 'TEXT:',
- 'bgp_neighbor_timers_Keepalive': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_timers_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_ttl_hops': 'INTEGER_VALUE:1-254',
- 'bgp_neighbor_update_options': 'TEXT_OPTIONS:ethernet,loopback,\
- vlan',
- 'bgp_neighbor_update_ethernet': 'TEXT:',
- 'bgp_neighbor_update_loopback': 'INTEGER_VALUE:0-7',
- 'bgp_neighbor_update_vlan': 'INTEGER_VALUE:1-4094',
- 'bgp_neighbor_weight': 'INTEGER_VALUE:0-65535',
- 'ethernet_interface_value': 'INTEGER_VALUE:1-54',
- 'ethernet_interface_range': 'INTEGER_VALUE_RANGE:1-54',
- 'ethernet_interface_string': 'TEXT:',
- 'loopback_interface_value': 'INTEGER_VALUE:0-7',
- 'mgmt_interface_value': 'INTEGER_VALUE:0-0',
- 'vlan_interface_value': 'INTEGER_VALUE:1-4094',
- 'portchannel_interface_value': 'INTEGER_VALUE:1-4096',
- 'portchannel_interface_range': 'INTEGER_VALUE_RANGE:1-4096',
- 'portchannel_interface_string': 'TEXT:',
- 'aggregation_group_no': 'INTEGER_VALUE:1-4096',
- 'aggregation_group_mode': 'TEXT_OPTIONS:active,on,passive',
- 'bfd_options': 'TEXT_OPTIONS:authentication,echo,interval,ipv4,\
- ipv6,neighbor',
- 'bfd_interval': 'INTEGER_VALUE:50-999',
- 'bfd_minrx': 'INTEGER_VALUE:50-999',
- 'bfd_ multiplier': 'INTEGER_VALUE:3-50',
- 'bfd_ipv4_options': 'TEXT_OPTIONS:authentication,echo,interval',
- 'bfd_auth_options': 'TEXT_OPTIONS:keyed-md5,keyed-sha1,\
- meticulous-keyed-md5,meticulous-keyed-sha1,simple',
- 'bfd_key_options': 'TEXT_OPTIONS:key-chain,key-id',
- 'bfd_key_chain': 'TEXT:',
- 'bfd_key_id': 'INTEGER_VALUE:0-255',
- 'bfd_key_name': 'TEXT:',
- 'bfd_neighbor_ip': 'TEXT:',
- 'bfd_neighbor_options': 'TEXT_OPTIONS:admin-down,multihop,\
- non-persistent',
- 'bfd_access_vlan': 'INTEGER_VALUE:1-3999',
- 'bfd_bridgeport_mode': 'TEXT_OPTIONS:access,dot1q-tunnel,trunk',
- 'trunk_options': 'TEXT_OPTIONS:allowed,native',
- 'trunk_vlanid': 'INTEGER_VALUE:1-3999',
- 'portCh_description': 'TEXT:',
- 'duplex_option': 'TEXT_OPTIONS:auto,full,half',
- 'flowcontrol_options': 'TEXT_OPTIONS:receive,send',
- 'portchannel_ip_options': 'TEXT_OPTIONS:access-group,address,\
- arp,dhcp,ospf,port,port-unreachable,redirects,router,\
- unreachables',
- 'accessgroup_name': 'TEXT:',
- 'portchannel_ipv4': 'IPV4Address:',
- 'portchannel_ipv4_mask': 'TEXT:',
- 'arp_ipaddress': 'IPV4Address:',
- 'arp_macaddress': 'TEXT:',
- 'arp_timeout_value': 'INTEGER_VALUE:60-28800',
- 'relay_ipaddress': 'IPV4Address:',
- 'ip_ospf_options': 'TEXT_OPTIONS:authentication,\
- authentication-key,bfd,cost,database-filter,dead-interval,\
- hello-interval,message-digest-key,mtu,mtu-ignore,network,\
- passive-interface,priority,retransmit-interval,shutdown,\
- transmit-delay',
- 'ospf_id_decimal_value': 'NO_VALIDATION:1-4294967295',
- 'ospf_id_ipaddres_value': 'IPV4Address:',
- 'lacp_options': 'TEXT_OPTIONS:port-priority,suspend-individual,\
- timeout',
- 'port_priority': 'INTEGER_VALUE:1-65535',
- 'lldp_options': 'TEXT_OPTIONS:receive,tlv-select,transmit,\
- trap-notification',
- 'lldp_tlv_options': 'TEXT_OPTIONS:link-aggregation,\
- mac-phy-status,management-address,max-frame-size,\
- port-description,port-protocol-vlan,port-vlan,power-mdi,\
- protocol-identity,system-capabilities,system-description,\
- system-name,vid-management,vlan-name',
- 'load_interval_delay': 'INTEGER_VALUE:30-300',
- 'load_interval_counter': 'INTEGER_VALUE:1-3',
- 'mac_accessgroup_name': 'TEXT:',
- 'mac_address': 'TEXT:',
- 'microburst_threshold': 'NO_VALIDATION:1-4294967295',
- 'mtu_value': 'INTEGER_VALUE:64-9216',
- 'service_instance': 'NO_VALIDATION:1-4294967295',
- 'service_policy_options': 'TEXT_OPTIONS:copp-system-policy,input,\
- output,type',
- 'service_policy_name': 'TEXT:',
- 'spanning_tree_options': 'TEXT_OPTIONS:bpdufilter,bpduguard,\
- cost,disable,enable,guard,link-type,mst,port,port-priority,vlan',
- 'spanning_tree_cost': 'NO_VALIDATION:1-200000000',
- 'spanning_tree_interfacerange': 'INTEGER_VALUE_RANGE:1-3999',
- 'spanning_tree_portpriority': 'TEXT_OPTIONS:0,32,64,96,128,160,\
- 192,224',
- 'portchannel_ipv6_neighbor_mac': 'TEXT:',
- 'portchannel_ipv6_neighbor_address': 'IPV6Address:',
- 'portchannel_ipv6_linklocal': 'IPV6Address:',
- 'portchannel_ipv6_dhcp_vlan': 'INTEGER_VALUE:1-4094',
- 'portchannel_ipv6_dhcp_ethernet': 'TEXT:',
- 'portchannel_ipv6_dhcp': 'IPV6Address:',
- 'portchannel_ipv6_address': 'IPV6Address:',
- 'portchannel_ipv6_options': 'TEXT_OPTIONS:address,dhcp,\
- link-local,nd,neighbor',
- 'interface_speed': 'TEXT_OPTIONS:1000,10000,40000',
- 'stormcontrol_options': 'TEXT_OPTIONS:broadcast,multicast,\
- unicast',
- 'stormcontrol_level': 'FLOAT:',
- 'portchannel_dot1q_tag': 'TEXT_OPTIONS:disable,enable,\
- egress-only',
- 'vrrp_id': 'INTEGER_VALUE:1-255',
- }
-g8296_cnos = {'vlan_id': 'INTEGER_VALUE:1-3999',
- 'vlan_id_range': 'INTEGER_VALUE_RANGE:1-3999',
- 'vlan_name': 'TEXT:',
- 'vlan_flood': 'TEXT_OPTIONS:ipv4,ipv6',
- 'vlan_state': 'TEXT_OPTIONS:active,suspend',
- 'vlan_last_member_query_interval': 'INTEGER_VALUE:1-25',
- 'vlan_querier': 'IPV4Address:',
- 'vlan_querier_timeout': 'INTEGER_VALUE:1-65535',
- 'vlan_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_query_max_response_time': 'INTEGER_VALUE:1-25',
- 'vlan_report_suppression': 'INTEGER_VALUE:1-25',
- 'vlan_robustness_variable': 'INTEGER_VALUE:1-7',
- 'vlan_startup_query_count': 'INTEGER_VALUE:1-10',
- 'vlan_startup_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_snooping_version': 'INTEGER_VALUE:2-3',
- 'vlan_access_map_name': 'TEXT: ',
- 'vlan_ethernet_interface': 'TEXT:',
- 'vlan_portagg_number': 'INTEGER_VALUE:1-4096',
- 'vlan_accessmap_action': 'TEXT_OPTIONS:drop,forward,redirect',
- 'vlan_dot1q_tag': 'MATCH_TEXT_OR_EMPTY:egress-only',
- 'vlan_filter_name': 'TEXT:',
- 'vlag_auto_recovery': 'INTEGER_VALUE:240-3600',
- 'vlag_config_consistency': 'TEXT_OPTIONS:disable,strict',
- 'vlag_instance': 'INTEGER_VALUE:1-128',
- 'vlag_port_aggregation': 'INTEGER_VALUE:1-4096',
- 'vlag_priority': 'INTEGER_VALUE:0-65535',
- 'vlag_startup_delay': 'INTEGER_VALUE:0-3600',
- 'vlag_tier_id': 'INTEGER_VALUE:1-512',
- 'vlag_hlthchk_options': 'TEXT_OPTIONS:keepalive-attempts,\
- keepalive-interval,peer-ip,retry-interval',
- 'vlag_keepalive_attempts': 'INTEGER_VALUE:1-24',
- 'vlag_keepalive_interval': 'INTEGER_VALUE:2-300',
- 'vlag_retry_interval': 'INTEGER_VALUE:1-300',
- 'vlag_peerip': 'IPV4Address:',
- 'vlag_peerip_vrf': 'TEXT_OPTIONS:default,management',
- 'bgp_as_number': 'NO_VALIDATION:1-4294967295',
- 'bgp_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_bgp_local_count': 'INTEGER_VALUE:2-64',
- 'cluster_id_as_ip': 'IPV4Address:',
- 'cluster_id_as_number': 'NO_VALIDATION:1-4294967295',
- 'confederation_identifier': 'INTEGER_VALUE:1-65535',
- 'condeferation_peers_as': 'INTEGER_VALUE:1-65535',
- 'stalepath_delay_value': 'INTEGER_VALUE:1-3600',
- 'maxas_limit_as': 'INTEGER_VALUE:1-2000',
- 'neighbor_ipaddress': 'IPV4Address:',
- 'neighbor_as': 'NO_VALIDATION:1-4294967295',
- 'router_id': 'IPV4Address:',
- 'bgp_keepalive_interval': 'INTEGER_VALUE:0-3600',
- 'bgp_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_aggregate_prefix': 'IPV4AddressWithMask:',
- 'addrfamily_routemap_name': 'TEXT:',
- 'reachability_half_life': 'INTEGER_VALUE:1-45',
- 'start_reuse_route_value': 'INTEGER_VALUE:1-20000',
- 'start_suppress_route_value': 'INTEGER_VALUE:1-20000',
- 'max_duration_to_suppress_route': 'INTEGER_VALUE:1-255',
- 'unreachability_halftime_for_penalty': 'INTEGER_VALUE:1-45',
- 'distance_external_AS': 'INTEGER_VALUE:1-255',
- 'distance_internal_AS': 'INTEGER_VALUE:1-255',
- 'distance_local_routes': 'INTEGER_VALUE:1-255',
- 'maxpath_option': 'TEXT_OPTIONS:ebgp,ibgp',
- 'maxpath_numbers': 'INTEGER_VALUE:2-32',
- 'network_ip_prefix_with_mask': 'IPV4AddressWithMask:',
- 'network_ip_prefix_value': 'IPV4Address:',
- 'network_ip_prefix_mask': 'IPV4Address:',
- 'nexthop_crtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'nexthop_noncrtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'addrfamily_redistribute_option': 'TEXT_OPTIONS:direct,ospf,\
- static',
- 'bgp_neighbor_af_occurances': 'INTEGER_VALUE:1-10',
- 'bgp_neighbor_af_filtername': 'TEXT:',
- 'bgp_neighbor_af_maxprefix': 'INTEGER_VALUE:1-15870',
- 'bgp_neighbor_af_prefixname': 'TEXT:',
- 'bgp_neighbor_af_routemap': 'TEXT:',
- 'bgp_neighbor_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_neighbor_connection_retrytime': 'INTEGER_VALUE:1-65535',
- 'bgp_neighbor_description': 'TEXT:',
- 'bgp_neighbor_maxhopcount': 'INTEGER_VALUE:1-255',
- 'bgp_neighbor_local_as': 'NO_VALIDATION:1-4294967295',
- 'bgp_neighbor_maxpeers': 'INTEGER_VALUE:1-96',
- 'bgp_neighbor_password': 'TEXT:',
- 'bgp_neighbor_timers_Keepalive': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_timers_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_ttl_hops': 'INTEGER_VALUE:1-254',
- 'bgp_neighbor_update_options': 'TEXT_OPTIONS:ethernet,loopback,\
- vlan',
- 'bgp_neighbor_update_ethernet': 'TEXT:',
- 'bgp_neighbor_update_loopback': 'INTEGER_VALUE:0-7',
- 'bgp_neighbor_update_vlan': 'INTEGER_VALUE:1-4094',
- 'bgp_neighbor_weight': 'INTEGER_VALUE:0-65535',
- 'ethernet_interface_value': 'INTEGER_VALUE:1-96',
- 'ethernet_interface_range': 'INTEGER_VALUE_RANGE:1-96',
- 'ethernet_interface_string': 'TEXT:',
- 'loopback_interface_value': 'INTEGER_VALUE:0-7',
- 'mgmt_interface_value': 'INTEGER_VALUE:0-0',
- 'vlan_interface_value': 'INTEGER_VALUE:1-4094',
- 'portchannel_interface_value': 'INTEGER_VALUE:1-4096',
- 'portchannel_interface_range': 'INTEGER_VALUE_RANGE:1-4096',
- 'portchannel_interface_string': 'TEXT:',
- 'aggregation_group_no': 'INTEGER_VALUE:1-4096',
- 'aggregation_group_mode': 'TEXT_OPTIONS:active,on,passive',
- 'bfd_options': 'TEXT_OPTIONS:authentication,echo,interval,ipv4,\
- ipv6,neighbor',
- 'bfd_interval': 'INTEGER_VALUE:50-999',
- 'bfd_minrx': 'INTEGER_VALUE:50-999',
- 'bfd_ multiplier': 'INTEGER_VALUE:3-50',
- 'bfd_ipv4_options': 'TEXT_OPTIONS:authentication,echo,interval',
- 'bfd_auth_options': 'TEXT_OPTIONS:keyed-md5,keyed-sha1,\
- meticulous-keyed-md5,meticulous-keyed-sha1,simple',
- 'bfd_key_options': 'TEXT_OPTIONS:key-chain,key-id',
- 'bfd_key_chain': 'TEXT:',
- 'bfd_key_id': 'INTEGER_VALUE:0-255',
- 'bfd_key_name': 'TEXT:',
- 'bfd_neighbor_ip': 'TEXT:',
- 'bfd_neighbor_options': 'TEXT_OPTIONS:admin-down,multihop,\
- non-persistent',
- 'bfd_access_vlan': 'INTEGER_VALUE:1-3999',
- 'bfd_bridgeport_mode': 'TEXT_OPTIONS:access,dot1q-tunnel,trunk',
- 'trunk_options': 'TEXT_OPTIONS:allowed,native',
- 'trunk_vlanid': 'INTEGER_VALUE:1-3999',
- 'portCh_description': 'TEXT:',
- 'duplex_option': 'TEXT_OPTIONS:auto,full,half',
- 'flowcontrol_options': 'TEXT_OPTIONS:receive,send',
- 'portchannel_ip_options': 'TEXT_OPTIONS:access-group,address,\
- arp,dhcp,ospf,port,port-unreachable,redirects,router,\
- unreachables',
- 'accessgroup_name': 'TEXT:',
- 'portchannel_ipv4': 'IPV4Address:',
- 'portchannel_ipv4_mask': 'TEXT:',
- 'arp_ipaddress': 'IPV4Address:',
- 'arp_macaddress': 'TEXT:',
- 'arp_timeout_value': 'INTEGER_VALUE:60-28800',
- 'relay_ipaddress': 'IPV4Address:',
- 'ip_ospf_options': 'TEXT_OPTIONS:authentication,\
- authentication-key,bfd,cost,database-filter,dead-interval,\
- hello-interval,message-digest-key,mtu,mtu-ignore,network,\
- passive-interface,priority,retransmit-interval,shutdown,\
- transmit-delay',
- 'ospf_id_decimal_value': 'NO_VALIDATION:1-4294967295',
- 'ospf_id_ipaddres_value': 'IPV4Address:',
- 'lacp_options': 'TEXT_OPTIONS:port-priority,suspend-individual,\
- timeout',
- 'port_priority': 'INTEGER_VALUE:1-65535',
- 'lldp_options': 'TEXT_OPTIONS:receive,tlv-select,transmit,\
- trap-notification',
- 'lldp_tlv_options': 'TEXT_OPTIONS:link-aggregation,\
- mac-phy-status,management-address,max-frame-size,\
- port-description,port-protocol-vlan,port-vlan,power-mdi,\
- protocol-identity,system-capabilities,system-description,\
- system-name,vid-management,vlan-name',
- 'load_interval_delay': 'INTEGER_VALUE:30-300',
- 'load_interval_counter': 'INTEGER_VALUE:1-3',
- 'mac_accessgroup_name': 'TEXT:',
- 'mac_address': 'TEXT:',
- 'microburst_threshold': 'NO_VALIDATION:1-4294967295',
- 'mtu_value': 'INTEGER_VALUE:64-9216',
- 'service_instance': 'NO_VALIDATION:1-4294967295',
- 'service_policy_options': 'TEXT_OPTIONS:copp-system-policy,\
- input,output,type',
- 'service_policy_name': 'TEXT:',
- 'spanning_tree_options': 'TEXT_OPTIONS:bpdufilter,bpduguard,\
- cost,disable,enable,guard,link-type,mst,port,port-priority,vlan',
- 'spanning_tree_cost': 'NO_VALIDATION:1-200000000',
- 'spanning_tree_interfacerange': 'INTEGER_VALUE_RANGE:1-3999',
- 'spanning_tree_portpriority': 'TEXT_OPTIONS:0,32,64,96,128,160,\
- 192,224',
- 'portchannel_ipv6_neighbor_mac': 'TEXT:',
- 'portchannel_ipv6_neighbor_address': 'IPV6Address:',
- 'portchannel_ipv6_linklocal': 'IPV6Address:',
- 'portchannel_ipv6_dhcp_vlan': 'INTEGER_VALUE:1-4094',
- 'portchannel_ipv6_dhcp_ethernet': 'TEXT:',
- 'portchannel_ipv6_dhcp': 'IPV6Address:',
- 'portchannel_ipv6_address': 'IPV6Address:',
- 'portchannel_ipv6_options': 'TEXT_OPTIONS:address,dhcp,\
- link-local,nd,neighbor',
- 'interface_speed': 'TEXT_OPTIONS:1000,10000,40000,auto',
- 'stormcontrol_options': 'TEXT_OPTIONS:broadcast,multicast,\
- unicast',
- 'stormcontrol_level': 'FLOAT:',
- 'portchannel_dot1q_tag': 'TEXT_OPTIONS:disable,enable,\
- egress-only',
- 'vrrp_id': 'INTEGER_VALUE:1-255',
- }
-g8332_cnos = {'vlan_id': 'INTEGER_VALUE:1-3999',
- 'vlan_id_range': 'INTEGER_VALUE_RANGE:1-3999',
- 'vlan_name': 'TEXT:',
- 'vlan_flood': 'TEXT_OPTIONS:ipv4,ipv6',
- 'vlan_state': 'TEXT_OPTIONS:active,suspend',
- 'vlan_last_member_query_interval': 'INTEGER_VALUE:1-25',
- 'vlan_querier': 'IPV4Address:',
- 'vlan_querier_timeout': 'INTEGER_VALUE:1-65535',
- 'vlan_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_query_max_response_time': 'INTEGER_VALUE:1-25',
- 'vlan_report_suppression': 'INTEGER_VALUE:1-25',
- 'vlan_robustness_variable': 'INTEGER_VALUE:1-7',
- 'vlan_startup_query_count': 'INTEGER_VALUE:1-10',
- 'vlan_startup_query_interval': 'INTEGER_VALUE:1-18000',
- 'vlan_snooping_version': 'INTEGER_VALUE:2-3',
- 'vlan_access_map_name': 'TEXT: ',
- 'vlan_ethernet_interface': 'TEXT:',
- 'vlan_portagg_number': 'INTEGER_VALUE:1-4096',
- 'vlan_accessmap_action': 'TEXT_OPTIONS:drop,forward,redirect',
- 'vlan_dot1q_tag': 'MATCH_TEXT_OR_EMPTY:egress-only',
- 'vlan_filter_name': 'TEXT:',
- 'vlag_auto_recovery': 'INTEGER_VALUE:240-3600',
- 'vlag_config_consistency': 'TEXT_OPTIONS:disable,strict',
- 'vlag_instance': 'INTEGER_VALUE:1-128',
- 'vlag_port_aggregation': 'INTEGER_VALUE:1-4096',
- 'vlag_priority': 'INTEGER_VALUE:0-65535',
- 'vlag_startup_delay': 'INTEGER_VALUE:0-3600',
- 'vlag_tier_id': 'INTEGER_VALUE:1-512',
- 'vlag_hlthchk_options': 'TEXT_OPTIONS:keepalive-attempts,\
- keepalive-interval,peer-ip,retry-interval',
- 'vlag_keepalive_attempts': 'INTEGER_VALUE:1-24',
- 'vlag_keepalive_interval': 'INTEGER_VALUE:2-300',
- 'vlag_retry_interval': 'INTEGER_VALUE:1-300',
- 'vlag_peerip': 'IPV4Address:',
- 'vlag_peerip_vrf': 'TEXT_OPTIONS:default,management',
- 'bgp_as_number': 'NO_VALIDATION:1-4294967295',
- 'bgp_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_bgp_local_count': 'INTEGER_VALUE:2-64',
- 'cluster_id_as_ip': 'IPV4Address:',
- 'cluster_id_as_number': 'NO_VALIDATION:1-4294967295',
- 'confederation_identifier': 'INTEGER_VALUE:1-65535',
- 'condeferation_peers_as': 'INTEGER_VALUE:1-65535',
- 'stalepath_delay_value': 'INTEGER_VALUE:1-3600',
- 'maxas_limit_as': 'INTEGER_VALUE:1-2000',
- 'neighbor_ipaddress': 'IPV4Address:',
- 'neighbor_as': 'NO_VALIDATION:1-4294967295',
- 'router_id': 'IPV4Address:',
- 'bgp_keepalive_interval': 'INTEGER_VALUE:0-3600',
- 'bgp_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_aggregate_prefix': 'IPV4AddressWithMask:',
- 'addrfamily_routemap_name': 'TEXT:',
- 'reachability_half_life': 'INTEGER_VALUE:1-45',
- 'start_reuse_route_value': 'INTEGER_VALUE:1-20000',
- 'start_suppress_route_value': 'INTEGER_VALUE:1-20000',
- 'max_duration_to_suppress_route': 'INTEGER_VALUE:1-255',
- 'unreachability_halftime_for_penalty': 'INTEGER_VALUE:1-45',
- 'distance_external_AS': 'INTEGER_VALUE:1-255',
- 'distance_internal_AS': 'INTEGER_VALUE:1-255',
- 'distance_local_routes': 'INTEGER_VALUE:1-255',
- 'maxpath_option': 'TEXT_OPTIONS:ebgp,ibgp',
- 'maxpath_numbers': 'INTEGER_VALUE:2-32',
- 'network_ip_prefix_with_mask': 'IPV4AddressWithMask:',
- 'network_ip_prefix_value': 'IPV4Address:',
- 'network_ip_prefix_mask': 'IPV4Address:',
- 'nexthop_crtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'nexthop_noncrtitical_delay': 'NO_VALIDATION:1-4294967295',
- 'addrfamily_redistribute_option': 'TEXT_OPTIONS:direct,ospf,\
- static',
- 'bgp_neighbor_af_occurances': 'INTEGER_VALUE:1-10',
- 'bgp_neighbor_af_filtername': 'TEXT:',
- 'bgp_neighbor_af_maxprefix': 'INTEGER_VALUE:1-15870',
- 'bgp_neighbor_af_prefixname': 'TEXT:',
- 'bgp_neighbor_af_routemap': 'TEXT:',
- 'bgp_neighbor_address_family': 'TEXT_OPTIONS:ipv4,ipv6',
- 'bgp_neighbor_connection_retrytime': 'INTEGER_VALUE:1-65535',
- 'bgp_neighbor_description': 'TEXT:',
- 'bgp_neighbor_maxhopcount': 'INTEGER_VALUE:1-255',
- 'bgp_neighbor_local_as': 'NO_VALIDATION:1-4294967295',
- 'bgp_neighbor_maxpeers': 'INTEGER_VALUE:1-96',
- 'bgp_neighbor_password': 'TEXT:',
- 'bgp_neighbor_timers_Keepalive': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_timers_holdtime': 'INTEGER_VALUE:0-3600',
- 'bgp_neighbor_ttl_hops': 'INTEGER_VALUE:1-254',
- 'bgp_neighbor_update_options': 'TEXT_OPTIONS:ethernet,loopback,\
- vlan',
- 'bgp_neighbor_update_ethernet': 'TEXT:',
- 'bgp_neighbor_update_loopback': 'INTEGER_VALUE:0-7',
- 'bgp_neighbor_update_vlan': 'INTEGER_VALUE:1-4094',
- 'bgp_neighbor_weight': 'INTEGER_VALUE:0-65535',
- 'ethernet_interface_value': 'INTEGER_VALUE:1-32',
- 'ethernet_interface_range': 'INTEGER_VALUE_RANGE:1-32',
- 'ethernet_interface_string': 'TEXT:',
- 'loopback_interface_value': 'INTEGER_VALUE:0-7',
- 'mgmt_interface_value': 'INTEGER_VALUE:0-0',
- 'vlan_interface_value': 'INTEGER_VALUE:1-4094',
- 'portchannel_interface_value': 'INTEGER_VALUE:1-4096',
- 'portchannel_interface_range': 'INTEGER_VALUE_RANGE:1-4096',
- 'portchannel_interface_string': 'TEXT:',
- 'aggregation_group_no': 'INTEGER_VALUE:1-4096',
- 'aggregation_group_mode': 'TEXT_OPTIONS:active,on,passive',
- 'bfd_options': 'TEXT_OPTIONS:authentication,echo,interval,ipv4,\
- ipv6,neighbor',
- 'bfd_interval': 'INTEGER_VALUE:50-999',
- 'bfd_minrx': 'INTEGER_VALUE:50-999',
- 'bfd_ multiplier': 'INTEGER_VALUE:3-50',
- 'bfd_ipv4_options': 'TEXT_OPTIONS:authentication,echo,interval',
- 'bfd_auth_options': 'TEXT_OPTIONS:keyed-md5,keyed-sha1,\
- meticulous-keyed-md5,meticulous-keyed-sha1,simple',
- 'bfd_key_options': 'TEXT_OPTIONS:key-chain,key-id',
- 'bfd_key_chain': 'TEXT:',
- 'bfd_key_id': 'INTEGER_VALUE:0-255',
- 'bfd_key_name': 'TEXT:',
- 'bfd_neighbor_ip': 'TEXT:',
- 'bfd_neighbor_options': 'TEXT_OPTIONS:admin-down,multihop,\
- non-persistent',
- 'bfd_access_vlan': 'INTEGER_VALUE:1-3999',
- 'bfd_bridgeport_mode': 'TEXT_OPTIONS:access,dot1q-tunnel,trunk',
- 'trunk_options': 'TEXT_OPTIONS:allowed,native',
- 'trunk_vlanid': 'INTEGER_VALUE:1-3999',
- 'portCh_description': 'TEXT:',
- 'duplex_option': 'TEXT_OPTIONS:auto,full,half',
- 'flowcontrol_options': 'TEXT_OPTIONS:receive,send',
- 'portchannel_ip_options': 'TEXT_OPTIONS:access-group,address,arp,\
- dhcp,ospf,port,port-unreachable,redirects,router,unreachables',
- 'accessgroup_name': 'TEXT:',
- 'portchannel_ipv4': 'IPV4Address:',
- 'portchannel_ipv4_mask': 'TEXT:',
- 'arp_ipaddress': 'IPV4Address:',
- 'arp_macaddress': 'TEXT:',
- 'arp_timeout_value': 'INTEGER_VALUE:60-28800',
- 'relay_ipaddress': 'IPV4Address:',
- 'ip_ospf_options': 'TEXT_OPTIONS:authentication,\
- authentication-key,bfd,cost,database-filter,dead-interval,\
- hello-interval,message-digest-key,mtu,mtu-ignore,network,\
- passive-interface,priority,retransmit-interval,shutdown,\
- transmit-delay',
- 'ospf_id_decimal_value': 'NO_VALIDATION:1-4294967295',
- 'ospf_id_ipaddres_value': 'IPV4Address:',
- 'lacp_options': 'TEXT_OPTIONS:port-priority,suspend-individual,\
- timeout',
- 'port_priority': 'INTEGER_VALUE:1-65535',
- 'lldp_options': 'TEXT_OPTIONS:receive,tlv-select,transmit,\
- trap-notification',
- 'lldp_tlv_options': 'TEXT_OPTIONS:link-aggregation,\
- mac-phy-status,management-address,max-frame-size,\
- port-description,port-protocol-vlan,port-vlan,power-mdi,\
- protocol-identity,system-capabilities,system-description,\
- system-name,vid-management,vlan-name',
- 'load_interval_delay': 'INTEGER_VALUE:30-300',
- 'load_interval_counter': 'INTEGER_VALUE:1-3',
- 'mac_accessgroup_name': 'TEXT:',
- 'mac_address': 'TEXT:',
- 'microburst_threshold': 'NO_VALIDATION:1-4294967295',
- 'mtu_value': 'INTEGER_VALUE:64-9216',
- 'service_instance': 'NO_VALIDATION:1-4294967295',
- 'service_policy_options': 'TEXT_OPTIONS:copp-system-policy,\
- input,output,type',
- 'service_policy_name': 'TEXT:',
- 'spanning_tree_options': 'TEXT_OPTIONS:bpdufilter,bpduguard,\
- cost,disable,enable,guard,link-type,mst,port,port-priority,vlan',
- 'spanning_tree_cost': 'NO_VALIDATION:1-200000000',
- 'spanning_tree_interfacerange': 'INTEGER_VALUE_RANGE:1-3999',
- 'spanning_tree_portpriority': 'TEXT_OPTIONS:0,32,64,96,128,160,\
- 192,224',
- 'portchannel_ipv6_neighbor_mac': 'TEXT:',
- 'portchannel_ipv6_neighbor_address': 'IPV6Address:',
- 'portchannel_ipv6_linklocal': 'IPV6Address:',
- 'portchannel_ipv6_dhcp_vlan': 'INTEGER_VALUE:1-4094',
- 'portchannel_ipv6_dhcp_ethernet': 'TEXT:',
- 'portchannel_ipv6_dhcp': 'IPV6Address:',
- 'portchannel_ipv6_address': 'IPV6Address:',
- 'portchannel_ipv6_options': 'TEXT_OPTIONS:address,dhcp,\
- link-local,nd,neighbor',
- 'interface_speed': 'TEXT_OPTIONS:1000,10000,40000,50000,auto',
- 'stormcontrol_options': 'TEXT_OPTIONS:broadcast,multicast,\
- unicast',
- 'stormcontrol_level': 'FLOAT:',
- 'portchannel_dot1q_tag': 'TEXT_OPTIONS:disable,enable,\
- egress-only',
- 'vrrp_id': 'INTEGER_VALUE:1-255',
- }
diff --git a/plugins/module_utils/network/cnos/cnos_errorcodes.py b/plugins/module_utils/network/cnos/cnos_errorcodes.py
deleted file mode 100644
index 3a83af00fc..0000000000
--- a/plugins/module_utils/network/cnos/cnos_errorcodes.py
+++ /dev/null
@@ -1,256 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by
-# Ansible still belong to the author of the module, and may assign their own
-# license to the complete work.
-#
-# Copyright (C) 2017 Lenovo, Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# Contains error codes and methods
-# Lenovo Networking
-
-errorDict = {0: 'Success',
- 1: 'NOK',
- 101: 'Device Response Timed out',
- 102: 'Command Not supported - Use CLI command',
- 103: 'Invalid Context',
- 104: 'Command Value Not Supported as of Now. Use vlan Id only',
- 105: 'Invalid interface Range',
- 106: 'Please provide Enable Password.',
- 108: '',
- 109: '',
- 110: 'Invalid protocol option',
- 111: 'The Value is not Integer',
- 112: 'The Value is not Float',
- 113: 'Value is not in Range',
- 114: 'Range value is not Integer',
- 115: 'Value is not in Options',
- 116: 'The Value is not Long',
- 117: 'Range value is not Long',
- 118: 'The Value cannot be empty',
- 119: 'The Value is not String',
- 120: 'The Value is not Matching',
- 121: 'The Value is not IPV4 Address',
- 122: 'The Value is not IPV6 Address',
- 123: '',
- 124: '',
- 125: '',
- 126: '',
- 127: '',
- 128: '',
- 129: '',
- 130: 'Invalid Access Map Name',
- 131: 'Invalid Vlan Dot1q Tag',
- 132: 'Invalid Vlan filter value',
- 133: 'Invalid Vlan Range Value',
- 134: 'Invalid Vlan Id',
- 135: 'Invalid Vlan Access Map Action',
- 136: 'Invalid Vlan Access Map Name',
- 137: 'Invalid Access List',
- 138: 'Invalid Vlan Access Map parameter',
- 139: 'Invalid Vlan Name',
- 140: 'Invalid Vlan Flood value,',
- 141: 'Invalid Vlan State Value',
- 142: 'Invalid Vlan Last Member query Interval',
- 143: 'Invalid Querier IP address',
- 144: 'Invalid Querier Time out',
- 145: 'Invalid Query Interval',
- 146: 'Invalid Vlan query max response time',
- 147: 'Invalid vlan robustness variable',
- 148: 'Invalid Vlan Startup Query count',
- 149: 'Invalid vlan Startup Query Interval',
- 150: 'Invalid Vlan snooping version',
- 151: 'Invalid Vlan Ethernet Interface',
- 152: 'Invalid Vlan Port Tag Number',
- 153: 'Invalid mrouter option',
- 154: 'Invalid Vlan Option',
- 155: '',
- 156: '',
- 157: '',
- 158: '',
- 159: '',
- 160: 'Invalid Vlag Auto Recovery Value',
- 161: 'Invalid Vlag Config Consistency Value',
- 162: 'Invalid Vlag Port Aggregation Number',
- 163: 'Invalid Vlag Priority Value',
- 164: 'Invalid Vlag Startup delay value',
- 165: 'Invalid Vlag Trie Id',
- 166: 'Invalid Vlag Instance Option',
- 167: 'Invalid Vlag Keep Alive Attempts',
- 168: 'Invalid Vlag Keep Alive Interval',
- 169: 'Invalid Vlag Retry Interval',
- 170: 'Invalid Vlag Peer Ip VRF Value',
- 171: 'Invalid Vlag Health Check Options',
- 172: 'Invalid Vlag Option',
- 173: '',
- 174: '',
- 175: '',
- 176: 'Invalid BGP As Number',
- 177: 'Invalid Routing protocol option',
- 178: 'Invalid BGP Address Family',
- 179: 'Invalid AS Path options',
- 180: 'Invalid BGP med options',
- 181: 'Invalid Best Path option',
- 182: 'Invalid BGP Local count number',
- 183: 'Cluster Id has to either IP or AS Number',
- 184: 'Invalid confederation identifier',
- 185: 'Invalid Confederation Peer AS Value',
- 186: 'Invalid Confederation Option',
- 187: 'Invalid state path relay value',
- 188: 'Invalid Maxas Limit AS Value',
- 189: 'Invalid Neighbor IP Address or Neighbor AS Number',
- 190: 'Invalid Router Id',
- 191: 'Invalid BGP Keep Alive Interval',
- 192: 'Invalid BGP Hold time',
- 193: 'Invalid BGP Option',
- 194: 'Invalid BGP Address Family option',
- 195: 'Invalid BGP Address Family Redistribution option. ',
- 196: 'Invalid BGP Address Family Route Map Name',
- 197: 'Invalid Next Hop Critical Delay',
- 198: 'Invalid Next Hop Non Critical Delay',
- 199: 'Invalid Multipath Number Value',
- 200: 'Invalid Aggegation Group Mode',
- 201: 'Invalid Aggregation Group No',
- 202: 'Invalid BFD Access Vlan',
- 203: 'Invalid CFD Bridgeport Mode',
- 204: 'Invalid Trunk Option',
- 205: 'Invalid BFD Option',
- 206: 'Invalid Portchannel description',
- 207: 'Invalid Portchannel duplex option',
- 208: 'Invalid Flow control option state',
- 209: 'Invalid Flow control option',
- 210: 'Invalid LACP Port priority',
- 211: 'Invalid LACP Time out options',
- 212: 'Invalid LACP Command options',
- 213: 'Invalid LLDP TLV Option',
- 214: 'Invalid LLDP Option',
- 215: 'Invalid Load interval delay',
- 216: 'Invalid Load interval Counter Number',
- 217: 'Invalid Load Interval option',
- 218: 'Invalid Mac Access Group Name',
- 219: 'Invalid Mac Address',
- 220: 'Invalid Microburst threshold value',
- 221: 'Invalid MTU Value',
- 222: 'Invalid Service instance value',
- 223: 'Invalid service policy name',
- 224: 'Invalid service policy options',
- 225: 'Invalid Interface speed value',
- 226: 'Invalid Storm control level value',
- 227: 'Invalid Storm control option',
- 228: 'Invalid Portchannel dot1q tag',
- 229: 'Invalid VRRP Id Value',
- 230: 'Invalid VRRP Options',
- 231: 'Invalid portchannel source interface option',
- 232: 'Invalid portchannel load balance options',
- 233: 'Invalid Portchannel configuration attribute',
- 234: 'Invalid BFD Interval Value',
- 235: 'Invalid BFD minrx Value',
- 236: 'Invalid BFD multiplier Value',
- 237: 'Invalid Key Chain Value',
- 238: 'Invalid key name option',
- 239: 'Invalid key id value',
- 240: 'Invalid Key Option',
- 241: 'Invalid authentication option',
- 242: 'Invalid destination Ip',
- 243: 'Invalid source Ip',
- 244: 'Invalid IP Option',
- 245: 'Invalid Access group option',
- 246: 'Invalid Access group name',
- 247: 'Invalid ARP MacAddress Value',
- 248: 'Invalid ARP timeout value',
- 249: 'Invalid ARP Option',
- 250: 'Invalid dhcp request option',
- 251: 'Invalid dhcp Client option',
- 252: 'Invalid relay Ip Address',
- 253: 'Invalid dhcp Option',
- 254: 'Invalid OSPF Option',
- 255: 'Invalid OSPF Id IP Address Value',
- 256: 'Invalid Ip Router Option',
- 257: 'Invalid Spanning tree bpdufilter Options',
- 258: 'Invalid Spanning tree bpduguard Options',
- 259: 'Invalid Spanning tree cost Options',
- 260: 'Invalid Spanning tree guard Options',
- 261: 'Invalid Spanning tree link-type Options',
- 262: 'Invalid Spanning tree link-type Options',
- 263: 'Invalid Spanning tree options',
- 264: 'Port-priority in increments of 32 is required',
- 265: 'Invalid Spanning tree vlan options',
- 266: 'Invalid IPv6 option',
- 267: 'Invalid IPV6 neighbor IP Address',
- 268: 'Invalid IPV6 neighbor mac address',
- 269: 'Invalid IPV6 dhcp option',
- 270: 'Invalid IPV6 relay address option',
- 271: 'Invalid IPV6 Ethernet option',
- 272: 'Invalid IPV6 Vlan option',
- 273: 'Invalid IPV6 Link Local option',
- 274: 'Invalid IPV6 dhcp option',
- 275: 'Invalid IPV6 Address',
- 276: 'Invalid IPV6 Address option',
- 277: 'Invalid BFD neighbor options',
- 278: 'Invalid Secondary option',
- 289: 'Invalid PortChannel IPV4 address',
- 290: 'Invalid Max Path Options',
- 291: 'Invalid Distance Local Route value',
- 292: 'Invalid Distance Internal AS value',
- 293: 'Invalid Distance External AS value',
- 294: 'Invalid BGP Reachability Half Life',
- 295: 'Invalid BGP Dampening parameter',
- 296: 'Invalid BGP Aggregate Prefix value',
- 297: 'Invalid BGP Aggregate Prefix Option',
- 298: 'Invalid BGP Address Family Route Map Name',
- 299: 'Invalid BGP Net IP Mask Value',
- 300: 'Invalid BGP Net IP Prefix Value',
- 301: 'Invalid BGP Neighbor configuration option',
- 302: 'Invalid BGP Neighbor Weight Value',
- 303: 'Invalid Neigbor update source option',
- 304: 'Invalid Ethernet slot/chassis number',
- 305: 'Invalid Loopback Interface number',
- 306: 'Invalid vlan id',
- 307: 'Invalid Number of hops',
- 308: 'Invalid Neighbor Keepalive interval',
- 309: 'Invalid Neighbor timer hold time',
- 310: 'Invalid neighbor password ',
- 311: 'Invalid Max peer limit',
- 312: 'Invalid Local AS Number',
- 313: 'Invalid maximum hop count',
- 314: 'Invalid neighbor description',
- 315: 'Invalid Neighbor connect timer value',
- 316: 'Invalid Neighbor address family option',
- 317: 'Invalid neighbor address family option',
- 318: 'Invalid route-map name',
- 319: 'Invalid route-map',
- 320: 'Invalid Name of a prefix list',
- 321: 'Invalid Filter incoming option',
- 322: 'Invalid AS path access-list name',
- 323: 'Invalid Filter route option',
- 324: 'Invalid route-map name',
- 325: 'Invalid Number of occurrences of AS number',
- 326: 'Invalid Prefix Limit'}
-
-
-def getErrorString(errorCode):
- retVal = errorDict[int(errorCode)]
- return retVal
-# EOM
diff --git a/plugins/module_utils/network/edgeos/__init__.py b/plugins/module_utils/network/edgeos/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/edgeos/edgeos.py b/plugins/module_utils/network/edgeos/edgeos.py
deleted file mode 100644
index c7eef62179..0000000000
--- a/plugins/module_utils/network/edgeos/edgeos.py
+++ /dev/null
@@ -1,132 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# (c) 2018 Red Hat Inc.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-import json
-from ansible.module_utils._text import to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.module_utils.connection import Connection, ConnectionError
-
-_DEVICE_CONFIGS = None
-
-
-def get_connection(module):
- if hasattr(module, '_edgeos_connection'):
- return module._edgeos_connection
-
- capabilities = get_capabilities(module)
- network_api = capabilities.get('network_api')
- if network_api == 'cliconf':
- module._edgeos_connection = Connection(module._socket_path)
- else:
- module.fail_json(msg='Invalid connection type %s' % network_api)
-
- return module._edgeos_connection
-
-
-def get_capabilities(module):
- if hasattr(module, '_edgeos_capabilities'):
- return module._edgeos_capabilities
-
- capabilities = Connection(module._socket_path).get_capabilities()
- module._edgeos_capabilities = json.loads(capabilities)
- return module._edgeos_capabilities
-
-
-def get_config(module):
- global _DEVICE_CONFIGS
-
- if _DEVICE_CONFIGS is not None:
- return _DEVICE_CONFIGS
- else:
- connection = get_connection(module)
- out = connection.get_config()
- cfg = to_text(out, errors='surrogate_then_replace').strip()
- _DEVICE_CONFIGS = cfg
- return cfg
-
-
-def run_commands(module, commands, check_rc=True):
- responses = list()
- connection = get_connection(module)
-
- for cmd in to_list(commands):
- if isinstance(cmd, dict):
- command = cmd['command']
- prompt = cmd['prompt']
- answer = cmd['answer']
- else:
- command = cmd
- prompt = None
- answer = None
-
- try:
- out = connection.get(command, prompt, answer)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
-
- try:
- out = to_text(out, errors='surrogate_or_strict')
- except UnicodeError:
- module.fail_json(msg=u'Failed to decode output from %s: %s' %
- (cmd, to_text(out)))
-
- responses.append(out)
-
- return responses
-
-
-def load_config(module, commands, commit=False, comment=None):
- connection = get_connection(module)
-
- try:
- out = connection.edit_config(commands)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
-
- diff = None
- if module._diff:
- out = connection.get('compare')
- out = to_text(out, errors='surrogate_or_strict')
-
- if not out.startswith('No changes'):
- out = connection.get('show')
- diff = to_text(out, errors='surrogate_or_strict').strip()
-
- if commit:
- try:
- out = connection.commit(comment)
- except ConnectionError:
- connection.discard_changes()
- module.fail_json(msg='commit failed: %s' % out)
-
- if not commit:
- connection.discard_changes()
- else:
- connection.get('exit')
-
- if diff:
- return diff
diff --git a/plugins/module_utils/network/edgeswitch/__init__.py b/plugins/module_utils/network/edgeswitch/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/edgeswitch/edgeswitch.py b/plugins/module_utils/network/edgeswitch/edgeswitch.py
deleted file mode 100644
index 78073c2158..0000000000
--- a/plugins/module_utils/network/edgeswitch/edgeswitch.py
+++ /dev/null
@@ -1,168 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# (c) 2018 Red Hat Inc.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-import json
-import re
-
-from copy import deepcopy
-
-from ansible.module_utils._text import to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList
-from ansible.module_utils.connection import Connection, ConnectionError
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec
-
-_DEVICE_CONFIGS = {}
-
-
-def build_aggregate_spec(element_spec, required, *extra_spec):
- aggregate_spec = deepcopy(element_spec)
- for elt in required:
- aggregate_spec[elt] = dict(required=True)
- remove_default_spec(aggregate_spec)
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec)
- )
- argument_spec.update(element_spec)
- for elt in extra_spec:
- argument_spec.update(elt)
- return argument_spec
-
-
-def map_params_to_obj(module):
- obj = []
- aggregate = module.params.get('aggregate')
- if aggregate:
- for item in aggregate:
- for key in item:
- if item.get(key) is None:
- item[key] = module.params[key]
-
- d = item.copy()
- obj.append(d)
- else:
- obj.append(module.params)
-
- return obj
-
-
-def get_connection(module):
- if hasattr(module, '_edgeswitch_connection'):
- return module._edgeswitch_connection
-
- capabilities = get_capabilities(module)
- network_api = capabilities.get('network_api')
- if network_api == 'cliconf':
- module._edgeswitch_connection = Connection(module._socket_path)
- else:
- module.fail_json(msg='Invalid connection type %s' % network_api)
-
- return module._edgeswitch_connection
-
-
-def get_capabilities(module):
- if hasattr(module, '_edgeswitch_capabilities'):
- return module._edgeswitch_capabilities
- try:
- capabilities = Connection(module._socket_path).get_capabilities()
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- module._edgeswitch_capabilities = json.loads(capabilities)
- return module._edgeswitch_capabilities
-
-
-def get_defaults_flag(module):
- connection = get_connection(module)
- try:
- out = connection.get_defaults_flag()
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- return to_text(out, errors='surrogate_then_replace').strip()
-
-
-def get_config(module, flags=None):
- flag_str = ' '.join(to_list(flags))
-
- try:
- return _DEVICE_CONFIGS[flag_str]
- except KeyError:
- connection = get_connection(module)
- try:
- out = connection.get_config(flags=flags)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- cfg = to_text(out, errors='surrogate_then_replace').strip()
- _DEVICE_CONFIGS[flag_str] = cfg
- return cfg
-
-
-def get_interfaces_config(module):
- config = get_config(module)
- lines = config.split('\n')
- interfaces = {}
- interface = None
- for line in lines:
- if line == 'exit':
- if interface:
- interfaces[interface[0]] = interface
- interface = None
- elif interface:
- interface.append(line)
- else:
- match = re.match(r'^interface (.*)$', line)
- if match:
- interface = list()
- interface.append(line)
-
- return interfaces
-
-
-def to_commands(module, commands):
- spec = {
- 'command': dict(key=True),
- 'prompt': dict(),
- 'answer': dict()
- }
- transform = ComplexList(spec, module)
- return transform(commands)
-
-
-def run_commands(module, commands, check_rc=True):
- connection = get_connection(module)
- try:
- return connection.run_commands(commands=commands, check_rc=check_rc)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
-
-
-def load_config(module, commands):
- connection = get_connection(module)
-
- try:
- resp = connection.edit_config(commands)
- return resp.get('response')
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
diff --git a/plugins/module_utils/network/edgeswitch/edgeswitch_interface.py b/plugins/module_utils/network/edgeswitch/edgeswitch_interface.py
deleted file mode 100644
index 793d0e0831..0000000000
--- a/plugins/module_utils/network/edgeswitch/edgeswitch_interface.py
+++ /dev/null
@@ -1,91 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# (c) 2018 Red Hat Inc.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-import re
-
-
-class InterfaceConfiguration:
- def __init__(self):
- self.commands = []
- self.merged = False
-
- def has_same_commands(self, interface):
- len1 = len(self.commands)
- len2 = len(interface.commands)
- return len1 == len2 and len1 == len(frozenset(self.commands).intersection(interface.commands))
-
-
-def merge_interfaces(interfaces):
- """ to reduce commands generated by an edgeswitch module
- we take interfaces one by one and we try to merge them with neighbors if everyone has same commands to run
- """
- merged = {}
-
- for i, interface in interfaces.items():
- if interface.merged:
- continue
- interface.merged = True
-
- match = re.match(r'(\d+)\/(\d+)', i)
- group = int(match.group(1))
- start = int(match.group(2))
- end = start
-
- while True:
- try:
- start = start - 1
- key = '{0}/{1}'.format(group, start)
- neighbor = interfaces[key]
- if not neighbor.merged and interface.has_same_commands(neighbor):
- neighbor.merged = True
- else:
- break
- except KeyError:
- break
- start = start + 1
-
- while True:
- try:
- end = end + 1
- key = '{0}/{1}'.format(group, end)
- neighbor = interfaces[key]
- if not neighbor.merged and interface.has_same_commands(neighbor):
- neighbor.merged = True
- else:
- break
- except KeyError:
- break
- end = end - 1
-
- if end == start:
- key = '{0}/{1}'.format(group, start)
- else:
- key = '{0}/{1}-{2}/{3}'.format(group, start, group, end)
-
- merged[key] = interface
- return merged
diff --git a/plugins/module_utils/network/enos/__init__.py b/plugins/module_utils/network/enos/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/enos/enos.py b/plugins/module_utils/network/enos/enos.py
deleted file mode 100644
index 9cb4ba0081..0000000000
--- a/plugins/module_utils/network/enos/enos.py
+++ /dev/null
@@ -1,172 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by
-# Ansible still belong to the author of the module, and may assign their own
-# license to the complete work.
-#
-# Copyright (C) 2017 Lenovo.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# Contains utility methods
-# Lenovo Networking
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import env_fallback
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, EntityCollection
-from ansible.module_utils.connection import Connection, exec_command
-from ansible.module_utils.connection import ConnectionError
-
-_DEVICE_CONFIGS = {}
-_CONNECTION = None
-
-enos_provider_spec = {
- 'host': dict(),
- 'port': dict(type='int'),
- 'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
- 'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True),
- 'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
- 'authorize': dict(fallback=(env_fallback, ['ANSIBLE_NET_AUTHORIZE']), type='bool'),
- 'auth_pass': dict(fallback=(env_fallback, ['ANSIBLE_NET_AUTH_PASS']), no_log=True),
- 'timeout': dict(type='int'),
- 'context': dict(),
- 'passwords': dict()
-}
-
-enos_argument_spec = {
- 'provider': dict(type='dict', options=enos_provider_spec),
-}
-
-command_spec = {
- 'command': dict(key=True),
- 'prompt': dict(),
- 'answer': dict()
-}
-
-
-def get_provider_argspec():
- return enos_provider_spec
-
-
-def check_args(module, warnings):
- pass
-
-
-def get_connection(module):
- global _CONNECTION
- if _CONNECTION:
- return _CONNECTION
- _CONNECTION = Connection(module._socket_path)
-
- context = None
- try:
- context = module.params['context']
- except KeyError:
- context = None
-
- if context:
- if context == 'system':
- command = 'changeto system'
- else:
- command = 'changeto context %s' % context
- _CONNECTION.get(command)
-
- return _CONNECTION
-
-
-def get_config(module, flags=None):
- flags = [] if flags is None else flags
-
- passwords = None
- try:
- passwords = module.params['passwords']
- except KeyError:
- passwords = None
- if passwords:
- cmd = 'more system:running-config'
- else:
- cmd = 'show running-config '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- try:
- return _DEVICE_CONFIGS[cmd]
- except KeyError:
- conn = get_connection(module)
- out = conn.get(cmd)
- cfg = to_text(out, errors='surrogate_then_replace').strip()
- _DEVICE_CONFIGS[cmd] = cfg
- return cfg
-
-
-def to_commands(module, commands):
- if not isinstance(commands, list):
- raise AssertionError('argument must be of type ')
-
- transform = EntityCollection(module, command_spec)
- commands = transform(commands)
-
- for index, item in enumerate(commands):
- if module.check_mode and not item['command'].startswith('show'):
- module.warn('only show commands are supported when using check '
- 'mode, not executing `%s`' % item['command'])
-
- return commands
-
-
-def run_commands(module, commands, check_rc=True):
- connection = get_connection(module)
-
- commands = to_commands(module, to_list(commands))
-
- responses = list()
-
- for cmd in commands:
- out = connection.get(**cmd)
- responses.append(to_text(out, errors='surrogate_then_replace'))
-
- return responses
-
-
-def load_config(module, config):
- try:
- conn = get_connection(module)
- conn.get('enable')
- conn.edit_config(config)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
-
-
-def get_defaults_flag(module):
- rc, out, err = exec_command(module, 'show running-config ?')
- out = to_text(out, errors='surrogate_then_replace')
-
- commands = set()
- for line in out.splitlines():
- if line:
- commands.add(line.strip().split()[0])
-
- if 'all' in commands:
- return 'all'
- else:
- return 'full'
diff --git a/plugins/module_utils/network/eric_eccli/__init__.py b/plugins/module_utils/network/eric_eccli/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/eric_eccli/eric_eccli.py b/plugins/module_utils/network/eric_eccli/eric_eccli.py
deleted file mode 100644
index 19a526ec28..0000000000
--- a/plugins/module_utils/network/eric_eccli/eric_eccli.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# Copyright (c) 2019 Ericsson AB.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import json
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import env_fallback
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList
-from ansible.module_utils.connection import Connection, ConnectionError
-
-_DEVICE_CONFIGS = {}
-
-
-def get_connection(module):
- if hasattr(module, '_eric_eccli_connection'):
- return module._eric_eccli_connection
-
- capabilities = get_capabilities(module)
- network_api = capabilities.get('network_api')
- if network_api == 'cliconf':
- module._eric_eccli_connection = Connection(module._socket_path)
- else:
- module.fail_json(msg='Invalid connection type %s' % network_api)
-
- return module._eric_eccli_connection
-
-
-def get_capabilities(module):
- if hasattr(module, '_eric_eccli_capabilities'):
- return module._eric_eccli_capabilities
- try:
- capabilities = Connection(module._socket_path).get_capabilities()
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- module._eric_eccli_capabilities = json.loads(capabilities)
- return module._eric_eccli_capabilities
-
-
-def run_commands(module, commands, check_rc=True):
- connection = get_connection(module)
- try:
- return connection.run_commands(commands=commands, check_rc=check_rc)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
diff --git a/plugins/module_utils/network/exos/__init__.py b/plugins/module_utils/network/exos/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/argspec/__init__.py b/plugins/module_utils/network/exos/argspec/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/argspec/facts/__init__.py b/plugins/module_utils/network/exos/argspec/facts/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/argspec/facts/facts.py b/plugins/module_utils/network/exos/argspec/facts/facts.py
deleted file mode 100644
index 4ab2e934ea..0000000000
--- a/plugins/module_utils/network/exos/argspec/facts/facts.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The arg spec for the exos facts module.
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class FactsArgs(object): # pylint: disable=R0903
- """ The arg spec for the exos facts module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'gather_subset': dict(default=['!config'], type='list'),
- 'gather_network_resources': dict(type='list'),
- }
diff --git a/plugins/module_utils/network/exos/argspec/l2_interfaces/__init__.py b/plugins/module_utils/network/exos/argspec/l2_interfaces/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/argspec/l2_interfaces/l2_interfaces.py b/plugins/module_utils/network/exos/argspec/l2_interfaces/l2_interfaces.py
deleted file mode 100644
index 3c6f250811..0000000000
--- a/plugins/module_utils/network/exos/argspec/l2_interfaces/l2_interfaces.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-"""
-The arg spec for the exos_l2_interfaces module
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class L2_interfacesArgs(object): # pylint: disable=R0903
- """The arg spec for the exos_l2_interfaces module
- """
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'elements': 'dict',
- 'options': {
- 'access': {'options': {'vlan': {'type': 'int'}},
- 'type': 'dict'},
- 'name': {'required': True, 'type': 'str'},
- 'trunk': {'options': {'native_vlan': {'type': 'int'}, 'trunk_allowed_vlans': {'type': 'list'}},
- 'type': 'dict'}},
- 'type': 'list'},
- 'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'], 'default': 'merged', 'type': 'str'}
- } # pylint: disable=C0301
diff --git a/plugins/module_utils/network/exos/argspec/lldp_global/__init__.py b/plugins/module_utils/network/exos/argspec/lldp_global/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/argspec/lldp_global/lldp_global.py b/plugins/module_utils/network/exos/argspec/lldp_global/lldp_global.py
deleted file mode 100644
index 4106c53428..0000000000
--- a/plugins/module_utils/network/exos/argspec/lldp_global/lldp_global.py
+++ /dev/null
@@ -1,57 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-
-"""
-The arg spec for the exos_lldp_global module
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class Lldp_globalArgs(object): # pylint: disable=R0903
- """The arg spec for the exos_lldp_global module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'options': {
- 'interval': {'default': 30, 'type': 'int'},
- 'tlv_select': {
- 'options': {
- 'management_address': {'type': 'bool'},
- 'port_description': {'type': 'bool'},
- 'system_capabilities': {'type': 'bool'},
- 'system_description': {
- 'default': True,
- 'type': 'bool'},
- 'system_name': {'default': True, 'type': 'bool'}},
- 'type': 'dict'}},
- 'type': 'dict'},
- 'state': {
- 'choices': ['merged', 'replaced', 'deleted'],
- 'default': 'merged',
- 'type': 'str'}} # pylint: disable=C0301
diff --git a/plugins/module_utils/network/exos/argspec/lldp_interfaces/__init__.py b/plugins/module_utils/network/exos/argspec/lldp_interfaces/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/argspec/lldp_interfaces/lldp_interfaces.py b/plugins/module_utils/network/exos/argspec/lldp_interfaces/lldp_interfaces.py
deleted file mode 100644
index c2a981f919..0000000000
--- a/plugins/module_utils/network/exos/argspec/lldp_interfaces/lldp_interfaces.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-
-"""
-The arg spec for the exos_lldp_interfaces module
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class Lldp_interfacesArgs(object): # pylint: disable=R0903
- """The arg spec for the exos_lldp_interfaces module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'elements': 'dict',
- 'options': {
- 'enabled': {'type': 'bool'},
- 'name': {'required': True, 'type': 'str'}},
- 'type': 'list'},
- 'state': {
- 'choices': ['merged', 'replaced', 'overridden', 'deleted'],
- 'default': 'merged',
- 'type': 'str'}} # pylint: disable=C0301
diff --git a/plugins/module_utils/network/exos/argspec/vlans/__init__.py b/plugins/module_utils/network/exos/argspec/vlans/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/argspec/vlans/vlans.py b/plugins/module_utils/network/exos/argspec/vlans/vlans.py
deleted file mode 100644
index 538a155a7d..0000000000
--- a/plugins/module_utils/network/exos/argspec/vlans/vlans.py
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-
-"""
-The arg spec for the exos_vlans module
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class VlansArgs(object): # pylint: disable=R0903
- """The arg spec for the exos_vlans module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'elements': 'dict',
- 'options': {
- 'name': {'type': 'str'},
- 'state': {
- 'choices': ['active', 'suspend'],
- 'default': 'active',
- 'type': 'str'},
- 'vlan_id': {'required': True, 'type': 'int'}},
- 'type': 'list'},
- 'state': {
- 'choices': ['merged', 'replaced', 'overridden', 'deleted'],
- 'default': 'merged',
- 'type': 'str'}} # pylint: disable=C0301
diff --git a/plugins/module_utils/network/exos/config/__init__.py b/plugins/module_utils/network/exos/config/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/config/l2_interfaces/__init__.py b/plugins/module_utils/network/exos/config/l2_interfaces/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/config/l2_interfaces/l2_interfaces.py b/plugins/module_utils/network/exos/config/l2_interfaces/l2_interfaces.py
deleted file mode 100644
index 51f8951db2..0000000000
--- a/plugins/module_utils/network/exos/config/l2_interfaces/l2_interfaces.py
+++ /dev/null
@@ -1,294 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The exos_l2_interfaces class
-It is in this file where the current configuration (as dict)
-is compared to the provided configuration (as dict) and the command set
-necessary to bring the current configuration to it's desired end-state is
-created
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-import json
-from copy import deepcopy
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ConfigBase
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, dict_diff
-from ansible_collections.community.general.plugins.module_utils.network.exos.facts.facts import Facts
-from ansible_collections.community.general.plugins.module_utils.network.exos.exos import send_requests
-
-
-class L2_interfaces(ConfigBase):
- """
- The exos_l2_interfaces class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'l2_interfaces',
- ]
-
- L2_INTERFACE_NATIVE = {
- "data": {
- "openconfig-vlan:config": {
- "interface-mode": "TRUNK",
- "native-vlan": None,
- "trunk-vlans": []
- }
- },
- "method": "PATCH",
- "path": None
- }
-
- L2_INTERFACE_TRUNK = {
- "data": {
- "openconfig-vlan:config": {
- "interface-mode": "TRUNK",
- "trunk-vlans": []
- }
- },
- "method": "PATCH",
- "path": None
- }
-
- L2_INTERFACE_ACCESS = {
- "data": {
- "openconfig-vlan:config": {
- "interface-mode": "ACCESS",
- "access-vlan": None
- }
- },
- "method": "PATCH",
- "path": None
- }
-
- L2_PATH = "/rest/restconf/data/openconfig-interfaces:interfaces/interface="
-
- def __init__(self, module):
- super(L2_interfaces, self).__init__(module)
-
- def get_l2_interfaces_facts(self):
- """ Get the 'facts' (the current configuration)
-
- :rtype: A dictionary
- :returns: The current configuration as a dictionary
- """
- facts, _warnings = Facts(self._module).get_facts(
- self.gather_subset, self.gather_network_resources)
- l2_interfaces_facts = facts['ansible_network_resources'].get(
- 'l2_interfaces')
- if not l2_interfaces_facts:
- return []
- return l2_interfaces_facts
-
- def execute_module(self):
- """ Execute the module
-
- :rtype: A dictionary
- :returns: The result from module execution
- """
- result = {'changed': False}
- warnings = list()
- requests = list()
-
- existing_l2_interfaces_facts = self.get_l2_interfaces_facts()
- requests.extend(self.set_config(existing_l2_interfaces_facts))
- if requests:
- if not self._module.check_mode:
- send_requests(self._module, requests=requests)
- result['changed'] = True
- result['requests'] = requests
-
- changed_l2_interfaces_facts = self.get_l2_interfaces_facts()
-
- result['before'] = existing_l2_interfaces_facts
- if result['changed']:
- result['after'] = changed_l2_interfaces_facts
-
- result['warnings'] = warnings
- return result
-
- def set_config(self, existing_l2_interfaces_facts):
- """ Collect the configuration from the args passed to the module,
- collect the current configuration (as a dict from facts)
-
- :rtype: A list
- :returns: the requests necessary to migrate the current configuration
- to the desired configuration
- """
- want = self._module.params['config']
- have = existing_l2_interfaces_facts
- resp = self.set_state(want, have)
- return to_list(resp)
-
- def set_state(self, want, have):
- """ Select the appropriate function based on the state provided
-
- :param want: the desired configuration as a dictionary
- :param have: the current configuration as a dictionary
- :rtype: A list
- :returns: the requests necessary to migrate the current configuration
- to the desired configuration
- """
- state = self._module.params['state']
- if state == 'overridden':
- requests = self._state_overridden(want, have)
- elif state == 'deleted':
- requests = self._state_deleted(want, have)
- elif state == 'merged':
- requests = self._state_merged(want, have)
- elif state == 'replaced':
- requests = self._state_replaced(want, have)
- return requests
-
- def _state_replaced(self, want, have):
- """ The request generator when state is replaced
-
- :rtype: A list
- :returns: the requests necessary to migrate the current configuration
- to the desired configuration
- """
- requests = []
- for w in want:
- for h in have:
- if w["name"] == h["name"]:
- if dict_diff(w, h):
- l2_request = self._update_patch_request(w, h)
- l2_request["data"] = json.dumps(l2_request["data"])
- requests.append(l2_request)
- break
-
- return requests
-
- def _state_overridden(self, want, have):
- """ The request generator when state is overridden
-
- :rtype: A list
- :returns: the requests necessary to migrate the current configuration
- to the desired configuration
- """
- requests = []
- have_copy = []
- for w in want:
- for h in have:
- if w["name"] == h["name"]:
- if dict_diff(w, h):
- l2_request = self._update_patch_request(w, h)
- l2_request["data"] = json.dumps(l2_request["data"])
- requests.append(l2_request)
- have_copy.append(h)
- break
-
- for h in have:
- if h not in have_copy:
- l2_delete = self._update_delete_request(h)
- if l2_delete["path"]:
- l2_delete["data"] = json.dumps(l2_delete["data"])
- requests.append(l2_delete)
-
- return requests
-
- def _state_merged(self, want, have):
- """ The request generator when state is merged
-
- :rtype: A list
- :returns: the requests necessary to merge the provided into
- the current configuration
- """
- requests = []
- for w in want:
- for h in have:
- if w["name"] == h["name"]:
- if dict_diff(h, w):
- l2_request = self._update_patch_request(w, h)
- l2_request["data"] = json.dumps(l2_request["data"])
- requests.append(l2_request)
- break
-
- return requests
-
- def _state_deleted(self, want, have):
- """ The request generator when state is deleted
-
- :rtype: A list
- :returns: the requests necessary to remove the current configuration
- of the provided objects
- """
- requests = []
- if want:
- for w in want:
- for h in have:
- if w["name"] == h["name"]:
- l2_delete = self._update_delete_request(h)
- if l2_delete["path"]:
- l2_delete["data"] = json.dumps(l2_delete["data"])
- requests.append(l2_delete)
- break
-
- else:
- for h in have:
- l2_delete = self._update_delete_request(h)
- if l2_delete["path"]:
- l2_delete["data"] = json.dumps(l2_delete["data"])
- requests.append(l2_delete)
-
- return requests
-
- def _update_patch_request(self, want, have):
-
- facts, _warnings = Facts(self._module).get_facts(
- self.gather_subset, ['vlans', ])
- vlans_facts = facts['ansible_network_resources'].get('vlans')
-
- vlan_id = []
-
- for vlan in vlans_facts:
- vlan_id.append(vlan['vlan_id'])
-
- if want.get("access"):
- if want["access"]["vlan"] in vlan_id:
- l2_request = deepcopy(self.L2_INTERFACE_ACCESS)
- l2_request["data"]["openconfig-vlan:config"]["access-vlan"] = want["access"]["vlan"]
- l2_request["path"] = self.L2_PATH + str(want["name"]) + "/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
- else:
- self._module.fail_json(msg="VLAN %s does not exist" % (want["access"]["vlan"]))
-
- elif want.get("trunk"):
- if want["trunk"]["native_vlan"]:
- if want["trunk"]["native_vlan"] in vlan_id:
- l2_request = deepcopy(self.L2_INTERFACE_NATIVE)
- l2_request["data"]["openconfig-vlan:config"]["native-vlan"] = want["trunk"]["native_vlan"]
- l2_request["path"] = self.L2_PATH + str(want["name"]) + "/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
- for vlan in want["trunk"]["trunk_allowed_vlans"]:
- if int(vlan) in vlan_id:
- l2_request["data"]["openconfig-vlan:config"]["trunk-vlans"].append(int(vlan))
- else:
- self._module.fail_json(msg="VLAN %s does not exist" % (vlan))
- else:
- self._module.fail_json(msg="VLAN %s does not exist" % (want["trunk"]["native_vlan"]))
- else:
- l2_request = deepcopy(self.L2_INTERFACE_TRUNK)
- l2_request["path"] = self.L2_PATH + str(want["name"]) + "/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
- for vlan in want["trunk"]["trunk_allowed_vlans"]:
- if int(vlan) in vlan_id:
- l2_request["data"]["openconfig-vlan:config"]["trunk-vlans"].append(int(vlan))
- else:
- self._module.fail_json(msg="VLAN %s does not exist" % (vlan))
- return l2_request
-
- def _update_delete_request(self, have):
-
- l2_request = deepcopy(self.L2_INTERFACE_ACCESS)
-
- if have["access"] and have["access"]["vlan"] != 1 or have["trunk"] or not have["access"]:
- l2_request["data"]["openconfig-vlan:config"]["access-vlan"] = 1
- l2_request["path"] = self.L2_PATH + str(have["name"]) + "/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
-
- return l2_request
diff --git a/plugins/module_utils/network/exos/config/lldp_global/__init__.py b/plugins/module_utils/network/exos/config/lldp_global/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/config/lldp_global/lldp_global.py b/plugins/module_utils/network/exos/config/lldp_global/lldp_global.py
deleted file mode 100644
index 0bac6bf505..0000000000
--- a/plugins/module_utils/network/exos/config/lldp_global/lldp_global.py
+++ /dev/null
@@ -1,199 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The exos_lldp_global class
-It is in this file where the current configuration (as dict)
-is compared to the provided configuration (as dict) and the command set
-necessary to bring the current configuration to it's desired end-state is
-created
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ConfigBase
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible_collections.community.general.plugins.module_utils.network.exos.facts.facts import Facts
-from ansible_collections.community.general.plugins.module_utils.network.exos.exos import send_requests
-
-import json
-from copy import deepcopy
-
-
-class Lldp_global(ConfigBase):
- """
- The exos_lldp_global class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'lldp_global',
- ]
-
- LLDP_DEFAULT_INTERVAL = 30
- LLDP_DEFAULT_TLV = {
- 'system_name': True,
- 'system_description': True,
- 'system_capabilities': False,
- 'port_description': False,
- 'management_address': False
- }
- LLDP_REQUEST = {
- "data": {"openconfig-lldp:config": {}},
- "method": "PUT",
- "path": "/rest/restconf/data/openconfig-lldp:lldp/config"
- }
-
- def __init__(self, module):
- super(Lldp_global, self).__init__(module)
-
- def get_lldp_global_facts(self):
- """ Get the 'facts' (the current configuration)
-
- :rtype: A dictionary
- :returns: The current configuration as a dictionary
- """
- facts, _warnings = Facts(self._module).get_facts(
- self.gather_subset, self.gather_network_resources)
- lldp_global_facts = facts['ansible_network_resources'].get('lldp_global')
- if not lldp_global_facts:
- return {}
- return lldp_global_facts
-
- def execute_module(self):
- """ Execute the module
-
- :rtype: A dictionary
- :returns: The result from module execution
- """
- result = {'changed': False}
- warnings = list()
- requests = list()
-
- existing_lldp_global_facts = self.get_lldp_global_facts()
- requests.extend(self.set_config(existing_lldp_global_facts))
- if requests:
- if not self._module.check_mode:
- send_requests(self._module, requests)
- result['changed'] = True
- result['requests'] = requests
-
- changed_lldp_global_facts = self.get_lldp_global_facts()
-
- result['before'] = existing_lldp_global_facts
- if result['changed']:
- result['after'] = changed_lldp_global_facts
-
- result['warnings'] = warnings
- return result
-
- def set_config(self, existing_lldp_global_facts):
- """ Collect the configuration from the args passed to the module,
- collect the current configuration (as a dict from facts)
-
- :rtype: A list
- :returns: the requests necessary to migrate the current configuration
- to the desired configuration
- """
- want = self._module.params['config']
- have = existing_lldp_global_facts
- resp = self.set_state(want, have)
- return to_list(resp)
-
- def set_state(self, want, have):
- """ Select the appropriate function based on the state provided
-
- :param want: the desired configuration as a dictionary
- :param have: the current configuration as a dictionary
- :rtype: A list
- :returns: the requests necessary to migrate the current configuration
- to the desired configuration
- """
- state = self._module.params['state']
-
- if state == 'deleted':
- requests = self._state_deleted(want, have)
- elif state == 'merged':
- requests = self._state_merged(want, have)
- elif state == 'replaced':
- requests = self._state_replaced(want, have)
-
- return requests
-
- def _state_replaced(self, want, have):
- """ The request generator when state is replaced
-
- :rtype: A list
- :returns: the requests necessary to migrate the current configuration
- to the desired configuration
- """
- requests = []
- requests.extend(self._state_deleted(want, have))
- requests.extend(self._state_merged(want, have))
- return requests
-
- def _state_merged(self, want, have):
- """ The request generator when state is merged
-
- :rtype: A list
- :returns: the requests necessary to merge the provided into
- the current configuration
- """
- requests = []
-
- request = deepcopy(self.LLDP_REQUEST)
- self._update_lldp_config_body_if_diff(want, have, request)
-
- if len(request["data"]["openconfig-lldp:config"]):
- request["data"] = json.dumps(request["data"])
- requests.append(request)
-
- return requests
-
- def _state_deleted(self, want, have):
- """ The request generator when state is deleted
-
- :rtype: A list
- :returns: the requests necessary to remove the current configuration
- of the provided objects
- """
- requests = []
-
- request = deepcopy(self.LLDP_REQUEST)
- if want:
- self._update_lldp_config_body_if_diff(want, have, request)
- else:
- if self.LLDP_DEFAULT_INTERVAL != have['interval']:
- request["data"]["openconfig-lldp:config"].update(
- {"hello-timer": self.LLDP_DEFAULT_INTERVAL})
-
- if have['tlv_select'] != self.LLDP_DEFAULT_TLV:
- request["data"]["openconfig-lldp:config"].update(
- {"suppress-tlv-advertisement": [key.upper() for key, value in self.LLDP_DEFAULT_TLV.items() if not value]})
- request["data"]["openconfig-lldp:config"]["suppress-tlv-advertisement"].sort()
- if len(request["data"]["openconfig-lldp:config"]):
- request["data"] = json.dumps(request["data"])
- requests.append(request)
-
- return requests
-
- def _update_lldp_config_body_if_diff(self, want, have, request):
- if want.get('interval'):
- if want['interval'] != have['interval']:
- request["data"]["openconfig-lldp:config"].update(
- {"hello-timer": want['interval']})
- if want.get('tlv_select'):
- # Create list of TLVs to be suppressed which aren't already
- want_suppress = [key.upper() for key, value in want["tlv_select"].items() if have["tlv_select"][key] != value and value is False]
- if want_suppress:
- # Add previously suppressed TLVs to the list as we are doing a PUT op
- want_suppress.extend([key.upper() for key, value in have["tlv_select"].items() if value is False])
- request["data"]["openconfig-lldp:config"].update(
- {"suppress-tlv-advertisement": want_suppress})
- request["data"]["openconfig-lldp:config"]["suppress-tlv-advertisement"].sort()
diff --git a/plugins/module_utils/network/exos/config/lldp_interfaces/__init__.py b/plugins/module_utils/network/exos/config/lldp_interfaces/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/config/lldp_interfaces/lldp_interfaces.py b/plugins/module_utils/network/exos/config/lldp_interfaces/lldp_interfaces.py
deleted file mode 100644
index 6b81806b6a..0000000000
--- a/plugins/module_utils/network/exos/config/lldp_interfaces/lldp_interfaces.py
+++ /dev/null
@@ -1,243 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The exos_lldp_interfaces class
-It is in this file where the current configuration (as dict)
-is compared to the provided configuration (as dict) and the command set
-necessary to bring the current configuration to it's desired end-state is
-created
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-import json
-from copy import deepcopy
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ConfigBase
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, dict_diff
-from ansible_collections.community.general.plugins.module_utils.network.exos.facts.facts import Facts
-from ansible_collections.community.general.plugins.module_utils.network.exos.exos import send_requests
-
-
-class Lldp_interfaces(ConfigBase):
- """
- The exos_lldp_interfaces class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'lldp_interfaces',
- ]
-
- LLDP_INTERFACE = {
- "data": {
- "openconfig-lldp:config": {
- "name": None,
- "enabled": True
- }
- },
- "method": "PATCH",
- "path": None
- }
-
- LLDP_PATH = "/rest/restconf/data/openconfig-lldp:lldp/interfaces/interface="
-
- def __init__(self, module):
- super(Lldp_interfaces, self).__init__(module)
-
- def get_lldp_interfaces_facts(self):
- """ Get the 'facts' (the current configuration)
-
- :rtype: A dictionary
- :returns: The current configuration as a dictionary
- """
- facts, _warnings = Facts(self._module).get_facts(
- self.gather_subset, self.gather_network_resources)
- lldp_interfaces_facts = facts['ansible_network_resources'].get(
- 'lldp_interfaces')
- if not lldp_interfaces_facts:
- return []
- return lldp_interfaces_facts
-
- def execute_module(self):
- """ Execute the module
-
- :rtype: A dictionary
- :returns: The result from module execution
- """
- result = {'changed': False}
- warnings = list()
- requests = list()
-
- existing_lldp_interfaces_facts = self.get_lldp_interfaces_facts()
- requests.extend(self.set_config(existing_lldp_interfaces_facts))
- if requests:
- if not self._module.check_mode:
- send_requests(self._module, requests=requests)
- result['changed'] = True
- result['requests'] = requests
-
- changed_lldp_interfaces_facts = self.get_lldp_interfaces_facts()
-
- result['before'] = existing_lldp_interfaces_facts
- if result['changed']:
- result['after'] = changed_lldp_interfaces_facts
-
- result['warnings'] = warnings
- return result
-
- def set_config(self, existing_lldp_interfaces_facts):
- """ Collect the configuration from the args passed to the module,
- collect the current configuration (as a dict from facts)
-
- :rtype: A list
- :returns: the requests necessary to migrate the current configuration
- to the desired configuration
- """
- want = self._module.params['config']
- have = existing_lldp_interfaces_facts
- resp = self.set_state(want, have)
- return to_list(resp)
-
- def set_state(self, want, have):
- """ Select the appropriate function based on the state provided
-
- :param want: the desired configuration as a dictionary
- :param have: the current configuration as a dictionary
- :rtype: A list
- :returns: the requests necessary to migrate the current configuration
- to the desired configuration
- """
- state = self._module.params['state']
- if state == 'overridden':
- requests = self._state_overridden(want, have)
- elif state == 'deleted':
- requests = self._state_deleted(want, have)
- elif state == 'merged':
- requests = self._state_merged(want, have)
- elif state == 'replaced':
- requests = self._state_replaced(want, have)
- return requests
-
- def _state_replaced(self, want, have):
- """ The request generator when state is replaced
-
- :rtype: A list
- :returns: the requests necessary to migrate the current configuration
- to the desired configuration
- """
- requests = []
-
- for w in want:
- for h in have:
- if w['name'] == h['name']:
- lldp_request = self._update_patch_request(w, h)
- if lldp_request["path"]:
- lldp_request["data"] = json.dumps(lldp_request["data"])
- requests.append(lldp_request)
-
- return requests
-
- def _state_overridden(self, want, have):
- """ The request generator when state is overridden
-
- :rtype: A list
- :returns: the requests necessary to migrate the current configuration
- to the desired configuration
- """
- requests = []
- have_copy = []
- for w in want:
- for h in have:
- if w['name'] == h['name']:
- lldp_request = self._update_patch_request(w, h)
- if lldp_request["path"]:
- lldp_request["data"] = json.dumps(lldp_request["data"])
- requests.append(lldp_request)
- have_copy.append(h)
-
- for h in have:
- if h not in have_copy:
- if not h['enabled']:
- lldp_delete = self._update_delete_request(h)
- if lldp_delete["path"]:
- lldp_delete["data"] = json.dumps(lldp_delete["data"])
- requests.append(lldp_delete)
-
- return requests
-
- def _state_merged(self, want, have):
- """ The request generator when state is merged
-
- :rtype: A list
- :returns: the requests necessary to merge the provided into
- the current configuration
- """
- requests = []
- for w in want:
- for h in have:
- if w['name'] == h['name']:
- lldp_request = self._update_patch_request(w, h)
- if lldp_request["path"]:
- lldp_request["data"] = json.dumps(lldp_request["data"])
- requests.append(lldp_request)
-
- return requests
-
- def _state_deleted(self, want, have):
- """ The request generator when state is deleted
-
- :rtype: A list
- :returns: the requests necessary to remove the current configuration
- of the provided objects
- """
- requests = []
- if want:
- for w in want:
- for h in have:
- if w['name'] == h['name']:
- if not h['enabled']:
- lldp_delete = self._update_delete_request(h)
- if lldp_delete["path"]:
- lldp_delete["data"] = json.dumps(
- lldp_delete["data"])
- requests.append(lldp_delete)
- else:
- for h in have:
- if not h['enabled']:
- lldp_delete = self._update_delete_request(h)
- if lldp_delete["path"]:
- lldp_delete["data"] = json.dumps(lldp_delete["data"])
- requests.append(lldp_delete)
-
- return requests
-
- def _update_patch_request(self, want, have):
-
- lldp_request = deepcopy(self.LLDP_INTERFACE)
-
- if have['enabled'] != want['enabled']:
- lldp_request["data"]["openconfig-lldp:config"]["name"] = want[
- 'name']
- lldp_request["data"]["openconfig-lldp:config"]["enabled"] = want[
- 'enabled']
- lldp_request["path"] = self.LLDP_PATH + str(
- want['name']) + "/config"
-
- return lldp_request
-
- def _update_delete_request(self, have):
-
- lldp_delete = deepcopy(self.LLDP_INTERFACE)
-
- lldp_delete["data"]["openconfig-lldp:config"]["name"] = have['name']
- lldp_delete["data"]["openconfig-lldp:config"]["enabled"] = True
- lldp_delete["path"] = self.LLDP_PATH + str(have['name']) + "/config"
-
- return lldp_delete
diff --git a/plugins/module_utils/network/exos/config/vlans/__init__.py b/plugins/module_utils/network/exos/config/vlans/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/config/vlans/vlans.py b/plugins/module_utils/network/exos/config/vlans/vlans.py
deleted file mode 100644
index bd4c102025..0000000000
--- a/plugins/module_utils/network/exos/config/vlans/vlans.py
+++ /dev/null
@@ -1,277 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The exos_vlans class
-It is in this file where the current configuration (as dict)
-is compared to the provided configuration (as dict) and the command set
-necessary to bring the current configuration to it's desired end-state is
-created
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-import json
-from copy import deepcopy
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ConfigBase
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, dict_diff
-from ansible_collections.community.general.plugins.module_utils.network.exos.facts.facts import Facts
-from ansible_collections.community.general.plugins.module_utils.network.exos.exos import send_requests
-from ansible_collections.community.general.plugins.module_utils.network.exos.utils.utils import search_obj_in_list
-
-
-class Vlans(ConfigBase):
- """
- The exos_vlans class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'vlans',
- ]
-
- VLAN_POST = {
- "data": {"openconfig-vlan:vlans": []},
- "method": "POST",
- "path": "/rest/restconf/data/openconfig-vlan:vlans/"
- }
-
- VLAN_PATCH = {
- "data": {"openconfig-vlan:vlans": {"vlan": []}},
- "method": "PATCH",
- "path": "/rest/restconf/data/openconfig-vlan:vlans/"
- }
-
- VLAN_DELETE = {
- "method": "DELETE",
- "path": None
- }
-
- DEL_PATH = "/rest/restconf/data/openconfig-vlan:vlans/vlan="
-
- REQUEST_BODY = {
- "config": {"name": None, "status": "ACTIVE", "tpid": "oc-vlan-types:TPID_0x8100", "vlan-id": None}
- }
-
- def __init__(self, module):
- super(Vlans, self).__init__(module)
-
- def get_vlans_facts(self):
- """ Get the 'facts' (the current configuration)
-
- :rtype: A dictionary
- :returns: The current configuration as a dictionary
- """
- facts, _warnings = Facts(self._module).get_facts(
- self.gather_subset, self.gather_network_resources)
- vlans_facts = facts['ansible_network_resources'].get('vlans')
- if not vlans_facts:
- return []
- return vlans_facts
-
- def execute_module(self):
- """ Execute the module
-
- :rtype: A dictionary
- :returns: The result from module execution
- """
- result = {'changed': False}
- warnings = list()
- requests = list()
-
- existing_vlans_facts = self.get_vlans_facts()
- requests.extend(self.set_config(existing_vlans_facts))
- if requests:
- if not self._module.check_mode:
- send_requests(self._module, requests=requests)
- result['changed'] = True
- result['requests'] = requests
-
- changed_vlans_facts = self.get_vlans_facts()
-
- result['before'] = existing_vlans_facts
- if result['changed']:
- result['after'] = changed_vlans_facts
-
- result['warnings'] = warnings
- return result
-
- def set_config(self, existing_vlans_facts):
- """ Collect the configuration from the args passed to the module,
- collect the current configuration (as a dict from facts)
-
- :rtype: A list
- :returns: the requests necessary to migrate the current configuration
- to the desired configuration
- """
- want = self._module.params['config']
- have = existing_vlans_facts
- resp = self.set_state(want, have)
- return to_list(resp)
-
- def set_state(self, want, have):
- """ Select the appropriate function based on the state provided
-
- :param want: the desired configuration as a dictionary
- :param have: the current configuration as a dictionary
- :rtype: A list
- :returns: the requests necessary to migrate the current configuration
- to the desired configuration
- """
- state = self._module.params['state']
- if state == 'overridden':
- requests = self._state_overridden(want, have)
- elif state == 'deleted':
- requests = self._state_deleted(want, have)
- elif state == 'merged':
- requests = self._state_merged(want, have)
- elif state == 'replaced':
- requests = self._state_replaced(want, have)
- return requests
-
- def _state_replaced(self, want, have):
- """ The request generator when state is replaced
-
- :rtype: A list
- :returns: the requests necessary to migrate the current configuration
- to the desired configuration
- """
- requests = []
- request_patch = deepcopy(self.VLAN_PATCH)
-
- for w in want:
- if w.get('vlan_id'):
- h = search_obj_in_list(w['vlan_id'], have, 'vlan_id')
- if h:
- if dict_diff(w, h):
- request_body = self._update_patch_request(w)
- request_patch["data"]["openconfig-vlan:vlans"]["vlan"].append(request_body)
- else:
- request_post = self._update_post_request(w)
- requests.append(request_post)
-
- if len(request_patch["data"]["openconfig-vlan:vlans"]["vlan"]):
- request_patch["data"] = json.dumps(request_patch["data"])
- requests.append(request_patch)
-
- return requests
-
- def _state_overridden(self, want, have):
- """ The request generator when state is overridden
-
- :rtype: A list
- :returns: the requests necessary to migrate the current configuration
- to the desired configuration
- """
- requests = []
- request_patch = deepcopy(self.VLAN_PATCH)
-
- have_copy = []
- for w in want:
- if w.get('vlan_id'):
- h = search_obj_in_list(w['vlan_id'], have, 'vlan_id')
- if h:
- if dict_diff(w, h):
- request_body = self._update_patch_request(w)
- request_patch["data"]["openconfig-vlan:vlans"]["vlan"].append(request_body)
- have_copy.append(h)
- else:
- request_post = self._update_post_request(w)
- requests.append(request_post)
-
- for h in have:
- if h not in have_copy and h['vlan_id'] != 1:
- request_delete = self._update_delete_request(h)
- requests.append(request_delete)
-
- if len(request_patch["data"]["openconfig-vlan:vlans"]["vlan"]):
- request_patch["data"] = json.dumps(request_patch["data"])
- requests.append(request_patch)
-
- return requests
-
- def _state_merged(self, want, have):
- """ The requests generator when state is merged
-
- :rtype: A list
- :returns: the requests necessary to merge the provided into
- the current configuration
- """
- requests = []
-
- request_patch = deepcopy(self.VLAN_PATCH)
-
- for w in want:
- if w.get('vlan_id'):
- h = search_obj_in_list(w['vlan_id'], have, 'vlan_id')
- if h:
- if dict_diff(w, h):
- request_body = self._update_patch_request(w)
- request_patch["data"]["openconfig-vlan:vlans"]["vlan"].append(request_body)
- else:
- request_post = self._update_post_request(w)
- requests.append(request_post)
-
- if len(request_patch["data"]["openconfig-vlan:vlans"]["vlan"]):
- request_patch["data"] = json.dumps(request_patch["data"])
- requests.append(request_patch)
- return requests
-
- def _state_deleted(self, want, have):
- """ The requests generator when state is deleted
-
- :rtype: A list
- :returns: the requests necessary to remove the current configuration
- of the provided objects
- """
- requests = []
-
- if want:
- for w in want:
- if w.get('vlan_id'):
- h = search_obj_in_list(w['vlan_id'], have, 'vlan_id')
- if h:
- request_delete = self._update_delete_request(h)
- requests.append(request_delete)
-
- else:
- if not have:
- return requests
- for h in have:
- if h['vlan_id'] == 1:
- continue
- else:
- request_delete = self._update_delete_request(h)
- requests.append(request_delete)
-
- return requests
-
- def _update_vlan_config_body(self, want, request):
- request["config"]["name"] = want["name"]
- request["config"]["status"] = "SUSPENDED" if want["state"] == "suspend" else want["state"].upper()
- request["config"]["vlan-id"] = want["vlan_id"]
- return request
-
- def _update_patch_request(self, want):
- request_body = deepcopy(self.REQUEST_BODY)
- request_body = self._update_vlan_config_body(want, request_body)
- return request_body
-
- def _update_post_request(self, want):
- request_post = deepcopy(self.VLAN_POST)
- request_body = deepcopy(self.REQUEST_BODY)
- request_body = self._update_vlan_config_body(want, request_body)
- request_post["data"]["openconfig-vlan:vlans"].append(request_body)
- request_post["data"] = json.dumps(request_post["data"])
- return request_post
-
- def _update_delete_request(self, have):
- request_delete = deepcopy(self.VLAN_DELETE)
- request_delete["path"] = self.DEL_PATH + str(have['vlan_id'])
- return request_delete
diff --git a/plugins/module_utils/network/exos/exos.py b/plugins/module_utils/network/exos/exos.py
deleted file mode 100644
index f7f70ae3e3..0000000000
--- a/plugins/module_utils/network/exos/exos.py
+++ /dev/null
@@ -1,219 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# (c) 2016 Red Hat Inc.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-import json
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import env_fallback
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList
-from ansible.module_utils.common._collections_compat import Mapping
-from ansible.module_utils.connection import Connection, ConnectionError
-
-_DEVICE_CONNECTION = None
-
-
-class Cli:
- def __init__(self, module):
- self._module = module
- self._device_configs = {}
- self._connection = None
-
- def get_capabilities(self):
- """Returns platform info of the remove device
- """
- connection = self._get_connection()
- return json.loads(connection.get_capabilities())
-
- def _get_connection(self):
- if not self._connection:
- self._connection = Connection(self._module._socket_path)
- return self._connection
-
- def get_config(self, flags=None):
- """Retrieves the current config from the device or cache
- """
- flags = [] if flags is None else flags
- if self._device_configs == {}:
- connection = self._get_connection()
- try:
- out = connection.get_config(flags=flags)
- except ConnectionError as exc:
- self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- self._device_configs = to_text(out, errors='surrogate_then_replace').strip()
- return self._device_configs
-
- def run_commands(self, commands, check_rc=True):
- """Runs list of commands on remote device and returns results
- """
- connection = self._get_connection()
- try:
- response = connection.run_commands(commands=commands, check_rc=check_rc)
- except ConnectionError as exc:
- self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- return response
-
- def get_diff(self, candidate=None, running=None, diff_match='line', diff_ignore_lines=None, path=None, diff_replace='line'):
- conn = self._get_connection()
- try:
- diff = conn.get_diff(candidate=candidate, running=running, diff_match=diff_match,
- diff_ignore_lines=diff_ignore_lines, path=path, diff_replace=diff_replace)
- except ConnectionError as exc:
- self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- return diff
-
-
-class HttpApi:
- def __init__(self, module):
- self._module = module
- self._device_configs = {}
- self._connection_obj = None
-
- def get_capabilities(self):
- """Returns platform info of the remove device
- """
- try:
- capabilities = self._connection.get_capabilities()
- except ConnectionError as exc:
- self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
-
- return json.loads(capabilities)
-
- @property
- def _connection(self):
- if not self._connection_obj:
- self._connection_obj = Connection(self._module._socket_path)
- return self._connection_obj
-
- def get_config(self, flags=None):
- """Retrieves the current config from the device or cache
- """
- flags = [] if flags is None else flags
- if self._device_configs == {}:
- try:
- out = self._connection.get_config(flags=flags)
- except ConnectionError as exc:
- self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- self._device_configs = to_text(out, errors='surrogate_then_replace').strip()
- return self._device_configs
-
- def run_commands(self, commands, check_rc=True):
- """Runs list of commands on remote device and returns results
- """
- try:
- response = self._connection.run_commands(commands=commands, check_rc=check_rc)
- except ConnectionError as exc:
- self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- return response
-
- def send_requests(self, requests):
- """Send a list of http requests to remote device and return results
- """
- if requests is None:
- raise ValueError("'requests' value is required")
-
- responses = list()
- for req in to_list(requests):
- try:
- response = self._connection.send_request(**req)
- except ConnectionError as exc:
- self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- responses.append(response)
- return responses
-
- def get_diff(self, candidate=None, running=None, diff_match='line', diff_ignore_lines=None, path=None, diff_replace='line'):
- try:
- diff = self._connection.get_diff(candidate=candidate, running=running, diff_match=diff_match,
- diff_ignore_lines=diff_ignore_lines, path=path, diff_replace=diff_replace)
- except ConnectionError as exc:
- self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- return diff
-
-
-def get_capabilities(module):
- conn = get_connection(module)
- return conn.get_capabilities()
-
-
-def get_connection(module):
- global _DEVICE_CONNECTION
- if not _DEVICE_CONNECTION:
- connection_proxy = Connection(module._socket_path)
- cap = json.loads(connection_proxy.get_capabilities())
- if cap['network_api'] == 'cliconf':
- conn = Cli(module)
- elif cap['network_api'] == 'exosapi':
- conn = HttpApi(module)
- else:
- module.fail_json(msg='Invalid connection type %s' % cap['network_api'])
- _DEVICE_CONNECTION = conn
- return _DEVICE_CONNECTION
-
-
-def get_config(module, flags=None):
- flags = None if flags is None else flags
- conn = get_connection(module)
- return conn.get_config(flags)
-
-
-def load_config(module, commands):
- conn = get_connection(module)
- return conn.run_commands(to_command(module, commands))
-
-
-def run_commands(module, commands, check_rc=True):
- conn = get_connection(module)
- return conn.run_commands(to_command(module, commands), check_rc=check_rc)
-
-
-def to_command(module, commands):
- transform = ComplexList(dict(
- command=dict(key=True),
- output=dict(default='text'),
- prompt=dict(type='list'),
- answer=dict(type='list'),
- sendonly=dict(type='bool', default=False),
- check_all=dict(type='bool', default=False),
- ), module)
- return transform(to_list(commands))
-
-
-def send_requests(module, requests):
- conn = get_connection(module)
- return conn.send_requests(to_request(module, requests))
-
-
-def to_request(module, requests):
- transform = ComplexList(dict(
- path=dict(key=True),
- method=dict(),
- data=dict(type='dict'),
- ), module)
- return transform(to_list(requests))
-
-
-def get_diff(module, candidate=None, running=None, diff_match='line', diff_ignore_lines=None, path=None, diff_replace='line'):
- conn = get_connection(module)
- return conn.get_diff(candidate=candidate, running=running, diff_match=diff_match, diff_ignore_lines=diff_ignore_lines, path=path, diff_replace=diff_replace)
diff --git a/plugins/module_utils/network/exos/facts/__init__.py b/plugins/module_utils/network/exos/facts/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/facts/facts.py b/plugins/module_utils/network/exos/facts/facts.py
deleted file mode 100644
index b9b058304f..0000000000
--- a/plugins/module_utils/network/exos/facts/facts.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The facts class for exos
-this file validates each subset of facts and selectively
-calls the appropriate facts gathering function
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-from ansible_collections.community.general.plugins.module_utils.network.exos.argspec.facts.facts import FactsArgs
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts import FactsBase
-from ansible_collections.community.general.plugins.module_utils.network.exos.facts.lldp_global.lldp_global import Lldp_globalFacts
-from ansible_collections.community.general.plugins.module_utils.network.exos.facts.vlans.vlans import VlansFacts
-from ansible_collections.community.general.plugins.module_utils.network.exos.facts.legacy.base import Default, Hardware, Interfaces, Config
-from ansible_collections.community.general.plugins.module_utils.network.exos.facts.lldp_interfaces.lldp_interfaces import Lldp_interfacesFacts
-from ansible_collections.community.general.plugins.module_utils.network.exos.facts.l2_interfaces.l2_interfaces import L2_interfacesFacts
-
-FACT_LEGACY_SUBSETS = dict(
- default=Default,
- hardware=Hardware,
- interfaces=Interfaces,
- config=Config)
-
-FACT_RESOURCE_SUBSETS = dict(
- lldp_global=Lldp_globalFacts,
- vlans=VlansFacts,
- lldp_interfaces=Lldp_interfacesFacts,
- l2_interfaces=L2_interfacesFacts,
-)
-
-
-class Facts(FactsBase):
- """ The fact class for exos
- """
-
- VALID_LEGACY_GATHER_SUBSETS = frozenset(FACT_LEGACY_SUBSETS.keys())
- VALID_RESOURCE_SUBSETS = frozenset(FACT_RESOURCE_SUBSETS.keys())
-
- def __init__(self, module):
- super(Facts, self).__init__(module)
-
- def get_facts(self, legacy_facts_type=None, resource_facts_type=None, data=None):
- """ Collect the facts for exos
-
- :param legacy_facts_type: List of legacy facts types
- :param resource_facts_type: List of resource fact types
- :param data: previously collected conf
- :rtype: dict
- :return: the facts gathered
- """
- if self.VALID_RESOURCE_SUBSETS:
- self.get_network_resources_facts(FACT_RESOURCE_SUBSETS, resource_facts_type, data)
-
- if self.VALID_LEGACY_GATHER_SUBSETS:
- self.get_network_legacy_facts(FACT_LEGACY_SUBSETS, legacy_facts_type)
-
- return self.ansible_facts, self._warnings
diff --git a/plugins/module_utils/network/exos/facts/l2_interfaces/__init__.py b/plugins/module_utils/network/exos/facts/l2_interfaces/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/facts/l2_interfaces/l2_interfaces.py b/plugins/module_utils/network/exos/facts/l2_interfaces/l2_interfaces.py
deleted file mode 100644
index bbe9ab4402..0000000000
--- a/plugins/module_utils/network/exos/facts/l2_interfaces/l2_interfaces.py
+++ /dev/null
@@ -1,92 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The exos l2_interfaces fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-import re
-from copy import deepcopy
-
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
-from ansible_collections.community.general.plugins.module_utils.network.exos.argspec.l2_interfaces.l2_interfaces import L2_interfacesArgs
-from ansible_collections.community.general.plugins.module_utils.network.exos.exos import send_requests
-
-
-class L2_interfacesFacts(object):
- """ The exos l2_interfaces fact class
- """
- def __init__(self, module, subspec='config', options='options'):
- self._module = module
- self.argument_spec = L2_interfacesArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for l2_interfaces
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
-
- if not data:
- request = [{
- "path": "/rest/restconf/data/openconfig-interfaces:interfaces",
- "method": "GET"
- }]
- data = send_requests(self._module, requests=request)
-
- objs = []
- if data:
- for d in data[0]["openconfig-interfaces:interfaces"]["interface"]:
- obj = self.render_config(self.generated_spec, d)
- if obj:
- objs.append(obj)
-
- ansible_facts['ansible_network_resources'].pop('l2_interfaces', None)
- facts = {}
- if objs:
- params = utils.validate_config(self.argument_spec, {'config': objs})
- facts['l2_interfaces'] = params['config']
-
- ansible_facts['ansible_network_resources'].update(facts)
- return ansible_facts
-
- def render_config(self, spec, conf):
- """
- Render config as dictionary structure and delete keys
- from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- config = deepcopy(spec)
- if conf["config"]["type"] == "ethernetCsmacd":
- conf_dict = conf["openconfig-if-ethernet:ethernet"]["openconfig-vlan:switched-vlan"]["config"]
- config["name"] = conf["name"]
- if conf_dict["interface-mode"] == "ACCESS":
- config["access"]["vlan"] = conf_dict.get("access-vlan")
- else:
- if 'native-vlan' in conf_dict:
- config["trunk"]["native_vlan"] = conf_dict.get("native-vlan")
- config["trunk"]["trunk_allowed_vlans"] = conf_dict.get("trunk-vlans")
- return utils.remove_empties(config)
diff --git a/plugins/module_utils/network/exos/facts/legacy/__init__.py b/plugins/module_utils/network/exos/facts/legacy/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/facts/legacy/base.py b/plugins/module_utils/network/exos/facts/legacy/base.py
deleted file mode 100644
index c913350973..0000000000
--- a/plugins/module_utils/network/exos/facts/legacy/base.py
+++ /dev/null
@@ -1,263 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-"""
-The exos legacy fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-import re
-import json
-
-from ansible_collections.community.general.plugins.module_utils.network.exos.exos import run_commands
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.six import iteritems
-
-
-class FactsBase(object):
-
- COMMANDS = list()
-
- def __init__(self, module):
- self.module = module
- self.facts = dict()
- self.warnings = list()
- self.responses = None
-
- def populate(self):
- self.responses = run_commands(self.module, self.COMMANDS)
-
- def run(self, cmd):
- return run_commands(self.module, cmd)
-
-
-class Default(FactsBase):
-
- COMMANDS = [
- 'show version',
- 'show switch'
- ]
-
- def populate(self):
- super(Default, self).populate()
- data = self.responses[0]
- if data:
- self.facts['version'] = self.parse_version(data)
- self.facts['serialnum'] = self.parse_serialnum(data)
-
- data = self.responses[1]
- if data:
- self.facts['model'] = self.parse_model(data)
- self.facts['hostname'] = self.parse_hostname(data)
-
- def parse_version(self, data):
- match = re.search(r'Image\s+: ExtremeXOS version (\S+)', data)
- if match:
- return match.group(1)
-
- def parse_model(self, data):
- match = re.search(r'System Type:\s+(.*$)', data, re.M)
- if match:
- return match.group(1)
-
- def parse_hostname(self, data):
- match = re.search(r'SysName:\s+(\S+)', data, re.M)
- if match:
- return match.group(1)
-
- def parse_serialnum(self, data):
- match = re.search(r'Switch\s+: \S+ (\S+)', data, re.M)
- if match:
- return match.group(1)
- # For stack, return serial number of the first switch in the stack.
- match = re.search(r'Slot-\d+\s+: \S+ (\S+)', data, re.M)
- if match:
- return match.group(1)
- # Handle unique formatting for VM
- match = re.search(r'Switch\s+: PN:\S+\s+SN:(\S+)', data, re.M)
- if match:
- return match.group(1)
-
-
-class Hardware(FactsBase):
-
- COMMANDS = [
- 'show memory'
- ]
-
- def populate(self):
- super(Hardware, self).populate()
- data = self.responses[0]
- if data:
- self.facts['memtotal_mb'] = int(round(int(self.parse_memtotal(data)) / 1024, 0))
- self.facts['memfree_mb'] = int(round(int(self.parse_memfree(data)) / 1024, 0))
-
- def parse_memtotal(self, data):
- match = re.search(r' Total DRAM \(KB\): (\d+)', data, re.M)
- if match:
- return match.group(1)
- # Handle unique formatting for VM
- match = re.search(r' Total \s+\(KB\): (\d+)', data, re.M)
- if match:
- return match.group(1)
-
- def parse_memfree(self, data):
- match = re.search(r' Free\s+\(KB\): (\d+)', data, re.M)
- if match:
- return match.group(1)
-
-
-class Config(FactsBase):
-
- COMMANDS = ['show configuration detail']
-
- def populate(self):
- super(Config, self).populate()
- data = self.responses[0]
- if data:
- self.facts['config'] = data
-
-
-class Interfaces(FactsBase):
-
- COMMANDS = [
- 'show switch',
- {'command': 'show port config', 'output': 'json'},
- {'command': 'show port description', 'output': 'json'},
- {'command': 'show vlan detail', 'output': 'json'},
- {'command': 'show lldp neighbors', 'output': 'json'}
- ]
-
- def populate(self):
- super(Interfaces, self).populate()
-
- self.facts['all_ipv4_addresses'] = list()
- self.facts['all_ipv6_addresses'] = list()
-
- data = self.responses[0]
- if data:
- sysmac = self.parse_sysmac(data)
-
- data = self.responses[1]
- if data:
- self.facts['interfaces'] = self.populate_interfaces(data, sysmac)
-
- data = self.responses[2]
- if data:
- self.populate_interface_descriptions(data)
-
- data = self.responses[3]
- if data:
- self.populate_vlan_interfaces(data, sysmac)
-
- data = self.responses[4]
- if data:
- self.facts['neighbors'] = self.parse_neighbors(data)
-
- def parse_sysmac(self, data):
- match = re.search(r'System MAC:\s+(\S+)', data, re.M)
- if match:
- return match.group(1)
-
- def populate_interfaces(self, interfaces, sysmac):
- facts = dict()
- for elem in interfaces:
- intf = dict()
-
- if 'show_ports_config' not in elem:
- continue
-
- key = str(elem['show_ports_config']['port'])
-
- if elem['show_ports_config']['linkState'] == 2:
- # Link state is "not present", don't include
- continue
-
- intf['type'] = 'Ethernet'
- intf['macaddress'] = sysmac
- intf['bandwidth_configured'] = str(elem['show_ports_config']['speedCfg'])
- intf['bandwidth'] = str(elem['show_ports_config']['speedActual'])
- intf['duplex_configured'] = elem['show_ports_config']['duplexCfg']
- intf['duplex'] = elem['show_ports_config']['duplexActual']
- if elem['show_ports_config']['linkState'] == 1:
- intf['lineprotocol'] = 'up'
- else:
- intf['lineprotocol'] = 'down'
- if elem['show_ports_config']['portState'] == 1:
- intf['operstatus'] = 'up'
- else:
- intf['operstatus'] = 'admin down'
-
- facts[key] = intf
- return facts
-
- def populate_interface_descriptions(self, data):
- for elem in data:
- if 'show_ports_description' not in elem:
- continue
- key = str(elem['show_ports_description']['port'])
-
- if 'descriptionString' in elem['show_ports_description']:
- desc = elem['show_ports_description']['descriptionString']
- self.facts['interfaces'][key]['description'] = desc
-
- def populate_vlan_interfaces(self, data, sysmac):
- for elem in data:
- if 'vlanProc' in elem:
- key = elem['vlanProc']['name1']
- if key not in self.facts['interfaces']:
- intf = dict()
- intf['type'] = 'VLAN'
- intf['macaddress'] = sysmac
- self.facts['interfaces'][key] = intf
-
- if elem['vlanProc']['ipAddress'] != '0.0.0.0':
- self.facts['interfaces'][key]['ipv4'] = list()
- addr = elem['vlanProc']['ipAddress']
- subnet = elem['vlanProc']['maskForDisplay']
- ipv4 = dict(address=addr, subnet=subnet)
- self.add_ip_address(addr, 'ipv4')
- self.facts['interfaces'][key]['ipv4'].append(ipv4)
-
- if 'rtifIpv6Address' in elem:
- key = elem['rtifIpv6Address']['rtifName']
- if key not in self.facts['interfaces']:
- intf = dict()
- intf['type'] = 'VLAN'
- intf['macaddress'] = sysmac
- self.facts['interfaces'][key] = intf
- self.facts['interfaces'][key]['ipv6'] = list()
- addr, subnet = elem['rtifIpv6Address']['ipv6_address_mask'].split('/')
- ipv6 = dict(address=addr, subnet=subnet)
- self.add_ip_address(addr, 'ipv6')
- self.facts['interfaces'][key]['ipv6'].append(ipv6)
-
- def add_ip_address(self, address, family):
- if family == 'ipv4':
- if address not in self.facts['all_ipv4_addresses']:
- self.facts['all_ipv4_addresses'].append(address)
- else:
- if address not in self.facts['all_ipv6_addresses']:
- self.facts['all_ipv6_addresses'].append(address)
-
- def parse_neighbors(self, data):
- facts = dict()
- for elem in data:
- if 'lldpPortNbrInfoShort' not in elem:
- continue
- intf = str(elem['lldpPortNbrInfoShort']['port'])
- if intf not in facts:
- facts[intf] = list()
- fact = dict()
- fact['host'] = elem['lldpPortNbrInfoShort']['nbrSysName']
- fact['port'] = str(elem['lldpPortNbrInfoShort']['nbrPortID'])
- facts[intf].append(fact)
- return facts
diff --git a/plugins/module_utils/network/exos/facts/lldp_global/__init__.py b/plugins/module_utils/network/exos/facts/lldp_global/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/facts/lldp_global/lldp_global.py b/plugins/module_utils/network/exos/facts/lldp_global/lldp_global.py
deleted file mode 100644
index f01893da81..0000000000
--- a/plugins/module_utils/network/exos/facts/lldp_global/lldp_global.py
+++ /dev/null
@@ -1,97 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The exos lldp_global fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-import re
-from copy import deepcopy
-
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
-from ansible_collections.community.general.plugins.module_utils.network.exos.argspec.lldp_global.lldp_global \
- import Lldp_globalArgs
-from ansible_collections.community.general.plugins.module_utils.network.exos.exos import send_requests
-
-
-class Lldp_globalFacts(object):
- """ The exos lldp_global fact class
- """
-
- TLV_SELECT_OPTIONS = [
- "SYSTEM_NAME",
- "SYSTEM_DESCRIPTION",
- "SYSTEM_CAPABILITIES",
- "MANAGEMENT_ADDRESS",
- "PORT_DESCRIPTION"]
-
- def __init__(self, module, subspec='config', options='options'):
- self._module = module
- self.argument_spec = Lldp_globalArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for lldp_global
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- request = {
- "path": "/rest/restconf/data/openconfig-lldp:lldp/config/",
- "method": "GET",
- }
- data = send_requests(self._module, request)
-
- obj = {}
- if data:
- lldp_obj = self.render_config(self.generated_spec, data[0])
- if lldp_obj:
- obj = lldp_obj
-
- ansible_facts['ansible_network_resources'].pop('lldp_global', None)
- facts = {}
-
- params = utils.validate_config(self.argument_spec, {'config': obj})
- facts['lldp_global'] = params['config']
-
- ansible_facts['ansible_network_resources'].update(facts)
- return ansible_facts
-
- def render_config(self, spec, conf):
- """
- Render config as dictionary structure and delete keys
- from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- config = deepcopy(spec)
- config['interval'] = conf["openconfig-lldp:config"]["hello-timer"]
-
- for item in self.TLV_SELECT_OPTIONS:
- config["tlv_select"][item.lower()] = (
- False if (item in conf["openconfig-lldp:config"]["suppress-tlv-advertisement"])
- else True)
-
- return utils.remove_empties(config)
diff --git a/plugins/module_utils/network/exos/facts/lldp_interfaces/__init__.py b/plugins/module_utils/network/exos/facts/lldp_interfaces/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/facts/lldp_interfaces/lldp_interfaces.py b/plugins/module_utils/network/exos/facts/lldp_interfaces/lldp_interfaces.py
deleted file mode 100644
index 444dee443e..0000000000
--- a/plugins/module_utils/network/exos/facts/lldp_interfaces/lldp_interfaces.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The exos lldp_interfaces fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-import re
-from copy import deepcopy
-
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
-from ansible_collections.community.general.plugins.module_utils.network.exos.argspec.lldp_interfaces.lldp_interfaces import Lldp_interfacesArgs
-from ansible_collections.community.general.plugins.module_utils.network.exos.exos import send_requests
-
-
-class Lldp_interfacesFacts(object):
- """ The exos lldp_interfaces fact class
- """
-
- def __init__(self, module, subspec='config', options='options'):
- self._module = module
- self.argument_spec = Lldp_interfacesArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for lldp_interfaces
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
-
- if not data:
- request = [{
- "path": "/rest/restconf/data/openconfig-lldp:lldp/interfaces?depth=4",
- "method": "GET"
- }]
- data = send_requests(self._module, requests=request)
-
- objs = []
- if data:
- for d in data[0]["openconfig-lldp:interfaces"]["interface"]:
- obj = self.render_config(self.generated_spec, d["config"])
- if obj:
- objs.append(obj)
-
- ansible_facts['ansible_network_resources'].pop('lldp_interfaces', None)
- facts = {}
- if objs:
- params = utils.validate_config(self.argument_spec, {'config': objs})
- facts['lldp_interfaces'] = params['config']
-
- ansible_facts['ansible_network_resources'].update(facts)
- return ansible_facts
-
- def render_config(self, spec, conf):
- """
- Render config as dictionary structure and delete keys
- from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- config = deepcopy(spec)
-
- config["name"] = conf["name"]
- config["enabled"] = bool(conf["enabled"])
-
- return utils.remove_empties(config)
diff --git a/plugins/module_utils/network/exos/facts/vlans/__init__.py b/plugins/module_utils/network/exos/facts/vlans/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/facts/vlans/vlans.py b/plugins/module_utils/network/exos/facts/vlans/vlans.py
deleted file mode 100644
index 4ba7284747..0000000000
--- a/plugins/module_utils/network/exos/facts/vlans/vlans.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The exos vlans fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-import re
-from copy import deepcopy
-
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
-from ansible_collections.community.general.plugins.module_utils.network.exos.argspec.vlans.vlans import VlansArgs
-from ansible_collections.community.general.plugins.module_utils.network.exos.exos import send_requests
-
-
-class VlansFacts(object):
- """ The exos vlans fact class
- """
-
- def __init__(self, module, subspec='config', options='options'):
- self._module = module
- self.argument_spec = VlansArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for vlans
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
-
- if not data:
- request = [{
- "path": "/rest/restconf/data/openconfig-vlan:vlans?depth=5",
- "method": "GET"
- }]
- data = send_requests(self._module, requests=request)
-
- objs = []
- if data:
- for d in data[0]["openconfig-vlan:vlans"]["vlan"]:
- obj = self.render_config(self.generated_spec, d["config"])
- if obj:
- objs.append(obj)
-
- ansible_facts['ansible_network_resources'].pop('vlans', None)
- facts = {}
- if objs:
- params = utils.validate_config(self.argument_spec, {'config': objs})
- facts['vlans'] = params['config']
-
- ansible_facts['ansible_network_resources'].update(facts)
- return ansible_facts
-
- def render_config(self, spec, conf):
- """
- Render config as dictionary structure and delete keys
- from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- config = deepcopy(spec)
-
- config["name"] = conf["name"]
- config["state"] = "suspend" if conf["status"] == "SUSPENDED" else conf["status"].lower()
- config["vlan_id"] = conf["vlan-id"]
-
- return utils.remove_empties(config)
diff --git a/plugins/module_utils/network/exos/utils/__init__.py b/plugins/module_utils/network/exos/utils/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/exos/utils/utils.py b/plugins/module_utils/network/exos/utils/utils.py
deleted file mode 100644
index d40f81714c..0000000000
--- a/plugins/module_utils/network/exos/utils/utils.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-def search_obj_in_list(item, lst, key):
- for o in lst:
- if o[key] == item:
- return o
- return None
diff --git a/plugins/module_utils/network/f5/__init__.py b/plugins/module_utils/network/f5/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/f5/iworkflow.py b/plugins/module_utils/network/f5/iworkflow.py
deleted file mode 100644
index 92496a4f63..0000000000
--- a/plugins/module_utils/network/f5/iworkflow.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2017 F5 Networks Inc.
-# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-import time
-
-try:
- from f5.iworkflow import ManagementRoot
- from icontrol.exceptions import iControlUnexpectedHTTPError
- HAS_F5SDK = True
-except ImportError:
- HAS_F5SDK = False
-
-try:
- from library.module_utils.network.f5.common import F5BaseClient
- from library.module_utils.network.f5.common import F5ModuleError
-except ImportError:
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import F5BaseClient
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import F5ModuleError
-
-
-class F5Client(F5BaseClient):
- @property
- def api(self):
- exc = None
- if self._client:
- return self._client
- for x in range(0, 3):
- try:
- server = self.params['provider']['server'] or self.params['server']
- user = self.params['provider']['user'] or self.params['user']
- password = self.params['provider']['password'] or self.params['password']
- server_port = self.params['provider']['server_port'] or self.params['server_port'] or 443
- validate_certs = self.params['provider']['validate_certs'] or self.params['validate_certs']
-
- result = ManagementRoot(
- server,
- user,
- password,
- port=server_port,
- verify=validate_certs,
- token='local'
- )
- self._client = result
- return self._client
- except Exception as ex:
- exc = ex
- time.sleep(3)
- error = 'Unable to connect to {0} on port {1}.'.format(self.params['server'], self.params['server_port'])
- if exc is not None:
- error += ' The reported error was "{0}".'.format(str(exc))
- raise F5ModuleError(error)
diff --git a/plugins/module_utils/network/f5/legacy.py b/plugins/module_utils/network/f5/legacy.py
deleted file mode 100644
index bb2189c2bb..0000000000
--- a/plugins/module_utils/network/f5/legacy.py
+++ /dev/null
@@ -1,121 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2017 F5 Networks Inc.
-# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-try:
- import bigsuds
- bigsuds_found = True
-except ImportError:
- bigsuds_found = False
-
-
-from ansible.module_utils.basic import env_fallback
-
-
-def f5_argument_spec():
- return dict(
- server=dict(
- type='str',
- required=True,
- fallback=(env_fallback, ['F5_SERVER'])
- ),
- user=dict(
- type='str',
- required=True,
- fallback=(env_fallback, ['F5_USER'])
- ),
- password=dict(
- type='str',
- aliases=['pass', 'pwd'],
- required=True,
- no_log=True,
- fallback=(env_fallback, ['F5_PASSWORD'])
- ),
- validate_certs=dict(
- default='yes',
- type='bool',
- fallback=(env_fallback, ['F5_VALIDATE_CERTS'])
- ),
- server_port=dict(
- type='int',
- default=443,
- fallback=(env_fallback, ['F5_SERVER_PORT'])
- ),
- state=dict(
- type='str',
- default='present',
- choices=['present', 'absent']
- ),
- partition=dict(
- type='str',
- default='Common',
- fallback=(env_fallback, ['F5_PARTITION'])
- )
- )
-
-
-def f5_parse_arguments(module):
- if not bigsuds_found:
- module.fail_json(msg="the python bigsuds module is required")
-
- if module.params['validate_certs']:
- import ssl
- if not hasattr(ssl, 'SSLContext'):
- module.fail_json(
- msg="bigsuds does not support verifying certificates with python < 2.7.9."
- "Either update python or set validate_certs=False on the task'")
-
- return (
- module.params['server'],
- module.params['user'],
- module.params['password'],
- module.params['state'],
- module.params['partition'],
- module.params['validate_certs'],
- module.params['server_port']
- )
-
-
-def bigip_api(bigip, user, password, validate_certs, port=443):
- try:
- if bigsuds.__version__ >= '1.0.4':
- api = bigsuds.BIGIP(hostname=bigip, username=user, password=password, verify=validate_certs, port=port)
- elif bigsuds.__version__ == '1.0.3':
- api = bigsuds.BIGIP(hostname=bigip, username=user, password=password, verify=validate_certs)
- else:
- api = bigsuds.BIGIP(hostname=bigip, username=user, password=password)
- except TypeError:
- # bigsuds < 1.0.3, no verify param
- if validate_certs:
- # Note: verified we have SSLContext when we parsed params
- api = bigsuds.BIGIP(hostname=bigip, username=user, password=password)
- else:
- import ssl
- if hasattr(ssl, 'SSLContext'):
- # Really, you should never do this. It disables certificate
- # verification *globally*. But since older bigip libraries
- # don't give us a way to toggle verification we need to
- # disable it at the global level.
- # From https://www.python.org/dev/peps/pep-0476/#id29
- ssl._create_default_https_context = ssl._create_unverified_context
- api = bigsuds.BIGIP(hostname=bigip, username=user, password=password)
-
- return api
-
-
-# Fully Qualified name (with the partition)
-def fq_name(partition, name):
- if name is not None and not name.startswith('/'):
- return '/%s/%s' % (partition, name)
- return name
-
-
-# Fully Qualified name (with partition) for a list
-def fq_list_names(partition, list_names):
- if list_names is None:
- return None
- return map(lambda x: fq_name(partition, x), list_names)
diff --git a/plugins/module_utils/network/f5/urls.py b/plugins/module_utils/network/f5/urls.py
deleted file mode 100644
index ed6dc3b5aa..0000000000
--- a/plugins/module_utils/network/f5/urls.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2017, F5 Networks Inc.
-# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-import re
-
-try:
- from library.module_utils.network.f5.common import F5ModuleError
-except ImportError:
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import F5ModuleError
-
-_CLEAN_HEADER_REGEX_BYTE = re.compile(b'^\\S[^\\r\\n]*$|^$')
-_CLEAN_HEADER_REGEX_STR = re.compile(r'^\S[^\r\n]*$|^$')
-
-
-def check_header_validity(header):
- """Verifies that header value is a string which doesn't contain
- leading whitespace or return characters.
-
- NOTE: This is a slightly modified version of the original function
- taken from the requests library:
- http://docs.python-requests.org/en/master/_modules/requests/utils/
-
- :param header: string containing ':'.
- """
- try:
- name, value = header.split(':')
- except ValueError:
- raise F5ModuleError('Invalid header format: {0}'.format(header))
- if name == '':
- raise F5ModuleError('Invalid header format: {0}'.format(header))
-
- if isinstance(value, bytes):
- pat = _CLEAN_HEADER_REGEX_BYTE
- else:
- pat = _CLEAN_HEADER_REGEX_STR
- try:
- if not pat.match(value):
- raise F5ModuleError("Invalid return character or leading space in header: %s" % name)
- except TypeError:
- raise F5ModuleError("Value for header {%s: %s} must be of type str or "
- "bytes, not %s" % (name, value, type(value)))
-
-
-def build_service_uri(base_uri, partition, name):
- """Build the proper uri for a service resource.
- This follows the scheme:
- /~~<.app>~
- :param base_uri: str -- base uri of the REST endpoint
- :param partition: str -- partition for the service
- :param name: str -- name of the service
- :returns: str -- uri to access the service
- """
- name = name.replace('/', '~')
- return '%s~%s~%s.app~%s' % (base_uri, partition, name, name)
-
-
-def parseStats(entry):
- if 'description' in entry:
- return entry['description']
- elif 'value' in entry:
- return entry['value']
- elif 'entries' in entry or 'nestedStats' in entry and 'entries' in entry['nestedStats']:
- if 'entries' in entry:
- entries = entry['entries']
- else:
- entries = entry['nestedStats']['entries']
- result = None
-
- for name in entries:
- entry = entries[name]
- if 'https://localhost' in name:
- name = name.split('/')
- name = name[-1]
- if result and isinstance(result, list):
- result.append(parseStats(entry))
- elif result and isinstance(result, dict):
- result[name] = parseStats(entry)
- else:
- try:
- int(name)
- result = list()
- result.append(parseStats(entry))
- except ValueError:
- result = dict()
- result[name] = parseStats(entry)
- else:
- if '.' in name:
- names = name.split('.')
- key = names[0]
- value = names[1]
- if result is None:
- # result can be None if this branch is reached first
- #
- # For example, the mgmt/tm/net/trunk/NAME/stats API
- # returns counters.bitsIn before anything else.
- result = dict()
- result[key] = dict()
- elif key not in result:
- result[key] = dict()
- elif result[key] is None:
- result[key] = dict()
- result[key][value] = parseStats(entry)
- else:
- if result and isinstance(result, list):
- result.append(parseStats(entry))
- elif result and isinstance(result, dict):
- result[name] = parseStats(entry)
- else:
- try:
- int(name)
- result = list()
- result.append(parseStats(entry))
- except ValueError:
- result = dict()
- result[name] = parseStats(entry)
- return result
diff --git a/plugins/module_utils/network/fortianalyzer/__init__.py b/plugins/module_utils/network/fortianalyzer/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/fortianalyzer/common.py b/plugins/module_utils/network/fortianalyzer/common.py
deleted file mode 100644
index 546f71aa12..0000000000
--- a/plugins/module_utils/network/fortianalyzer/common.py
+++ /dev/null
@@ -1,292 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# (c) 2017 Fortinet, Inc
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-
-# BEGIN STATIC DATA AND MESSAGES
-class FAZMethods:
- GET = "get"
- SET = "set"
- EXEC = "exec"
- EXECUTE = "exec"
- UPDATE = "update"
- ADD = "add"
- DELETE = "delete"
- REPLACE = "replace"
- CLONE = "clone"
- MOVE = "move"
-
-
-BASE_HEADERS = {
- 'Content-Type': 'application/json',
- 'Accept': 'application/json'
-}
-
-
-# FAZ RETURN CODES
-FAZ_RC = {
- "faz_return_codes": {
- 0: {
- "msg": "OK",
- "changed": True,
- "stop_on_success": True
- },
- -100000: {
- "msg": "Module returned without actually running anything. "
- "Check parameters, and please contact the authors if needed.",
- "failed": True
- },
- -2: {
- "msg": "Object already exists.",
- "skipped": True,
- "changed": False,
- "good_codes": [0, -2]
- },
- -6: {
- "msg": "Invalid Url. Sometimes this can happen because the path is mapped to a hostname or object that"
- " doesn't exist. Double check your input object parameters."
- },
- -3: {
- "msg": "Object doesn't exist.",
- "skipped": True,
- "changed": False,
- "good_codes": [0, -3]
- },
- -10131: {
- "msg": "Object dependency failed. Do all named objects in parameters exist?",
- "changed": False,
- "skipped": True
- },
- -9998: {
- "msg": "Duplicate object. Try using mode='set', if using add. STOPPING. Use 'ignore_errors=yes' in playbook"
- "to override and mark successful.",
- },
- -20042: {
- "msg": "Device Unreachable.",
- "skipped": True
- },
- -10033: {
- "msg": "Duplicate object. Try using mode='set', if using add.",
- "changed": False,
- "skipped": True
- },
- -10000: {
- "msg": "Duplicate object. Try using mode='set', if using add.",
- "changed": False,
- "skipped": True
- },
- -20010: {
- "msg": "Device already added to FortiAnalyzer. Serial number already in use.",
- "good_codes": [0, -20010],
- "changed": False,
- "stop_on_failure": False
- },
- -20002: {
- "msg": "Invalid Argument -- Does this Device exist on FortiAnalyzer?",
- "changed": False,
- "skipped": True,
- }
- }
-}
-
-DEFAULT_RESULT_OBJ = (-100000, {"msg": "Nothing Happened. Check that handle_response is being called!"})
-FAIL_SOCKET_MSG = {"msg": "Socket Path Empty! The persistent connection manager is messed up. "
- "Try again in a few moments."}
-
-
-# BEGIN ERROR EXCEPTIONS
-class FAZBaseException(Exception):
- """Wrapper to catch the unexpected"""
-
- def __init__(self, msg=None, *args, **kwargs):
- if msg is None:
- msg = "An exception occurred within the fortianalyzer.py httpapi connection plugin."
- super(FAZBaseException, self).__init__(msg, *args)
-
-# END ERROR CLASSES
-
-
-# BEGIN CLASSES
-class FAZCommon(object):
-
- @staticmethod
- def format_request(method, url, *args, **kwargs):
- """
- Formats the payload from the module, into a payload the API handler can use.
-
- :param url: Connection URL to access
- :type url: string
- :param method: The preferred API Request method (GET, ADD, POST, etc....)
- :type method: basestring
- :param kwargs: The payload dictionary from the module to be converted.
-
- :return: Properly formatted dictionary payload for API Request via Connection Plugin.
- :rtype: dict
- """
-
- params = [{"url": url}]
- if args:
- for arg in args:
- params[0].update(arg)
- if kwargs:
- keylist = list(kwargs)
- for k in keylist:
- kwargs[k.replace("__", "-")] = kwargs.pop(k)
- if method == "get" or method == "clone":
- params[0].update(kwargs)
- else:
- if kwargs.get("data", False):
- params[0]["data"] = kwargs["data"]
- else:
- params[0]["data"] = kwargs
- return params
-
- @staticmethod
- def split_comma_strings_into_lists(obj):
- """
- Splits a CSV String into a list. Also takes a dictionary, and converts any CSV strings in any key, to a list.
-
- :param obj: object in CSV format to be parsed.
- :type obj: str or dict
-
- :return: A list containing the CSV items.
- :rtype: list
- """
- return_obj = ()
- if isinstance(obj, dict):
- if len(obj) > 0:
- for k, v in obj.items():
- if isinstance(v, str):
- new_list = list()
- if "," in v:
- new_items = v.split(",")
- for item in new_items:
- new_list.append(item.strip())
- obj[k] = new_list
- return_obj = obj
- elif isinstance(obj, str):
- return_obj = obj.replace(" ", "").split(",")
-
- return return_obj
-
- @staticmethod
- def cidr_to_netmask(cidr):
- """
- Converts a CIDR Network string to full blown IP/Subnet format in decimal format.
- Decided not use IP Address module to keep includes to a minimum.
-
- :param cidr: String object in CIDR format to be processed
- :type cidr: str
-
- :return: A string object that looks like this "x.x.x.x/y.y.y.y"
- :rtype: str
- """
- if isinstance(cidr, str):
- cidr = int(cidr)
- mask = (0xffffffff >> (32 - cidr)) << (32 - cidr)
- return (str((0xff000000 & mask) >> 24) + '.'
- + str((0x00ff0000 & mask) >> 16) + '.'
- + str((0x0000ff00 & mask) >> 8) + '.'
- + str((0x000000ff & mask)))
-
- @staticmethod
- def paramgram_child_list_override(list_overrides, paramgram, module):
- """
- If a list of items was provided to a "parent" paramgram attribute, the paramgram needs to be rewritten.
- The child keys of the desired attribute need to be deleted, and then that "parent" keys' contents is replaced
- With the list of items that was provided.
-
- :param list_overrides: Contains the response from the FortiAnalyzer.
- :type list_overrides: list
- :param paramgram: Contains the paramgram passed to the modules' local modify function.
- :type paramgram: dict
- :param module: Contains the Ansible Module Object being used by the module.
- :type module: classObject
-
- :return: A new "paramgram" refactored to allow for multiple entries being added.
- :rtype: dict
- """
- if len(list_overrides) > 0:
- for list_variable in list_overrides:
- try:
- list_variable = list_variable.replace("-", "_")
- override_data = module.params[list_variable]
- if override_data:
- del paramgram[list_variable]
- paramgram[list_variable] = override_data
- except BaseException as e:
- raise FAZBaseException("Error occurred merging custom lists for the paramgram parent: " + str(e))
- return paramgram
-
- @staticmethod
- def syslog(module, msg):
- try:
- module.log(msg=msg)
- except BaseException:
- pass
-
-
-# RECURSIVE FUNCTIONS START
-def prepare_dict(obj):
- """
- Removes any keys from a dictionary that are only specific to our use in the module. FortiAnalyzer will reject
- requests with these empty/None keys in it.
-
- :param obj: Dictionary object to be processed.
- :type obj: dict
-
- :return: Processed dictionary.
- :rtype: dict
- """
-
- list_of_elems = ["mode", "adom", "host", "username", "password"]
-
- if isinstance(obj, dict):
- obj = dict((key, prepare_dict(value)) for (key, value) in obj.items() if key not in list_of_elems)
- return obj
-
-
-def scrub_dict(obj):
- """
- Removes any keys from a dictionary that are EMPTY -- this includes parent keys. FortiAnalyzer doesn't
- like empty keys in dictionaries
-
- :param obj: Dictionary object to be processed.
- :type obj: dict
-
- :return: Processed dictionary.
- :rtype: dict
- """
-
- if isinstance(obj, dict):
- return dict((k, scrub_dict(v)) for k, v in obj.items() if v and scrub_dict(v))
- else:
- return obj
diff --git a/plugins/module_utils/network/fortianalyzer/fortianalyzer.py b/plugins/module_utils/network/fortianalyzer/fortianalyzer.py
deleted file mode 100644
index 94d83cd7ef..0000000000
--- a/plugins/module_utils/network/fortianalyzer/fortianalyzer.py
+++ /dev/null
@@ -1,477 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# (c) 2017 Fortinet, Inc
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-
-from ansible_collections.community.general.plugins.module_utils.network.fortianalyzer.common import FAZ_RC
-from ansible_collections.community.general.plugins.module_utils.network.fortianalyzer.common import FAZBaseException
-from ansible_collections.community.general.plugins.module_utils.network.fortianalyzer.common import FAZCommon
-from ansible_collections.community.general.plugins.module_utils.network.fortianalyzer.common import scrub_dict
-from ansible_collections.community.general.plugins.module_utils.network.fortianalyzer.common import FAZMethods
-
-
-# ACTIVE BUG WITH OUR DEBUG IMPORT CALL - BECAUSE IT'S UNDER MODULE_UTILITIES
-# WHEN module_common.recursive_finder() runs under the module loader, it looks for this namespace debug import
-# and because it's not there, it always fails, regardless of it being under a try/catch here.
-# we're going to move it to a different namespace.
-# # check for debug lib
-# try:
-# from ansible.module_utils.network.fortianalyzer.fortianalyzer_debug import debug_dump
-# HAS_FAZ_DEBUG = True
-# except:
-# HAS_FAZ_DEBUG = False
-
-
-# BEGIN HANDLER CLASSES
-class FortiAnalyzerHandler(object):
- def __init__(self, conn, module):
- self._conn = conn
- self._module = module
- self._tools = FAZCommon
- self._uses_workspace = None
- self._uses_adoms = None
- self._locked_adom_list = list()
- self._lock_info = None
-
- self.workspace_check()
- if self._uses_workspace:
- self.get_lock_info(adom=self._module.paramgram["adom"])
-
- def process_request(self, url, datagram, method):
- """
- Formats and Runs the API Request via Connection Plugin. Streamlined for use from Modules.
-
- :param url: Connection URL to access
- :type url: string
- :param datagram: The prepared payload for the API Request in dictionary format
- :type datagram: dict
- :param method: The preferred API Request method (GET, ADD, POST, etc....)
- :type method: basestring
-
- :return: Dictionary containing results of the API Request via Connection Plugin.
- :rtype: dict
- """
- try:
- adom = self._module.paramgram["adom"]
- if self.uses_workspace and adom not in self._locked_adom_list and method != FAZMethods.GET:
- self.lock_adom(adom=adom)
- except BaseException as err:
- raise FAZBaseException(err)
-
- data = self._tools.format_request(method, url, **datagram)
- response = self._conn.send_request(method, data)
-
- try:
- adom = self._module.paramgram["adom"]
- if self.uses_workspace and adom in self._locked_adom_list \
- and response[0] == 0 and method != FAZMethods.GET:
- self.commit_changes(adom=adom)
- except BaseException as err:
- raise FAZBaseException(err)
-
- # if HAS_FAZ_DEBUG:
- # try:
- # debug_dump(response, datagram, self._module.paramgram, url, method)
- # except BaseException:
- # pass
-
- return response
-
- def workspace_check(self):
- """
- Checks FortiAnalyzer for the use of Workspace mode.
- """
- url = "/cli/global/system/global"
- data = {"fields": ["workspace-mode", "adom-status"]}
- resp_obj = self.process_request(url, data, FAZMethods.GET)
- try:
- if resp_obj[1]["workspace-mode"] in ["workflow", "normal"]:
- self.uses_workspace = True
- elif resp_obj[1]["workspace-mode"] == "disabled":
- self.uses_workspace = False
- except KeyError:
- self.uses_workspace = False
- except BaseException as err:
- raise FAZBaseException(msg="Couldn't determine workspace-mode in the plugin. Error: " + str(err))
- try:
- if resp_obj[1]["adom-status"] in [1, "enable"]:
- self.uses_adoms = True
- else:
- self.uses_adoms = False
- except KeyError:
- self.uses_adoms = False
- except BaseException as err:
- raise FAZBaseException(msg="Couldn't determine adom-status in the plugin. Error: " + str(err))
-
- def run_unlock(self):
- """
- Checks for ADOM status, if locked, it will unlock
- """
- for adom_locked in self._locked_adom_list:
- self.unlock_adom(adom_locked)
-
- def lock_adom(self, adom=None):
- """
- Locks an ADOM for changes
- """
- if not adom or adom == "root":
- url = "/dvmdb/adom/root/workspace/lock"
- else:
- if adom.lower() == "global":
- url = "/dvmdb/global/workspace/lock/"
- else:
- url = "/dvmdb/adom/{adom}/workspace/lock/".format(adom=adom)
- datagram = {}
- data = self._tools.format_request(FAZMethods.EXEC, url, **datagram)
- resp_obj = self._conn.send_request(FAZMethods.EXEC, data)
- code = resp_obj[0]
- if code == 0 and resp_obj[1]["status"]["message"].lower() == "ok":
- self.add_adom_to_lock_list(adom)
- else:
- lockinfo = self.get_lock_info(adom=adom)
- self._module.fail_json(msg=("An error occurred trying to lock the adom. Error: "
- + str(resp_obj) + ", LOCK INFO: " + str(lockinfo)))
- return resp_obj
-
- def unlock_adom(self, adom=None):
- """
- Unlocks an ADOM after changes
- """
- if not adom or adom == "root":
- url = "/dvmdb/adom/root/workspace/unlock"
- else:
- if adom.lower() == "global":
- url = "/dvmdb/global/workspace/unlock/"
- else:
- url = "/dvmdb/adom/{adom}/workspace/unlock/".format(adom=adom)
- datagram = {}
- data = self._tools.format_request(FAZMethods.EXEC, url, **datagram)
- resp_obj = self._conn.send_request(FAZMethods.EXEC, data)
- code = resp_obj[0]
- if code == 0 and resp_obj[1]["status"]["message"].lower() == "ok":
- self.remove_adom_from_lock_list(adom)
- else:
- self._module.fail_json(msg=("An error occurred trying to unlock the adom. Error: " + str(resp_obj)))
- return resp_obj
-
- def get_lock_info(self, adom=None):
- """
- Gets ADOM lock info so it can be displayed with the error messages. Or if determined to be locked by ansible
- for some reason, then unlock it.
- """
- if not adom or adom == "root":
- url = "/dvmdb/adom/root/workspace/lockinfo"
- else:
- if adom.lower() == "global":
- url = "/dvmdb/global/workspace/lockinfo/"
- else:
- url = "/dvmdb/adom/{adom}/workspace/lockinfo/".format(adom=adom)
- datagram = {}
- data = self._tools.format_request(FAZMethods.GET, url, **datagram)
- resp_obj = self._conn.send_request(FAZMethods.GET, data)
- code = resp_obj[0]
- if code != 0:
- self._module.fail_json(msg=("An error occurred trying to get the ADOM Lock Info. Error: " + str(resp_obj)))
- elif code == 0:
- self._lock_info = resp_obj[1]
- return resp_obj
-
- def commit_changes(self, adom=None, aux=False):
- """
- Commits changes to an ADOM
- """
- if not adom or adom == "root":
- url = "/dvmdb/adom/root/workspace/commit"
- else:
- if aux:
- url = "/pm/config/adom/{adom}/workspace/commit".format(adom=adom)
- else:
- if adom.lower() == "global":
- url = "/dvmdb/global/workspace/commit/"
- else:
- url = "/dvmdb/adom/{adom}/workspace/commit".format(adom=adom)
- datagram = {}
- data = self._tools.format_request(FAZMethods.EXEC, url, **datagram)
- resp_obj = self._conn.send_request(FAZMethods.EXEC, data)
- code = resp_obj[0]
- if code != 0:
- self._module.fail_json(msg=("An error occurred trying to commit changes to the adom. Error: "
- + str(resp_obj)))
-
- def govern_response(self, module, results, msg=None, good_codes=None,
- stop_on_fail=None, stop_on_success=None, skipped=None,
- changed=None, unreachable=None, failed=None, success=None, changed_if_success=None,
- ansible_facts=None):
- """
- This function will attempt to apply default values to canned responses from FortiAnalyzer we know of.
- This saves time, and turns the response in the module into a "one-liner", while still giving us...
- the flexibility to directly use return_response in modules if we have too. This function saves repeated code.
-
- :param module: The Ansible Module CLASS object, used to run fail/exit json
- :type module: object
- :param msg: An overridable custom message from the module that called this.
- :type msg: string
- :param results: A dictionary object containing an API call results
- :type results: dict
- :param good_codes: A list of exit codes considered successful from FortiAnalyzer
- :type good_codes: list
- :param stop_on_fail: If true, stops playbook run when return code is NOT IN good codes (default: true)
- :type stop_on_fail: boolean
- :param stop_on_success: If true, stops playbook run when return code is IN good codes (default: false)
- :type stop_on_success: boolean
- :param changed: If True, tells Ansible that object was changed (default: false)
- :type skipped: boolean
- :param skipped: If True, tells Ansible that object was skipped (default: false)
- :type skipped: boolean
- :param unreachable: If True, tells Ansible that object was unreachable (default: false)
- :type unreachable: boolean
- :param failed: If True, tells Ansible that execution was a failure. Overrides good_codes. (default: false)
- :type unreachable: boolean
- :param success: If True, tells Ansible that execution was a success. Overrides good_codes. (default: false)
- :type unreachable: boolean
- :param changed_if_success: If True, defaults to changed if successful if you specify or not"
- :type changed_if_success: boolean
- :param ansible_facts: A prepared dictionary of ansible facts from the execution.
- :type ansible_facts: dict
- """
- if module is None and results is None:
- raise FAZBaseException("govern_response() was called without a module and/or results tuple! Fix!")
- # Get the Return code from results
- try:
- rc = results[0]
- except BaseException:
- raise FAZBaseException("govern_response() was called without the return code at results[0]")
-
- # init a few items
- rc_data = None
-
- # Get the default values for the said return code.
- try:
- rc_codes = FAZ_RC.get('faz_return_codes')
- rc_data = rc_codes.get(rc)
- except BaseException:
- pass
-
- if not rc_data:
- rc_data = {}
- # ONLY add to overrides if not none -- This is very important that the keys aren't added at this stage
- # if they are empty. And there aren't that many, so let's just do a few if then statements.
- if good_codes is not None:
- rc_data["good_codes"] = good_codes
- if stop_on_fail is not None:
- rc_data["stop_on_fail"] = stop_on_fail
- if stop_on_success is not None:
- rc_data["stop_on_success"] = stop_on_success
- if skipped is not None:
- rc_data["skipped"] = skipped
- if changed is not None:
- rc_data["changed"] = changed
- if unreachable is not None:
- rc_data["unreachable"] = unreachable
- if failed is not None:
- rc_data["failed"] = failed
- if success is not None:
- rc_data["success"] = success
- if changed_if_success is not None:
- rc_data["changed_if_success"] = changed_if_success
- if results is not None:
- rc_data["results"] = results
- if msg is not None:
- rc_data["msg"] = msg
- if ansible_facts is None:
- rc_data["ansible_facts"] = {}
- else:
- rc_data["ansible_facts"] = ansible_facts
-
- return self.return_response(module=module,
- results=results,
- msg=rc_data.get("msg", "NULL"),
- good_codes=rc_data.get("good_codes", (0,)),
- stop_on_fail=rc_data.get("stop_on_fail", True),
- stop_on_success=rc_data.get("stop_on_success", False),
- skipped=rc_data.get("skipped", False),
- changed=rc_data.get("changed", False),
- changed_if_success=rc_data.get("changed_if_success", False),
- unreachable=rc_data.get("unreachable", False),
- failed=rc_data.get("failed", False),
- success=rc_data.get("success", False),
- ansible_facts=rc_data.get("ansible_facts", dict()))
-
- def return_response(self, module, results, msg="NULL", good_codes=(0,),
- stop_on_fail=True, stop_on_success=False, skipped=False,
- changed=False, unreachable=False, failed=False, success=False, changed_if_success=True,
- ansible_facts=()):
- """
- This function controls the logout and error reporting after an method or function runs. The exit_json for
- ansible comes from logic within this function. If this function returns just the msg, it means to continue
- execution on the playbook. It is called from the ansible module, or from the self.govern_response function.
-
- :param module: The Ansible Module CLASS object, used to run fail/exit json
- :type module: object
- :param msg: An overridable custom message from the module that called this.
- :type msg: string
- :param results: A dictionary object containing an API call results
- :type results: dict
- :param good_codes: A list of exit codes considered successful from FortiAnalyzer
- :type good_codes: list
- :param stop_on_fail: If true, stops playbook run when return code is NOT IN good codes (default: true)
- :type stop_on_fail: boolean
- :param stop_on_success: If true, stops playbook run when return code is IN good codes (default: false)
- :type stop_on_success: boolean
- :param changed: If True, tells Ansible that object was changed (default: false)
- :type skipped: boolean
- :param skipped: If True, tells Ansible that object was skipped (default: false)
- :type skipped: boolean
- :param unreachable: If True, tells Ansible that object was unreachable (default: false)
- :type unreachable: boolean
- :param failed: If True, tells Ansible that execution was a failure. Overrides good_codes. (default: false)
- :type unreachable: boolean
- :param success: If True, tells Ansible that execution was a success. Overrides good_codes. (default: false)
- :type unreachable: boolean
- :param changed_if_success: If True, defaults to changed if successful if you specify or not"
- :type changed_if_success: boolean
- :param ansible_facts: A prepared dictionary of ansible facts from the execution.
- :type ansible_facts: dict
-
- :return: A string object that contains an error message
- :rtype: str
- """
-
- # VALIDATION ERROR
- if (len(results) == 0) or (failed and success) or (changed and unreachable):
- module.exit_json(msg="Handle_response was called with no results, or conflicting failed/success or "
- "changed/unreachable parameters. Fix the exit code on module. "
- "Generic Failure", failed=True)
-
- # IDENTIFY SUCCESS/FAIL IF NOT DEFINED
- if not failed and not success:
- if len(results) > 0:
- if results[0] not in good_codes:
- failed = True
- elif results[0] in good_codes:
- success = True
-
- if len(results) > 0:
- # IF NO MESSAGE WAS SUPPLIED, GET IT FROM THE RESULTS, IF THAT DOESN'T WORK, THEN WRITE AN ERROR MESSAGE
- if msg == "NULL":
- try:
- msg = results[1]['status']['message']
- except BaseException:
- msg = "No status message returned at results[1][status][message], " \
- "and none supplied to msg parameter for handle_response."
-
- if failed:
- # BECAUSE SKIPPED/FAILED WILL OFTEN OCCUR ON CODES THAT DON'T GET INCLUDED, THEY ARE CONSIDERED FAILURES
- # HOWEVER, THEY ARE MUTUALLY EXCLUSIVE, SO IF IT IS MARKED SKIPPED OR UNREACHABLE BY THE MODULE LOGIC
- # THEN REMOVE THE FAILED FLAG SO IT DOESN'T OVERRIDE THE DESIRED STATUS OF SKIPPED OR UNREACHABLE.
- if failed and skipped:
- failed = False
- if failed and unreachable:
- failed = False
- if stop_on_fail:
- if self._uses_workspace:
- try:
- self.run_unlock()
- except BaseException as err:
- raise FAZBaseException(msg=("Couldn't unlock ADOM! Error: " + str(err)))
- module.exit_json(msg=msg, failed=failed, changed=changed, unreachable=unreachable, skipped=skipped,
- results=results[1], ansible_facts=ansible_facts, rc=results[0],
- invocation={"module_args": ansible_facts["ansible_params"]})
- elif success:
- if changed_if_success:
- changed = True
- success = False
- if stop_on_success:
- if self._uses_workspace:
- try:
- self.run_unlock()
- except BaseException as err:
- raise FAZBaseException(msg=("Couldn't unlock ADOM! Error: " + str(err)))
- module.exit_json(msg=msg, success=success, changed=changed, unreachable=unreachable,
- skipped=skipped, results=results[1], ansible_facts=ansible_facts, rc=results[0],
- invocation={"module_args": ansible_facts["ansible_params"]})
- return msg
-
- @staticmethod
- def construct_ansible_facts(response, ansible_params, paramgram, *args, **kwargs):
- """
- Constructs a dictionary to return to ansible facts, containing various information about the execution.
-
- :param response: Contains the response from the FortiAnalyzer.
- :type response: dict
- :param ansible_params: Contains the parameters Ansible was called with.
- :type ansible_params: dict
- :param paramgram: Contains the paramgram passed to the modules' local modify function.
- :type paramgram: dict
- :param args: Free-form arguments that could be added.
- :param kwargs: Free-form keyword arguments that could be added.
-
- :return: A dictionary containing lots of information to append to Ansible Facts.
- :rtype: dict
- """
-
- facts = {
- "response": response,
- "ansible_params": scrub_dict(ansible_params),
- "paramgram": scrub_dict(paramgram),
- }
-
- if args:
- facts["custom_args"] = args
- if kwargs:
- facts.update(kwargs)
-
- return facts
-
- @property
- def uses_workspace(self):
- return self._uses_workspace
-
- @uses_workspace.setter
- def uses_workspace(self, val):
- self._uses_workspace = val
-
- @property
- def uses_adoms(self):
- return self._uses_adoms
-
- @uses_adoms.setter
- def uses_adoms(self, val):
- self._uses_adoms = val
-
- def add_adom_to_lock_list(self, adom):
- if adom not in self._locked_adom_list:
- self._locked_adom_list.append(adom)
-
- def remove_adom_from_lock_list(self, adom):
- if adom in self._locked_adom_list:
- self._locked_adom_list.remove(adom)
diff --git a/plugins/module_utils/network/ftd/__init__.py b/plugins/module_utils/network/ftd/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/ftd/common.py b/plugins/module_utils/network/ftd/common.py
deleted file mode 100644
index de3f459d5b..0000000000
--- a/plugins/module_utils/network/ftd/common.py
+++ /dev/null
@@ -1,238 +0,0 @@
-# Copyright (c) 2018 Cisco and/or its affiliates.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-import re
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.common.collections import is_string
-from ansible.module_utils.six import iteritems
-
-INVALID_IDENTIFIER_SYMBOLS = r'[^a-zA-Z0-9_]'
-
-IDENTITY_PROPERTIES = ['id', 'version', 'ruleId']
-NON_COMPARABLE_PROPERTIES = IDENTITY_PROPERTIES + ['isSystemDefined', 'links', 'token', 'rulePosition']
-
-
-class HTTPMethod:
- GET = 'get'
- POST = 'post'
- PUT = 'put'
- DELETE = 'delete'
-
-
-class ResponseParams:
- SUCCESS = 'success'
- STATUS_CODE = 'status_code'
- RESPONSE = 'response'
-
-
-class FtdConfigurationError(Exception):
- def __init__(self, msg, obj=None):
- super(FtdConfigurationError, self).__init__(msg)
- self.msg = msg
- self.obj = obj
-
-
-class FtdServerError(Exception):
- def __init__(self, response, code):
- super(FtdServerError, self).__init__(response)
- self.response = response
- self.code = code
-
-
-class FtdUnexpectedResponse(Exception):
- """The exception to be raised in case of unexpected responses from 3d parties."""
- pass
-
-
-def construct_ansible_facts(response, params):
- facts = dict()
- if response:
- response_body = response['items'] if 'items' in response else response
- if params.get('register_as'):
- facts[params['register_as']] = response_body
- elif type(response_body) is dict and response_body.get('name') and response_body.get('type'):
- object_name = re.sub(INVALID_IDENTIFIER_SYMBOLS, '_', response_body['name'].lower())
- fact_name = '%s_%s' % (response_body['type'], object_name)
- facts[fact_name] = response_body
- return facts
-
-
-def copy_identity_properties(source_obj, dest_obj):
- for property_name in IDENTITY_PROPERTIES:
- if property_name in source_obj:
- dest_obj[property_name] = source_obj[property_name]
- return dest_obj
-
-
-def is_object_ref(d):
- """
- Checks if a dictionary is a reference object. The dictionary is considered to be a
- reference object when it contains non-empty 'id' and 'type' fields.
-
- :type d: dict
- :return: True if passed dictionary is a reference object, otherwise False
- """
- has_id = 'id' in d.keys() and d['id']
- has_type = 'type' in d.keys() and d['type']
- return has_id and has_type
-
-
-def equal_object_refs(d1, d2):
- """
- Checks whether two references point to the same object.
-
- :type d1: dict
- :type d2: dict
- :return: True if passed references point to the same object, otherwise False
- """
- have_equal_ids = d1['id'] == d2['id']
- have_equal_types = d1['type'] == d2['type']
- return have_equal_ids and have_equal_types
-
-
-def equal_lists(l1, l2):
- """
- Checks whether two lists are equal. The order of elements in the arrays is important.
-
- :type l1: list
- :type l2: list
- :return: True if passed lists, their elements and order of elements are equal. Otherwise, returns False.
- """
- if len(l1) != len(l2):
- return False
-
- for v1, v2 in zip(l1, l2):
- if not equal_values(v1, v2):
- return False
-
- return True
-
-
-def equal_dicts(d1, d2, compare_by_reference=True):
- """
- Checks whether two dictionaries are equal. If `compare_by_reference` is set to True, dictionaries referencing
- objects are compared using `equal_object_refs` method. Otherwise, every key and value is checked.
-
- :type d1: dict
- :type d2: dict
- :param compare_by_reference: if True, dictionaries referencing objects are compared using `equal_object_refs` method
- :return: True if passed dicts are equal. Otherwise, returns False.
- """
- if compare_by_reference and is_object_ref(d1) and is_object_ref(d2):
- return equal_object_refs(d1, d2)
-
- if len(d1) != len(d2):
- return False
-
- for key, v1 in d1.items():
- if key not in d2:
- return False
-
- v2 = d2[key]
- if not equal_values(v1, v2):
- return False
-
- return True
-
-
-def equal_values(v1, v2):
- """
- Checks whether types and content of two values are the same. In case of complex objects, the method might be
- called recursively.
-
- :param v1: first value
- :param v2: second value
- :return: True if types and content of passed values are equal. Otherwise, returns False.
- :rtype: bool
- """
-
- # string-like values might have same text but different types, so checking them separately
- if is_string(v1) and is_string(v2):
- return to_text(v1) == to_text(v2)
-
- if type(v1) != type(v2):
- return False
- value_type = type(v1)
-
- if value_type == list:
- return equal_lists(v1, v2)
- elif value_type == dict:
- return equal_dicts(v1, v2)
- else:
- return v1 == v2
-
-
-def equal_objects(d1, d2):
- """
- Checks whether two objects are equal. Ignores special object properties (e.g. 'id', 'version') and
- properties with None and empty values. In case properties contains a reference to the other object,
- only object identities (ids and types) are checked. Also, if an array field contains multiple references
- to the same object, duplicates are ignored when comparing objects.
-
- :type d1: dict
- :type d2: dict
- :return: True if passed objects and their properties are equal. Otherwise, returns False.
- """
-
- def prepare_data_for_comparison(d):
- d = dict((k, d[k]) for k in d.keys() if k not in NON_COMPARABLE_PROPERTIES and d[k])
- d = delete_ref_duplicates(d)
- return d
-
- d1 = prepare_data_for_comparison(d1)
- d2 = prepare_data_for_comparison(d2)
- return equal_dicts(d1, d2, compare_by_reference=False)
-
-
-def delete_ref_duplicates(d):
- """
- Removes reference duplicates from array fields: if an array contains multiple items and some of
- them refer to the same object, only unique references are preserved (duplicates are removed).
-
- :param d: dict with data
- :type d: dict
- :return: dict without reference duplicates
- """
-
- def delete_ref_duplicates_from_list(refs):
- if all(type(i) == dict and is_object_ref(i) for i in refs):
- unique_refs = set()
- unique_list = list()
- for i in refs:
- key = (i['id'], i['type'])
- if key not in unique_refs:
- unique_refs.add(key)
- unique_list.append(i)
-
- return list(unique_list)
-
- else:
- return refs
-
- if not d:
- return d
-
- modified_d = {}
- for k, v in iteritems(d):
- if type(v) == list:
- modified_d[k] = delete_ref_duplicates_from_list(v)
- elif type(v) == dict:
- modified_d[k] = delete_ref_duplicates(v)
- else:
- modified_d[k] = v
- return modified_d
diff --git a/plugins/module_utils/network/ftd/configuration.py b/plugins/module_utils/network/ftd/configuration.py
deleted file mode 100644
index d8c92758f5..0000000000
--- a/plugins/module_utils/network/ftd/configuration.py
+++ /dev/null
@@ -1,565 +0,0 @@
-# Copyright (c) 2018 Cisco and/or its affiliates.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-import copy
-from functools import partial
-
-from ansible_collections.community.general.plugins.module_utils.network.ftd.common import HTTPMethod, equal_objects, FtdConfigurationError, \
- FtdServerError, ResponseParams, copy_identity_properties, FtdUnexpectedResponse
-from ansible_collections.community.general.plugins.module_utils.network.ftd.fdm_swagger_client import OperationField, ValidationError
-from ansible.module_utils.six import iteritems
-
-DEFAULT_PAGE_SIZE = 10
-DEFAULT_OFFSET = 0
-
-UNPROCESSABLE_ENTITY_STATUS = 422
-INVALID_UUID_ERROR_MESSAGE = "Validation failed due to an invalid UUID"
-DUPLICATE_NAME_ERROR_MESSAGE = "Validation failed due to a duplicate name"
-
-MULTIPLE_DUPLICATES_FOUND_ERROR = (
- "Multiple objects matching specified filters are found. "
- "Please, define filters more precisely to match one object exactly."
-)
-DUPLICATE_ERROR = (
- "Cannot add a new object. "
- "An object with the same name but different parameters already exists."
-)
-ADD_OPERATION_NOT_SUPPORTED_ERROR = (
- "Cannot add a new object while executing an upsert request. "
- "Creation of objects with this type is not supported."
-)
-
-PATH_PARAMS_FOR_DEFAULT_OBJ = {'objId': 'default'}
-
-
-class OperationNamePrefix:
- ADD = 'add'
- EDIT = 'edit'
- GET = 'get'
- DELETE = 'delete'
- UPSERT = 'upsert'
-
-
-class QueryParams:
- FILTER = 'filter'
-
-
-class ParamName:
- QUERY_PARAMS = 'query_params'
- PATH_PARAMS = 'path_params'
- DATA = 'data'
- FILTERS = 'filters'
-
-
-class CheckModeException(Exception):
- pass
-
-
-class FtdInvalidOperationNameError(Exception):
- def __init__(self, operation_name):
- super(FtdInvalidOperationNameError, self).__init__(operation_name)
- self.operation_name = operation_name
-
-
-class OperationChecker(object):
-
- @classmethod
- def is_add_operation(cls, operation_name, operation_spec):
- """
- Check if operation defined with 'operation_name' is add object operation according to 'operation_spec'.
-
- :param operation_name: name of the operation being called by the user
- :type operation_name: str
- :param operation_spec: specification of the operation being called by the user
- :type operation_spec: dict
- :return: True if the called operation is add object operation, otherwise False
- :rtype: bool
- """
- # Some endpoints have non-CRUD operations, so checking operation name is required in addition to the HTTP method
- return operation_name.startswith(OperationNamePrefix.ADD) and is_post_request(operation_spec)
-
- @classmethod
- def is_edit_operation(cls, operation_name, operation_spec):
- """
- Check if operation defined with 'operation_name' is edit object operation according to 'operation_spec'.
-
- :param operation_name: name of the operation being called by the user
- :type operation_name: str
- :param operation_spec: specification of the operation being called by the user
- :type operation_spec: dict
- :return: True if the called operation is edit object operation, otherwise False
- :rtype: bool
- """
- # Some endpoints have non-CRUD operations, so checking operation name is required in addition to the HTTP method
- return operation_name.startswith(OperationNamePrefix.EDIT) and is_put_request(operation_spec)
-
- @classmethod
- def is_delete_operation(cls, operation_name, operation_spec):
- """
- Check if operation defined with 'operation_name' is delete object operation according to 'operation_spec'.
-
- :param operation_name: name of the operation being called by the user
- :type operation_name: str
- :param operation_spec: specification of the operation being called by the user
- :type operation_spec: dict
- :return: True if the called operation is delete object operation, otherwise False
- :rtype: bool
- """
- # Some endpoints have non-CRUD operations, so checking operation name is required in addition to the HTTP method
- return operation_name.startswith(OperationNamePrefix.DELETE) \
- and operation_spec[OperationField.METHOD] == HTTPMethod.DELETE
-
- @classmethod
- def is_get_list_operation(cls, operation_name, operation_spec):
- """
- Check if operation defined with 'operation_name' is get list of objects operation according to 'operation_spec'.
-
- :param operation_name: name of the operation being called by the user
- :type operation_name: str
- :param operation_spec: specification of the operation being called by the user
- :type operation_spec: dict
- :return: True if the called operation is get a list of objects operation, otherwise False
- :rtype: bool
- """
- return operation_spec[OperationField.METHOD] == HTTPMethod.GET \
- and operation_spec[OperationField.RETURN_MULTIPLE_ITEMS]
-
- @classmethod
- def is_get_operation(cls, operation_name, operation_spec):
- """
- Check if operation defined with 'operation_name' is get objects operation according to 'operation_spec'.
-
- :param operation_name: name of the operation being called by the user
- :type operation_name: str
- :param operation_spec: specification of the operation being called by the user
- :type operation_spec: dict
- :return: True if the called operation is get object operation, otherwise False
- :rtype: bool
- """
- return operation_spec[OperationField.METHOD] == HTTPMethod.GET \
- and not operation_spec[OperationField.RETURN_MULTIPLE_ITEMS]
-
- @classmethod
- def is_upsert_operation(cls, operation_name):
- """
- Check if operation defined with 'operation_name' is upsert objects operation according to 'operation_name'.
-
- :param operation_name: name of the operation being called by the user
- :type operation_name: str
- :return: True if the called operation is upsert object operation, otherwise False
- :rtype: bool
- """
- return operation_name.startswith(OperationNamePrefix.UPSERT)
-
- @classmethod
- def is_find_by_filter_operation(cls, operation_name, params, operation_spec):
- """
- Checks whether the called operation is 'find by filter'. This operation fetches all objects and finds
- the matching ones by the given filter. As filtering is done on the client side, this operation should be used
- only when selected filters are not implemented on the server side.
-
- :param operation_name: name of the operation being called by the user
- :type operation_name: str
- :param operation_spec: specification of the operation being called by the user
- :type operation_spec: dict
- :param params: params - params should contain 'filters'
- :return: True if the called operation is find by filter, otherwise False
- :rtype: bool
- """
- is_get_list = cls.is_get_list_operation(operation_name, operation_spec)
- return is_get_list and ParamName.FILTERS in params and params[ParamName.FILTERS]
-
- @classmethod
- def is_upsert_operation_supported(cls, operations):
- """
- Checks if all operations required for upsert object operation are defined in 'operations'.
-
- :param operations: specification of the operations supported by model
- :type operations: dict
- :return: True if all criteria required to provide requested called operation are satisfied, otherwise False
- :rtype: bool
- """
- has_edit_op = next((name for name, spec in iteritems(operations) if cls.is_edit_operation(name, spec)), None)
- has_get_list_op = next((name for name, spec in iteritems(operations)
- if cls.is_get_list_operation(name, spec)), None)
- return has_edit_op and has_get_list_op
-
-
-class BaseConfigurationResource(object):
-
- def __init__(self, conn, check_mode=False):
- self._conn = conn
- self.config_changed = False
- self._operation_spec_cache = {}
- self._models_operations_specs_cache = {}
- self._check_mode = check_mode
- self._operation_checker = OperationChecker
- self._system_info = None
-
- def execute_operation(self, op_name, params):
- """
- Allow user request execution of simple operations(natively supported by API provider) as well as complex
- operations(operations that are implemented as a set of simple operations).
-
- :param op_name: name of the operation being called by the user
- :type op_name: str
- :param params: definition of the params that operation should be executed with
- :type params: dict
- :return: Result of the operation being executed
- :rtype: dict
- """
- if self._operation_checker.is_upsert_operation(op_name):
- return self.upsert_object(op_name, params)
- else:
- return self.crud_operation(op_name, params)
-
- def crud_operation(self, op_name, params):
- """
- Allow user request execution of simple operations(natively supported by API provider) only.
-
- :param op_name: name of the operation being called by the user
- :type op_name: str
- :param params: definition of the params that operation should be executed with
- :type params: dict
- :return: Result of the operation being executed
- :rtype: dict
- """
- op_spec = self.get_operation_spec(op_name)
- if op_spec is None:
- raise FtdInvalidOperationNameError(op_name)
-
- if self._operation_checker.is_add_operation(op_name, op_spec):
- resp = self.add_object(op_name, params)
- elif self._operation_checker.is_edit_operation(op_name, op_spec):
- resp = self.edit_object(op_name, params)
- elif self._operation_checker.is_delete_operation(op_name, op_spec):
- resp = self.delete_object(op_name, params)
- elif self._operation_checker.is_find_by_filter_operation(op_name, params, op_spec):
- resp = list(self.get_objects_by_filter(op_name, params))
- else:
- resp = self.send_general_request(op_name, params)
- return resp
-
- def get_operation_spec(self, operation_name):
- if operation_name not in self._operation_spec_cache:
- self._operation_spec_cache[operation_name] = self._conn.get_operation_spec(operation_name)
- return self._operation_spec_cache[operation_name]
-
- def get_operation_specs_by_model_name(self, model_name):
- if model_name not in self._models_operations_specs_cache:
- model_op_specs = self._conn.get_operation_specs_by_model_name(model_name)
- self._models_operations_specs_cache[model_name] = model_op_specs
- for op_name, op_spec in iteritems(model_op_specs):
- self._operation_spec_cache.setdefault(op_name, op_spec)
- return self._models_operations_specs_cache[model_name]
-
- def get_objects_by_filter(self, operation_name, params):
-
- def match_filters(filter_params, obj):
- for k, v in iteritems(filter_params):
- if k not in obj or obj[k] != v:
- return False
- return True
-
- dummy, query_params, path_params = _get_user_params(params)
- # copy required params to avoid mutation of passed `params` dict
- url_params = {ParamName.QUERY_PARAMS: dict(query_params), ParamName.PATH_PARAMS: dict(path_params)}
-
- filters = params.get(ParamName.FILTERS) or {}
- if QueryParams.FILTER not in url_params[ParamName.QUERY_PARAMS] and 'name' in filters:
- # most endpoints only support filtering by name, so remaining `filters` are applied on returned objects
- url_params[ParamName.QUERY_PARAMS][QueryParams.FILTER] = self._stringify_name_filter(filters)
-
- item_generator = iterate_over_pageable_resource(
- partial(self.send_general_request, operation_name=operation_name), url_params
- )
- return (i for i in item_generator if match_filters(filters, i))
-
- def _stringify_name_filter(self, filters):
- build_version = self.get_build_version()
- if build_version >= '6.4.0':
- return "fts~%s" % filters['name']
- return "name:%s" % filters['name']
-
- def _fetch_system_info(self):
- if not self._system_info:
- params = {ParamName.PATH_PARAMS: PATH_PARAMS_FOR_DEFAULT_OBJ}
- self._system_info = self.send_general_request('getSystemInformation', params)
-
- return self._system_info
-
- def get_build_version(self):
- system_info = self._fetch_system_info()
- return system_info['databaseInfo']['buildVersion']
-
- def add_object(self, operation_name, params):
- def is_duplicate_name_error(err):
- return err.code == UNPROCESSABLE_ENTITY_STATUS and DUPLICATE_NAME_ERROR_MESSAGE in str(err)
-
- try:
- return self.send_general_request(operation_name, params)
- except FtdServerError as e:
- if is_duplicate_name_error(e):
- return self._check_equality_with_existing_object(operation_name, params, e)
- else:
- raise e
-
- def _check_equality_with_existing_object(self, operation_name, params, e):
- """
- Looks for an existing object that caused "object duplicate" error and
- checks whether it corresponds to the one specified in `params`.
-
- In case a single object is found and it is equal to one we are trying
- to create, the existing object is returned.
-
- When the existing object is not equal to the object being created or
- several objects are returned, an exception is raised.
- """
- model_name = self.get_operation_spec(operation_name)[OperationField.MODEL_NAME]
- existing_obj = self._find_object_matching_params(model_name, params)
-
- if existing_obj is not None:
- if equal_objects(existing_obj, params[ParamName.DATA]):
- return existing_obj
- else:
- raise FtdConfigurationError(DUPLICATE_ERROR, existing_obj)
-
- raise e
-
- def _find_object_matching_params(self, model_name, params):
- get_list_operation = self._find_get_list_operation(model_name)
- if not get_list_operation:
- return None
-
- data = params[ParamName.DATA]
- if not params.get(ParamName.FILTERS):
- params[ParamName.FILTERS] = {'name': data['name']}
-
- obj = None
- filtered_objs = self.get_objects_by_filter(get_list_operation, params)
-
- for i, obj in enumerate(filtered_objs):
- if i > 0:
- raise FtdConfigurationError(MULTIPLE_DUPLICATES_FOUND_ERROR)
- obj = obj
-
- return obj
-
- def _find_get_list_operation(self, model_name):
- operations = self.get_operation_specs_by_model_name(model_name) or {}
- return next((
- op for op, op_spec in operations.items()
- if self._operation_checker.is_get_list_operation(op, op_spec)), None)
-
- def _find_get_operation(self, model_name):
- operations = self.get_operation_specs_by_model_name(model_name) or {}
- return next((
- op for op, op_spec in operations.items()
- if self._operation_checker.is_get_operation(op, op_spec)), None)
-
- def delete_object(self, operation_name, params):
- def is_invalid_uuid_error(err):
- return err.code == UNPROCESSABLE_ENTITY_STATUS and INVALID_UUID_ERROR_MESSAGE in str(err)
-
- try:
- return self.send_general_request(operation_name, params)
- except FtdServerError as e:
- if is_invalid_uuid_error(e):
- return {'status': 'Referenced object does not exist'}
- else:
- raise e
-
- def edit_object(self, operation_name, params):
- data, dummy, path_params = _get_user_params(params)
-
- model_name = self.get_operation_spec(operation_name)[OperationField.MODEL_NAME]
- get_operation = self._find_get_operation(model_name)
-
- if get_operation:
- existing_object = self.send_general_request(get_operation, {ParamName.PATH_PARAMS: path_params})
- if not existing_object:
- raise FtdConfigurationError('Referenced object does not exist')
- elif equal_objects(existing_object, data):
- return existing_object
-
- return self.send_general_request(operation_name, params)
-
- def send_general_request(self, operation_name, params):
- def stop_if_check_mode():
- if self._check_mode:
- raise CheckModeException()
-
- self.validate_params(operation_name, params)
- stop_if_check_mode()
-
- data, query_params, path_params = _get_user_params(params)
- op_spec = self.get_operation_spec(operation_name)
- url, method = op_spec[OperationField.URL], op_spec[OperationField.METHOD]
-
- return self._send_request(url, method, data, path_params, query_params)
-
- def _send_request(self, url_path, http_method, body_params=None, path_params=None, query_params=None):
- def raise_for_failure(resp):
- if not resp[ResponseParams.SUCCESS]:
- raise FtdServerError(resp[ResponseParams.RESPONSE], resp[ResponseParams.STATUS_CODE])
-
- response = self._conn.send_request(url_path=url_path, http_method=http_method, body_params=body_params,
- path_params=path_params, query_params=query_params)
- raise_for_failure(response)
- if http_method != HTTPMethod.GET:
- self.config_changed = True
- return response[ResponseParams.RESPONSE]
-
- def validate_params(self, operation_name, params):
- report = {}
- op_spec = self.get_operation_spec(operation_name)
- data, query_params, path_params = _get_user_params(params)
-
- def validate(validation_method, field_name, user_params):
- key = 'Invalid %s provided' % field_name
- try:
- is_valid, validation_report = validation_method(operation_name, user_params)
- if not is_valid:
- report[key] = validation_report
- except Exception as e:
- report[key] = str(e)
- return report
-
- validate(self._conn.validate_query_params, ParamName.QUERY_PARAMS, query_params)
- validate(self._conn.validate_path_params, ParamName.PATH_PARAMS, path_params)
- if is_post_request(op_spec) or is_put_request(op_spec):
- validate(self._conn.validate_data, ParamName.DATA, data)
-
- if report:
- raise ValidationError(report)
-
- @staticmethod
- def _get_operation_name(checker, operations):
- return next((op_name for op_name, op_spec in iteritems(operations) if checker(op_name, op_spec)), None)
-
- def _add_upserted_object(self, model_operations, params):
- add_op_name = self._get_operation_name(self._operation_checker.is_add_operation, model_operations)
- if not add_op_name:
- raise FtdConfigurationError(ADD_OPERATION_NOT_SUPPORTED_ERROR)
- return self.add_object(add_op_name, params)
-
- def _edit_upserted_object(self, model_operations, existing_object, params):
- edit_op_name = self._get_operation_name(self._operation_checker.is_edit_operation, model_operations)
- _set_default(params, 'path_params', {})
- _set_default(params, 'data', {})
-
- params['path_params']['objId'] = existing_object['id']
- copy_identity_properties(existing_object, params['data'])
- return self.edit_object(edit_op_name, params)
-
- def upsert_object(self, op_name, params):
- """
- Updates an object if it already exists, or tries to create a new one if there is no
- such object. If multiple objects match filter criteria, or add operation is not supported,
- the exception is raised.
-
- :param op_name: upsert operation name
- :type op_name: str
- :param params: params that upsert operation should be executed with
- :type params: dict
- :return: upserted object representation
- :rtype: dict
- """
-
- def extract_and_validate_model():
- model = op_name[len(OperationNamePrefix.UPSERT):]
- if not self._conn.get_model_spec(model):
- raise FtdInvalidOperationNameError(op_name)
- return model
-
- model_name = extract_and_validate_model()
- model_operations = self.get_operation_specs_by_model_name(model_name)
-
- if not self._operation_checker.is_upsert_operation_supported(model_operations):
- raise FtdInvalidOperationNameError(op_name)
-
- existing_obj = self._find_object_matching_params(model_name, params)
- if existing_obj:
- equal_to_existing_obj = equal_objects(existing_obj, params[ParamName.DATA])
- return existing_obj if equal_to_existing_obj \
- else self._edit_upserted_object(model_operations, existing_obj, params)
- else:
- return self._add_upserted_object(model_operations, params)
-
-
-def _set_default(params, field_name, value):
- if field_name not in params or params[field_name] is None:
- params[field_name] = value
-
-
-def is_post_request(operation_spec):
- return operation_spec[OperationField.METHOD] == HTTPMethod.POST
-
-
-def is_put_request(operation_spec):
- return operation_spec[OperationField.METHOD] == HTTPMethod.PUT
-
-
-def _get_user_params(params):
- return params.get(ParamName.DATA) or {}, params.get(ParamName.QUERY_PARAMS) or {}, params.get(
- ParamName.PATH_PARAMS) or {}
-
-
-def iterate_over_pageable_resource(resource_func, params):
- """
- A generator function that iterates over a resource that supports pagination and lazily returns present items
- one by one.
-
- :param resource_func: function that receives `params` argument and returns a page of objects
- :type resource_func: callable
- :param params: initial dictionary of parameters that will be passed to the resource_func.
- Should contain `query_params` inside.
- :type params: dict
- :return: an iterator containing returned items
- :rtype: iterator of dict
- """
- # creating a copy not to mutate passed dict
- params = copy.deepcopy(params)
- params[ParamName.QUERY_PARAMS].setdefault('limit', DEFAULT_PAGE_SIZE)
- params[ParamName.QUERY_PARAMS].setdefault('offset', DEFAULT_OFFSET)
- limit = int(params[ParamName.QUERY_PARAMS]['limit'])
-
- def received_less_items_than_requested(items_in_response, items_expected):
- if items_in_response == items_expected:
- return False
- elif items_in_response < items_expected:
- return True
-
- raise FtdUnexpectedResponse(
- "Get List of Objects Response from the server contains more objects than requested. "
- "There are {0} item(s) in the response while {1} was(ere) requested".format(
- items_in_response, items_expected)
- )
-
- while True:
- result = resource_func(params=params)
-
- for item in result['items']:
- yield item
-
- if received_less_items_than_requested(len(result['items']), limit):
- break
-
- # creating a copy not to mutate existing dict
- params = copy.deepcopy(params)
- query_params = params[ParamName.QUERY_PARAMS]
- query_params['offset'] = int(query_params['offset']) + limit
diff --git a/plugins/module_utils/network/ftd/device.py b/plugins/module_utils/network/ftd/device.py
deleted file mode 100644
index 47b0eb3a43..0000000000
--- a/plugins/module_utils/network/ftd/device.py
+++ /dev/null
@@ -1,138 +0,0 @@
-# Copyright (c) 2019 Cisco and/or its affiliates.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from ansible.module_utils.six.moves.urllib.parse import urlparse
-
-try:
- from kick.device2.ftd5500x.actions.ftd5500x import Ftd5500x
- from kick.device2.kp.actions import Kp
-
- HAS_KICK = True
-except ImportError:
- HAS_KICK = False
-
-
-def assert_kick_is_installed(module):
- if not HAS_KICK:
- module.fail_json(msg='Firepower-kickstart library is required to run this module. '
- 'Please, install the library with `pip install firepower-kickstart` '
- 'command and run the playbook again.')
-
-
-class FtdModel:
- FTD_ASA5506_X = 'Cisco ASA5506-X Threat Defense'
- FTD_ASA5508_X = 'Cisco ASA5508-X Threat Defense'
- FTD_ASA5516_X = 'Cisco ASA5516-X Threat Defense'
-
- FTD_2110 = 'Cisco Firepower 2110 Threat Defense'
- FTD_2120 = 'Cisco Firepower 2120 Threat Defense'
- FTD_2130 = 'Cisco Firepower 2130 Threat Defense'
- FTD_2140 = 'Cisco Firepower 2140 Threat Defense'
-
- @classmethod
- def supported_models(cls):
- return [getattr(cls, item) for item in dir(cls) if item.startswith('FTD_')]
-
-
-class FtdPlatformFactory(object):
-
- @staticmethod
- def create(model, module_params):
- for cls in AbstractFtdPlatform.__subclasses__():
- if cls.supports_ftd_model(model):
- return cls(module_params)
- raise ValueError("FTD model '%s' is not supported by this module." % model)
-
-
-class AbstractFtdPlatform(object):
- PLATFORM_MODELS = []
-
- def install_ftd_image(self, params):
- raise NotImplementedError('The method should be overridden in subclass')
-
- @classmethod
- def supports_ftd_model(cls, model):
- return model in cls.PLATFORM_MODELS
-
- @staticmethod
- def parse_rommon_file_location(rommon_file_location):
- rommon_url = urlparse(rommon_file_location)
- if rommon_url.scheme != 'tftp':
- raise ValueError('The ROMMON image must be downloaded from TFTP server, other protocols are not supported.')
- return rommon_url.netloc, rommon_url.path
-
-
-class Ftd2100Platform(AbstractFtdPlatform):
- PLATFORM_MODELS = [FtdModel.FTD_2110, FtdModel.FTD_2120, FtdModel.FTD_2130, FtdModel.FTD_2140]
-
- def __init__(self, params):
- self._ftd = Kp(hostname=params["device_hostname"],
- login_username=params["device_username"],
- login_password=params["device_password"],
- sudo_password=params.get("device_sudo_password") or params["device_password"])
-
- def install_ftd_image(self, params):
- line = self._ftd.ssh_console(ip=params["console_ip"],
- port=params["console_port"],
- username=params["console_username"],
- password=params["console_password"])
-
- try:
- rommon_server, rommon_path = self.parse_rommon_file_location(params["rommon_file_location"])
- line.baseline_fp2k_ftd(tftp_server=rommon_server,
- rommon_file=rommon_path,
- uut_hostname=params["device_hostname"],
- uut_username=params["device_username"],
- uut_password=params.get("device_new_password") or params["device_password"],
- uut_ip=params["device_ip"],
- uut_netmask=params["device_netmask"],
- uut_gateway=params["device_gateway"],
- dns_servers=params["dns_server"],
- search_domains=params["search_domains"],
- fxos_url=params["image_file_location"],
- ftd_version=params["image_version"])
- finally:
- line.disconnect()
-
-
-class FtdAsa5500xPlatform(AbstractFtdPlatform):
- PLATFORM_MODELS = [FtdModel.FTD_ASA5506_X, FtdModel.FTD_ASA5508_X, FtdModel.FTD_ASA5516_X]
-
- def __init__(self, params):
- self._ftd = Ftd5500x(hostname=params["device_hostname"],
- login_password=params["device_password"],
- sudo_password=params.get("device_sudo_password") or params["device_password"])
-
- def install_ftd_image(self, params):
- line = self._ftd.ssh_console(ip=params["console_ip"],
- port=params["console_port"],
- username=params["console_username"],
- password=params["console_password"])
- try:
- rommon_server, rommon_path = self.parse_rommon_file_location(params["rommon_file_location"])
- line.rommon_to_new_image(rommon_tftp_server=rommon_server,
- rommon_image=rommon_path,
- pkg_image=params["image_file_location"],
- uut_ip=params["device_ip"],
- uut_netmask=params["device_netmask"],
- uut_gateway=params["device_gateway"],
- dns_server=params["dns_server"],
- search_domains=params["search_domains"],
- hostname=params["device_hostname"])
- finally:
- line.disconnect()
diff --git a/plugins/module_utils/network/ftd/fdm_swagger_client.py b/plugins/module_utils/network/ftd/fdm_swagger_client.py
deleted file mode 100644
index f7d4114be2..0000000000
--- a/plugins/module_utils/network/ftd/fdm_swagger_client.py
+++ /dev/null
@@ -1,638 +0,0 @@
-# Copyright (c) 2018 Cisco and/or its affiliates.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from ansible_collections.community.general.plugins.module_utils.network.ftd.common import HTTPMethod
-from ansible.module_utils.six import integer_types, string_types, iteritems
-
-FILE_MODEL_NAME = '_File'
-SUCCESS_RESPONSE_CODE = '200'
-DELETE_PREFIX = 'delete'
-
-
-class OperationField:
- URL = 'url'
- METHOD = 'method'
- PARAMETERS = 'parameters'
- MODEL_NAME = 'modelName'
- DESCRIPTION = 'description'
- RETURN_MULTIPLE_ITEMS = 'returnMultipleItems'
- TAGS = "tags"
-
-
-class SpecProp:
- DEFINITIONS = 'definitions'
- OPERATIONS = 'operations'
- MODELS = 'models'
- MODEL_OPERATIONS = 'model_operations'
-
-
-class PropName:
- ENUM = 'enum'
- TYPE = 'type'
- REQUIRED = 'required'
- INVALID_TYPE = 'invalid_type'
- REF = '$ref'
- ALL_OF = 'allOf'
- BASE_PATH = 'basePath'
- PATHS = 'paths'
- OPERATION_ID = 'operationId'
- SCHEMA = 'schema'
- ITEMS = 'items'
- PROPERTIES = 'properties'
- RESPONSES = 'responses'
- NAME = 'name'
- DESCRIPTION = 'description'
-
-
-class PropType:
- STRING = 'string'
- BOOLEAN = 'boolean'
- INTEGER = 'integer'
- NUMBER = 'number'
- OBJECT = 'object'
- ARRAY = 'array'
- FILE = 'file'
-
-
-class OperationParams:
- PATH = 'path'
- QUERY = 'query'
-
-
-class QueryParams:
- FILTER = 'filter'
-
-
-class PathParams:
- OBJ_ID = 'objId'
-
-
-def _get_model_name_from_url(schema_ref):
- path = schema_ref.split('/')
- return path[len(path) - 1]
-
-
-class IllegalArgumentException(ValueError):
- """
- Exception raised when the function parameters:
- - not all passed
- - empty string
- - wrong type
- """
- pass
-
-
-class ValidationError(ValueError):
- pass
-
-
-class FdmSwaggerParser:
- _definitions = None
- _base_path = None
-
- def parse_spec(self, spec, docs=None):
- """
- This method simplifies a swagger format, resolves a model name for each operation, and adds documentation for
- each operation and model if it is provided.
-
- :param spec: An API specification in the swagger format, see
-
- :type spec: dict
- :param spec: A documentation map containing descriptions for models, operations and operation parameters.
- :type docs: dict
- :rtype: dict
- :return:
- Ex.
- The models field contains model definition from swagger see
- <#https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#definitions>
- {
- 'models':{
- 'model_name':{...},
- ...
- },
- 'operations':{
- 'operation_name':{
- 'method': 'get', #post, put, delete
- 'url': '/api/fdm/v2/object/networks', #url already contains a value from `basePath`
- 'modelName': 'NetworkObject', # it is a link to the model from 'models'
- # None - for a delete operation or we don't have information
- # '_File' - if an endpoint works with files
- 'returnMultipleItems': False, # shows if the operation returns a single item or an item list
- 'parameters': {
- 'path':{
- 'param_name':{
- 'type': 'string'#integer, boolean, number
- 'required' True #False
- }
- ...
- },
- 'query':{
- 'param_name':{
- 'type': 'string'#integer, boolean, number
- 'required' True #False
- }
- ...
- }
- }
- },
- ...
- },
- 'model_operations':{
- 'model_name':{ # a list of operations available for the current model
- 'operation_name':{
- ... # the same as in the operations section
- },
- ...
- },
- ...
- }
- }
- """
- self._definitions = spec[SpecProp.DEFINITIONS]
- self._base_path = spec[PropName.BASE_PATH]
- operations = self._get_operations(spec)
-
- if docs:
- operations = self._enrich_operations_with_docs(operations, docs)
- self._definitions = self._enrich_definitions_with_docs(self._definitions, docs)
-
- return {
- SpecProp.MODELS: self._definitions,
- SpecProp.OPERATIONS: operations,
- SpecProp.MODEL_OPERATIONS: self._get_model_operations(operations)
- }
-
- @property
- def base_path(self):
- return self._base_path
-
- def _get_model_operations(self, operations):
- model_operations = {}
- for operations_name, params in iteritems(operations):
- model_name = params[OperationField.MODEL_NAME]
- model_operations.setdefault(model_name, {})[operations_name] = params
- return model_operations
-
- def _get_operations(self, spec):
- paths_dict = spec[PropName.PATHS]
- operations_dict = {}
- for url, operation_params in iteritems(paths_dict):
- for method, params in iteritems(operation_params):
- operation = {
- OperationField.METHOD: method,
- OperationField.URL: self._base_path + url,
- OperationField.MODEL_NAME: self._get_model_name(method, params),
- OperationField.RETURN_MULTIPLE_ITEMS: self._return_multiple_items(params),
- OperationField.TAGS: params.get(OperationField.TAGS, [])
- }
- if OperationField.PARAMETERS in params:
- operation[OperationField.PARAMETERS] = self._get_rest_params(params[OperationField.PARAMETERS])
-
- operation_id = params[PropName.OPERATION_ID]
- operations_dict[operation_id] = operation
- return operations_dict
-
- def _enrich_operations_with_docs(self, operations, docs):
- def get_operation_docs(op):
- op_url = op[OperationField.URL][len(self._base_path):]
- return docs[PropName.PATHS].get(op_url, {}).get(op[OperationField.METHOD], {})
-
- for operation in operations.values():
- operation_docs = get_operation_docs(operation)
- operation[OperationField.DESCRIPTION] = operation_docs.get(PropName.DESCRIPTION, '')
-
- if OperationField.PARAMETERS in operation:
- param_descriptions = dict((
- (p[PropName.NAME], p[PropName.DESCRIPTION])
- for p in operation_docs.get(OperationField.PARAMETERS, {})
- ))
-
- for param_name, params_spec in operation[OperationField.PARAMETERS][OperationParams.PATH].items():
- params_spec[OperationField.DESCRIPTION] = param_descriptions.get(param_name, '')
-
- for param_name, params_spec in operation[OperationField.PARAMETERS][OperationParams.QUERY].items():
- params_spec[OperationField.DESCRIPTION] = param_descriptions.get(param_name, '')
-
- return operations
-
- def _enrich_definitions_with_docs(self, definitions, docs):
- for model_name, model_def in definitions.items():
- model_docs = docs[SpecProp.DEFINITIONS].get(model_name, {})
- model_def[PropName.DESCRIPTION] = model_docs.get(PropName.DESCRIPTION, '')
- for prop_name, prop_spec in model_def.get(PropName.PROPERTIES, {}).items():
- prop_spec[PropName.DESCRIPTION] = model_docs.get(PropName.PROPERTIES, {}).get(prop_name, '')
- prop_spec[PropName.REQUIRED] = prop_name in model_def.get(PropName.REQUIRED, [])
- return definitions
-
- def _get_model_name(self, method, params):
- if method == HTTPMethod.GET:
- return self._get_model_name_from_responses(params)
- elif method == HTTPMethod.POST or method == HTTPMethod.PUT:
- return self._get_model_name_for_post_put_requests(params)
- elif method == HTTPMethod.DELETE:
- return self._get_model_name_from_delete_operation(params)
- else:
- return None
-
- @staticmethod
- def _return_multiple_items(op_params):
- """
- Defines if the operation returns one item or a list of items.
-
- :param op_params: operation specification
- :return: True if the operation returns a list of items, otherwise False
- """
- try:
- schema = op_params[PropName.RESPONSES][SUCCESS_RESPONSE_CODE][PropName.SCHEMA]
- return PropName.ITEMS in schema[PropName.PROPERTIES]
- except KeyError:
- return False
-
- def _get_model_name_from_delete_operation(self, params):
- operation_id = params[PropName.OPERATION_ID]
- if operation_id.startswith(DELETE_PREFIX):
- model_name = operation_id[len(DELETE_PREFIX):]
- if model_name in self._definitions:
- return model_name
- return None
-
- def _get_model_name_for_post_put_requests(self, params):
- model_name = None
- if OperationField.PARAMETERS in params:
- body_param_dict = self._get_body_param_from_parameters(params[OperationField.PARAMETERS])
- if body_param_dict:
- schema_ref = body_param_dict[PropName.SCHEMA][PropName.REF]
- model_name = self._get_model_name_byschema_ref(schema_ref)
- if model_name is None:
- model_name = self._get_model_name_from_responses(params)
- return model_name
-
- @staticmethod
- def _get_body_param_from_parameters(params):
- return next((param for param in params if param['in'] == 'body'), None)
-
- def _get_model_name_from_responses(self, params):
- responses = params[PropName.RESPONSES]
- if SUCCESS_RESPONSE_CODE in responses:
- response = responses[SUCCESS_RESPONSE_CODE][PropName.SCHEMA]
- if PropName.REF in response:
- return self._get_model_name_byschema_ref(response[PropName.REF])
- elif PropName.PROPERTIES in response:
- ref = response[PropName.PROPERTIES][PropName.ITEMS][PropName.ITEMS][PropName.REF]
- return self._get_model_name_byschema_ref(ref)
- elif (PropName.TYPE in response) and response[PropName.TYPE] == PropType.FILE:
- return FILE_MODEL_NAME
- else:
- return None
-
- def _get_rest_params(self, params):
- path = {}
- query = {}
- operation_param = {
- OperationParams.PATH: path,
- OperationParams.QUERY: query
- }
- for param in params:
- in_param = param['in']
- if in_param == OperationParams.QUERY:
- query[param[PropName.NAME]] = self._simplify_param_def(param)
- elif in_param == OperationParams.PATH:
- path[param[PropName.NAME]] = self._simplify_param_def(param)
- return operation_param
-
- @staticmethod
- def _simplify_param_def(param):
- return {
- PropName.TYPE: param[PropName.TYPE],
- PropName.REQUIRED: param[PropName.REQUIRED]
- }
-
- def _get_model_name_byschema_ref(self, schema_ref):
- model_name = _get_model_name_from_url(schema_ref)
- model_def = self._definitions[model_name]
- if PropName.ALL_OF in model_def:
- return self._get_model_name_byschema_ref(model_def[PropName.ALL_OF][0][PropName.REF])
- else:
- return model_name
-
-
-class FdmSwaggerValidator:
- def __init__(self, spec):
- """
- :param spec: dict
- data from FdmSwaggerParser().parse_spec()
- """
- self._operations = spec[SpecProp.OPERATIONS]
- self._models = spec[SpecProp.MODELS]
-
- def validate_data(self, operation_name, data=None):
- """
- Validate data for the post|put requests
- :param operation_name: string
- The value must be non empty string.
- The operation name is used to get a model specification
- :param data: dict
- The value must be in the format that the model(from operation) expects
- :rtype: (bool, string|dict)
- :return:
- (True, None) - if data valid
- Invalid:
- (False, {
- 'required': [ #list of the fields that are required but were not present in the data
- 'field_name',
- 'patent.field_name',# when the nested field is omitted
- 'patent.list[2].field_name' # if data is array and one of the field is omitted
- ],
- 'invalid_type':[ #list of the fields with invalid data
- {
- 'path': 'objId', #field name or path to the field. Ex. objects[3].id, parent.name
- 'expected_type': 'string',# expected type. Ex. 'object', 'array', 'string', 'integer',
- # 'boolean', 'number'
- 'actually_value': 1 # the value that user passed
- }
- ]
- })
- :raises IllegalArgumentException
- 'The operation_name parameter must be a non-empty string' if operation_name is not valid
- 'The data parameter must be a dict' if data neither dict or None
- '{operation_name} operation does not support' if the spec does not contain the operation
- """
- if data is None:
- data = {}
-
- self._check_validate_data_params(data, operation_name)
-
- operation = self._operations[operation_name]
- model = self._models[operation[OperationField.MODEL_NAME]]
- status = self._init_report()
-
- self._validate_object(status, model, data, '')
-
- if len(status[PropName.REQUIRED]) > 0 or len(status[PropName.INVALID_TYPE]) > 0:
- return False, self._delete_empty_field_from_report(status)
- return True, None
-
- def _check_validate_data_params(self, data, operation_name):
- if not operation_name or not isinstance(operation_name, string_types):
- raise IllegalArgumentException("The operation_name parameter must be a non-empty string")
- if not isinstance(data, dict):
- raise IllegalArgumentException("The data parameter must be a dict")
- if operation_name not in self._operations:
- raise IllegalArgumentException("{0} operation does not support".format(operation_name))
-
- def validate_query_params(self, operation_name, params):
- """
- Validate params for the get requests. Use this method for validating the query part of the url.
- :param operation_name: string
- The value must be non empty string.
- The operation name is used to get a params specification
- :param params: dict
- should be in the format that the specification(from operation) expects
- Ex.
- {
- 'objId': "string_value",
- 'p_integer': 1,
- 'p_boolean': True,
- 'p_number': 2.3
- }
- :rtype:(Boolean, msg)
- :return:
- (True, None) - if params valid
- Invalid:
- (False, {
- 'required': [ #list of the fields that are required but are not present in the params
- 'field_name'
- ],
- 'invalid_type':[ #list of the fields with invalid data and expected type of the params
- {
- 'path': 'objId', #field name
- 'expected_type': 'string',#expected type. Ex. 'string', 'integer', 'boolean', 'number'
- 'actually_value': 1 # the value that user passed
- }
- ]
- })
- :raises IllegalArgumentException
- 'The operation_name parameter must be a non-empty string' if operation_name is not valid
- 'The params parameter must be a dict' if params neither dict or None
- '{operation_name} operation does not support' if the spec does not contain the operation
- """
- return self._validate_url_params(operation_name, params, resource=OperationParams.QUERY)
-
- def validate_path_params(self, operation_name, params):
- """
- Validate params for the get requests. Use this method for validating the path part of the url.
- :param operation_name: string
- The value must be non empty string.
- The operation name is used to get a params specification
- :param params: dict
- should be in the format that the specification(from operation) expects
-
- Ex.
- {
- 'objId': "string_value",
- 'p_integer': 1,
- 'p_boolean': True,
- 'p_number': 2.3
- }
- :rtype:(Boolean, msg)
- :return:
- (True, None) - if params valid
- Invalid:
- (False, {
- 'required': [ #list of the fields that are required but are not present in the params
- 'field_name'
- ],
- 'invalid_type':[ #list of the fields with invalid data and expected type of the params
- {
- 'path': 'objId', #field name
- 'expected_type': 'string',#expected type. Ex. 'string', 'integer', 'boolean', 'number'
- 'actually_value': 1 # the value that user passed
- }
- ]
- })
- :raises IllegalArgumentException
- 'The operation_name parameter must be a non-empty string' if operation_name is not valid
- 'The params parameter must be a dict' if params neither dict or None
- '{operation_name} operation does not support' if the spec does not contain the operation
- """
- return self._validate_url_params(operation_name, params, resource=OperationParams.PATH)
-
- def _validate_url_params(self, operation, params, resource):
- if params is None:
- params = {}
-
- self._check_validate_url_params(operation, params)
-
- operation = self._operations[operation]
- if OperationField.PARAMETERS in operation and resource in operation[OperationField.PARAMETERS]:
- spec = operation[OperationField.PARAMETERS][resource]
- status = self._init_report()
- self._check_url_params(status, spec, params)
-
- if len(status[PropName.REQUIRED]) > 0 or len(status[PropName.INVALID_TYPE]) > 0:
- return False, self._delete_empty_field_from_report(status)
- return True, None
- else:
- return True, None
-
- def _check_validate_url_params(self, operation, params):
- if not operation or not isinstance(operation, string_types):
- raise IllegalArgumentException("The operation_name parameter must be a non-empty string")
- if not isinstance(params, dict):
- raise IllegalArgumentException("The params parameter must be a dict")
- if operation not in self._operations:
- raise IllegalArgumentException("{0} operation does not support".format(operation))
-
- def _check_url_params(self, status, spec, params):
- for prop_name in spec.keys():
- prop = spec[prop_name]
- if prop[PropName.REQUIRED] and prop_name not in params:
- status[PropName.REQUIRED].append(prop_name)
- continue
- if prop_name in params:
- expected_type = prop[PropName.TYPE]
- value = params[prop_name]
- if prop_name in params and not self._is_correct_simple_types(expected_type, value, allow_null=False):
- self._add_invalid_type_report(status, '', prop_name, expected_type, value)
-
- def _validate_object(self, status, model, data, path):
- if self._is_enum(model):
- self._check_enum(status, model, data, path)
- elif self._is_object(model):
- self._check_object(status, model, data, path)
-
- def _is_enum(self, model):
- return self._is_string_type(model) and PropName.ENUM in model
-
- def _check_enum(self, status, model, value, path):
- if value is not None and value not in model[PropName.ENUM]:
- self._add_invalid_type_report(status, path, '', PropName.ENUM, value)
-
- def _add_invalid_type_report(self, status, path, prop_name, expected_type, actually_value):
- status[PropName.INVALID_TYPE].append({
- 'path': self._create_path_to_field(path, prop_name),
- 'expected_type': expected_type,
- 'actually_value': actually_value
- })
-
- def _check_object(self, status, model, data, path):
- if data is None:
- return
-
- if not isinstance(data, dict):
- self._add_invalid_type_report(status, path, '', PropType.OBJECT, data)
- return None
-
- if PropName.REQUIRED in model:
- self._check_required_fields(status, model[PropName.REQUIRED], data, path)
-
- model_properties = model[PropName.PROPERTIES]
- for prop in model_properties.keys():
- if prop in data:
- model_prop_val = model_properties[prop]
- expected_type = model_prop_val[PropName.TYPE]
- actually_value = data[prop]
- self._check_types(status, actually_value, expected_type, model_prop_val, path, prop)
-
- def _check_types(self, status, actually_value, expected_type, model, path, prop_name):
- if expected_type == PropType.OBJECT:
- ref_model = self._get_model_by_ref(model)
-
- self._validate_object(status, ref_model, actually_value,
- path=self._create_path_to_field(path, prop_name))
- elif expected_type == PropType.ARRAY:
- self._check_array(status, model, actually_value,
- path=self._create_path_to_field(path, prop_name))
- elif not self._is_correct_simple_types(expected_type, actually_value):
- self._add_invalid_type_report(status, path, prop_name, expected_type, actually_value)
-
- def _get_model_by_ref(self, model_prop_val):
- model = _get_model_name_from_url(model_prop_val[PropName.REF])
- return self._models[model]
-
- def _check_required_fields(self, status, required_fields, data, path):
- missed_required_fields = [self._create_path_to_field(path, field) for field in
- required_fields if field not in data.keys() or data[field] is None]
- if len(missed_required_fields) > 0:
- status[PropName.REQUIRED] += missed_required_fields
-
- def _check_array(self, status, model, data, path):
- if data is None:
- return
- elif not isinstance(data, list):
- self._add_invalid_type_report(status, path, '', PropType.ARRAY, data)
- else:
- item_model = model[PropName.ITEMS]
- for i, item_data in enumerate(data):
- self._check_types(status, item_data, item_model[PropName.TYPE], item_model, "{0}[{1}]".format(path, i),
- '')
-
- @staticmethod
- def _is_correct_simple_types(expected_type, value, allow_null=True):
- def is_numeric_string(s):
- try:
- float(s)
- return True
- except ValueError:
- return False
-
- if value is None and allow_null:
- return True
- elif expected_type == PropType.STRING:
- return isinstance(value, string_types)
- elif expected_type == PropType.BOOLEAN:
- return isinstance(value, bool)
- elif expected_type == PropType.INTEGER:
- is_integer = isinstance(value, integer_types) and not isinstance(value, bool)
- is_digit_string = isinstance(value, string_types) and value.isdigit()
- return is_integer or is_digit_string
- elif expected_type == PropType.NUMBER:
- is_number = isinstance(value, (integer_types, float)) and not isinstance(value, bool)
- is_numeric_string = isinstance(value, string_types) and is_numeric_string(value)
- return is_number or is_numeric_string
- return False
-
- @staticmethod
- def _is_string_type(model):
- return PropName.TYPE in model and model[PropName.TYPE] == PropType.STRING
-
- @staticmethod
- def _init_report():
- return {
- PropName.REQUIRED: [],
- PropName.INVALID_TYPE: []
- }
-
- @staticmethod
- def _delete_empty_field_from_report(status):
- if not status[PropName.REQUIRED]:
- del status[PropName.REQUIRED]
- if not status[PropName.INVALID_TYPE]:
- del status[PropName.INVALID_TYPE]
- return status
-
- @staticmethod
- def _create_path_to_field(path='', field=''):
- separator = ''
- if path and field:
- separator = '.'
- return "{0}{1}{2}".format(path, separator, field)
-
- @staticmethod
- def _is_object(model):
- return PropName.TYPE in model and model[PropName.TYPE] == PropType.OBJECT
diff --git a/plugins/module_utils/network/ftd/operation.py b/plugins/module_utils/network/ftd/operation.py
deleted file mode 100644
index ecba70e6b5..0000000000
--- a/plugins/module_utils/network/ftd/operation.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (c) 2018 Cisco and/or its affiliates.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from ansible_collections.community.general.plugins.module_utils.network.ftd.configuration import ParamName, PATH_PARAMS_FOR_DEFAULT_OBJ
-
-
-class FtdOperations:
- """
- Utility class for common operation names
- """
- GET_SYSTEM_INFO = 'getSystemInformation'
- GET_MANAGEMENT_IP_LIST = 'getManagementIPList'
- GET_DNS_SETTING_LIST = 'getDeviceDNSSettingsList'
- GET_DNS_SERVER_GROUP = 'getDNSServerGroup'
-
-
-def get_system_info(resource):
- """
- Executes `getSystemInformation` operation and returns information about the system.
-
- :param resource: a BaseConfigurationResource object to connect to the device
- :return: a dictionary with system information about the device and its software
- """
- path_params = {ParamName.PATH_PARAMS: PATH_PARAMS_FOR_DEFAULT_OBJ}
- system_info = resource.execute_operation(FtdOperations.GET_SYSTEM_INFO, path_params)
- return system_info
diff --git a/plugins/module_utils/network/icx/__init__.py b/plugins/module_utils/network/icx/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/icx/icx.py b/plugins/module_utils/network/icx/icx.py
deleted file mode 100644
index cabece78d4..0000000000
--- a/plugins/module_utils/network/icx/icx.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright: (c) 2019, Ansible Project
-# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-import json
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import env_fallback
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.module_utils.connection import Connection, ConnectionError
-
-_DEVICE_CONFIGS = {}
-
-
-def get_connection(module):
- return Connection(module._socket_path)
-
-
-def load_config(module, commands):
- connection = get_connection(module)
-
- try:
- resp = connection.edit_config(candidate=commands)
- return resp.get('response')
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
-
-
-def run_commands(module, commands, check_rc=True):
- connection = get_connection(module)
- try:
- return connection.run_commands(commands=commands, check_rc=check_rc)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
-
-
-def exec_scp(module, command):
- connection = Connection(module._socket_path)
- return connection.scp(**command)
-
-
-def get_config(module, flags=None, compare=None):
- flag_str = ' '.join(to_list(flags))
- try:
- return _DEVICE_CONFIGS[flag_str]
- except KeyError:
- connection = get_connection(module)
- try:
- out = connection.get_config(flags=flags, compare=compare)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- cfg = to_text(out, errors='surrogate_then_replace').strip()
- _DEVICE_CONFIGS[flag_str] = cfg
- return cfg
-
-
-def check_args(module, warnings):
- pass
-
-
-def get_defaults_flag(module):
- connection = get_connection(module)
- try:
- out = connection.get_defaults_flag()
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- return to_text(out, errors='surrogate_then_replace').strip()
diff --git a/plugins/module_utils/network/ingate/__init__.py b/plugins/module_utils/network/ingate/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/ingate/common.py b/plugins/module_utils/network/ingate/common.py
deleted file mode 100644
index ff632520b0..0000000000
--- a/plugins/module_utils/network/ingate/common.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Ingate Systems AB
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-try:
- from ingate import ingatesdk
- HAS_INGATESDK = True
-except ImportError:
- HAS_INGATESDK = False
-
-
-def ingate_argument_spec(**kwargs):
- client_options = dict(
- version=dict(choices=['v1'], default='v1'),
- scheme=dict(choices=['http', 'https'], required=True),
- address=dict(type='str', required=True),
- username=dict(type='str', required=True),
- password=dict(type='str', required=True, no_log=True),
- port=dict(type='int'),
- timeout=dict(type='int'),
- validate_certs=dict(default=True, type='bool', aliases=['verify_ssl']),
- )
- argument_spec = dict(
- client=dict(type='dict', required=True,
- options=client_options),
- )
- argument_spec.update(kwargs)
- return argument_spec
-
-
-def ingate_create_client(**kwargs):
- api_client = ingate_create_client_noauth(**kwargs)
-
- # Authenticate and get hold of a security token.
- api_client.authenticate()
-
- # Return the client.
- return api_client
-
-
-def ingate_create_client_noauth(**kwargs):
- client_params = kwargs['client']
-
- # Create API client.
- api_client = ingatesdk.Client(client_params['version'],
- client_params['scheme'],
- client_params['address'],
- client_params['username'],
- client_params['password'],
- port=client_params['port'],
- timeout=client_params['timeout'])
-
- # Check if we should skip SSL Certificate verification.
- verify_ssl = client_params.get('validate_certs')
- if not verify_ssl:
- api_client.skip_verify_certificate()
-
- # Return the client.
- return api_client
-
-
-def is_ingatesdk_installed(module):
- if not HAS_INGATESDK:
- module.fail_json(msg="The Ingate Python SDK module is required for this module.")
diff --git a/plugins/module_utils/network/ironware/__init__.py b/plugins/module_utils/network/ironware/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/ironware/ironware.py b/plugins/module_utils/network/ironware/ironware.py
deleted file mode 100644
index f09338de16..0000000000
--- a/plugins/module_utils/network/ironware/ironware.py
+++ /dev/null
@@ -1,113 +0,0 @@
-#
-# Copyright (c) 2017, Paul Baker
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import env_fallback
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, EntityCollection
-from ansible.module_utils.connection import Connection, exec_command
-
-_DEVICE_CONFIG = None
-_CONNECTION = None
-
-ironware_provider_spec = {
- 'host': dict(),
- 'port': dict(type='int'),
- 'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
- 'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True),
- 'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
- 'authorize': dict(fallback=(env_fallback, ['ANSIBLE_NET_AUTHORIZE']), type='bool'),
- 'auth_pass': dict(fallback=(env_fallback, ['ANSIBLE_NET_AUTH_PASS']), no_log=True),
- 'timeout': dict(type='int'),
-}
-
-ironware_argument_spec = {
- 'provider': dict(type='dict', options=ironware_provider_spec)
-}
-
-command_spec = {
- 'command': dict(key=True),
- 'prompt': dict(),
- 'answer': dict()
-}
-
-
-def get_provider_argspec():
- return ironware_provider_spec
-
-
-def check_args(module):
- pass
-
-
-def get_connection(module):
- global _CONNECTION
- if _CONNECTION:
- return _CONNECTION
- _CONNECTION = Connection(module._socket_path)
-
- return _CONNECTION
-
-
-def to_commands(module, commands):
- if not isinstance(commands, list):
- raise AssertionError('argument must be of type ')
-
- transform = EntityCollection(module, command_spec)
- commands = transform(commands)
-
- for index, item in enumerate(commands):
- if module.check_mode and not item['command'].startswith('show'):
- module.warn('only show commands are supported when using check '
- 'mode, not executing `%s`' % item['command'])
-
- return commands
-
-
-def run_commands(module, commands, check_rc=True):
- connection = get_connection(module)
-
- commands = to_commands(module, to_list(commands))
-
- responses = list()
-
- for cmd in commands:
- out = connection.get(**cmd)
- responses.append(to_text(out, errors='surrogate_then_replace'))
-
- return responses
-
-
-def get_config(module, source='running', flags=None):
- global _DEVICE_CONFIG
- if source == 'running' and flags is None and _DEVICE_CONFIG is not None:
- return _DEVICE_CONFIG
- else:
- conn = get_connection(module)
- out = conn.get_config(source=source, flags=flags)
- cfg = to_text(out, errors='surrogate_then_replace').strip()
- if source == 'running' and flags is None:
- _DEVICE_CONFIG = cfg
- return cfg
-
-
-def load_config(module, config):
- conn = get_connection(module)
- conn.edit_config(config)
diff --git a/plugins/module_utils/network/netscaler/__init__.py b/plugins/module_utils/network/netscaler/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/netscaler/netscaler.py b/plugins/module_utils/network/netscaler/netscaler.py
deleted file mode 100644
index ccf0dbff8f..0000000000
--- a/plugins/module_utils/network/netscaler/netscaler.py
+++ /dev/null
@@ -1,322 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2017 Citrix Systems
-#
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-import json
-import re
-import sys
-
-from ansible.module_utils.basic import env_fallback
-from ansible.module_utils.six import binary_type, text_type
-from ansible.module_utils._text import to_native
-
-
-class ConfigProxy(object):
-
- def __init__(self, actual, client, attribute_values_dict, readwrite_attrs, transforms=None, readonly_attrs=None, immutable_attrs=None, json_encodes=None):
- transforms = {} if transforms is None else transforms
- readonly_attrs = [] if readonly_attrs is None else readonly_attrs
- immutable_attrs = [] if immutable_attrs is None else immutable_attrs
- json_encodes = [] if json_encodes is None else json_encodes
-
- # Actual config object from nitro sdk
- self.actual = actual
-
- # nitro client
- self.client = client
-
- # ansible attribute_values_dict
- self.attribute_values_dict = attribute_values_dict
-
- self.readwrite_attrs = readwrite_attrs
- self.readonly_attrs = readonly_attrs
- self.immutable_attrs = immutable_attrs
- self.json_encodes = json_encodes
- self.transforms = transforms
-
- self.attribute_values_processed = {}
- for attribute, value in self.attribute_values_dict.items():
- if value is None:
- continue
- if attribute in transforms:
- for transform in self.transforms[attribute]:
- if transform == 'bool_yes_no':
- if value is True:
- value = 'YES'
- elif value is False:
- value = 'NO'
- elif transform == 'bool_on_off':
- if value is True:
- value = 'ON'
- elif value is False:
- value = 'OFF'
- elif callable(transform):
- value = transform(value)
- else:
- raise Exception('Invalid transform %s' % transform)
- self.attribute_values_processed[attribute] = value
-
- self._copy_attributes_to_actual()
-
- def _copy_attributes_to_actual(self):
- for attribute in self.readwrite_attrs:
- if attribute in self.attribute_values_processed:
- attribute_value = self.attribute_values_processed[attribute]
-
- if attribute_value is None:
- continue
-
- # Fallthrough
- if attribute in self.json_encodes:
- attribute_value = json.JSONEncoder().encode(attribute_value).strip('"')
- setattr(self.actual, attribute, attribute_value)
-
- def __getattr__(self, name):
- if name in self.attribute_values_dict:
- return self.attribute_values_dict[name]
- else:
- raise AttributeError('No attribute %s found' % name)
-
- def add(self):
- self.actual.__class__.add(self.client, self.actual)
-
- def update(self):
- return self.actual.__class__.update(self.client, self.actual)
-
- def delete(self):
- self.actual.__class__.delete(self.client, self.actual)
-
- def get(self, *args, **kwargs):
- result = self.actual.__class__.get(self.client, *args, **kwargs)
-
- return result
-
- def has_equal_attributes(self, other):
- if self.diff_object(other) == {}:
- return True
- else:
- return False
-
- def diff_object(self, other):
- diff_dict = {}
- for attribute in self.attribute_values_processed:
- # Skip readonly attributes
- if attribute not in self.readwrite_attrs:
- continue
-
- # Skip attributes not present in module arguments
- if self.attribute_values_processed[attribute] is None:
- continue
-
- # Check existence
- if hasattr(other, attribute):
- attribute_value = getattr(other, attribute)
- else:
- diff_dict[attribute] = 'missing from other'
- continue
-
- # Compare values
- param_type = self.attribute_values_processed[attribute].__class__
- if attribute_value is None or param_type(attribute_value) != self.attribute_values_processed[attribute]:
- str_tuple = (
- type(self.attribute_values_processed[attribute]),
- self.attribute_values_processed[attribute],
- type(attribute_value),
- attribute_value,
- )
- diff_dict[attribute] = 'difference. ours: (%s) %s other: (%s) %s' % str_tuple
- return diff_dict
-
- def get_actual_rw_attributes(self, filter='name'):
- if self.actual.__class__.count_filtered(self.client, '%s:%s' % (filter, self.attribute_values_dict[filter])) == 0:
- return {}
- server_list = self.actual.__class__.get_filtered(self.client, '%s:%s' % (filter, self.attribute_values_dict[filter]))
- actual_instance = server_list[0]
- ret_val = {}
- for attribute in self.readwrite_attrs:
- if not hasattr(actual_instance, attribute):
- continue
- ret_val[attribute] = getattr(actual_instance, attribute)
- return ret_val
-
- def get_actual_ro_attributes(self, filter='name'):
- if self.actual.__class__.count_filtered(self.client, '%s:%s' % (filter, self.attribute_values_dict[filter])) == 0:
- return {}
- server_list = self.actual.__class__.get_filtered(self.client, '%s:%s' % (filter, self.attribute_values_dict[filter]))
- actual_instance = server_list[0]
- ret_val = {}
- for attribute in self.readonly_attrs:
- if not hasattr(actual_instance, attribute):
- continue
- ret_val[attribute] = getattr(actual_instance, attribute)
- return ret_val
-
- def get_missing_rw_attributes(self):
- return list(set(self.readwrite_attrs) - set(self.get_actual_rw_attributes().keys()))
-
- def get_missing_ro_attributes(self):
- return list(set(self.readonly_attrs) - set(self.get_actual_ro_attributes().keys()))
-
-
-def get_immutables_intersection(config_proxy, keys):
- immutables_set = set(config_proxy.immutable_attrs)
- keys_set = set(keys)
- # Return list of sets' intersection
- return list(immutables_set & keys_set)
-
-
-def ensure_feature_is_enabled(client, feature_str):
- enabled_features = client.get_enabled_features()
-
- if enabled_features is None:
- enabled_features = []
-
- if feature_str not in enabled_features:
- client.enable_features(feature_str)
- client.save_config()
-
-
-def get_nitro_client(module):
- from nssrc.com.citrix.netscaler.nitro.service.nitro_service import nitro_service
-
- client = nitro_service(module.params['nsip'], module.params['nitro_protocol'])
- client.set_credential(module.params['nitro_user'], module.params['nitro_pass'])
- client.timeout = float(module.params['nitro_timeout'])
- client.certvalidation = module.params['validate_certs']
- return client
-
-
-netscaler_common_arguments = dict(
- nsip=dict(
- required=True,
- fallback=(env_fallback, ['NETSCALER_NSIP']),
- ),
- nitro_user=dict(
- required=True,
- fallback=(env_fallback, ['NETSCALER_NITRO_USER']),
- no_log=True
- ),
- nitro_pass=dict(
- required=True,
- fallback=(env_fallback, ['NETSCALER_NITRO_PASS']),
- no_log=True
- ),
- nitro_protocol=dict(
- choices=['http', 'https'],
- fallback=(env_fallback, ['NETSCALER_NITRO_PROTOCOL']),
- default='http'
- ),
- validate_certs=dict(
- default=True,
- type='bool'
- ),
- nitro_timeout=dict(default=310, type='float'),
- state=dict(
- choices=[
- 'present',
- 'absent',
- ],
- default='present',
- ),
- save_config=dict(
- type='bool',
- default=True,
- ),
-)
-
-
-loglines = []
-
-
-def complete_missing_attributes(actual, attrs_list, fill_value=None):
- for attribute in attrs_list:
- if not hasattr(actual, attribute):
- setattr(actual, attribute, fill_value)
-
-
-def log(msg):
- loglines.append(msg)
-
-
-def get_ns_version(client):
- from nssrc.com.citrix.netscaler.nitro.resource.config.ns.nsversion import nsversion
- result = nsversion.get(client)
- m = re.match(r'^.*NS(\d+)\.(\d+).*$', result[0].version)
- if m is None:
- return None
- else:
- return int(m.group(1)), int(m.group(2))
-
-
-def get_ns_hardware(client):
- from nssrc.com.citrix.netscaler.nitro.resource.config.ns.nshardware import nshardware
- result = nshardware.get(client)
- return result
-
-
-def monkey_patch_nitro_api():
-
- from nssrc.com.citrix.netscaler.nitro.resource.base.Json import Json
-
- def new_resource_to_string_convert(self, resrc):
- # Line below is the actual patch
- dict_valid_values = dict((k.replace('_', '', 1), v) for k, v in resrc.__dict__.items() if v)
- return json.dumps(dict_valid_values)
- Json.resource_to_string_convert = new_resource_to_string_convert
-
- from nssrc.com.citrix.netscaler.nitro.util.nitro_util import nitro_util
-
- @classmethod
- def object_to_string_new(cls, obj):
- output = []
- flds = obj.__dict__
- for k, v in ((k.replace('_', '', 1), v) for k, v in flds.items() if v):
- if isinstance(v, bool):
- output.append('"%s":%s' % (k, v))
- elif isinstance(v, (binary_type, text_type)):
- v = to_native(v, errors='surrogate_or_strict')
- output.append('"%s":"%s"' % (k, v))
- elif isinstance(v, int):
- output.append('"%s":"%s"' % (k, v))
- return ','.join(output)
-
- @classmethod
- def object_to_string_withoutquotes_new(cls, obj):
- output = []
- flds = obj.__dict__
- for k, v in ((k.replace('_', '', 1), v) for k, v in flds.items() if v):
- if isinstance(v, (int, bool)):
- output.append('%s:%s' % (k, v))
- elif isinstance(v, (binary_type, text_type)):
- v = to_native(v, errors='surrogate_or_strict')
- output.append('%s:%s' % (k, cls.encode(v)))
- return ','.join(output)
-
- nitro_util.object_to_string = object_to_string_new
- nitro_util.object_to_string_withoutquotes = object_to_string_withoutquotes_new
diff --git a/plugins/module_utils/network/netvisor/__init__.py b/plugins/module_utils/network/netvisor/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/netvisor/netvisor.py b/plugins/module_utils/network/netvisor/netvisor.py
deleted file mode 100644
index 0be1af2e3d..0000000000
--- a/plugins/module_utils/network/netvisor/netvisor.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright: (c) 2018, Pluribus Networks
-# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-import json
-from ansible.module_utils._text import to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList
-from ansible.module_utils.connection import Connection, ConnectionError
-from ansible.module_utils.connection import exec_command
-
-
-def get_connection(module):
- if hasattr(module, '_nvos_connection'):
- return module._nvos_connection
-
- capabilities = get_capabilities(module)
- network_api = capabilities.get('network_api')
- if network_api == 'cliconf':
- module._nvos_connection = Connection(module._socket_path)
- else:
- module.fail_json(msg='Invalid connection type %s' % network_api)
-
- return module._nvos_connection
-
-
-def get_capabilities(module):
- if hasattr(module, '_nvos_capabilities'):
- return module._nvos_capabilities
- try:
- capabilities = Connection(module._socket_path).get_capabilities()
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- module._nvos_capabilities = json.loads(capabilities)
- return module._nvos_capabilities
-
-
-def to_commands(module, commands):
- spec = {
- 'command': dict(key=True),
- 'prompt': dict(),
- 'answer': dict()
- }
- transform = ComplexList(spec, module)
- return transform(commands)
-
-
-def run_commands(module, commands, check_rc=True):
- commands = to_commands(module, to_list(commands))
- for cmd in commands:
- cmd = module.jsonify(cmd)
- rc, out, err = exec_command(module, cmd)
- if check_rc and rc != 0:
- module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), rc=rc)
- responses = (to_text(out, errors='surrogate_or_strict'))
-
- return rc, out, err
diff --git a/plugins/module_utils/network/netvisor/pn_nvos.py b/plugins/module_utils/network/netvisor/pn_nvos.py
deleted file mode 100644
index cd5cdc598f..0000000000
--- a/plugins/module_utils/network/netvisor/pn_nvos.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright: (c) 2018, Pluribus Networks
-# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-from ansible_collections.community.general.plugins.module_utils.network.netvisor.netvisor import run_commands
-
-
-def pn_cli(module, switch=None, username=None, password=None, switch_local=None):
- """
- Method to generate the cli portion to launch the Netvisor cli.
- :param module: The Ansible module to fetch username and password.
- :return: The cli string for further processing.
- """
-
- cli = ''
-
- if username and password:
- cli += '--user "%s":"%s" ' % (username, password)
- if switch:
- cli += ' switch ' + switch
- if switch_local:
- cli += ' switch-local '
-
- return cli
-
-
-def booleanArgs(arg, trueString, falseString):
- if arg is True:
- return " %s " % trueString
- elif arg is False:
- return " %s " % falseString
- else:
- return ""
-
-
-def run_cli(module, cli, state_map):
- """
- This method executes the cli command on the target node(s) and returns the
- output. The module then exits based on the output.
- :param cli: the complete cli string to be executed on the target node(s).
- :param state_map: Provides state of the command.
- :param module: The Ansible module to fetch command
- """
- state = module.params['state']
- command = state_map[state]
-
- result, out, err = run_commands(module, cli)
-
- results = dict(
- command=cli,
- msg="%s operation completed" % cli,
- changed=True
- )
- # Response in JSON format
- if result != 0:
- module.exit_json(
- command=cli,
- msg="%s operation failed" % cli,
- changed=False
- )
-
- module.exit_json(**results)
diff --git a/plugins/module_utils/network/nos/__init__.py b/plugins/module_utils/network/nos/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/nos/nos.py b/plugins/module_utils/network/nos/nos.py
deleted file mode 100644
index c87b0644f6..0000000000
--- a/plugins/module_utils/network/nos/nos.py
+++ /dev/null
@@ -1,160 +0,0 @@
-#
-# (c) 2018 Extreme Networks Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-import json
-from ansible.module_utils._text import to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible.module_utils.connection import Connection, ConnectionError
-
-
-def get_connection(module):
- """Get switch connection
-
- Creates reusable SSH connection to the switch described in a given module.
-
- Args:
- module: A valid AnsibleModule instance.
-
- Returns:
- An instance of `ansible.module_utils.connection.Connection` with a
- connection to the switch described in the provided module.
-
- Raises:
- AnsibleConnectionFailure: An error occurred connecting to the device
- """
- if hasattr(module, 'nos_connection'):
- return module.nos_connection
-
- capabilities = get_capabilities(module)
- network_api = capabilities.get('network_api')
- if network_api == 'cliconf':
- module.nos_connection = Connection(module._socket_path)
- else:
- module.fail_json(msg='Invalid connection type %s' % network_api)
-
- return module.nos_connection
-
-
-def get_capabilities(module):
- """Get switch capabilities
-
- Collects and returns a python object with the switch capabilities.
-
- Args:
- module: A valid AnsibleModule instance.
-
- Returns:
- A dictionary containing the switch capabilities.
- """
- if hasattr(module, 'nos_capabilities'):
- return module.nos_capabilities
-
- try:
- capabilities = Connection(module._socket_path).get_capabilities()
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- module.nos_capabilities = json.loads(capabilities)
- return module.nos_capabilities
-
-
-def run_commands(module, commands):
- """Run command list against connection.
-
- Get new or previously used connection and send commands to it one at a time,
- collecting response.
-
- Args:
- module: A valid AnsibleModule instance.
- commands: Iterable of command strings.
-
- Returns:
- A list of output strings.
- """
- responses = list()
- connection = get_connection(module)
-
- for cmd in to_list(commands):
- if isinstance(cmd, dict):
- command = cmd['command']
- prompt = cmd['prompt']
- answer = cmd['answer']
- else:
- command = cmd
- prompt = None
- answer = None
-
- try:
- out = connection.get(command, prompt, answer)
- out = to_text(out, errors='surrogate_or_strict')
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
- except UnicodeError:
- module.fail_json(msg=u'Failed to decode output from %s: %s' % (cmd, to_text(out)))
-
- responses.append(out)
-
- return responses
-
-
-def get_config(module):
- """Get switch configuration
-
- Gets the described device's current configuration. If a configuration has
- already been retrieved it will return the previously obtained configuration.
-
- Args:
- module: A valid AnsibleModule instance.
-
- Returns:
- A string containing the configuration.
- """
- if not hasattr(module, 'device_configs'):
- module.device_configs = {}
- elif module.device_configs != {}:
- return module.device_configs
-
- connection = get_connection(module)
- try:
- out = connection.get_config()
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- cfg = to_text(out, errors='surrogate_then_replace').strip()
- module.device_configs = cfg
- return cfg
-
-
-def load_config(module, commands):
- """Apply a list of commands to a device.
-
- Given a list of commands apply them to the device to modify the
- configuration in bulk.
-
- Args:
- module: A valid AnsibleModule instance.
- commands: Iterable of command strings.
-
- Returns:
- None
- """
- connection = get_connection(module)
-
- try:
- resp = connection.edit_config(commands)
- return resp.get('response')
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
diff --git a/plugins/module_utils/network/nso/__init__.py b/plugins/module_utils/network/nso/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/nso/nso.py b/plugins/module_utils/network/nso/nso.py
deleted file mode 100644
index 217ac5dd8b..0000000000
--- a/plugins/module_utils/network/nso/nso.py
+++ /dev/null
@@ -1,822 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Cisco and/or its affiliates.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from ansible.module_utils.basic import env_fallback
-from ansible.module_utils.urls import open_url
-from ansible.module_utils._text import to_text
-
-import json
-import re
-import socket
-
-try:
- unicode
- HAVE_UNICODE = True
-except NameError:
- unicode = str
- HAVE_UNICODE = False
-
-
-nso_argument_spec = dict(
- url=dict(type='str', required=True),
- username=dict(type='str', required=True, fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
- password=dict(type='str', required=True, no_log=True, fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD'])),
- timeout=dict(type='int', default=300),
- validate_certs=dict(type='bool', default=False)
-)
-
-
-class State(object):
- SET = 'set'
- PRESENT = 'present'
- ABSENT = 'absent'
- CHECK_SYNC = 'check-sync'
- DEEP_CHECK_SYNC = 'deep-check-sync'
- IN_SYNC = 'in-sync'
- DEEP_IN_SYNC = 'deep-in-sync'
-
- SYNC_STATES = ('check-sync', 'deep-check-sync', 'in-sync', 'deep-in-sync')
-
-
-class ModuleFailException(Exception):
- def __init__(self, message):
- super(ModuleFailException, self).__init__(message)
- self.message = message
-
-
-class NsoException(Exception):
- def __init__(self, message, error):
- super(NsoException, self).__init__(message)
- self.message = message
- self.error = error
-
-
-class JsonRpc(object):
- def __init__(self, url, timeout, validate_certs):
- self._url = url
- self._timeout = timeout
- self._validate_certs = validate_certs
- self._id = 0
- self._trans = {}
- self._headers = {'Content-Type': 'application/json'}
- self._conn = None
- self._system_settings = {}
-
- def login(self, user, passwd):
- payload = {
- 'method': 'login',
- 'params': {'user': user, 'passwd': passwd}
- }
- resp, resp_json = self._call(payload)
- self._headers['Cookie'] = resp.headers['set-cookie']
-
- def logout(self):
- payload = {'method': 'logout', 'params': {}}
- self._call(payload)
-
- def get_system_setting(self, setting):
- if setting not in self._system_settings:
- payload = {'method': 'get_system_setting', 'params': {'operation': setting}}
- resp, resp_json = self._call(payload)
- self._system_settings[setting] = resp_json['result']
- return self._system_settings[setting]
-
- def new_trans(self, **kwargs):
- payload = {'method': 'new_trans', 'params': kwargs}
- resp, resp_json = self._call(payload)
- return resp_json['result']['th']
-
- def get_trans(self, mode):
- if mode not in self._trans:
- th = self.new_trans(mode=mode)
- self._trans[mode] = th
- return self._trans[mode]
-
- def delete_trans(self, th):
- payload = {'method': 'delete_trans', 'params': {'th': th}}
- resp, resp_json = self._call(payload)
- self._maybe_delete_trans(th)
-
- def validate_trans(self, th):
- payload = {'method': 'validate_trans', 'params': {'th': th}}
- resp, resp_json = self._write_call(payload)
- return resp_json['result']
-
- def get_trans_changes(self, th):
- payload = {'method': 'get_trans_changes', 'params': {'th': th}}
- resp, resp_json = self._write_call(payload)
- return resp_json['result']['changes']
-
- def validate_commit(self, th):
- payload = {'method': 'validate_commit', 'params': {'th': th}}
- resp, resp_json = self._write_call(payload)
- return resp_json['result'].get('warnings', [])
-
- def commit(self, th):
- payload = {'method': 'commit', 'params': {'th': th}}
- resp, resp_json = self._write_call(payload)
- if len(resp_json['result']) == 0:
- self._maybe_delete_trans(th)
- return resp_json['result']
-
- def get_schema(self, **kwargs):
- payload = {'method': 'get_schema', 'params': kwargs}
- resp, resp_json = self._maybe_write_call(payload)
- return resp_json['result']
-
- def get_module_prefix_map(self, path=None):
- if path is None:
- payload = {'method': 'get_module_prefix_map', 'params': {}}
- resp, resp_json = self._call(payload)
- else:
- payload = {'method': 'get_module_prefix_map', 'params': {'path': path}}
- resp, resp_json = self._maybe_write_call(payload)
- return resp_json['result']
-
- def get_value(self, path):
- payload = {
- 'method': 'get_value',
- 'params': {'path': path}
- }
- resp, resp_json = self._read_call(payload)
- return resp_json['result']
-
- def exists(self, path):
- payload = {'method': 'exists', 'params': {'path': path}}
- try:
- resp, resp_json = self._read_call(payload)
- return resp_json['result']['exists']
- except NsoException as ex:
- # calling exists on a sub-list when the parent list does
- # not exists will cause data.not_found errors on recent
- # NSO
- if 'type' in ex.error and ex.error['type'] == 'data.not_found':
- return False
- raise
-
- def create(self, th, path):
- payload = {'method': 'create', 'params': {'th': th, 'path': path}}
- self._write_call(payload)
-
- def delete(self, th, path):
- payload = {'method': 'delete', 'params': {'th': th, 'path': path}}
- self._write_call(payload)
-
- def set_value(self, th, path, value):
- payload = {
- 'method': 'set_value',
- 'params': {'th': th, 'path': path, 'value': value}
- }
- resp, resp_json = self._write_call(payload)
- return resp_json['result']
-
- def show_config(self, path, operational=False):
- payload = {
- 'method': 'show_config',
- 'params': {
- 'path': path,
- 'result_as': 'json',
- 'with_oper': operational}
- }
- resp, resp_json = self._read_call(payload)
- return resp_json['result']
-
- def query(self, xpath, fields):
- payload = {
- 'method': 'query',
- 'params': {
- 'xpath_expr': xpath,
- 'selection': fields
- }
- }
- resp, resp_json = self._read_call(payload)
- return resp_json['result']['results']
-
- def run_action(self, th, path, params=None):
- if params is None:
- params = {}
-
- if is_version(self, [(4, 5), (4, 4, 3)]):
- result_format = 'json'
- else:
- result_format = 'normal'
-
- payload = {
- 'method': 'run_action',
- 'params': {
- 'format': result_format,
- 'path': path,
- 'params': params
- }
- }
- if th is None:
- resp, resp_json = self._read_call(payload)
- else:
- payload['params']['th'] = th
- resp, resp_json = self._call(payload)
-
- if result_format == 'normal':
- # this only works for one-level results, list entries,
- # containers etc will have / in their name.
- result = {}
- for info in resp_json['result']:
- result[info['name']] = info['value']
- else:
- result = resp_json['result']
-
- return result
-
- def _call(self, payload):
- self._id += 1
- if 'id' not in payload:
- payload['id'] = self._id
-
- if 'jsonrpc' not in payload:
- payload['jsonrpc'] = '2.0'
-
- data = json.dumps(payload)
- try:
- resp = open_url(
- self._url, timeout=self._timeout,
- method='POST', data=data, headers=self._headers,
- validate_certs=self._validate_certs)
- if resp.code != 200:
- raise NsoException(
- 'NSO returned HTTP code {0}, expected 200'.format(resp.status), {})
- except socket.timeout:
- raise NsoException('request timed out against NSO at {0}'.format(self._url), {})
-
- resp_body = resp.read()
- resp_json = json.loads(resp_body)
-
- if 'error' in resp_json:
- self._handle_call_error(payload, resp_json)
- return resp, resp_json
-
- def _handle_call_error(self, payload, resp_json):
- method = payload['method']
-
- error = resp_json['error']
- error_type = error['type'][len('rpc.method.'):]
- if error_type in ('unexpected_params',
- 'unknown_params_value',
- 'invalid_params',
- 'invalid_params_type',
- 'data_not_found'):
- key = error['data']['param']
- error_type_s = error_type.replace('_', ' ')
- if key == 'path':
- msg = 'NSO {0} {1}. path = {2}'.format(
- method, error_type_s, payload['params']['path'])
- else:
- path = payload['params'].get('path', 'unknown')
- msg = 'NSO {0} {1}. path = {2}. {3} = {4}'.format(
- method, error_type_s, path, key, payload['params'][key])
- else:
- msg = 'NSO {0} returned JSON-RPC error: {1}'.format(method, error)
-
- raise NsoException(msg, error)
-
- def _read_call(self, payload):
- if 'th' not in payload['params']:
- payload['params']['th'] = self.get_trans(mode='read')
- return self._call(payload)
-
- def _write_call(self, payload):
- if 'th' not in payload['params']:
- payload['params']['th'] = self.get_trans(mode='read_write')
- return self._call(payload)
-
- def _maybe_write_call(self, payload):
- if 'read_write' in self._trans:
- return self._write_call(payload)
- else:
- return self._read_call(payload)
-
- def _maybe_delete_trans(self, th):
- for mode in ('read', 'read_write'):
- if th == self._trans.get(mode, None):
- del self._trans[mode]
-
-
-class ValueBuilder(object):
- PATH_RE = re.compile('{[^}]*}')
- PATH_RE_50 = re.compile('{[^}]*}$')
-
- class Value(object):
- __slots__ = ['path', 'tag_path', 'state', 'value', 'deps']
-
- def __init__(self, path, state, value, deps):
- self.path = path
- self.tag_path = ValueBuilder.PATH_RE.sub('', path)
- self.state = state
- self.value = value
- self.deps = deps
-
- # nodes can depend on themselves
- if self.tag_path in self.deps:
- self.deps.remove(self.tag_path)
-
- def __lt__(self, rhs):
- l_len = len(self.path.split('/'))
- r_len = len(rhs.path.split('/'))
- if l_len == r_len:
- return self.path.__lt__(rhs.path)
- return l_len < r_len
-
- def __str__(self):
- return 'Value'.format(
- self.path, self.state, self.value)
-
- class ValueIterator(object):
- def __init__(self, client, values, delayed_values):
- self._client = client
- self._values = values
- self._delayed_values = delayed_values
- self._pos = 0
-
- def __iter__(self):
- return self
-
- def __next__(self):
- return self.next()
-
- def next(self):
- if self._pos >= len(self._values):
- if len(self._delayed_values) == 0:
- raise StopIteration()
-
- builder = ValueBuilder(self._client, delay=False)
- for (parent, maybe_qname, value) in self._delayed_values:
- builder.build(parent, maybe_qname, value)
- del self._delayed_values[:]
- self._values.extend(builder.values)
-
- return self.next()
-
- value = self._values[self._pos]
- self._pos += 1
- return value
-
- def __init__(self, client, mode='config', delay=None):
- self._client = client
- self._mode = mode
- self._schema_cache = {}
- self._module_prefix_map_cache = {}
- self._values = []
- self._values_dirty = False
- self._delay = delay is None and mode == 'config' and is_version(self._client, [(5, 0)])
- self._delayed_values = []
-
- def build(self, parent, maybe_qname, value, schema=None):
- qname, name = self.get_prefix_name(parent, maybe_qname)
- if name is None:
- path = parent
- else:
- path = '{0}/{1}'.format(parent, qname)
-
- if schema is None:
- schema = self._get_schema(path)
-
- if self._delay and schema.get('is_mount_point', False):
- # delay conversion of mounted values, required to get
- # shema information on 5.0 and later.
- self._delayed_values.append((parent, maybe_qname, value))
- elif self._is_leaf_list(schema) and is_version(self._client, [(4, 5)]):
- self._build_leaf_list(path, schema, value)
- elif self._is_leaf(schema):
- deps = schema.get('deps', [])
- if self._is_empty_leaf(schema):
- exists = self._client.exists(path)
- if exists and value != [None]:
- self._add_value(path, State.ABSENT, None, deps)
- elif not exists and value == [None]:
- self._add_value(path, State.PRESENT, None, deps)
- else:
- if maybe_qname is None:
- value_type = self.get_type(path)
- else:
- value_type = self._get_child_type(parent, qname)
-
- if 'identityref' in value_type:
- if isinstance(value, list):
- value = [ll_v for ll_v, t_ll_v
- in [self.get_prefix_name(parent, v) for v in value]]
- else:
- value, t_value = self.get_prefix_name(parent, value)
- self._add_value(path, State.SET, value, deps)
- elif isinstance(value, dict):
- self._build_dict(path, schema, value)
- elif isinstance(value, list):
- self._build_list(path, schema, value)
- else:
- raise ModuleFailException(
- 'unsupported schema {0} at {1}'.format(
- schema['kind'], path))
-
- @property
- def values(self):
- if self._values_dirty:
- self._values = ValueBuilder.sort_values(self._values)
- self._values_dirty = False
-
- return ValueBuilder.ValueIterator(self._client, self._values, self._delayed_values)
-
- @staticmethod
- def sort_values(values):
- class N(object):
- def __init__(self, v):
- self.tmp_mark = False
- self.mark = False
- self.v = v
-
- sorted_values = []
- nodes = [N(v) for v in sorted(values)]
-
- def get_node(tag_path):
- return next((m for m in nodes
- if m.v.tag_path == tag_path), None)
-
- def is_cycle(n, dep, visited):
- visited.add(n.v.tag_path)
- if dep in visited:
- return True
-
- dep_n = get_node(dep)
- if dep_n is not None:
- for sub_dep in dep_n.v.deps:
- if is_cycle(dep_n, sub_dep, visited):
- return True
-
- return False
-
- # check for dependency cycles, remove if detected. sort will
- # not be 100% but allows for a best-effort to work around
- # issue in NSO.
- for n in nodes:
- for dep in n.v.deps:
- if is_cycle(n, dep, set()):
- n.v.deps.remove(dep)
-
- def visit(n):
- if n.tmp_mark:
- return False
- if not n.mark:
- n.tmp_mark = True
- for m in nodes:
- if m.v.tag_path in n.v.deps:
- if not visit(m):
- return False
-
- n.tmp_mark = False
- n.mark = True
-
- sorted_values.insert(0, n.v)
-
- return True
-
- n = next((n for n in nodes if not n.mark), None)
- while n is not None:
- visit(n)
- n = next((n for n in nodes if not n.mark), None)
-
- return sorted_values[::-1]
-
- def _build_dict(self, path, schema, value):
- keys = schema.get('key', [])
- for dict_key, dict_value in value.items():
- qname, name = self.get_prefix_name(path, dict_key)
- if dict_key in ('__state', ) or name in keys:
- continue
-
- child_schema = self._find_child(path, schema, qname)
- self.build(path, dict_key, dict_value, child_schema)
-
- def _build_leaf_list(self, path, schema, value):
- deps = schema.get('deps', [])
- entry_type = self.get_type(path, schema)
-
- if self._mode == 'verify':
- for entry in value:
- if 'identityref' in entry_type:
- entry, t_entry = self.get_prefix_name(path, entry)
- entry_path = '{0}{{{1}}}'.format(path, entry)
- if not self._client.exists(entry_path):
- self._add_value(entry_path, State.ABSENT, None, deps)
- else:
- # remove leaf list if treated as a list and then re-create the
- # expected list entries.
- self._add_value(path, State.ABSENT, None, deps)
-
- for entry in value:
- if 'identityref' in entry_type:
- entry, t_entry = self.get_prefix_name(path, entry)
- entry_path = '{0}{{{1}}}'.format(path, entry)
- self._add_value(entry_path, State.PRESENT, None, deps)
-
- def _build_list(self, path, schema, value):
- deps = schema.get('deps', [])
- for entry in value:
- entry_key = self._build_key(path, entry, schema['key'])
- entry_path = '{0}{{{1}}}'.format(path, entry_key)
- entry_state = entry.get('__state', 'present')
- entry_exists = self._client.exists(entry_path)
-
- if entry_state == 'absent':
- if entry_exists:
- self._add_value(entry_path, State.ABSENT, None, deps)
- else:
- if not entry_exists:
- self._add_value(entry_path, State.PRESENT, None, deps)
- if entry_state in State.SYNC_STATES:
- self._add_value(entry_path, entry_state, None, deps)
-
- self.build(entry_path, None, entry)
-
- def _build_key(self, path, entry, schema_keys):
- key_parts = []
- for key in schema_keys:
- value = entry.get(key, None)
- if value is None:
- raise ModuleFailException(
- 'required leaf {0} in {1} not set in data'.format(
- key, path))
-
- value_type = self._get_child_type(path, key)
- if 'identityref' in value_type:
- value, t_value = self.get_prefix_name(path, value)
- key_parts.append(self._quote_key(value))
- return ' '.join(key_parts)
-
- def _quote_key(self, key):
- if isinstance(key, bool):
- return key and 'true' or 'false'
-
- q_key = []
- for c in str(key):
- if c in ('{', '}', "'", '\\'):
- q_key.append('\\')
- q_key.append(c)
- q_key = ''.join(q_key)
- if ' ' in q_key:
- return '"{0}"'.format(q_key)
- return q_key
-
- def _find_child(self, path, schema, qname):
- if 'children' not in schema:
- schema = self._get_schema(path)
-
- # look for the qualified name if : is in the name
- child_schema = self._get_child(schema, qname)
- if child_schema is not None:
- return child_schema
-
- # no child was found, look for a choice with a child matching
- for child_schema in schema['children']:
- if child_schema['kind'] != 'choice':
- continue
- choice_child_schema = self._get_choice_child(child_schema, qname)
- if choice_child_schema is not None:
- return choice_child_schema
-
- raise ModuleFailException(
- 'no child in {0} with name {1}. children {2}'.format(
- path, qname, ','.join((c.get('qname', c.get('name', None)) for c in schema['children']))))
-
- def _add_value(self, path, state, value, deps):
- self._values.append(ValueBuilder.Value(path, state, value, deps))
- self._values_dirty = True
-
- def get_prefix_name(self, path, qname):
- if not isinstance(qname, (str, unicode)):
- return qname, None
- if ':' not in qname:
- return qname, qname
-
- module_prefix_map = self._get_module_prefix_map(path)
- module, name = qname.split(':', 1)
- if module not in module_prefix_map:
- raise ModuleFailException(
- 'no module mapping for module {0}. loaded modules {1}'.format(
- module, ','.join(sorted(module_prefix_map.keys()))))
-
- return '{0}:{1}'.format(module_prefix_map[module], name), name
-
- def _get_schema(self, path):
- return self._ensure_schema_cached(path)['data']
-
- def _get_child_type(self, parent_path, key):
- all_schema = self._ensure_schema_cached(parent_path)
- parent_schema = all_schema['data']
- meta = all_schema['meta']
- schema = self._find_child(parent_path, parent_schema, key)
- return self.get_type(parent_path, schema, meta)
-
- def get_type(self, path, schema=None, meta=None):
- if schema is None or meta is None:
- all_schema = self._ensure_schema_cached(path)
- schema = all_schema['data']
- meta = all_schema['meta']
-
- if self._is_leaf(schema):
- def get_type(meta, curr_type):
- if curr_type.get('primitive', False):
- return [curr_type['name']]
- if 'namespace' in curr_type:
- curr_type_key = '{0}:{1}'.format(
- curr_type['namespace'], curr_type['name'])
- type_info = meta['types'][curr_type_key][-1]
- return get_type(meta, type_info)
- if 'leaf_type' in curr_type:
- return get_type(meta, curr_type['leaf_type'][-1])
- if 'union' in curr_type:
- union_types = []
- for union_type in curr_type['union']:
- union_types.extend(get_type(meta, union_type[-1]))
- return union_types
- return [curr_type.get('name', 'unknown')]
-
- return get_type(meta, schema['type'])
- return None
-
- def _ensure_schema_cached(self, path):
- if not self._delay and is_version(self._client, [(5, 0)]):
- # newer versions of NSO support multiple different schemas
- # for different devices, thus the device is required to
- # look up the schema. Remove the key entry to get schema
- # logic working ok.
- path = ValueBuilder.PATH_RE_50.sub('', path)
- else:
- path = ValueBuilder.PATH_RE.sub('', path)
-
- if path not in self._schema_cache:
- schema = self._client.get_schema(path=path, levels=1)
- self._schema_cache[path] = schema
- return self._schema_cache[path]
-
- def _get_module_prefix_map(self, path):
- # newer versions of NSO support multiple mappings from module
- # to prefix depending on which device is used.
- if path != '' and is_version(self._client, [(5, 0)]):
- if path not in self._module_prefix_map_cache:
- self._module_prefix_map_cache[path] = self._client.get_module_prefix_map(path)
- return self._module_prefix_map_cache[path]
-
- if '' not in self._module_prefix_map_cache:
- self._module_prefix_map_cache[''] = self._client.get_module_prefix_map()
- return self._module_prefix_map_cache['']
-
- def _get_child(self, schema, qname):
- # no child specified, return parent
- if qname is None:
- return schema
-
- name_key = ':' in qname and 'qname' or 'name'
- return next((c for c in schema['children']
- if c.get(name_key, None) == qname), None)
-
- def _get_choice_child(self, schema, qname):
- name_key = ':' in qname and 'qname' or 'name'
- for child_case in schema['cases']:
- # look for direct child
- choice_child_schema = next(
- (c for c in child_case['children']
- if c.get(name_key, None) == qname), None)
- if choice_child_schema is not None:
- return choice_child_schema
-
- # look for nested choice
- for child_schema in child_case['children']:
- if child_schema['kind'] != 'choice':
- continue
- choice_child_schema = self._get_choice_child(child_schema, qname)
- if choice_child_schema is not None:
- return choice_child_schema
- return None
-
- def _is_leaf_list(self, schema):
- return schema.get('kind', None) == 'leaf-list'
-
- def _is_leaf(self, schema):
- # still checking for leaf-list here to be compatible with pre
- # 4.5 versions of NSO.
- return schema.get('kind', None) in ('key', 'leaf', 'leaf-list')
-
- def _is_empty_leaf(self, schema):
- return (schema.get('kind', None) == 'leaf' and
- schema['type'].get('primitive', False) and
- schema['type'].get('name', '') == 'empty')
-
-
-def connect(params):
- client = JsonRpc(params['url'],
- params['timeout'],
- params['validate_certs'])
- client.login(params['username'], params['password'])
- return client
-
-
-def verify_version(client, required_versions):
- version_str = client.get_system_setting('version')
- if not verify_version_str(version_str, required_versions):
- supported_versions = ', '.join(
- ['.'.join([str(p) for p in required_version])
- for required_version in required_versions])
- raise ModuleFailException(
- 'unsupported NSO version {0}. {1} or later supported'.format(
- version_str, supported_versions))
-
-
-def is_version(client, required_versions):
- version_str = client.get_system_setting('version')
- return verify_version_str(version_str, required_versions)
-
-
-def verify_version_str(version_str, required_versions):
- version_str = re.sub('_.*', '', version_str)
-
- version = [int(p) for p in version_str.split('.')]
- if len(version) < 2:
- raise ModuleFailException(
- 'unsupported NSO version format {0}'.format(version_str))
-
- def check_version(required_version, version):
- for pos in range(len(required_version)):
- if pos >= len(version):
- return False
- if version[pos] > required_version[pos]:
- return True
- if version[pos] < required_version[pos]:
- return False
- return True
-
- for required_version in required_versions:
- if check_version(required_version, version):
- return True
- return False
-
-
-def normalize_value(expected_value, value, key):
- if value is None:
- return None
- if (isinstance(expected_value, bool) and
- isinstance(value, (str, unicode))):
- return value == 'true'
- if isinstance(expected_value, int):
- try:
- return int(value)
- except TypeError:
- raise ModuleFailException(
- 'returned value {0} for {1} is not a valid integer'.format(
- key, value))
- if isinstance(expected_value, float):
- try:
- return float(value)
- except TypeError:
- raise ModuleFailException(
- 'returned value {0} for {1} is not a valid float'.format(
- key, value))
- if isinstance(expected_value, (list, tuple)):
- if not isinstance(value, (list, tuple)):
- raise ModuleFailException(
- 'returned value {0} for {1} is not a list'.format(value, key))
- if len(expected_value) != len(value):
- raise ModuleFailException(
- 'list length mismatch for {0}'.format(key))
-
- normalized_value = []
- for i in range(len(expected_value)):
- normalized_value.append(
- normalize_value(expected_value[i], value[i], '{0}[{1}]'.format(key, i)))
- return normalized_value
-
- if isinstance(expected_value, dict):
- if not isinstance(value, dict):
- raise ModuleFailException(
- 'returned value {0} for {1} is not a dict'.format(value, key))
- if len(expected_value) != len(value):
- raise ModuleFailException(
- 'dict length mismatch for {0}'.format(key))
-
- normalized_value = {}
- for k in expected_value.keys():
- n_k = normalize_value(k, k, '{0}[{1}]'.format(key, k))
- if n_k not in value:
- raise ModuleFailException('missing {0} in value'.format(n_k))
- normalized_value[n_k] = normalize_value(expected_value[k], value[k], '{0}[{1}]'.format(key, k))
- return normalized_value
-
- if HAVE_UNICODE:
- if isinstance(expected_value, unicode) and isinstance(value, str):
- return value.decode('utf-8')
- if isinstance(expected_value, str) and isinstance(value, unicode):
- return value.encode('utf-8')
- else:
- if hasattr(expected_value, 'encode') and hasattr(value, 'decode'):
- return value.decode('utf-8')
- if hasattr(expected_value, 'decode') and hasattr(value, 'encode'):
- return value.encode('utf-8')
-
- return value
diff --git a/plugins/module_utils/network/onyx/__init__.py b/plugins/module_utils/network/onyx/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/onyx/onyx.py b/plugins/module_utils/network/onyx/onyx.py
deleted file mode 100644
index d537e048b9..0000000000
--- a/plugins/module_utils/network/onyx/onyx.py
+++ /dev/null
@@ -1,261 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# (c) 2017, Ansible by Red Hat, inc
-#
-# This file is part of Ansible by Red Hat
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-import json
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.connection import Connection, ConnectionError
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, EntityCollection
-
-_DEVICE_CONFIGS = {}
-_CONNECTION = None
-
-_COMMAND_SPEC = {
- 'command': dict(key=True),
- 'prompt': dict(),
- 'answer': dict()
-}
-
-
-def get_connection(module):
- global _CONNECTION
- if _CONNECTION:
- return _CONNECTION
- _CONNECTION = Connection(module._socket_path)
- return _CONNECTION
-
-
-def to_commands(module, commands):
- if not isinstance(commands, list):
- raise AssertionError('argument must be of type ')
-
- transform = EntityCollection(module, _COMMAND_SPEC)
- commands = transform(commands)
- return commands
-
-
-def run_commands(module, commands, check_rc=True):
- connection = get_connection(module)
-
- commands = to_commands(module, to_list(commands))
-
- responses = list()
-
- for cmd in commands:
- out = connection.get(**cmd)
- responses.append(to_text(out, errors='surrogate_then_replace'))
-
- return responses
-
-
-def get_config(module, source='running'):
- conn = get_connection(module)
- out = conn.get_config(source)
- cfg = to_text(out, errors='surrogate_then_replace').strip()
- return cfg
-
-
-def load_config(module, config):
- try:
- conn = get_connection(module)
- conn.edit_config(config)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
-
-
-def _parse_json_output(out):
- out_list = out.split('\n')
- first_index = 0
- opening_char = None
- lines_count = len(out_list)
- while first_index < lines_count:
- first_line = out_list[first_index].strip()
- if not first_line or first_line[0] not in ("[", "{"):
- first_index += 1
- continue
- opening_char = first_line[0]
- break
- if not opening_char:
- return "null"
- closing_char = ']' if opening_char == '[' else '}'
- last_index = lines_count - 1
- found = False
- while last_index > first_index:
- last_line = out_list[last_index].strip()
- if not last_line or last_line[0] != closing_char:
- last_index -= 1
- continue
- found = True
- break
- if not found:
- return opening_char + closing_char
- return "".join(out_list[first_index:last_index + 1])
-
-
-def show_cmd(module, cmd, json_fmt=True, fail_on_error=True):
- if json_fmt:
- cmd += " | json-print"
- conn = get_connection(module)
- command_obj = to_commands(module, to_list(cmd))[0]
- try:
- out = conn.get(**command_obj)
- except ConnectionError:
- if fail_on_error:
- raise
- return None
- if json_fmt:
- out = _parse_json_output(out)
- try:
- cfg = json.loads(out)
- except ValueError:
- module.fail_json(
- msg="got invalid json",
- stderr=to_text(out, errors='surrogate_then_replace'))
- else:
- cfg = to_text(out, errors='surrogate_then_replace').strip()
- return cfg
-
-
-def get_interfaces_config(module, interface_type, flags=None, json_fmt=True):
- cmd = "show interfaces %s" % interface_type
- if flags:
- cmd += " %s" % flags
- return show_cmd(module, cmd, json_fmt)
-
-
-def get_bgp_summary(module):
- cmd = "show running-config protocol bgp"
- return show_cmd(module, cmd, json_fmt=False, fail_on_error=False)
-
-
-def get_capabilities(module):
- """Returns platform info of the remove device
- """
- if hasattr(module, '_capabilities'):
- return module._capabilities
-
- connection = get_connection(module)
- try:
- capabilities = connection.get_capabilities()
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
-
- module._capabilities = json.loads(capabilities)
- return module._capabilities
-
-
-class BaseOnyxModule(object):
- ONYX_API_VERSION = "3.6.6000"
-
- def __init__(self):
- self._module = None
- self._commands = list()
- self._current_config = None
- self._required_config = None
- self._os_version = None
-
- def init_module(self):
- pass
-
- def load_current_config(self):
- pass
-
- def get_required_config(self):
- pass
-
- def _get_os_version(self):
- capabilities = get_capabilities(self._module)
- device_info = capabilities['device_info']
- return device_info['network_os_version']
-
- # pylint: disable=unused-argument
- def check_declarative_intent_params(self, result):
- return None
-
- def _validate_key(self, param, key):
- validator = getattr(self, 'validate_%s' % key)
- if callable(validator):
- validator(param.get(key))
-
- def validate_param_values(self, obj, param=None):
- if param is None:
- param = self._module.params
- for key in obj:
- # validate the param value (if validator func exists)
- try:
- self._validate_key(param, key)
- except AttributeError:
- pass
-
- @classmethod
- def get_config_attr(cls, item, arg):
- return item.get(arg)
-
- @classmethod
- def get_mtu(cls, item):
- mtu = cls.get_config_attr(item, "MTU")
- mtu_parts = mtu.split()
- try:
- return int(mtu_parts[0])
- except ValueError:
- return None
-
- def _validate_range(self, attr_name, min_val, max_val, value):
- if value is None:
- return True
- if not min_val <= int(value) <= max_val:
- msg = '%s must be between %s and %s' % (
- attr_name, min_val, max_val)
- self._module.fail_json(msg=msg)
-
- def validate_mtu(self, value):
- self._validate_range('mtu', 1500, 9612, value)
-
- def generate_commands(self):
- pass
-
- def run(self):
- self.init_module()
-
- result = {'changed': False}
-
- self.get_required_config()
- self.load_current_config()
-
- self.generate_commands()
- result['commands'] = self._commands
-
- if self._commands:
- if not self._module.check_mode:
- load_config(self._module, self._commands)
- result['changed'] = True
-
- failed_conditions = self.check_declarative_intent_params(result)
-
- if failed_conditions:
- msg = 'One or more conditional statements have not been satisfied'
- self._module.fail_json(msg=msg,
- failed_conditions=failed_conditions)
-
- self._module.exit_json(**result)
-
- @classmethod
- def main(cls):
- app = cls()
- app.run()
diff --git a/plugins/module_utils/network/ordnance/__init__.py b/plugins/module_utils/network/ordnance/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/ordnance/ordnance.py b/plugins/module_utils/network/ordnance/ordnance.py
deleted file mode 100644
index 070a86d3e1..0000000000
--- a/plugins/module_utils/network/ordnance/ordnance.py
+++ /dev/null
@@ -1,19 +0,0 @@
-_DEVICE_CONFIGS = {}
-
-
-def get_config(module, flags=None):
- flags = [] if flags is None else flags
-
- cmd = 'show running-config '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- try:
- return _DEVICE_CONFIGS[cmd]
- except KeyError:
- rc, out, err = module.exec_command(cmd)
- if rc != 0:
- module.fail_json(msg='unable to retrieve current config', stderr=err)
- cfg = str(out).strip()
- _DEVICE_CONFIGS[cmd] = cfg
- return cfg
diff --git a/plugins/module_utils/network/panos/__init__.py b/plugins/module_utils/network/panos/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/panos/panos.py b/plugins/module_utils/network/panos/panos.py
deleted file mode 100644
index f50257dcf2..0000000000
--- a/plugins/module_utils/network/panos/panos.py
+++ /dev/null
@@ -1,418 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# Copyright (c) 2018 Palo Alto Networks techbizdev,
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-_MIN_VERSION_ERROR = '{0} version ({1}) < minimum version ({2})'
-HAS_PANDEVICE = True
-try:
- import pandevice
- from pandevice.base import PanDevice
- from pandevice.firewall import Firewall
- from pandevice.panorama import DeviceGroup, Template, TemplateStack
- from pandevice.policies import PreRulebase, PostRulebase, Rulebase
- from pandevice.device import Vsys
- from pandevice.errors import PanDeviceError
-except ImportError:
- HAS_PANDEVICE = False
-
-
-def _vstr(val):
- return '{0}.{1}.{2}'.format(*val)
-
-
-class ConnectionHelper(object):
- def __init__(self, min_pandevice_version, min_panos_version,
- panorama_error, firewall_error):
- """Performs connection initialization and determines params."""
- # Params for AnsibleModule.
- self.argument_spec = {}
- self.required_one_of = []
-
- # Params for pandevice tree construction.
- self.vsys = None
- self.device_group = None
- self.vsys_dg = None
- self.rulebase = None
- self.template = None
- self.template_stack = None
- self.vsys_importable = None
- self.min_pandevice_version = min_pandevice_version
- self.min_panos_version = min_panos_version
- self.panorama_error = panorama_error
- self.firewall_error = firewall_error
-
- # The PAN-OS device.
- self.device = None
-
- def get_pandevice_parent(self, module):
- """Builds the pandevice object tree, returning the parent object.
-
- If pandevice is not installed, then module.fail_json() will be
- invoked.
-
- Arguments:
- * module(AnsibleModule): the ansible module.
-
- Returns:
- * The parent pandevice object based on the spec given to
- get_connection().
- """
- # Sanity check.
- if not HAS_PANDEVICE:
- module.fail_json(msg='Missing required library "pandevice".')
-
- # Verify pandevice minimum version.
- if self.min_pandevice_version is not None:
- pdv = tuple(int(x) for x in pandevice.__version__.split('.'))
- if pdv < self.min_pandevice_version:
- module.fail_json(msg=_MIN_VERSION_ERROR.format(
- 'pandevice', pandevice.__version__,
- _vstr(self.min_pandevice_version)))
-
- pan_device_auth, serial_number = None, None
- if module.params['provider'] and module.params['provider']['ip_address']:
- pan_device_auth = (
- module.params['provider']['ip_address'],
- module.params['provider']['username'],
- module.params['provider']['password'],
- module.params['provider']['api_key'],
- module.params['provider']['port'],
- )
- serial_number = module.params['provider']['serial_number']
- elif module.params.get('ip_address', None) is not None:
- pan_device_auth = (
- module.params['ip_address'],
- module.params['username'],
- module.params['password'],
- module.params['api_key'],
- module.params['port'],
- )
- msg = 'Classic provider params are deprecated; use "provider" instead'
- module.deprecate(msg, '2.12')
- else:
- module.fail_json(msg='Provider params are required.')
-
- # Create the connection object.
- try:
- self.device = PanDevice.create_from_device(*pan_device_auth)
- except PanDeviceError as e:
- module.fail_json(msg='Failed connection: {0}'.format(e))
-
- # Verify PAN-OS minimum version.
- if self.min_panos_version is not None:
- if self.device._version_info < self.min_panos_version:
- module.fail_json(msg=_MIN_VERSION_ERROR.format(
- 'PAN-OS', _vstr(self.device._version_info),
- _vstr(self.min_panos_version)))
-
- # Optional: Firewall via Panorama connectivity specified.
- if hasattr(self.device, 'refresh_devices') and serial_number:
- fw = Firewall(serial=serial_number)
- self.device.add(fw)
- self.device = fw
-
- parent = self.device
- not_found = '{0} "{1}" is not present.'
- pano_mia_param = 'Param "{0}" is required for Panorama but not specified.'
- ts_error = 'Specify either the template or the template stack{0}.'
- if hasattr(self.device, 'refresh_devices'):
- # Panorama connection.
- # Error if Panorama is not supported.
- if self.panorama_error is not None:
- module.fail_json(msg=self.panorama_error)
-
- # Spec: template stack.
- tmpl_required = False
- added_template = False
- if self.template_stack is not None:
- name = module.params[self.template_stack]
- if name is not None:
- stacks = TemplateStack.refreshall(parent, name_only=True)
- for ts in stacks:
- if ts.name == name:
- parent = ts
- added_template = True
- break
- else:
- module.fail_json(msg=not_found.format(
- 'Template stack', name,
- ))
- elif self.template is not None:
- tmpl_required = True
- else:
- module.fail_json(msg=pano_mia_param.format(self.template_stack))
-
- # Spec: template.
- if self.template is not None:
- name = module.params[self.template]
- if name is not None:
- if added_template:
- module.fail_json(msg=ts_error.format(', not both'))
- templates = Template.refreshall(parent, name_only=True)
- for t in templates:
- if t.name == name:
- parent = t
- break
- else:
- module.fail_json(msg=not_found.format(
- 'Template', name,
- ))
- elif tmpl_required:
- module.fail_json(msg=ts_error.format(''))
- else:
- module.fail_json(msg=pano_mia_param.format(self.template))
-
- # Spec: vsys importable.
- vsys_name = self.vsys_importable or self.vsys
- if vsys_name is not None:
- name = module.params[vsys_name]
- if name not in (None, 'shared'):
- vo = Vsys(name)
- parent.add(vo)
- parent = vo
-
- # Spec: vsys_dg or device_group.
- dg_name = self.vsys_dg or self.device_group
- if dg_name is not None:
- name = module.params[dg_name]
- if name not in (None, 'shared'):
- groups = DeviceGroup.refreshall(parent, name_only=True)
- for dg in groups:
- if dg.name == name:
- parent = dg
- break
- else:
- module.fail_json(msg=not_found.format(
- 'Device group', name,
- ))
-
- # Spec: rulebase.
- if self.rulebase is not None:
- if module.params[self.rulebase] in (None, 'pre-rulebase'):
- rb = PreRulebase()
- parent.add(rb)
- parent = rb
- elif module.params[self.rulebase] == 'rulebase':
- rb = Rulebase()
- parent.add(rb)
- parent = rb
- elif module.params[self.rulebase] == 'post-rulebase':
- rb = PostRulebase()
- parent.add(rb)
- parent = rb
- else:
- module.fail_json(msg=not_found.format(
- 'Rulebase', module.params[self.rulebase]))
- else:
- # Firewall connection.
- # Error if firewalls are not supported.
- if self.firewall_error is not None:
- module.fail_json(msg=self.firewall_error)
-
- # Spec: vsys or vsys_dg or vsys_importable.
- vsys_name = self.vsys_dg or self.vsys or self.vsys_importable
- if vsys_name is not None:
- parent.vsys = module.params[vsys_name]
-
- # Spec: rulebase.
- if self.rulebase is not None:
- rb = Rulebase()
- parent.add(rb)
- parent = rb
-
- # Done.
- return parent
-
-
-def get_connection(vsys=None, device_group=None,
- vsys_dg=None, vsys_importable=None,
- rulebase=None, template=None, template_stack=None,
- with_classic_provider_spec=False, with_state=True,
- argument_spec=None, required_one_of=None,
- min_pandevice_version=None, min_panos_version=None,
- panorama_error=None, firewall_error=None):
- """Returns a helper object that handles pandevice object tree init.
-
- The `vsys`, `device_group`, `vsys_dg`, `vsys_importable`, `rulebase`,
- `template`, and `template_stack` params can be any of the following types:
-
- * None - do not include this in the spec
- * True - use the default param name
- * string - use this string for the param name
-
- The `min_pandevice_version` and `min_panos_version` args expect a 3 element
- tuple of ints. For example, `(0, 6, 0)` or `(8, 1, 0)`.
-
- If you are including template support (by defining either `template` and/or
- `template_stack`), and the thing the module is enabling the management of is
- an "importable", you should define either `vsys_importable` (whose default
- value is None) or `vsys` (whose default value is 'vsys1').
-
- Arguments:
- vsys: The vsys (default: 'vsys1').
- device_group: Panorama only - The device group (default: 'shared').
- vsys_dg: The param name if vsys and device_group are a shared param.
- vsys_importable: Either this or `vsys` should be specified. For:
- - Interfaces
- - VLANs
- - Virtual Wires
- - Virtual Routers
- rulebase: This is a policy of some sort.
- template: Panorama - The template name.
- template_stack: Panorama - The template stack name.
- with_classic_provider_spec(bool): Include the ip_address, username,
- password, api_key, and port params in the base spec, and make the
- "provider" param optional.
- with_state(bool): Include the standard 'state' param.
- argument_spec(dict): The argument spec to mixin with the
- generated spec based on the given parameters.
- required_one_of(list): List of lists to extend into required_one_of.
- min_pandevice_version(tuple): Minimum pandevice version allowed.
- min_panos_version(tuple): Minimum PAN-OS version allowed.
- panorama_error(str): The error message if the device is Panorama.
- firewall_error(str): The error message if the device is a firewall.
-
- Returns:
- ConnectionHelper
- """
- helper = ConnectionHelper(
- min_pandevice_version, min_panos_version,
- panorama_error, firewall_error)
- req = []
- spec = {
- 'provider': {
- 'required': True,
- 'type': 'dict',
- 'required_one_of': [['password', 'api_key'], ],
- 'options': {
- 'ip_address': {'required': True},
- 'username': {'default': 'admin'},
- 'password': {'no_log': True},
- 'api_key': {'no_log': True},
- 'port': {'default': 443, 'type': 'int'},
- 'serial_number': {'no_log': True},
- },
- },
- }
-
- if with_classic_provider_spec:
- spec['provider']['required'] = False
- spec['provider']['options']['ip_address']['required'] = False
- del(spec['provider']['required_one_of'])
- spec.update({
- 'ip_address': {'required': False},
- 'username': {'default': 'admin'},
- 'password': {'no_log': True},
- 'api_key': {'no_log': True},
- 'port': {'default': 443, 'type': 'int'},
- })
- req.extend([
- ['provider', 'ip_address'],
- ['provider', 'password', 'api_key'],
- ])
-
- if with_state:
- spec['state'] = {
- 'default': 'present',
- 'choices': ['present', 'absent'],
- }
-
- if vsys_dg is not None:
- if isinstance(vsys_dg, bool):
- param = 'vsys_dg'
- else:
- param = vsys_dg
- spec[param] = {}
- helper.vsys_dg = param
- else:
- if vsys is not None:
- if isinstance(vsys, bool):
- param = 'vsys'
- else:
- param = vsys
- spec[param] = {'default': 'vsys1'}
- helper.vsys = param
- if device_group is not None:
- if isinstance(device_group, bool):
- param = 'device_group'
- else:
- param = device_group
- spec[param] = {'default': 'shared'}
- helper.device_group = param
- if vsys_importable is not None:
- if vsys is not None:
- raise KeyError('Define "vsys" or "vsys_importable", not both.')
- if isinstance(vsys_importable, bool):
- param = 'vsys'
- else:
- param = vsys_importable
- spec[param] = {}
- helper.vsys_importable = param
-
- if rulebase is not None:
- if isinstance(rulebase, bool):
- param = 'rulebase'
- else:
- param = rulebase
- spec[param] = {
- 'default': None,
- 'choices': ['pre-rulebase', 'rulebase', 'post-rulebase'],
- }
- helper.rulebase = param
-
- if template is not None:
- if isinstance(template, bool):
- param = 'template'
- else:
- param = template
- spec[param] = {}
- helper.template = param
-
- if template_stack is not None:
- if isinstance(template_stack, bool):
- param = 'template_stack'
- else:
- param = template_stack
- spec[param] = {}
- helper.template_stack = param
-
- if argument_spec is not None:
- for k in argument_spec.keys():
- if k in spec:
- raise KeyError('{0}: key used by connection helper.'.format(k))
- spec[k] = argument_spec[k]
-
- if required_one_of is not None:
- req.extend(required_one_of)
-
- # Done.
- helper.argument_spec = spec
- helper.required_one_of = req
- return helper
diff --git a/plugins/module_utils/network/routeros/__init__.py b/plugins/module_utils/network/routeros/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/routeros/routeros.py b/plugins/module_utils/network/routeros/routeros.py
deleted file mode 100644
index 63eb3c0470..0000000000
--- a/plugins/module_utils/network/routeros/routeros.py
+++ /dev/null
@@ -1,156 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# (c) 2016 Red Hat Inc.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-import json
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import env_fallback
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList
-from ansible.module_utils.connection import Connection, ConnectionError
-
-_DEVICE_CONFIGS = {}
-
-routeros_provider_spec = {
- 'host': dict(),
- 'port': dict(type='int'),
- 'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
- 'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True),
- 'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
- 'timeout': dict(type='int')
-}
-routeros_argument_spec = {}
-
-
-def get_provider_argspec():
- return routeros_provider_spec
-
-
-def get_connection(module):
- if hasattr(module, '_routeros_connection'):
- return module._routeros_connection
-
- capabilities = get_capabilities(module)
- network_api = capabilities.get('network_api')
- if network_api == 'cliconf':
- module._routeros_connection = Connection(module._socket_path)
- else:
- module.fail_json(msg='Invalid connection type %s' % network_api)
-
- return module._routeros_connection
-
-
-def get_capabilities(module):
- if hasattr(module, '_routeros_capabilities'):
- return module._routeros_capabilities
-
- capabilities = Connection(module._socket_path).get_capabilities()
- module._routeros_capabilities = json.loads(capabilities)
- return module._routeros_capabilities
-
-
-def get_defaults_flag(module):
- connection = get_connection(module)
-
- try:
- out = connection.get('/system default-configuration print')
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
-
- out = to_text(out, errors='surrogate_then_replace')
-
- commands = set()
- for line in out.splitlines():
- if line.strip():
- commands.add(line.strip().split()[0])
-
- if 'all' in commands:
- return ['all']
- else:
- return ['full']
-
-
-def get_config(module, flags=None):
- flag_str = ' '.join(to_list(flags))
-
- try:
- return _DEVICE_CONFIGS[flag_str]
- except KeyError:
- connection = get_connection(module)
-
- try:
- out = connection.get_config(flags=flags)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
-
- cfg = to_text(out, errors='surrogate_then_replace').strip()
- _DEVICE_CONFIGS[flag_str] = cfg
- return cfg
-
-
-def to_commands(module, commands):
- spec = {
- 'command': dict(key=True),
- 'prompt': dict(),
- 'answer': dict()
- }
- transform = ComplexList(spec, module)
- return transform(commands)
-
-
-def run_commands(module, commands, check_rc=True):
- responses = list()
- connection = get_connection(module)
-
- for cmd in to_list(commands):
- if isinstance(cmd, dict):
- command = cmd['command']
- prompt = cmd['prompt']
- answer = cmd['answer']
- else:
- command = cmd
- prompt = None
- answer = None
-
- try:
- out = connection.get(command, prompt, answer)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
-
- try:
- out = to_text(out, errors='surrogate_or_strict')
- except UnicodeError:
- module.fail_json(
- msg=u'Failed to decode output from %s: %s' % (cmd, to_text(out)))
-
- responses.append(out)
-
- return responses
-
-
-def load_config(module, commands):
- connection = get_connection(module)
-
- out = connection.edit_config(commands)
diff --git a/plugins/module_utils/network/slxos/__init__.py b/plugins/module_utils/network/slxos/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/slxos/slxos.py b/plugins/module_utils/network/slxos/slxos.py
deleted file mode 100644
index d9971840de..0000000000
--- a/plugins/module_utils/network/slxos/slxos.py
+++ /dev/null
@@ -1,148 +0,0 @@
-#
-# (c) 2018 Extreme Networks Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-import json
-from ansible.module_utils._text import to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList
-from ansible.module_utils.connection import Connection
-
-
-def get_connection(module):
- """Get switch connection
-
- Creates reusable SSH connection to the switch described in a given module.
-
- Args:
- module: A valid AnsibleModule instance.
-
- Returns:
- An instance of `ansible.module_utils.connection.Connection` with a
- connection to the switch described in the provided module.
-
- Raises:
- AnsibleConnectionFailure: An error occurred connecting to the device
- """
- if hasattr(module, 'slxos_connection'):
- return module.slxos_connection
-
- capabilities = get_capabilities(module)
- network_api = capabilities.get('network_api')
- if network_api == 'cliconf':
- module.slxos_connection = Connection(module._socket_path)
- else:
- module.fail_json(msg='Invalid connection type %s' % network_api)
-
- return module.slxos_connection
-
-
-def get_capabilities(module):
- """Get switch capabilities
-
- Collects and returns a python object with the switch capabilities.
-
- Args:
- module: A valid AnsibleModule instance.
-
- Returns:
- A dictionary containing the switch capabilities.
- """
- if hasattr(module, 'slxos_capabilities'):
- return module.slxos_capabilities
-
- capabilities = Connection(module._socket_path).get_capabilities()
- module.slxos_capabilities = json.loads(capabilities)
- return module.slxos_capabilities
-
-
-def run_commands(module, commands):
- """Run command list against connection.
-
- Get new or previously used connection and send commands to it one at a time,
- collecting response.
-
- Args:
- module: A valid AnsibleModule instance.
- commands: Iterable of command strings.
-
- Returns:
- A list of output strings.
- """
- responses = list()
- connection = get_connection(module)
-
- for cmd in to_list(commands):
- if isinstance(cmd, dict):
- command = cmd['command']
- prompt = cmd['prompt']
- answer = cmd['answer']
- else:
- command = cmd
- prompt = None
- answer = None
-
- out = connection.get(command, prompt, answer)
-
- try:
- out = to_text(out, errors='surrogate_or_strict')
- except UnicodeError:
- module.fail_json(msg=u'Failed to decode output from %s: %s' % (cmd, to_text(out)))
-
- responses.append(out)
-
- return responses
-
-
-def get_config(module):
- """Get switch configuration
-
- Gets the described device's current configuration. If a configuration has
- already been retrieved it will return the previously obtained configuration.
-
- Args:
- module: A valid AnsibleModule instance.
-
- Returns:
- A string containing the configuration.
- """
- if not hasattr(module, 'device_configs'):
- module.device_configs = {}
- elif module.device_configs != {}:
- return module.device_configs
-
- connection = get_connection(module)
- out = connection.get_config()
- cfg = to_text(out, errors='surrogate_then_replace').strip()
- module.device_configs = cfg
- return cfg
-
-
-def load_config(module, commands):
- """Apply a list of commands to a device.
-
- Given a list of commands apply them to the device to modify the
- configuration in bulk.
-
- Args:
- module: A valid AnsibleModule instance.
- commands: Iterable of command strings.
-
- Returns:
- None
- """
- connection = get_connection(module)
- connection.edit_config(commands)
diff --git a/plugins/module_utils/network/sros/__init__.py b/plugins/module_utils/network/sros/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/sros/sros.py b/plugins/module_utils/network/sros/sros.py
deleted file mode 100644
index 4bbce73903..0000000000
--- a/plugins/module_utils/network/sros/sros.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# Copyright (c) 2016 Peter Sprygada,
-#
-# Redistribution and use in source and binary forms, with or without
-# modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright
-# notice,
-# this list of conditions and the following disclaimer in the
-# documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-import re
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import env_fallback
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList
-from ansible.module_utils.connection import exec_command
-
-_DEVICE_CONFIGS = {}
-
-sros_provider_spec = {
- 'host': dict(),
- 'port': dict(type='int'),
- 'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
- 'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True),
- 'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
- 'timeout': dict(type='int'),
-}
-sros_argument_spec = {
- 'provider': dict(type='dict', options=sros_provider_spec),
-}
-sros_top_spec = {
- 'host': dict(removed_in_version=2.9),
- 'port': dict(removed_in_version=2.9, type='int'),
- 'username': dict(removed_in_version=2.9),
- 'password': dict(removed_in_version=2.9, no_log=True),
- 'ssh_keyfile': dict(removed_in_version=2.9, type='path'),
- 'timeout': dict(removed_in_version=2.9, type='int'),
-}
-sros_argument_spec.update(sros_top_spec)
-
-
-def check_args(module, warnings):
- pass
-
-
-def get_config(module, flags=None):
- flags = [] if flags is None else flags
-
- cmd = 'admin display-config '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- try:
- return _DEVICE_CONFIGS[cmd]
- except KeyError:
- rc, out, err = exec_command(module, cmd)
- if rc != 0:
- module.fail_json(msg='unable to retrieve current config', stderr=to_text(err, errors='surrogate_or_strict'))
- cfg = to_text(out, errors='surrogate_or_strict').strip()
- _DEVICE_CONFIGS[cmd] = cfg
- return cfg
-
-
-def to_commands(module, commands):
- spec = {
- 'command': dict(key=True),
- 'prompt': dict(),
- 'answer': dict()
- }
- transform = ComplexList(spec, module)
- return transform(commands)
-
-
-def run_commands(module, commands, check_rc=True):
- responses = list()
- commands = to_commands(module, to_list(commands))
- for cmd in commands:
- cmd = module.jsonify(cmd)
- rc, out, err = exec_command(module, cmd)
- if check_rc and rc != 0:
- module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), rc=rc)
- responses.append(to_text(out, errors='surrogate_or_strict'))
- return responses
-
-
-def load_config(module, commands):
- for command in to_list(commands):
- rc, out, err = exec_command(module, command)
- if rc != 0:
- module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), command=command, rc=rc)
- exec_command(module, 'exit all')
diff --git a/plugins/module_utils/network/voss/__init__.py b/plugins/module_utils/network/voss/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/module_utils/network/voss/voss.py b/plugins/module_utils/network/voss/voss.py
deleted file mode 100644
index 0de269e440..0000000000
--- a/plugins/module_utils/network/voss/voss.py
+++ /dev/null
@@ -1,219 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# (c) 2018 Extreme Networks Inc.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-import json
-import re
-
-from ansible.module_utils._text import to_native, to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList
-from ansible.module_utils.connection import Connection, ConnectionError
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, ConfigLine
-
-_DEVICE_CONFIGS = {}
-
-DEFAULT_COMMENT_TOKENS = ['#', '!', '/*', '*/', 'echo']
-
-DEFAULT_IGNORE_LINES_RE = set([
- re.compile(r"Preparing to Display Configuration\.\.\.")
-])
-
-
-def get_connection(module):
- if hasattr(module, '_voss_connection'):
- return module._voss_connection
-
- capabilities = get_capabilities(module)
- network_api = capabilities.get('network_api')
- if network_api == 'cliconf':
- module._voss_connection = Connection(module._socket_path)
- else:
- module.fail_json(msg='Invalid connection type %s' % network_api)
-
- return module._voss_connection
-
-
-def get_capabilities(module):
- if hasattr(module, '_voss_capabilities'):
- return module._voss_capabilities
- try:
- capabilities = Connection(module._socket_path).get_capabilities()
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- module._voss_capabilities = json.loads(capabilities)
- return module._voss_capabilities
-
-
-def get_defaults_flag(module):
- connection = get_connection(module)
- try:
- out = connection.get_defaults_flag()
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- return to_text(out, errors='surrogate_then_replace').strip()
-
-
-def get_config(module, source='running', flags=None):
- flag_str = ' '.join(to_list(flags))
-
- try:
- return _DEVICE_CONFIGS[flag_str]
- except KeyError:
- connection = get_connection(module)
- try:
- out = connection.get_config(source=source, flags=flags)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- cfg = to_text(out, errors='surrogate_then_replace').strip()
- _DEVICE_CONFIGS[flag_str] = cfg
- return cfg
-
-
-def to_commands(module, commands):
- spec = {
- 'command': dict(key=True),
- 'prompt': dict(),
- 'answer': dict()
- }
- transform = ComplexList(spec, module)
- return transform(commands)
-
-
-def run_commands(module, commands, check_rc=True):
- connection = get_connection(module)
- try:
- out = connection.run_commands(commands=commands, check_rc=check_rc)
- return out
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
-
-
-def load_config(module, commands):
- connection = get_connection(module)
-
- try:
- resp = connection.edit_config(commands)
- return resp.get('response')
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
-
-
-def get_sublevel_config(running_config, module):
- contents = list()
- current_config_contents = list()
- sublevel_config = VossNetworkConfig(indent=0)
- obj = running_config.get_object(module.params['parents'])
- if obj:
- contents = obj._children
- for c in contents:
- if isinstance(c, ConfigLine):
- current_config_contents.append(c.raw)
- sublevel_config.add(current_config_contents, module.params['parents'])
- return sublevel_config
-
-
-def ignore_line(text, tokens=None):
- for item in (tokens or DEFAULT_COMMENT_TOKENS):
- if text.startswith(item):
- return True
- for regex in DEFAULT_IGNORE_LINES_RE:
- if regex.match(text):
- return True
-
-
-def voss_parse(lines, indent=None, comment_tokens=None):
- toplevel = re.compile(r'(^interface.*$)|(^router \w+$)|(^router vrf \w+$)')
- exitline = re.compile(r'^exit$')
- entry_reg = re.compile(r'([{};])')
-
- ancestors = list()
- config = list()
- dup_parent_index = None
-
- for line in to_native(lines, errors='surrogate_or_strict').split('\n'):
- text = entry_reg.sub('', line).strip()
-
- cfg = ConfigLine(text)
-
- if not text or ignore_line(text, comment_tokens):
- continue
-
- # Handle top level commands
- if toplevel.match(text):
- # Looking to see if we have existing parent
- for index, item in enumerate(config):
- if item.text == text:
- # This means we have an existing parent with same label
- dup_parent_index = index
- break
- ancestors = [cfg]
- config.append(cfg)
-
- # Handle 'exit' line
- elif exitline.match(text):
- ancestors = list()
-
- if dup_parent_index is not None:
- # We're working with a duplicate parent
- # Don't need to store exit, just go to next line in config
- dup_parent_index = None
- else:
- cfg._parents = ancestors[:1]
- config.append(cfg)
-
- # Handle sub-level commands. Only have single sub-level
- elif ancestors:
- cfg._parents = ancestors[:1]
- if dup_parent_index is not None:
- # Update existing entry, since this already exists in config
- config[int(dup_parent_index)].add_child(cfg)
- new_index = dup_parent_index + 1
- config.insert(new_index, cfg)
- else:
- ancestors[0].add_child(cfg)
- config.append(cfg)
-
- else:
- # Global command, no further special handling needed
- config.append(cfg)
- return config
-
-
-class VossNetworkConfig(NetworkConfig):
-
- def load(self, s):
- self._config_text = s
- self._items = voss_parse(s, self._indent)
-
- def _diff_line(self, other):
- updates = list()
- for item in self.items:
- if str(item) == "exit":
- if updates and updates[-1]._parents:
- updates.append(item)
- elif item not in other:
- updates.append(item)
- return updates
diff --git a/plugins/modules/a10_server.py b/plugins/modules/a10_server.py
deleted file mode 120000
index 99fd065069..0000000000
--- a/plugins/modules/a10_server.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/a10/a10_server.py
\ No newline at end of file
diff --git a/plugins/modules/a10_server_axapi3.py b/plugins/modules/a10_server_axapi3.py
deleted file mode 120000
index d1b24a82aa..0000000000
--- a/plugins/modules/a10_server_axapi3.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/a10/a10_server_axapi3.py
\ No newline at end of file
diff --git a/plugins/modules/a10_service_group.py b/plugins/modules/a10_service_group.py
deleted file mode 120000
index 423b0b7a5e..0000000000
--- a/plugins/modules/a10_service_group.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/a10/a10_service_group.py
\ No newline at end of file
diff --git a/plugins/modules/a10_virtual_server.py b/plugins/modules/a10_virtual_server.py
deleted file mode 120000
index 2ea33dccb7..0000000000
--- a/plugins/modules/a10_virtual_server.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/a10/a10_virtual_server.py
\ No newline at end of file
diff --git a/plugins/modules/aci_interface_policy_fc.py b/plugins/modules/aci_interface_policy_fc.py
deleted file mode 120000
index e1390129c5..0000000000
--- a/plugins/modules/aci_interface_policy_fc.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/aci/aci_interface_policy_fc.py
\ No newline at end of file
diff --git a/plugins/modules/aci_interface_policy_l2.py b/plugins/modules/aci_interface_policy_l2.py
deleted file mode 120000
index cecdeeaa61..0000000000
--- a/plugins/modules/aci_interface_policy_l2.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/aci/aci_interface_policy_l2.py
\ No newline at end of file
diff --git a/plugins/modules/aci_interface_policy_lldp.py b/plugins/modules/aci_interface_policy_lldp.py
deleted file mode 120000
index 5b37254528..0000000000
--- a/plugins/modules/aci_interface_policy_lldp.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/aci/aci_interface_policy_lldp.py
\ No newline at end of file
diff --git a/plugins/modules/aci_interface_policy_mcp.py b/plugins/modules/aci_interface_policy_mcp.py
deleted file mode 120000
index 9e17981928..0000000000
--- a/plugins/modules/aci_interface_policy_mcp.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/aci/aci_interface_policy_mcp.py
\ No newline at end of file
diff --git a/plugins/modules/aci_interface_policy_port_channel.py b/plugins/modules/aci_interface_policy_port_channel.py
deleted file mode 120000
index ea297f0714..0000000000
--- a/plugins/modules/aci_interface_policy_port_channel.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/aci/aci_interface_policy_port_channel.py
\ No newline at end of file
diff --git a/plugins/modules/aci_interface_policy_port_security.py b/plugins/modules/aci_interface_policy_port_security.py
deleted file mode 120000
index 214bdc11df..0000000000
--- a/plugins/modules/aci_interface_policy_port_security.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/aci/aci_interface_policy_port_security.py
\ No newline at end of file
diff --git a/plugins/modules/aireos_command.py b/plugins/modules/aireos_command.py
deleted file mode 120000
index 03f4c2f9dc..0000000000
--- a/plugins/modules/aireos_command.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/aireos/aireos_command.py
\ No newline at end of file
diff --git a/plugins/modules/aireos_config.py b/plugins/modules/aireos_config.py
deleted file mode 120000
index ed05f96c95..0000000000
--- a/plugins/modules/aireos_config.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/aireos/aireos_config.py
\ No newline at end of file
diff --git a/plugins/modules/apconos_command.py b/plugins/modules/apconos_command.py
deleted file mode 120000
index ef8172f4f1..0000000000
--- a/plugins/modules/apconos_command.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/apconos/apconos_command.py
\ No newline at end of file
diff --git a/plugins/modules/aruba_command.py b/plugins/modules/aruba_command.py
deleted file mode 120000
index fa7d70fcbd..0000000000
--- a/plugins/modules/aruba_command.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/aruba/aruba_command.py
\ No newline at end of file
diff --git a/plugins/modules/aruba_config.py b/plugins/modules/aruba_config.py
deleted file mode 120000
index 269a7038b7..0000000000
--- a/plugins/modules/aruba_config.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/aruba/aruba_config.py
\ No newline at end of file
diff --git a/plugins/modules/avi_actiongroupconfig.py b/plugins/modules/avi_actiongroupconfig.py
deleted file mode 120000
index 84caa3c14e..0000000000
--- a/plugins/modules/avi_actiongroupconfig.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_actiongroupconfig.py
\ No newline at end of file
diff --git a/plugins/modules/avi_alertconfig.py b/plugins/modules/avi_alertconfig.py
deleted file mode 120000
index 42df98cc51..0000000000
--- a/plugins/modules/avi_alertconfig.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_alertconfig.py
\ No newline at end of file
diff --git a/plugins/modules/avi_alertemailconfig.py b/plugins/modules/avi_alertemailconfig.py
deleted file mode 120000
index 3ef61f542c..0000000000
--- a/plugins/modules/avi_alertemailconfig.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_alertemailconfig.py
\ No newline at end of file
diff --git a/plugins/modules/avi_alertscriptconfig.py b/plugins/modules/avi_alertscriptconfig.py
deleted file mode 120000
index 448dc7e2c6..0000000000
--- a/plugins/modules/avi_alertscriptconfig.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_alertscriptconfig.py
\ No newline at end of file
diff --git a/plugins/modules/avi_alertsyslogconfig.py b/plugins/modules/avi_alertsyslogconfig.py
deleted file mode 120000
index 0191598d40..0000000000
--- a/plugins/modules/avi_alertsyslogconfig.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_alertsyslogconfig.py
\ No newline at end of file
diff --git a/plugins/modules/avi_analyticsprofile.py b/plugins/modules/avi_analyticsprofile.py
deleted file mode 120000
index 146f3848d9..0000000000
--- a/plugins/modules/avi_analyticsprofile.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_analyticsprofile.py
\ No newline at end of file
diff --git a/plugins/modules/avi_api_session.py b/plugins/modules/avi_api_session.py
deleted file mode 120000
index c8fcc38c37..0000000000
--- a/plugins/modules/avi_api_session.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_api_session.py
\ No newline at end of file
diff --git a/plugins/modules/avi_api_version.py b/plugins/modules/avi_api_version.py
deleted file mode 120000
index 987b817a46..0000000000
--- a/plugins/modules/avi_api_version.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_api_version.py
\ No newline at end of file
diff --git a/plugins/modules/avi_applicationpersistenceprofile.py b/plugins/modules/avi_applicationpersistenceprofile.py
deleted file mode 120000
index 386672b470..0000000000
--- a/plugins/modules/avi_applicationpersistenceprofile.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_applicationpersistenceprofile.py
\ No newline at end of file
diff --git a/plugins/modules/avi_applicationprofile.py b/plugins/modules/avi_applicationprofile.py
deleted file mode 120000
index 5c66d51882..0000000000
--- a/plugins/modules/avi_applicationprofile.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_applicationprofile.py
\ No newline at end of file
diff --git a/plugins/modules/avi_authprofile.py b/plugins/modules/avi_authprofile.py
deleted file mode 120000
index d5a8fe4aa4..0000000000
--- a/plugins/modules/avi_authprofile.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_authprofile.py
\ No newline at end of file
diff --git a/plugins/modules/avi_autoscalelaunchconfig.py b/plugins/modules/avi_autoscalelaunchconfig.py
deleted file mode 120000
index 353ef3dbb6..0000000000
--- a/plugins/modules/avi_autoscalelaunchconfig.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_autoscalelaunchconfig.py
\ No newline at end of file
diff --git a/plugins/modules/avi_backup.py b/plugins/modules/avi_backup.py
deleted file mode 120000
index 7d24992bc7..0000000000
--- a/plugins/modules/avi_backup.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_backup.py
\ No newline at end of file
diff --git a/plugins/modules/avi_backupconfiguration.py b/plugins/modules/avi_backupconfiguration.py
deleted file mode 120000
index 539cd3543a..0000000000
--- a/plugins/modules/avi_backupconfiguration.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_backupconfiguration.py
\ No newline at end of file
diff --git a/plugins/modules/avi_certificatemanagementprofile.py b/plugins/modules/avi_certificatemanagementprofile.py
deleted file mode 120000
index 3b799bbae5..0000000000
--- a/plugins/modules/avi_certificatemanagementprofile.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_certificatemanagementprofile.py
\ No newline at end of file
diff --git a/plugins/modules/avi_cloud.py b/plugins/modules/avi_cloud.py
deleted file mode 120000
index 9b8b484630..0000000000
--- a/plugins/modules/avi_cloud.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_cloud.py
\ No newline at end of file
diff --git a/plugins/modules/avi_cloudconnectoruser.py b/plugins/modules/avi_cloudconnectoruser.py
deleted file mode 120000
index 7b6b034525..0000000000
--- a/plugins/modules/avi_cloudconnectoruser.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_cloudconnectoruser.py
\ No newline at end of file
diff --git a/plugins/modules/avi_cloudproperties.py b/plugins/modules/avi_cloudproperties.py
deleted file mode 120000
index 8dbec3a746..0000000000
--- a/plugins/modules/avi_cloudproperties.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_cloudproperties.py
\ No newline at end of file
diff --git a/plugins/modules/avi_cluster.py b/plugins/modules/avi_cluster.py
deleted file mode 120000
index c6f71755e8..0000000000
--- a/plugins/modules/avi_cluster.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_cluster.py
\ No newline at end of file
diff --git a/plugins/modules/avi_clusterclouddetails.py b/plugins/modules/avi_clusterclouddetails.py
deleted file mode 120000
index cc0d4856ef..0000000000
--- a/plugins/modules/avi_clusterclouddetails.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_clusterclouddetails.py
\ No newline at end of file
diff --git a/plugins/modules/avi_controllerproperties.py b/plugins/modules/avi_controllerproperties.py
deleted file mode 120000
index a7abc19bd0..0000000000
--- a/plugins/modules/avi_controllerproperties.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_controllerproperties.py
\ No newline at end of file
diff --git a/plugins/modules/avi_customipamdnsprofile.py b/plugins/modules/avi_customipamdnsprofile.py
deleted file mode 120000
index 572c54f0da..0000000000
--- a/plugins/modules/avi_customipamdnsprofile.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_customipamdnsprofile.py
\ No newline at end of file
diff --git a/plugins/modules/avi_dnspolicy.py b/plugins/modules/avi_dnspolicy.py
deleted file mode 120000
index af16af0fa6..0000000000
--- a/plugins/modules/avi_dnspolicy.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_dnspolicy.py
\ No newline at end of file
diff --git a/plugins/modules/avi_errorpagebody.py b/plugins/modules/avi_errorpagebody.py
deleted file mode 120000
index 41297c0eb1..0000000000
--- a/plugins/modules/avi_errorpagebody.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_errorpagebody.py
\ No newline at end of file
diff --git a/plugins/modules/avi_errorpageprofile.py b/plugins/modules/avi_errorpageprofile.py
deleted file mode 120000
index 832f151e4a..0000000000
--- a/plugins/modules/avi_errorpageprofile.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_errorpageprofile.py
\ No newline at end of file
diff --git a/plugins/modules/avi_gslb.py b/plugins/modules/avi_gslb.py
deleted file mode 120000
index 8303d3d01a..0000000000
--- a/plugins/modules/avi_gslb.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_gslb.py
\ No newline at end of file
diff --git a/plugins/modules/avi_gslbgeodbprofile.py b/plugins/modules/avi_gslbgeodbprofile.py
deleted file mode 120000
index e0dba0b569..0000000000
--- a/plugins/modules/avi_gslbgeodbprofile.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_gslbgeodbprofile.py
\ No newline at end of file
diff --git a/plugins/modules/avi_gslbservice.py b/plugins/modules/avi_gslbservice.py
deleted file mode 120000
index bf506833bd..0000000000
--- a/plugins/modules/avi_gslbservice.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_gslbservice.py
\ No newline at end of file
diff --git a/plugins/modules/avi_gslbservice_patch_member.py b/plugins/modules/avi_gslbservice_patch_member.py
deleted file mode 120000
index 8e565ff7df..0000000000
--- a/plugins/modules/avi_gslbservice_patch_member.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_gslbservice_patch_member.py
\ No newline at end of file
diff --git a/plugins/modules/avi_hardwaresecuritymodulegroup.py b/plugins/modules/avi_hardwaresecuritymodulegroup.py
deleted file mode 120000
index 4e53e1edce..0000000000
--- a/plugins/modules/avi_hardwaresecuritymodulegroup.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_hardwaresecuritymodulegroup.py
\ No newline at end of file
diff --git a/plugins/modules/avi_healthmonitor.py b/plugins/modules/avi_healthmonitor.py
deleted file mode 120000
index 37b015e75d..0000000000
--- a/plugins/modules/avi_healthmonitor.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_healthmonitor.py
\ No newline at end of file
diff --git a/plugins/modules/avi_httppolicyset.py b/plugins/modules/avi_httppolicyset.py
deleted file mode 120000
index 8e627d01fa..0000000000
--- a/plugins/modules/avi_httppolicyset.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_httppolicyset.py
\ No newline at end of file
diff --git a/plugins/modules/avi_ipaddrgroup.py b/plugins/modules/avi_ipaddrgroup.py
deleted file mode 120000
index d88d8f6110..0000000000
--- a/plugins/modules/avi_ipaddrgroup.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_ipaddrgroup.py
\ No newline at end of file
diff --git a/plugins/modules/avi_ipamdnsproviderprofile.py b/plugins/modules/avi_ipamdnsproviderprofile.py
deleted file mode 120000
index 9850e577e2..0000000000
--- a/plugins/modules/avi_ipamdnsproviderprofile.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_ipamdnsproviderprofile.py
\ No newline at end of file
diff --git a/plugins/modules/avi_l4policyset.py b/plugins/modules/avi_l4policyset.py
deleted file mode 120000
index 55c7a049e1..0000000000
--- a/plugins/modules/avi_l4policyset.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_l4policyset.py
\ No newline at end of file
diff --git a/plugins/modules/avi_microservicegroup.py b/plugins/modules/avi_microservicegroup.py
deleted file mode 120000
index e0477e46ec..0000000000
--- a/plugins/modules/avi_microservicegroup.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_microservicegroup.py
\ No newline at end of file
diff --git a/plugins/modules/avi_network.py b/plugins/modules/avi_network.py
deleted file mode 120000
index 191e944812..0000000000
--- a/plugins/modules/avi_network.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_network.py
\ No newline at end of file
diff --git a/plugins/modules/avi_networkprofile.py b/plugins/modules/avi_networkprofile.py
deleted file mode 120000
index b416bebcca..0000000000
--- a/plugins/modules/avi_networkprofile.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_networkprofile.py
\ No newline at end of file
diff --git a/plugins/modules/avi_networksecuritypolicy.py b/plugins/modules/avi_networksecuritypolicy.py
deleted file mode 120000
index 0e99b261ac..0000000000
--- a/plugins/modules/avi_networksecuritypolicy.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_networksecuritypolicy.py
\ No newline at end of file
diff --git a/plugins/modules/avi_pkiprofile.py b/plugins/modules/avi_pkiprofile.py
deleted file mode 120000
index 0d69e1ec5b..0000000000
--- a/plugins/modules/avi_pkiprofile.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_pkiprofile.py
\ No newline at end of file
diff --git a/plugins/modules/avi_pool.py b/plugins/modules/avi_pool.py
deleted file mode 120000
index 4c7b4d5335..0000000000
--- a/plugins/modules/avi_pool.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_pool.py
\ No newline at end of file
diff --git a/plugins/modules/avi_poolgroup.py b/plugins/modules/avi_poolgroup.py
deleted file mode 120000
index 743581442f..0000000000
--- a/plugins/modules/avi_poolgroup.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_poolgroup.py
\ No newline at end of file
diff --git a/plugins/modules/avi_poolgroupdeploymentpolicy.py b/plugins/modules/avi_poolgroupdeploymentpolicy.py
deleted file mode 120000
index 53e56e7816..0000000000
--- a/plugins/modules/avi_poolgroupdeploymentpolicy.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_poolgroupdeploymentpolicy.py
\ No newline at end of file
diff --git a/plugins/modules/avi_prioritylabels.py b/plugins/modules/avi_prioritylabels.py
deleted file mode 120000
index 9d8790b5b0..0000000000
--- a/plugins/modules/avi_prioritylabels.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_prioritylabels.py
\ No newline at end of file
diff --git a/plugins/modules/avi_role.py b/plugins/modules/avi_role.py
deleted file mode 120000
index 284e9a8bb2..0000000000
--- a/plugins/modules/avi_role.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_role.py
\ No newline at end of file
diff --git a/plugins/modules/avi_scheduler.py b/plugins/modules/avi_scheduler.py
deleted file mode 120000
index 1be9d96850..0000000000
--- a/plugins/modules/avi_scheduler.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_scheduler.py
\ No newline at end of file
diff --git a/plugins/modules/avi_seproperties.py b/plugins/modules/avi_seproperties.py
deleted file mode 120000
index 0a4857945b..0000000000
--- a/plugins/modules/avi_seproperties.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_seproperties.py
\ No newline at end of file
diff --git a/plugins/modules/avi_serverautoscalepolicy.py b/plugins/modules/avi_serverautoscalepolicy.py
deleted file mode 120000
index 43195a3fe9..0000000000
--- a/plugins/modules/avi_serverautoscalepolicy.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_serverautoscalepolicy.py
\ No newline at end of file
diff --git a/plugins/modules/avi_serviceengine.py b/plugins/modules/avi_serviceengine.py
deleted file mode 120000
index f465dab512..0000000000
--- a/plugins/modules/avi_serviceengine.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_serviceengine.py
\ No newline at end of file
diff --git a/plugins/modules/avi_serviceenginegroup.py b/plugins/modules/avi_serviceenginegroup.py
deleted file mode 120000
index a2b01114b3..0000000000
--- a/plugins/modules/avi_serviceenginegroup.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_serviceenginegroup.py
\ No newline at end of file
diff --git a/plugins/modules/avi_snmptrapprofile.py b/plugins/modules/avi_snmptrapprofile.py
deleted file mode 120000
index c2adc10307..0000000000
--- a/plugins/modules/avi_snmptrapprofile.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_snmptrapprofile.py
\ No newline at end of file
diff --git a/plugins/modules/avi_sslkeyandcertificate.py b/plugins/modules/avi_sslkeyandcertificate.py
deleted file mode 120000
index 9e623b82b0..0000000000
--- a/plugins/modules/avi_sslkeyandcertificate.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_sslkeyandcertificate.py
\ No newline at end of file
diff --git a/plugins/modules/avi_sslprofile.py b/plugins/modules/avi_sslprofile.py
deleted file mode 120000
index 4b6d15d032..0000000000
--- a/plugins/modules/avi_sslprofile.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_sslprofile.py
\ No newline at end of file
diff --git a/plugins/modules/avi_stringgroup.py b/plugins/modules/avi_stringgroup.py
deleted file mode 120000
index 63d5e4e5fa..0000000000
--- a/plugins/modules/avi_stringgroup.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_stringgroup.py
\ No newline at end of file
diff --git a/plugins/modules/avi_systemconfiguration.py b/plugins/modules/avi_systemconfiguration.py
deleted file mode 120000
index 70c77b6fbb..0000000000
--- a/plugins/modules/avi_systemconfiguration.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_systemconfiguration.py
\ No newline at end of file
diff --git a/plugins/modules/avi_tenant.py b/plugins/modules/avi_tenant.py
deleted file mode 120000
index 4ae0dd1086..0000000000
--- a/plugins/modules/avi_tenant.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_tenant.py
\ No newline at end of file
diff --git a/plugins/modules/avi_trafficcloneprofile.py b/plugins/modules/avi_trafficcloneprofile.py
deleted file mode 120000
index 905e20481e..0000000000
--- a/plugins/modules/avi_trafficcloneprofile.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_trafficcloneprofile.py
\ No newline at end of file
diff --git a/plugins/modules/avi_user.py b/plugins/modules/avi_user.py
deleted file mode 120000
index 6868e4e14e..0000000000
--- a/plugins/modules/avi_user.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_user.py
\ No newline at end of file
diff --git a/plugins/modules/avi_useraccount.py b/plugins/modules/avi_useraccount.py
deleted file mode 120000
index 33c782d5c9..0000000000
--- a/plugins/modules/avi_useraccount.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_useraccount.py
\ No newline at end of file
diff --git a/plugins/modules/avi_useraccountprofile.py b/plugins/modules/avi_useraccountprofile.py
deleted file mode 120000
index c6eb252d02..0000000000
--- a/plugins/modules/avi_useraccountprofile.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_useraccountprofile.py
\ No newline at end of file
diff --git a/plugins/modules/avi_virtualservice.py b/plugins/modules/avi_virtualservice.py
deleted file mode 120000
index 554185407d..0000000000
--- a/plugins/modules/avi_virtualservice.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_virtualservice.py
\ No newline at end of file
diff --git a/plugins/modules/avi_vrfcontext.py b/plugins/modules/avi_vrfcontext.py
deleted file mode 120000
index 5c7bb937fe..0000000000
--- a/plugins/modules/avi_vrfcontext.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_vrfcontext.py
\ No newline at end of file
diff --git a/plugins/modules/avi_vsdatascriptset.py b/plugins/modules/avi_vsdatascriptset.py
deleted file mode 120000
index 9a683f5e05..0000000000
--- a/plugins/modules/avi_vsdatascriptset.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_vsdatascriptset.py
\ No newline at end of file
diff --git a/plugins/modules/avi_vsvip.py b/plugins/modules/avi_vsvip.py
deleted file mode 120000
index 9e8a063f4d..0000000000
--- a/plugins/modules/avi_vsvip.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_vsvip.py
\ No newline at end of file
diff --git a/plugins/modules/avi_webhook.py b/plugins/modules/avi_webhook.py
deleted file mode 120000
index 2e5dcf4a38..0000000000
--- a/plugins/modules/avi_webhook.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/avi/avi_webhook.py
\ No newline at end of file
diff --git a/plugins/modules/bcf_switch.py b/plugins/modules/bcf_switch.py
deleted file mode 120000
index 374b19d591..0000000000
--- a/plugins/modules/bcf_switch.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/bigswitch/bcf_switch.py
\ No newline at end of file
diff --git a/plugins/modules/bigip_asm_policy.py b/plugins/modules/bigip_asm_policy.py
deleted file mode 120000
index 0eecd61082..0000000000
--- a/plugins/modules/bigip_asm_policy.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/f5/bigip_asm_policy.py
\ No newline at end of file
diff --git a/plugins/modules/bigip_device_info.py b/plugins/modules/bigip_device_info.py
deleted file mode 120000
index 45c144358e..0000000000
--- a/plugins/modules/bigip_device_info.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/f5/bigip_device_info.py
\ No newline at end of file
diff --git a/plugins/modules/bigip_device_traffic_group.py b/plugins/modules/bigip_device_traffic_group.py
deleted file mode 120000
index 0c80b87f6b..0000000000
--- a/plugins/modules/bigip_device_traffic_group.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/f5/bigip_device_traffic_group.py
\ No newline at end of file
diff --git a/plugins/modules/bigip_facts.py b/plugins/modules/bigip_facts.py
deleted file mode 120000
index a8038eeab5..0000000000
--- a/plugins/modules/bigip_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/f5/bigip_facts.py
\ No newline at end of file
diff --git a/plugins/modules/bigip_firewall_address_list.py b/plugins/modules/bigip_firewall_address_list.py
deleted file mode 120000
index 71634ff950..0000000000
--- a/plugins/modules/bigip_firewall_address_list.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/f5/bigip_firewall_address_list.py
\ No newline at end of file
diff --git a/plugins/modules/bigip_firewall_port_list.py b/plugins/modules/bigip_firewall_port_list.py
deleted file mode 120000
index a1e0da8f1c..0000000000
--- a/plugins/modules/bigip_firewall_port_list.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/f5/bigip_firewall_port_list.py
\ No newline at end of file
diff --git a/plugins/modules/bigip_gtm_facts.py b/plugins/modules/bigip_gtm_facts.py
deleted file mode 120000
index b18537ce3f..0000000000
--- a/plugins/modules/bigip_gtm_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/f5/bigip_gtm_facts.py
\ No newline at end of file
diff --git a/plugins/modules/bigip_lx_package.py b/plugins/modules/bigip_lx_package.py
deleted file mode 120000
index 712175a9bf..0000000000
--- a/plugins/modules/bigip_lx_package.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/f5/bigip_lx_package.py
\ No newline at end of file
diff --git a/plugins/modules/bigiq_device_info.py b/plugins/modules/bigiq_device_info.py
deleted file mode 120000
index 589fb5afc8..0000000000
--- a/plugins/modules/bigiq_device_info.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/f5/bigiq_device_info.py
\ No newline at end of file
diff --git a/plugins/modules/bigmon_chain.py b/plugins/modules/bigmon_chain.py
deleted file mode 120000
index 849bf2f6de..0000000000
--- a/plugins/modules/bigmon_chain.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/bigswitch/bigmon_chain.py
\ No newline at end of file
diff --git a/plugins/modules/bigmon_policy.py b/plugins/modules/bigmon_policy.py
deleted file mode 120000
index de140bab6c..0000000000
--- a/plugins/modules/bigmon_policy.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/bigswitch/bigmon_policy.py
\ No newline at end of file
diff --git a/plugins/modules/ce_aaa_server.py b/plugins/modules/ce_aaa_server.py
deleted file mode 120000
index 29e9b5301b..0000000000
--- a/plugins/modules/ce_aaa_server.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_aaa_server.py
\ No newline at end of file
diff --git a/plugins/modules/ce_aaa_server_host.py b/plugins/modules/ce_aaa_server_host.py
deleted file mode 120000
index a2b8f01d10..0000000000
--- a/plugins/modules/ce_aaa_server_host.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_aaa_server_host.py
\ No newline at end of file
diff --git a/plugins/modules/ce_acl.py b/plugins/modules/ce_acl.py
deleted file mode 120000
index 5d83d9afec..0000000000
--- a/plugins/modules/ce_acl.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_acl.py
\ No newline at end of file
diff --git a/plugins/modules/ce_acl_advance.py b/plugins/modules/ce_acl_advance.py
deleted file mode 120000
index e46f738617..0000000000
--- a/plugins/modules/ce_acl_advance.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_acl_advance.py
\ No newline at end of file
diff --git a/plugins/modules/ce_acl_interface.py b/plugins/modules/ce_acl_interface.py
deleted file mode 120000
index 2abd3140b4..0000000000
--- a/plugins/modules/ce_acl_interface.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_acl_interface.py
\ No newline at end of file
diff --git a/plugins/modules/ce_bfd_global.py b/plugins/modules/ce_bfd_global.py
deleted file mode 120000
index 34f873f45c..0000000000
--- a/plugins/modules/ce_bfd_global.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_bfd_global.py
\ No newline at end of file
diff --git a/plugins/modules/ce_bfd_session.py b/plugins/modules/ce_bfd_session.py
deleted file mode 120000
index 28aa41749a..0000000000
--- a/plugins/modules/ce_bfd_session.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_bfd_session.py
\ No newline at end of file
diff --git a/plugins/modules/ce_bfd_view.py b/plugins/modules/ce_bfd_view.py
deleted file mode 120000
index d11fe25051..0000000000
--- a/plugins/modules/ce_bfd_view.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_bfd_view.py
\ No newline at end of file
diff --git a/plugins/modules/ce_bgp.py b/plugins/modules/ce_bgp.py
deleted file mode 120000
index cc0294c2dc..0000000000
--- a/plugins/modules/ce_bgp.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_bgp.py
\ No newline at end of file
diff --git a/plugins/modules/ce_bgp_af.py b/plugins/modules/ce_bgp_af.py
deleted file mode 120000
index 3fcd850f3f..0000000000
--- a/plugins/modules/ce_bgp_af.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_bgp_af.py
\ No newline at end of file
diff --git a/plugins/modules/ce_bgp_neighbor.py b/plugins/modules/ce_bgp_neighbor.py
deleted file mode 120000
index c4adea5e39..0000000000
--- a/plugins/modules/ce_bgp_neighbor.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_bgp_neighbor.py
\ No newline at end of file
diff --git a/plugins/modules/ce_bgp_neighbor_af.py b/plugins/modules/ce_bgp_neighbor_af.py
deleted file mode 120000
index 765d9b7d63..0000000000
--- a/plugins/modules/ce_bgp_neighbor_af.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_bgp_neighbor_af.py
\ No newline at end of file
diff --git a/plugins/modules/ce_command.py b/plugins/modules/ce_command.py
deleted file mode 120000
index 1662530542..0000000000
--- a/plugins/modules/ce_command.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_command.py
\ No newline at end of file
diff --git a/plugins/modules/ce_config.py b/plugins/modules/ce_config.py
deleted file mode 120000
index 4ebe1271fc..0000000000
--- a/plugins/modules/ce_config.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_config.py
\ No newline at end of file
diff --git a/plugins/modules/ce_dldp.py b/plugins/modules/ce_dldp.py
deleted file mode 120000
index fb467a9527..0000000000
--- a/plugins/modules/ce_dldp.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_dldp.py
\ No newline at end of file
diff --git a/plugins/modules/ce_dldp_interface.py b/plugins/modules/ce_dldp_interface.py
deleted file mode 120000
index d2fcd41442..0000000000
--- a/plugins/modules/ce_dldp_interface.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_dldp_interface.py
\ No newline at end of file
diff --git a/plugins/modules/ce_eth_trunk.py b/plugins/modules/ce_eth_trunk.py
deleted file mode 120000
index 0726398a7e..0000000000
--- a/plugins/modules/ce_eth_trunk.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_eth_trunk.py
\ No newline at end of file
diff --git a/plugins/modules/ce_evpn_bd_vni.py b/plugins/modules/ce_evpn_bd_vni.py
deleted file mode 120000
index e4189d8a07..0000000000
--- a/plugins/modules/ce_evpn_bd_vni.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_evpn_bd_vni.py
\ No newline at end of file
diff --git a/plugins/modules/ce_evpn_bgp.py b/plugins/modules/ce_evpn_bgp.py
deleted file mode 120000
index 337478cfb8..0000000000
--- a/plugins/modules/ce_evpn_bgp.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_evpn_bgp.py
\ No newline at end of file
diff --git a/plugins/modules/ce_evpn_bgp_rr.py b/plugins/modules/ce_evpn_bgp_rr.py
deleted file mode 120000
index a21bf94464..0000000000
--- a/plugins/modules/ce_evpn_bgp_rr.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_evpn_bgp_rr.py
\ No newline at end of file
diff --git a/plugins/modules/ce_evpn_global.py b/plugins/modules/ce_evpn_global.py
deleted file mode 120000
index a1dc809de9..0000000000
--- a/plugins/modules/ce_evpn_global.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_evpn_global.py
\ No newline at end of file
diff --git a/plugins/modules/ce_facts.py b/plugins/modules/ce_facts.py
deleted file mode 120000
index a918251a12..0000000000
--- a/plugins/modules/ce_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_facts.py
\ No newline at end of file
diff --git a/plugins/modules/ce_file_copy.py b/plugins/modules/ce_file_copy.py
deleted file mode 120000
index cad0b3db10..0000000000
--- a/plugins/modules/ce_file_copy.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_file_copy.py
\ No newline at end of file
diff --git a/plugins/modules/ce_info_center_debug.py b/plugins/modules/ce_info_center_debug.py
deleted file mode 120000
index decc9d6276..0000000000
--- a/plugins/modules/ce_info_center_debug.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_info_center_debug.py
\ No newline at end of file
diff --git a/plugins/modules/ce_info_center_global.py b/plugins/modules/ce_info_center_global.py
deleted file mode 120000
index 1b7e46a5ae..0000000000
--- a/plugins/modules/ce_info_center_global.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_info_center_global.py
\ No newline at end of file
diff --git a/plugins/modules/ce_info_center_log.py b/plugins/modules/ce_info_center_log.py
deleted file mode 120000
index f1bb1149ac..0000000000
--- a/plugins/modules/ce_info_center_log.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_info_center_log.py
\ No newline at end of file
diff --git a/plugins/modules/ce_info_center_trap.py b/plugins/modules/ce_info_center_trap.py
deleted file mode 120000
index b3e89dfd56..0000000000
--- a/plugins/modules/ce_info_center_trap.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_info_center_trap.py
\ No newline at end of file
diff --git a/plugins/modules/ce_interface.py b/plugins/modules/ce_interface.py
deleted file mode 120000
index 596a9dee5d..0000000000
--- a/plugins/modules/ce_interface.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_interface.py
\ No newline at end of file
diff --git a/plugins/modules/ce_interface_ospf.py b/plugins/modules/ce_interface_ospf.py
deleted file mode 120000
index 0c88a16d40..0000000000
--- a/plugins/modules/ce_interface_ospf.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_interface_ospf.py
\ No newline at end of file
diff --git a/plugins/modules/ce_ip_interface.py b/plugins/modules/ce_ip_interface.py
deleted file mode 120000
index 9a191b3a82..0000000000
--- a/plugins/modules/ce_ip_interface.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_ip_interface.py
\ No newline at end of file
diff --git a/plugins/modules/ce_is_is_instance.py b/plugins/modules/ce_is_is_instance.py
deleted file mode 120000
index 4ac23b113c..0000000000
--- a/plugins/modules/ce_is_is_instance.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_is_is_instance.py
\ No newline at end of file
diff --git a/plugins/modules/ce_is_is_interface.py b/plugins/modules/ce_is_is_interface.py
deleted file mode 120000
index d75b377d5a..0000000000
--- a/plugins/modules/ce_is_is_interface.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_is_is_interface.py
\ No newline at end of file
diff --git a/plugins/modules/ce_is_is_view.py b/plugins/modules/ce_is_is_view.py
deleted file mode 120000
index 24a5c272d5..0000000000
--- a/plugins/modules/ce_is_is_view.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_is_is_view.py
\ No newline at end of file
diff --git a/plugins/modules/ce_lacp.py b/plugins/modules/ce_lacp.py
deleted file mode 120000
index da54997b1b..0000000000
--- a/plugins/modules/ce_lacp.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_lacp.py
\ No newline at end of file
diff --git a/plugins/modules/ce_link_status.py b/plugins/modules/ce_link_status.py
deleted file mode 120000
index 20c075c484..0000000000
--- a/plugins/modules/ce_link_status.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_link_status.py
\ No newline at end of file
diff --git a/plugins/modules/ce_lldp.py b/plugins/modules/ce_lldp.py
deleted file mode 120000
index 5c2b88a2b6..0000000000
--- a/plugins/modules/ce_lldp.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_lldp.py
\ No newline at end of file
diff --git a/plugins/modules/ce_lldp_interface.py b/plugins/modules/ce_lldp_interface.py
deleted file mode 120000
index 2a2e4be1e3..0000000000
--- a/plugins/modules/ce_lldp_interface.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_lldp_interface.py
\ No newline at end of file
diff --git a/plugins/modules/ce_mdn_interface.py b/plugins/modules/ce_mdn_interface.py
deleted file mode 120000
index 41bfdd699d..0000000000
--- a/plugins/modules/ce_mdn_interface.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_mdn_interface.py
\ No newline at end of file
diff --git a/plugins/modules/ce_mlag_config.py b/plugins/modules/ce_mlag_config.py
deleted file mode 120000
index 2043dcf3ae..0000000000
--- a/plugins/modules/ce_mlag_config.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_mlag_config.py
\ No newline at end of file
diff --git a/plugins/modules/ce_mlag_interface.py b/plugins/modules/ce_mlag_interface.py
deleted file mode 120000
index 11e01c958f..0000000000
--- a/plugins/modules/ce_mlag_interface.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_mlag_interface.py
\ No newline at end of file
diff --git a/plugins/modules/ce_mtu.py b/plugins/modules/ce_mtu.py
deleted file mode 120000
index b241140489..0000000000
--- a/plugins/modules/ce_mtu.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_mtu.py
\ No newline at end of file
diff --git a/plugins/modules/ce_multicast_global.py b/plugins/modules/ce_multicast_global.py
deleted file mode 120000
index 10395fbe0e..0000000000
--- a/plugins/modules/ce_multicast_global.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_multicast_global.py
\ No newline at end of file
diff --git a/plugins/modules/ce_multicast_igmp_enable.py b/plugins/modules/ce_multicast_igmp_enable.py
deleted file mode 120000
index 4f2a5bd5f6..0000000000
--- a/plugins/modules/ce_multicast_igmp_enable.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_multicast_igmp_enable.py
\ No newline at end of file
diff --git a/plugins/modules/ce_netconf.py b/plugins/modules/ce_netconf.py
deleted file mode 120000
index 29551885a9..0000000000
--- a/plugins/modules/ce_netconf.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_netconf.py
\ No newline at end of file
diff --git a/plugins/modules/ce_netstream_aging.py b/plugins/modules/ce_netstream_aging.py
deleted file mode 120000
index 43b9b6de55..0000000000
--- a/plugins/modules/ce_netstream_aging.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_netstream_aging.py
\ No newline at end of file
diff --git a/plugins/modules/ce_netstream_export.py b/plugins/modules/ce_netstream_export.py
deleted file mode 120000
index 177eb813d5..0000000000
--- a/plugins/modules/ce_netstream_export.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_netstream_export.py
\ No newline at end of file
diff --git a/plugins/modules/ce_netstream_global.py b/plugins/modules/ce_netstream_global.py
deleted file mode 120000
index 911ccfb550..0000000000
--- a/plugins/modules/ce_netstream_global.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_netstream_global.py
\ No newline at end of file
diff --git a/plugins/modules/ce_netstream_template.py b/plugins/modules/ce_netstream_template.py
deleted file mode 120000
index 4ff5927c4c..0000000000
--- a/plugins/modules/ce_netstream_template.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_netstream_template.py
\ No newline at end of file
diff --git a/plugins/modules/ce_ntp.py b/plugins/modules/ce_ntp.py
deleted file mode 120000
index adda3bb8e1..0000000000
--- a/plugins/modules/ce_ntp.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_ntp.py
\ No newline at end of file
diff --git a/plugins/modules/ce_ntp_auth.py b/plugins/modules/ce_ntp_auth.py
deleted file mode 120000
index 6004090fb8..0000000000
--- a/plugins/modules/ce_ntp_auth.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_ntp_auth.py
\ No newline at end of file
diff --git a/plugins/modules/ce_ospf.py b/plugins/modules/ce_ospf.py
deleted file mode 120000
index 32d1a68297..0000000000
--- a/plugins/modules/ce_ospf.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_ospf.py
\ No newline at end of file
diff --git a/plugins/modules/ce_ospf_vrf.py b/plugins/modules/ce_ospf_vrf.py
deleted file mode 120000
index 05ccc7c97b..0000000000
--- a/plugins/modules/ce_ospf_vrf.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_ospf_vrf.py
\ No newline at end of file
diff --git a/plugins/modules/ce_reboot.py b/plugins/modules/ce_reboot.py
deleted file mode 120000
index 86c21846f7..0000000000
--- a/plugins/modules/ce_reboot.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_reboot.py
\ No newline at end of file
diff --git a/plugins/modules/ce_rollback.py b/plugins/modules/ce_rollback.py
deleted file mode 120000
index 904394d753..0000000000
--- a/plugins/modules/ce_rollback.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_rollback.py
\ No newline at end of file
diff --git a/plugins/modules/ce_sflow.py b/plugins/modules/ce_sflow.py
deleted file mode 120000
index f7fefce3d0..0000000000
--- a/plugins/modules/ce_sflow.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_sflow.py
\ No newline at end of file
diff --git a/plugins/modules/ce_snmp_community.py b/plugins/modules/ce_snmp_community.py
deleted file mode 120000
index ff808f9b69..0000000000
--- a/plugins/modules/ce_snmp_community.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_snmp_community.py
\ No newline at end of file
diff --git a/plugins/modules/ce_snmp_contact.py b/plugins/modules/ce_snmp_contact.py
deleted file mode 120000
index 0ae4f7c0c5..0000000000
--- a/plugins/modules/ce_snmp_contact.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_snmp_contact.py
\ No newline at end of file
diff --git a/plugins/modules/ce_snmp_location.py b/plugins/modules/ce_snmp_location.py
deleted file mode 120000
index 1c4102a80c..0000000000
--- a/plugins/modules/ce_snmp_location.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_snmp_location.py
\ No newline at end of file
diff --git a/plugins/modules/ce_snmp_target_host.py b/plugins/modules/ce_snmp_target_host.py
deleted file mode 120000
index a7ba244102..0000000000
--- a/plugins/modules/ce_snmp_target_host.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_snmp_target_host.py
\ No newline at end of file
diff --git a/plugins/modules/ce_snmp_traps.py b/plugins/modules/ce_snmp_traps.py
deleted file mode 120000
index a3d1d35014..0000000000
--- a/plugins/modules/ce_snmp_traps.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_snmp_traps.py
\ No newline at end of file
diff --git a/plugins/modules/ce_snmp_user.py b/plugins/modules/ce_snmp_user.py
deleted file mode 120000
index abbe135d88..0000000000
--- a/plugins/modules/ce_snmp_user.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_snmp_user.py
\ No newline at end of file
diff --git a/plugins/modules/ce_startup.py b/plugins/modules/ce_startup.py
deleted file mode 120000
index ab98ad2f07..0000000000
--- a/plugins/modules/ce_startup.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_startup.py
\ No newline at end of file
diff --git a/plugins/modules/ce_static_route.py b/plugins/modules/ce_static_route.py
deleted file mode 120000
index e3b1d7abd1..0000000000
--- a/plugins/modules/ce_static_route.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_static_route.py
\ No newline at end of file
diff --git a/plugins/modules/ce_static_route_bfd.py b/plugins/modules/ce_static_route_bfd.py
deleted file mode 120000
index 84ad2de6fa..0000000000
--- a/plugins/modules/ce_static_route_bfd.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_static_route_bfd.py
\ No newline at end of file
diff --git a/plugins/modules/ce_stp.py b/plugins/modules/ce_stp.py
deleted file mode 120000
index 71632098a4..0000000000
--- a/plugins/modules/ce_stp.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_stp.py
\ No newline at end of file
diff --git a/plugins/modules/ce_switchport.py b/plugins/modules/ce_switchport.py
deleted file mode 120000
index 29c8e4230f..0000000000
--- a/plugins/modules/ce_switchport.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_switchport.py
\ No newline at end of file
diff --git a/plugins/modules/ce_vlan.py b/plugins/modules/ce_vlan.py
deleted file mode 120000
index cb6d11b712..0000000000
--- a/plugins/modules/ce_vlan.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_vlan.py
\ No newline at end of file
diff --git a/plugins/modules/ce_vrf.py b/plugins/modules/ce_vrf.py
deleted file mode 120000
index b7534a74bc..0000000000
--- a/plugins/modules/ce_vrf.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_vrf.py
\ No newline at end of file
diff --git a/plugins/modules/ce_vrf_af.py b/plugins/modules/ce_vrf_af.py
deleted file mode 120000
index a9a3676927..0000000000
--- a/plugins/modules/ce_vrf_af.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_vrf_af.py
\ No newline at end of file
diff --git a/plugins/modules/ce_vrf_interface.py b/plugins/modules/ce_vrf_interface.py
deleted file mode 120000
index 94ff7f0f3a..0000000000
--- a/plugins/modules/ce_vrf_interface.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_vrf_interface.py
\ No newline at end of file
diff --git a/plugins/modules/ce_vrrp.py b/plugins/modules/ce_vrrp.py
deleted file mode 120000
index f8910f02eb..0000000000
--- a/plugins/modules/ce_vrrp.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_vrrp.py
\ No newline at end of file
diff --git a/plugins/modules/ce_vxlan_arp.py b/plugins/modules/ce_vxlan_arp.py
deleted file mode 120000
index 04a187157f..0000000000
--- a/plugins/modules/ce_vxlan_arp.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_vxlan_arp.py
\ No newline at end of file
diff --git a/plugins/modules/ce_vxlan_gateway.py b/plugins/modules/ce_vxlan_gateway.py
deleted file mode 120000
index 83ab3b8a4f..0000000000
--- a/plugins/modules/ce_vxlan_gateway.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_vxlan_gateway.py
\ No newline at end of file
diff --git a/plugins/modules/ce_vxlan_global.py b/plugins/modules/ce_vxlan_global.py
deleted file mode 120000
index aa6032cc10..0000000000
--- a/plugins/modules/ce_vxlan_global.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_vxlan_global.py
\ No newline at end of file
diff --git a/plugins/modules/ce_vxlan_tunnel.py b/plugins/modules/ce_vxlan_tunnel.py
deleted file mode 120000
index 60adcf7a30..0000000000
--- a/plugins/modules/ce_vxlan_tunnel.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_vxlan_tunnel.py
\ No newline at end of file
diff --git a/plugins/modules/ce_vxlan_vap.py b/plugins/modules/ce_vxlan_vap.py
deleted file mode 120000
index fe9710bed7..0000000000
--- a/plugins/modules/ce_vxlan_vap.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudengine/ce_vxlan_vap.py
\ No newline at end of file
diff --git a/plugins/modules/checkpoint_access_layer_facts.py b/plugins/modules/checkpoint_access_layer_facts.py
deleted file mode 120000
index 1c8ddf8cc3..0000000000
--- a/plugins/modules/checkpoint_access_layer_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/check_point/checkpoint_access_layer_facts.py
\ No newline at end of file
diff --git a/plugins/modules/checkpoint_access_rule.py b/plugins/modules/checkpoint_access_rule.py
deleted file mode 120000
index d0d064b070..0000000000
--- a/plugins/modules/checkpoint_access_rule.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/check_point/checkpoint_access_rule.py
\ No newline at end of file
diff --git a/plugins/modules/checkpoint_access_rule_facts.py b/plugins/modules/checkpoint_access_rule_facts.py
deleted file mode 120000
index 6b84f9ad45..0000000000
--- a/plugins/modules/checkpoint_access_rule_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/check_point/checkpoint_access_rule_facts.py
\ No newline at end of file
diff --git a/plugins/modules/checkpoint_host.py b/plugins/modules/checkpoint_host.py
deleted file mode 120000
index 1bd4813c17..0000000000
--- a/plugins/modules/checkpoint_host.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/check_point/checkpoint_host.py
\ No newline at end of file
diff --git a/plugins/modules/checkpoint_host_facts.py b/plugins/modules/checkpoint_host_facts.py
deleted file mode 120000
index 80ac928bba..0000000000
--- a/plugins/modules/checkpoint_host_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/check_point/checkpoint_host_facts.py
\ No newline at end of file
diff --git a/plugins/modules/checkpoint_object_facts.py b/plugins/modules/checkpoint_object_facts.py
deleted file mode 120000
index ef7886f3b5..0000000000
--- a/plugins/modules/checkpoint_object_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/check_point/checkpoint_object_facts.py
\ No newline at end of file
diff --git a/plugins/modules/checkpoint_run_script.py b/plugins/modules/checkpoint_run_script.py
deleted file mode 120000
index fcbdb0bb71..0000000000
--- a/plugins/modules/checkpoint_run_script.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/check_point/checkpoint_run_script.py
\ No newline at end of file
diff --git a/plugins/modules/checkpoint_session.py b/plugins/modules/checkpoint_session.py
deleted file mode 120000
index d70cb2373e..0000000000
--- a/plugins/modules/checkpoint_session.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/check_point/checkpoint_session.py
\ No newline at end of file
diff --git a/plugins/modules/checkpoint_task_facts.py b/plugins/modules/checkpoint_task_facts.py
deleted file mode 120000
index 2524f306a5..0000000000
--- a/plugins/modules/checkpoint_task_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/check_point/checkpoint_task_facts.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_backup.py b/plugins/modules/cnos_backup.py
deleted file mode 120000
index 850557a743..0000000000
--- a/plugins/modules/cnos_backup.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_backup.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_banner.py b/plugins/modules/cnos_banner.py
deleted file mode 120000
index 6fff4900a2..0000000000
--- a/plugins/modules/cnos_banner.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_banner.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_bgp.py b/plugins/modules/cnos_bgp.py
deleted file mode 120000
index 416bb98821..0000000000
--- a/plugins/modules/cnos_bgp.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_bgp.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_command.py b/plugins/modules/cnos_command.py
deleted file mode 120000
index e6829fcf50..0000000000
--- a/plugins/modules/cnos_command.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_command.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_conditional_command.py b/plugins/modules/cnos_conditional_command.py
deleted file mode 120000
index 91d637a535..0000000000
--- a/plugins/modules/cnos_conditional_command.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_conditional_command.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_conditional_template.py b/plugins/modules/cnos_conditional_template.py
deleted file mode 120000
index 76c8bebae7..0000000000
--- a/plugins/modules/cnos_conditional_template.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_conditional_template.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_config.py b/plugins/modules/cnos_config.py
deleted file mode 120000
index 3facf7f0bb..0000000000
--- a/plugins/modules/cnos_config.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_config.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_factory.py b/plugins/modules/cnos_factory.py
deleted file mode 120000
index a3f6d7eb87..0000000000
--- a/plugins/modules/cnos_factory.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_factory.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_facts.py b/plugins/modules/cnos_facts.py
deleted file mode 120000
index be01441995..0000000000
--- a/plugins/modules/cnos_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_facts.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_image.py b/plugins/modules/cnos_image.py
deleted file mode 120000
index c727c306dc..0000000000
--- a/plugins/modules/cnos_image.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_image.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_interface.py b/plugins/modules/cnos_interface.py
deleted file mode 120000
index d274ab5eb4..0000000000
--- a/plugins/modules/cnos_interface.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_interface.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_l2_interface.py b/plugins/modules/cnos_l2_interface.py
deleted file mode 120000
index f7b879d6af..0000000000
--- a/plugins/modules/cnos_l2_interface.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_l2_interface.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_l3_interface.py b/plugins/modules/cnos_l3_interface.py
deleted file mode 120000
index 285b66bcc5..0000000000
--- a/plugins/modules/cnos_l3_interface.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_l3_interface.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_linkagg.py b/plugins/modules/cnos_linkagg.py
deleted file mode 120000
index f91e038187..0000000000
--- a/plugins/modules/cnos_linkagg.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_linkagg.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_lldp.py b/plugins/modules/cnos_lldp.py
deleted file mode 120000
index 03e13146ae..0000000000
--- a/plugins/modules/cnos_lldp.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_lldp.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_logging.py b/plugins/modules/cnos_logging.py
deleted file mode 120000
index b2abeb6547..0000000000
--- a/plugins/modules/cnos_logging.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_logging.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_reload.py b/plugins/modules/cnos_reload.py
deleted file mode 120000
index 06c7e8a303..0000000000
--- a/plugins/modules/cnos_reload.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_reload.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_rollback.py b/plugins/modules/cnos_rollback.py
deleted file mode 120000
index f5f6c11cec..0000000000
--- a/plugins/modules/cnos_rollback.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_rollback.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_save.py b/plugins/modules/cnos_save.py
deleted file mode 120000
index 8569b6cd29..0000000000
--- a/plugins/modules/cnos_save.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_save.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_showrun.py b/plugins/modules/cnos_showrun.py
deleted file mode 120000
index 52840a7a4d..0000000000
--- a/plugins/modules/cnos_showrun.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_showrun.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_static_route.py b/plugins/modules/cnos_static_route.py
deleted file mode 120000
index 7f6e25dd4f..0000000000
--- a/plugins/modules/cnos_static_route.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_static_route.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_system.py b/plugins/modules/cnos_system.py
deleted file mode 120000
index 634aa875c2..0000000000
--- a/plugins/modules/cnos_system.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_system.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_template.py b/plugins/modules/cnos_template.py
deleted file mode 120000
index 37bdf83e87..0000000000
--- a/plugins/modules/cnos_template.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_template.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_user.py b/plugins/modules/cnos_user.py
deleted file mode 120000
index adb93fbd84..0000000000
--- a/plugins/modules/cnos_user.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_user.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_vlag.py b/plugins/modules/cnos_vlag.py
deleted file mode 120000
index de9b337abf..0000000000
--- a/plugins/modules/cnos_vlag.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_vlag.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_vlan.py b/plugins/modules/cnos_vlan.py
deleted file mode 120000
index da4e32c373..0000000000
--- a/plugins/modules/cnos_vlan.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_vlan.py
\ No newline at end of file
diff --git a/plugins/modules/cnos_vrf.py b/plugins/modules/cnos_vrf.py
deleted file mode 120000
index 6095d30754..0000000000
--- a/plugins/modules/cnos_vrf.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cnos/cnos_vrf.py
\ No newline at end of file
diff --git a/plugins/modules/cp_publish.py b/plugins/modules/cp_publish.py
deleted file mode 120000
index 76f82d7c4a..0000000000
--- a/plugins/modules/cp_publish.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/check_point/cp_publish.py
\ No newline at end of file
diff --git a/plugins/modules/cv_server_provision.py b/plugins/modules/cv_server_provision.py
deleted file mode 120000
index cc5d1489eb..0000000000
--- a/plugins/modules/cv_server_provision.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cloudvision/cv_server_provision.py
\ No newline at end of file
diff --git a/plugins/modules/dladm_etherstub.py b/plugins/modules/dladm_etherstub.py
deleted file mode 120000
index 85402173ed..0000000000
--- a/plugins/modules/dladm_etherstub.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/illumos/dladm_etherstub.py
\ No newline at end of file
diff --git a/plugins/modules/dladm_iptun.py b/plugins/modules/dladm_iptun.py
deleted file mode 120000
index b05a8b25cc..0000000000
--- a/plugins/modules/dladm_iptun.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/illumos/dladm_iptun.py
\ No newline at end of file
diff --git a/plugins/modules/dladm_linkprop.py b/plugins/modules/dladm_linkprop.py
deleted file mode 120000
index 2b39c6bd3d..0000000000
--- a/plugins/modules/dladm_linkprop.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/illumos/dladm_linkprop.py
\ No newline at end of file
diff --git a/plugins/modules/dladm_vlan.py b/plugins/modules/dladm_vlan.py
deleted file mode 120000
index 35e1d8c010..0000000000
--- a/plugins/modules/dladm_vlan.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/illumos/dladm_vlan.py
\ No newline at end of file
diff --git a/plugins/modules/dladm_vnic.py b/plugins/modules/dladm_vnic.py
deleted file mode 120000
index 4b23d2da54..0000000000
--- a/plugins/modules/dladm_vnic.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/illumos/dladm_vnic.py
\ No newline at end of file
diff --git a/plugins/modules/edgeos_command.py b/plugins/modules/edgeos_command.py
deleted file mode 120000
index f6d5b9fc2e..0000000000
--- a/plugins/modules/edgeos_command.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/edgeos/edgeos_command.py
\ No newline at end of file
diff --git a/plugins/modules/edgeos_config.py b/plugins/modules/edgeos_config.py
deleted file mode 120000
index cadeff13f4..0000000000
--- a/plugins/modules/edgeos_config.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/edgeos/edgeos_config.py
\ No newline at end of file
diff --git a/plugins/modules/edgeos_facts.py b/plugins/modules/edgeos_facts.py
deleted file mode 120000
index 4f528ac81f..0000000000
--- a/plugins/modules/edgeos_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/edgeos/edgeos_facts.py
\ No newline at end of file
diff --git a/plugins/modules/edgeswitch_facts.py b/plugins/modules/edgeswitch_facts.py
deleted file mode 120000
index 5c71aae2a6..0000000000
--- a/plugins/modules/edgeswitch_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/edgeswitch/edgeswitch_facts.py
\ No newline at end of file
diff --git a/plugins/modules/edgeswitch_vlan.py b/plugins/modules/edgeswitch_vlan.py
deleted file mode 120000
index e4ac3b1fc2..0000000000
--- a/plugins/modules/edgeswitch_vlan.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/edgeswitch/edgeswitch_vlan.py
\ No newline at end of file
diff --git a/plugins/modules/enos_command.py b/plugins/modules/enos_command.py
deleted file mode 120000
index 3d52c0215f..0000000000
--- a/plugins/modules/enos_command.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/enos/enos_command.py
\ No newline at end of file
diff --git a/plugins/modules/enos_config.py b/plugins/modules/enos_config.py
deleted file mode 120000
index 46a93ca6ce..0000000000
--- a/plugins/modules/enos_config.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/enos/enos_config.py
\ No newline at end of file
diff --git a/plugins/modules/enos_facts.py b/plugins/modules/enos_facts.py
deleted file mode 120000
index 82a7af9f35..0000000000
--- a/plugins/modules/enos_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/enos/enos_facts.py
\ No newline at end of file
diff --git a/plugins/modules/eric_eccli_command.py b/plugins/modules/eric_eccli_command.py
deleted file mode 120000
index 2e7d85232f..0000000000
--- a/plugins/modules/eric_eccli_command.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/eric_eccli/eric_eccli_command.py
\ No newline at end of file
diff --git a/plugins/modules/exos_command.py b/plugins/modules/exos_command.py
deleted file mode 120000
index 6d53af8204..0000000000
--- a/plugins/modules/exos_command.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/exos/exos_command.py
\ No newline at end of file
diff --git a/plugins/modules/exos_config.py b/plugins/modules/exos_config.py
deleted file mode 120000
index cee202971f..0000000000
--- a/plugins/modules/exos_config.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/exos/exos_config.py
\ No newline at end of file
diff --git a/plugins/modules/exos_facts.py b/plugins/modules/exos_facts.py
deleted file mode 120000
index e23ecab36c..0000000000
--- a/plugins/modules/exos_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/exos/exos_facts.py
\ No newline at end of file
diff --git a/plugins/modules/exos_l2_interfaces.py b/plugins/modules/exos_l2_interfaces.py
deleted file mode 120000
index 01200d00b1..0000000000
--- a/plugins/modules/exos_l2_interfaces.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/exos/exos_l2_interfaces.py
\ No newline at end of file
diff --git a/plugins/modules/exos_lldp_global.py b/plugins/modules/exos_lldp_global.py
deleted file mode 120000
index 61d06a1c61..0000000000
--- a/plugins/modules/exos_lldp_global.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/exos/exos_lldp_global.py
\ No newline at end of file
diff --git a/plugins/modules/exos_lldp_interfaces.py b/plugins/modules/exos_lldp_interfaces.py
deleted file mode 120000
index 351bf1abfe..0000000000
--- a/plugins/modules/exos_lldp_interfaces.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/exos/exos_lldp_interfaces.py
\ No newline at end of file
diff --git a/plugins/modules/exos_vlans.py b/plugins/modules/exos_vlans.py
deleted file mode 120000
index 8d27b43e3d..0000000000
--- a/plugins/modules/exos_vlans.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/exos/exos_vlans.py
\ No newline at end of file
diff --git a/plugins/modules/faz_device.py b/plugins/modules/faz_device.py
deleted file mode 120000
index bcf5bb86d0..0000000000
--- a/plugins/modules/faz_device.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortianalyzer/faz_device.py
\ No newline at end of file
diff --git a/plugins/modules/flowadm.py b/plugins/modules/flowadm.py
deleted file mode 120000
index c321926d00..0000000000
--- a/plugins/modules/flowadm.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/illumos/flowadm.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_device.py b/plugins/modules/fmgr_device.py
deleted file mode 120000
index 99747877cf..0000000000
--- a/plugins/modules/fmgr_device.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_device.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_device_config.py b/plugins/modules/fmgr_device_config.py
deleted file mode 120000
index 095b509314..0000000000
--- a/plugins/modules/fmgr_device_config.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_device_config.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_device_group.py b/plugins/modules/fmgr_device_group.py
deleted file mode 120000
index d8399cf806..0000000000
--- a/plugins/modules/fmgr_device_group.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_device_group.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_device_provision_template.py b/plugins/modules/fmgr_device_provision_template.py
deleted file mode 120000
index 26db1584fd..0000000000
--- a/plugins/modules/fmgr_device_provision_template.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_device_provision_template.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_fwobj_address.py b/plugins/modules/fmgr_fwobj_address.py
deleted file mode 120000
index 6cfcfbfa69..0000000000
--- a/plugins/modules/fmgr_fwobj_address.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_fwobj_address.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_fwobj_ippool.py b/plugins/modules/fmgr_fwobj_ippool.py
deleted file mode 120000
index fd554ea64c..0000000000
--- a/plugins/modules/fmgr_fwobj_ippool.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_fwobj_ippool.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_fwobj_ippool6.py b/plugins/modules/fmgr_fwobj_ippool6.py
deleted file mode 120000
index 4768e64138..0000000000
--- a/plugins/modules/fmgr_fwobj_ippool6.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_fwobj_ippool6.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_fwobj_service.py b/plugins/modules/fmgr_fwobj_service.py
deleted file mode 120000
index 574cf226e6..0000000000
--- a/plugins/modules/fmgr_fwobj_service.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_fwobj_service.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_fwobj_vip.py b/plugins/modules/fmgr_fwobj_vip.py
deleted file mode 120000
index 65d517551d..0000000000
--- a/plugins/modules/fmgr_fwobj_vip.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_fwobj_vip.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_fwpol_ipv4.py b/plugins/modules/fmgr_fwpol_ipv4.py
deleted file mode 120000
index 8e01ba4300..0000000000
--- a/plugins/modules/fmgr_fwpol_ipv4.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_fwpol_ipv4.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_fwpol_package.py b/plugins/modules/fmgr_fwpol_package.py
deleted file mode 120000
index 5085bd7a6b..0000000000
--- a/plugins/modules/fmgr_fwpol_package.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_fwpol_package.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_ha.py b/plugins/modules/fmgr_ha.py
deleted file mode 120000
index d4e2b3768f..0000000000
--- a/plugins/modules/fmgr_ha.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_ha.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_provisioning.py b/plugins/modules/fmgr_provisioning.py
deleted file mode 120000
index 577aa80e81..0000000000
--- a/plugins/modules/fmgr_provisioning.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_provisioning.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_query.py b/plugins/modules/fmgr_query.py
deleted file mode 120000
index b3118879fc..0000000000
--- a/plugins/modules/fmgr_query.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_query.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_script.py b/plugins/modules/fmgr_script.py
deleted file mode 120000
index 9f97ec2d41..0000000000
--- a/plugins/modules/fmgr_script.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_script.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_secprof_appctrl.py b/plugins/modules/fmgr_secprof_appctrl.py
deleted file mode 120000
index 0e811096ff..0000000000
--- a/plugins/modules/fmgr_secprof_appctrl.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_secprof_appctrl.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_secprof_av.py b/plugins/modules/fmgr_secprof_av.py
deleted file mode 120000
index 1842fa6131..0000000000
--- a/plugins/modules/fmgr_secprof_av.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_secprof_av.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_secprof_dns.py b/plugins/modules/fmgr_secprof_dns.py
deleted file mode 120000
index aec4d164b1..0000000000
--- a/plugins/modules/fmgr_secprof_dns.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_secprof_dns.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_secprof_ips.py b/plugins/modules/fmgr_secprof_ips.py
deleted file mode 120000
index 22e3afc40e..0000000000
--- a/plugins/modules/fmgr_secprof_ips.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_secprof_ips.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_secprof_profile_group.py b/plugins/modules/fmgr_secprof_profile_group.py
deleted file mode 120000
index feed2ad213..0000000000
--- a/plugins/modules/fmgr_secprof_profile_group.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_secprof_profile_group.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_secprof_proxy.py b/plugins/modules/fmgr_secprof_proxy.py
deleted file mode 120000
index 20d7980772..0000000000
--- a/plugins/modules/fmgr_secprof_proxy.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_secprof_proxy.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_secprof_spam.py b/plugins/modules/fmgr_secprof_spam.py
deleted file mode 120000
index d0c9b31fd6..0000000000
--- a/plugins/modules/fmgr_secprof_spam.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_secprof_spam.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_secprof_ssl_ssh.py b/plugins/modules/fmgr_secprof_ssl_ssh.py
deleted file mode 120000
index 970622bb3e..0000000000
--- a/plugins/modules/fmgr_secprof_ssl_ssh.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_secprof_ssl_ssh.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_secprof_voip.py b/plugins/modules/fmgr_secprof_voip.py
deleted file mode 120000
index a892763689..0000000000
--- a/plugins/modules/fmgr_secprof_voip.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_secprof_voip.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_secprof_waf.py b/plugins/modules/fmgr_secprof_waf.py
deleted file mode 120000
index 5ae144ab19..0000000000
--- a/plugins/modules/fmgr_secprof_waf.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_secprof_waf.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_secprof_wanopt.py b/plugins/modules/fmgr_secprof_wanopt.py
deleted file mode 120000
index 7cabea53bd..0000000000
--- a/plugins/modules/fmgr_secprof_wanopt.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_secprof_wanopt.py
\ No newline at end of file
diff --git a/plugins/modules/fmgr_secprof_web.py b/plugins/modules/fmgr_secprof_web.py
deleted file mode 120000
index 98cc8ba334..0000000000
--- a/plugins/modules/fmgr_secprof_web.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/fortimanager/fmgr_secprof_web.py
\ No newline at end of file
diff --git a/plugins/modules/ftd_configuration.py b/plugins/modules/ftd_configuration.py
deleted file mode 120000
index ee1bf880ae..0000000000
--- a/plugins/modules/ftd_configuration.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/ftd/ftd_configuration.py
\ No newline at end of file
diff --git a/plugins/modules/ftd_file_download.py b/plugins/modules/ftd_file_download.py
deleted file mode 120000
index cb8cfbc4db..0000000000
--- a/plugins/modules/ftd_file_download.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/ftd/ftd_file_download.py
\ No newline at end of file
diff --git a/plugins/modules/ftd_file_upload.py b/plugins/modules/ftd_file_upload.py
deleted file mode 120000
index fcc8f9c49b..0000000000
--- a/plugins/modules/ftd_file_upload.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/ftd/ftd_file_upload.py
\ No newline at end of file
diff --git a/plugins/modules/ftd_install.py b/plugins/modules/ftd_install.py
deleted file mode 120000
index 16b3f65c1f..0000000000
--- a/plugins/modules/ftd_install.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/ftd/ftd_install.py
\ No newline at end of file
diff --git a/plugins/modules/iap_start_workflow.py b/plugins/modules/iap_start_workflow.py
deleted file mode 120000
index 0b7ce7400d..0000000000
--- a/plugins/modules/iap_start_workflow.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/itential/iap_start_workflow.py
\ No newline at end of file
diff --git a/plugins/modules/iap_token.py b/plugins/modules/iap_token.py
deleted file mode 120000
index f663909c8c..0000000000
--- a/plugins/modules/iap_token.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/itential/iap_token.py
\ No newline at end of file
diff --git a/plugins/modules/icx_banner.py b/plugins/modules/icx_banner.py
deleted file mode 120000
index d8637da47f..0000000000
--- a/plugins/modules/icx_banner.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/icx/icx_banner.py
\ No newline at end of file
diff --git a/plugins/modules/icx_command.py b/plugins/modules/icx_command.py
deleted file mode 120000
index e19b5d2307..0000000000
--- a/plugins/modules/icx_command.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/icx/icx_command.py
\ No newline at end of file
diff --git a/plugins/modules/icx_config.py b/plugins/modules/icx_config.py
deleted file mode 120000
index 061430c450..0000000000
--- a/plugins/modules/icx_config.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/icx/icx_config.py
\ No newline at end of file
diff --git a/plugins/modules/icx_copy.py b/plugins/modules/icx_copy.py
deleted file mode 120000
index f484d082bf..0000000000
--- a/plugins/modules/icx_copy.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/icx/icx_copy.py
\ No newline at end of file
diff --git a/plugins/modules/icx_facts.py b/plugins/modules/icx_facts.py
deleted file mode 120000
index 5042e91d10..0000000000
--- a/plugins/modules/icx_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/icx/icx_facts.py
\ No newline at end of file
diff --git a/plugins/modules/icx_interface.py b/plugins/modules/icx_interface.py
deleted file mode 120000
index c02b08a081..0000000000
--- a/plugins/modules/icx_interface.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/icx/icx_interface.py
\ No newline at end of file
diff --git a/plugins/modules/icx_l3_interface.py b/plugins/modules/icx_l3_interface.py
deleted file mode 120000
index 764edf7115..0000000000
--- a/plugins/modules/icx_l3_interface.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/icx/icx_l3_interface.py
\ No newline at end of file
diff --git a/plugins/modules/icx_linkagg.py b/plugins/modules/icx_linkagg.py
deleted file mode 120000
index fb7b55abc5..0000000000
--- a/plugins/modules/icx_linkagg.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/icx/icx_linkagg.py
\ No newline at end of file
diff --git a/plugins/modules/icx_lldp.py b/plugins/modules/icx_lldp.py
deleted file mode 120000
index 4a77ff98ec..0000000000
--- a/plugins/modules/icx_lldp.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/icx/icx_lldp.py
\ No newline at end of file
diff --git a/plugins/modules/icx_logging.py b/plugins/modules/icx_logging.py
deleted file mode 120000
index 8e1ed7a40f..0000000000
--- a/plugins/modules/icx_logging.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/icx/icx_logging.py
\ No newline at end of file
diff --git a/plugins/modules/icx_ping.py b/plugins/modules/icx_ping.py
deleted file mode 120000
index e1e937fe10..0000000000
--- a/plugins/modules/icx_ping.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/icx/icx_ping.py
\ No newline at end of file
diff --git a/plugins/modules/icx_static_route.py b/plugins/modules/icx_static_route.py
deleted file mode 120000
index e90273faa3..0000000000
--- a/plugins/modules/icx_static_route.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/icx/icx_static_route.py
\ No newline at end of file
diff --git a/plugins/modules/icx_system.py b/plugins/modules/icx_system.py
deleted file mode 120000
index db544241c3..0000000000
--- a/plugins/modules/icx_system.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/icx/icx_system.py
\ No newline at end of file
diff --git a/plugins/modules/icx_user.py b/plugins/modules/icx_user.py
deleted file mode 120000
index d1d6a045df..0000000000
--- a/plugins/modules/icx_user.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/icx/icx_user.py
\ No newline at end of file
diff --git a/plugins/modules/icx_vlan.py b/plugins/modules/icx_vlan.py
deleted file mode 120000
index 7203845cf7..0000000000
--- a/plugins/modules/icx_vlan.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/icx/icx_vlan.py
\ No newline at end of file
diff --git a/plugins/modules/ig_config.py b/plugins/modules/ig_config.py
deleted file mode 120000
index b2caf88803..0000000000
--- a/plugins/modules/ig_config.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/ingate/ig_config.py
\ No newline at end of file
diff --git a/plugins/modules/ig_unit_information.py b/plugins/modules/ig_unit_information.py
deleted file mode 120000
index e5262ddbba..0000000000
--- a/plugins/modules/ig_unit_information.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/ingate/ig_unit_information.py
\ No newline at end of file
diff --git a/plugins/modules/ipadm_addr.py b/plugins/modules/ipadm_addr.py
deleted file mode 120000
index eb0a46dfa1..0000000000
--- a/plugins/modules/ipadm_addr.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/illumos/ipadm_addr.py
\ No newline at end of file
diff --git a/plugins/modules/ipadm_addrprop.py b/plugins/modules/ipadm_addrprop.py
deleted file mode 120000
index 5130510848..0000000000
--- a/plugins/modules/ipadm_addrprop.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/illumos/ipadm_addrprop.py
\ No newline at end of file
diff --git a/plugins/modules/ipadm_if.py b/plugins/modules/ipadm_if.py
deleted file mode 120000
index 7a44831be0..0000000000
--- a/plugins/modules/ipadm_if.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/illumos/ipadm_if.py
\ No newline at end of file
diff --git a/plugins/modules/ipadm_ifprop.py b/plugins/modules/ipadm_ifprop.py
deleted file mode 120000
index a9de50486a..0000000000
--- a/plugins/modules/ipadm_ifprop.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/illumos/ipadm_ifprop.py
\ No newline at end of file
diff --git a/plugins/modules/ipadm_prop.py b/plugins/modules/ipadm_prop.py
deleted file mode 120000
index 6f0c221d96..0000000000
--- a/plugins/modules/ipadm_prop.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/illumos/ipadm_prop.py
\ No newline at end of file
diff --git a/plugins/modules/ironware_command.py b/plugins/modules/ironware_command.py
deleted file mode 120000
index 0cc3f7ee4d..0000000000
--- a/plugins/modules/ironware_command.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/ironware/ironware_command.py
\ No newline at end of file
diff --git a/plugins/modules/ironware_config.py b/plugins/modules/ironware_config.py
deleted file mode 120000
index a23fdd2280..0000000000
--- a/plugins/modules/ironware_config.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/ironware/ironware_config.py
\ No newline at end of file
diff --git a/plugins/modules/ironware_facts.py b/plugins/modules/ironware_facts.py
deleted file mode 120000
index b54c2463ac..0000000000
--- a/plugins/modules/ironware_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/ironware/ironware_facts.py
\ No newline at end of file
diff --git a/plugins/modules/mso_schema_template_external_epg_contract.py b/plugins/modules/mso_schema_template_external_epg_contract.py
deleted file mode 120000
index 60e98e6362..0000000000
--- a/plugins/modules/mso_schema_template_external_epg_contract.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/aci/mso_schema_template_external_epg_contract.py
\ No newline at end of file
diff --git a/plugins/modules/mso_schema_template_external_epg_subnet.py b/plugins/modules/mso_schema_template_external_epg_subnet.py
deleted file mode 120000
index 24c75707e9..0000000000
--- a/plugins/modules/mso_schema_template_external_epg_subnet.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/aci/mso_schema_template_external_epg_subnet.py
\ No newline at end of file
diff --git a/plugins/modules/nclu.py b/plugins/modules/nclu.py
deleted file mode 120000
index 9fafd0fe60..0000000000
--- a/plugins/modules/nclu.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/cumulus/nclu.py
\ No newline at end of file
diff --git a/plugins/modules/netact_cm_command.py b/plugins/modules/netact_cm_command.py
deleted file mode 120000
index cbedd83419..0000000000
--- a/plugins/modules/netact_cm_command.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/netact/netact_cm_command.py
\ No newline at end of file
diff --git a/plugins/modules/netscaler_cs_action.py b/plugins/modules/netscaler_cs_action.py
deleted file mode 120000
index 1676e45b32..0000000000
--- a/plugins/modules/netscaler_cs_action.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/netscaler/netscaler_cs_action.py
\ No newline at end of file
diff --git a/plugins/modules/netscaler_cs_policy.py b/plugins/modules/netscaler_cs_policy.py
deleted file mode 120000
index 56c47a9373..0000000000
--- a/plugins/modules/netscaler_cs_policy.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/netscaler/netscaler_cs_policy.py
\ No newline at end of file
diff --git a/plugins/modules/netscaler_cs_vserver.py b/plugins/modules/netscaler_cs_vserver.py
deleted file mode 120000
index 45faf87c70..0000000000
--- a/plugins/modules/netscaler_cs_vserver.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/netscaler/netscaler_cs_vserver.py
\ No newline at end of file
diff --git a/plugins/modules/netscaler_gslb_service.py b/plugins/modules/netscaler_gslb_service.py
deleted file mode 120000
index c142a293f1..0000000000
--- a/plugins/modules/netscaler_gslb_service.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/netscaler/netscaler_gslb_service.py
\ No newline at end of file
diff --git a/plugins/modules/netscaler_gslb_site.py b/plugins/modules/netscaler_gslb_site.py
deleted file mode 120000
index 1a94598704..0000000000
--- a/plugins/modules/netscaler_gslb_site.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/netscaler/netscaler_gslb_site.py
\ No newline at end of file
diff --git a/plugins/modules/netscaler_gslb_vserver.py b/plugins/modules/netscaler_gslb_vserver.py
deleted file mode 120000
index 4860b78c39..0000000000
--- a/plugins/modules/netscaler_gslb_vserver.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/netscaler/netscaler_gslb_vserver.py
\ No newline at end of file
diff --git a/plugins/modules/netscaler_lb_monitor.py b/plugins/modules/netscaler_lb_monitor.py
deleted file mode 120000
index 42eee0705a..0000000000
--- a/plugins/modules/netscaler_lb_monitor.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/netscaler/netscaler_lb_monitor.py
\ No newline at end of file
diff --git a/plugins/modules/netscaler_lb_vserver.py b/plugins/modules/netscaler_lb_vserver.py
deleted file mode 120000
index 0d62bf97d0..0000000000
--- a/plugins/modules/netscaler_lb_vserver.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/netscaler/netscaler_lb_vserver.py
\ No newline at end of file
diff --git a/plugins/modules/netscaler_nitro_request.py b/plugins/modules/netscaler_nitro_request.py
deleted file mode 120000
index 4090ee6a25..0000000000
--- a/plugins/modules/netscaler_nitro_request.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/netscaler/netscaler_nitro_request.py
\ No newline at end of file
diff --git a/plugins/modules/netscaler_save_config.py b/plugins/modules/netscaler_save_config.py
deleted file mode 120000
index 2214b15643..0000000000
--- a/plugins/modules/netscaler_save_config.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/netscaler/netscaler_save_config.py
\ No newline at end of file
diff --git a/plugins/modules/netscaler_server.py b/plugins/modules/netscaler_server.py
deleted file mode 120000
index eadb037852..0000000000
--- a/plugins/modules/netscaler_server.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/netscaler/netscaler_server.py
\ No newline at end of file
diff --git a/plugins/modules/netscaler_service.py b/plugins/modules/netscaler_service.py
deleted file mode 120000
index 86f43d5b67..0000000000
--- a/plugins/modules/netscaler_service.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/netscaler/netscaler_service.py
\ No newline at end of file
diff --git a/plugins/modules/netscaler_servicegroup.py b/plugins/modules/netscaler_servicegroup.py
deleted file mode 120000
index b1d45e4918..0000000000
--- a/plugins/modules/netscaler_servicegroup.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/netscaler/netscaler_servicegroup.py
\ No newline at end of file
diff --git a/plugins/modules/netscaler_ssl_certkey.py b/plugins/modules/netscaler_ssl_certkey.py
deleted file mode 120000
index e0c5898048..0000000000
--- a/plugins/modules/netscaler_ssl_certkey.py
+++ /dev/null
@@ -1 +0,0 @@
-./network/netscaler/netscaler_ssl_certkey.py
\ No newline at end of file
diff --git a/plugins/modules/network/a10/a10_server.py b/plugins/modules/network/a10/a10_server.py
deleted file mode 100644
index 3ffbadd66d..0000000000
--- a/plugins/modules/network/a10/a10_server.py
+++ /dev/null
@@ -1,285 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2014, Mischa Peters ,
-# (c) 2016, Eric Chou
-#
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: a10_server
-short_description: Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' server object.
-description:
- - Manage SLB (Server Load Balancer) server objects on A10 Networks devices via aXAPIv2.
-author:
- - Eric Chou (@ericchou1)
- - Mischa Peters (@mischapeters)
-notes:
- - Requires A10 Networks aXAPI 2.1.
-extends_documentation_fragment:
-- community.general.a10
-- url
-
-options:
- partition:
- description:
- - set active-partition
- server_name:
- description:
- - The SLB (Server Load Balancer) server name.
- required: true
- aliases: ['server']
- server_ip:
- description:
- - The SLB server IPv4 address.
- aliases: ['ip', 'address']
- server_status:
- description:
- - The SLB virtual server status.
- default: enabled
- aliases: ['status']
- choices: ['enabled', 'disabled']
- server_ports:
- description:
- - A list of ports to create for the server. Each list item should be a
- dictionary which specifies the C(port:) and C(protocol:), but can also optionally
- specify the C(status:). See the examples below for details. This parameter is
- required when C(state) is C(present).
- aliases: ['port']
- state:
- description:
- - This is to specify the operation to create, update or remove SLB server.
- default: present
- choices: ['present', 'absent']
- validate_certs:
- description:
- - If C(no), SSL certificates will not be validated. This should only be used
- on personally controlled devices using self-signed certificates.
- type: bool
- default: 'yes'
-
-'''
-
-EXAMPLES = '''
-# Create a new server
-- a10_server:
- host: a10.mydomain.com
- username: myadmin
- password: mypassword
- partition: mypartition
- server: test
- server_ip: 1.1.1.100
- server_ports:
- - port_num: 8080
- protocol: tcp
- - port_num: 8443
- protocol: TCP
-
-'''
-
-RETURN = '''
-content:
- description: the full info regarding the slb_server
- returned: success
- type: str
- sample: "mynewserver"
-'''
-import json
-
-from ansible_collections.community.general.plugins.module_utils.network.a10.a10 import (axapi_call, a10_argument_spec, axapi_authenticate, axapi_failure,
- axapi_get_port_protocol, axapi_enabled_disabled, AXAPI_PORT_PROTOCOLS)
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.urls import url_argument_spec
-
-
-VALID_PORT_FIELDS = ['port_num', 'protocol', 'status']
-
-
-def validate_ports(module, ports):
- for item in ports:
- for key in item:
- if key not in VALID_PORT_FIELDS:
- module.fail_json(msg="invalid port field (%s), must be one of: %s" % (key, ','.join(VALID_PORT_FIELDS)))
-
- # validate the port number is present and an integer
- if 'port_num' in item:
- try:
- item['port_num'] = int(item['port_num'])
- except Exception:
- module.fail_json(msg="port_num entries in the port definitions must be integers")
- else:
- module.fail_json(msg="port definitions must define the port_num field")
-
- # validate the port protocol is present, and convert it to
- # the internal API integer value (and validate it)
- if 'protocol' in item:
- protocol = axapi_get_port_protocol(item['protocol'])
- if not protocol:
- module.fail_json(msg="invalid port protocol, must be one of: %s" % ','.join(AXAPI_PORT_PROTOCOLS))
- else:
- item['protocol'] = protocol
- else:
- module.fail_json(msg="port definitions must define the port protocol (%s)" % ','.join(AXAPI_PORT_PROTOCOLS))
-
- # convert the status to the internal API integer value
- if 'status' in item:
- item['status'] = axapi_enabled_disabled(item['status'])
- else:
- item['status'] = 1
-
-
-def main():
- argument_spec = a10_argument_spec()
- argument_spec.update(url_argument_spec())
- argument_spec.update(
- dict(
- state=dict(type='str', default='present', choices=['present', 'absent']),
- server_name=dict(type='str', aliases=['server'], required=True),
- server_ip=dict(type='str', aliases=['ip', 'address']),
- server_status=dict(type='str', default='enabled', aliases=['status'], choices=['enabled', 'disabled']),
- server_ports=dict(type='list', aliases=['port'], default=[]),
- partition=dict(type='str', default=[]),
- )
- )
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=False
- )
-
- host = module.params['host']
- partition = module.params['partition']
- username = module.params['username']
- password = module.params['password']
- state = module.params['state']
- write_config = module.params['write_config']
- slb_server = module.params['server_name']
- slb_server_ip = module.params['server_ip']
- slb_server_status = module.params['server_status']
- slb_server_ports = module.params['server_ports']
-
- if slb_server is None:
- module.fail_json(msg='server_name is required')
-
- axapi_base_url = 'https://%s/services/rest/V2.1/?format=json' % host
- session_url = axapi_authenticate(module, axapi_base_url, username, password)
-
- # validate the ports data structure
- validate_ports(module, slb_server_ports)
-
- json_post = {
- 'server': {
- 'name': slb_server,
- }
- }
-
- # add optional module parameters
- if slb_server_ip:
- json_post['server']['host'] = slb_server_ip
-
- if slb_server_ports:
- json_post['server']['port_list'] = slb_server_ports
-
- if slb_server_status:
- json_post['server']['status'] = axapi_enabled_disabled(slb_server_status)
-
- axapi_call(module, session_url + '&method=system.partition.active', json.dumps({'name': partition}))
-
- slb_server_data = axapi_call(module, session_url + '&method=slb.server.search', json.dumps({'name': slb_server}))
- slb_server_exists = not axapi_failure(slb_server_data)
-
- changed = False
- if state == 'present':
- if not slb_server_exists:
- if not slb_server_ip:
- module.fail_json(msg='you must specify an IP address when creating a server')
-
- result = axapi_call(module, session_url + '&method=slb.server.create', json.dumps(json_post))
- if axapi_failure(result):
- module.fail_json(msg="failed to create the server: %s" % result['response']['err']['msg'])
- changed = True
- else:
- def port_needs_update(src_ports, dst_ports):
- '''
- Checks to determine if the port definitions of the src_ports
- array are in or different from those in dst_ports. If there is
- a difference, this function returns true, otherwise false.
- '''
- for src_port in src_ports:
- found = False
- different = False
- for dst_port in dst_ports:
- if src_port['port_num'] == dst_port['port_num']:
- found = True
- for valid_field in VALID_PORT_FIELDS:
- if src_port[valid_field] != dst_port[valid_field]:
- different = True
- break
- if found or different:
- break
- if not found or different:
- return True
- # every port from the src exists in the dst, and none of them were different
- return False
-
- def status_needs_update(current_status, new_status):
- '''
- Check to determine if we want to change the status of a server.
- If there is a difference between the current status of the server and
- the desired status, return true, otherwise false.
- '''
- if current_status != new_status:
- return True
- return False
-
- defined_ports = slb_server_data.get('server', {}).get('port_list', [])
- current_status = slb_server_data.get('server', {}).get('status')
-
- # we check for a needed update several ways
- # - in case ports are missing from the ones specified by the user
- # - in case ports are missing from those on the device
- # - in case we are change the status of a server
- if (port_needs_update(defined_ports, slb_server_ports) or
- port_needs_update(slb_server_ports, defined_ports) or
- status_needs_update(current_status, axapi_enabled_disabled(slb_server_status))):
- result = axapi_call(module, session_url + '&method=slb.server.update', json.dumps(json_post))
- if axapi_failure(result):
- module.fail_json(msg="failed to update the server: %s" % result['response']['err']['msg'])
- changed = True
-
- # if we changed things, get the full info regarding
- # the service group for the return data below
- if changed:
- result = axapi_call(module, session_url + '&method=slb.server.search', json.dumps({'name': slb_server}))
- else:
- result = slb_server_data
- elif state == 'absent':
- if slb_server_exists:
- result = axapi_call(module, session_url + '&method=slb.server.delete', json.dumps({'name': slb_server}))
- changed = True
- else:
- result = dict(msg="the server was not present")
-
- # if the config has changed, save the config unless otherwise requested
- if changed and write_config:
- write_result = axapi_call(module, session_url + '&method=system.action.write_memory')
- if axapi_failure(write_result):
- module.fail_json(msg="failed to save the configuration: %s" % write_result['response']['err']['msg'])
-
- # log out of the session nicely and exit
- axapi_call(module, session_url + '&method=session.close')
- module.exit_json(changed=changed, content=result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/a10/a10_server_axapi3.py b/plugins/modules/network/a10/a10_server_axapi3.py
deleted file mode 100644
index cf2eae0614..0000000000
--- a/plugins/modules/network/a10/a10_server_axapi3.py
+++ /dev/null
@@ -1,244 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2014, Mischa Peters
-# Copyright: (c) 2016, Eric Chou
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: a10_server_axapi3
-short_description: Manage A10 Networks AX/SoftAX/Thunder/vThunder devices
-description:
- - Manage SLB (Server Load Balancer) server objects on A10 Networks devices via aXAPIv3.
-author:
- - Eric Chou (@ericchou1)
-extends_documentation_fragment:
-- community.general.a10
-- url
-
-options:
- server_name:
- description:
- - The SLB (Server Load Balancer) server name.
- required: true
- aliases: ['server']
- server_ip:
- description:
- - The SLB (Server Load Balancer) server IPv4 address.
- required: true
- aliases: ['ip', 'address']
- server_status:
- description:
- - The SLB (Server Load Balancer) virtual server status.
- default: enable
- aliases: ['action']
- choices: ['enable', 'disable']
- server_ports:
- description:
- - A list of ports to create for the server. Each list item should be a dictionary which specifies the C(port:)
- and C(protocol:).
- aliases: ['port']
- operation:
- description:
- - Create, Update or Remove SLB server. For create and update operation, we use the IP address and server
- name specified in the POST message. For delete operation, we use the server name in the request URI.
- default: create
- choices: ['create', 'update', 'remove']
- validate_certs:
- description:
- - If C(no), SSL certificates will not be validated. This should only be used
- on personally controlled devices using self-signed certificates.
- type: bool
- default: 'yes'
-
-'''
-
-RETURN = '''
-#
-'''
-
-EXAMPLES = '''
-# Create a new server
-- a10_server:
- host: a10.mydomain.com
- username: myadmin
- password: mypassword
- server: test
- server_ip: 1.1.1.100
- validate_certs: false
- server_status: enable
- write_config: yes
- operation: create
- server_ports:
- - port-number: 8080
- protocol: tcp
- action: enable
- - port-number: 8443
- protocol: TCP
-
-'''
-import json
-
-from ansible_collections.community.general.plugins.module_utils.network.a10.a10 import axapi_call_v3, a10_argument_spec, axapi_authenticate_v3, axapi_failure
-from ansible_collections.community.general.plugins.module_utils.network.a10.a10 import AXAPI_PORT_PROTOCOLS
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.urls import url_argument_spec
-
-
-VALID_PORT_FIELDS = ['port-number', 'protocol', 'action']
-
-
-def validate_ports(module, ports):
- for item in ports:
- for key in item:
- if key not in VALID_PORT_FIELDS:
- module.fail_json(msg="invalid port field (%s), must be one of: %s" % (key, ','.join(VALID_PORT_FIELDS)))
-
- # validate the port number is present and an integer
- if 'port-number' in item:
- try:
- item['port-number'] = int(item['port-number'])
- except Exception:
- module.fail_json(msg="port-number entries in the port definitions must be integers")
- else:
- module.fail_json(msg="port definitions must define the port-number field")
-
- # validate the port protocol is present, no need to convert to the internal API integer value in v3
- if 'protocol' in item:
- protocol = item['protocol']
- if not protocol:
- module.fail_json(msg="invalid port protocol, must be one of: %s" % ','.join(AXAPI_PORT_PROTOCOLS))
- else:
- item['protocol'] = protocol
- else:
- module.fail_json(msg="port definitions must define the port protocol (%s)" % ','.join(AXAPI_PORT_PROTOCOLS))
-
- # 'status' is 'action' in AXAPIv3
- # no need to convert the status, a.k.a action, to the internal API integer value in v3
- # action is either enabled or disabled
- if 'action' in item:
- action = item['action']
- if action not in ['enable', 'disable']:
- module.fail_json(msg="server action must be enable or disable")
- else:
- item['action'] = 'enable'
-
-
-def main():
- argument_spec = a10_argument_spec()
- argument_spec.update(url_argument_spec())
- argument_spec.update(
- dict(
- operation=dict(type='str', default='create', choices=['create', 'update', 'delete']),
- server_name=dict(type='str', aliases=['server'], required=True),
- server_ip=dict(type='str', aliases=['ip', 'address'], required=True),
- server_status=dict(type='str', default='enable', aliases=['action'], choices=['enable', 'disable']),
- server_ports=dict(type='list', aliases=['port'], default=[]),
- )
- )
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=False
- )
-
- host = module.params['host']
- username = module.params['username']
- password = module.params['password']
- operation = module.params['operation']
- write_config = module.params['write_config']
- slb_server = module.params['server_name']
- slb_server_ip = module.params['server_ip']
- slb_server_status = module.params['server_status']
- slb_server_ports = module.params['server_ports']
-
- axapi_base_url = 'https://{0}/axapi/v3/'.format(host)
- axapi_auth_url = axapi_base_url + 'auth/'
- signature = axapi_authenticate_v3(module, axapi_auth_url, username, password)
-
- # validate the ports data structure
- validate_ports(module, slb_server_ports)
-
- json_post = {
- "server-list": [
- {
- "name": slb_server,
- "host": slb_server_ip
- }
- ]
- }
-
- # add optional module parameters
- if slb_server_ports:
- json_post['server-list'][0]['port-list'] = slb_server_ports
-
- if slb_server_status:
- json_post['server-list'][0]['action'] = slb_server_status
-
- slb_server_data = axapi_call_v3(module, axapi_base_url + 'slb/server/', method='GET', body='', signature=signature)
-
- # for empty slb server list
- if axapi_failure(slb_server_data):
- slb_server_exists = False
- else:
- slb_server_list = [server['name'] for server in slb_server_data['server-list']]
- if slb_server in slb_server_list:
- slb_server_exists = True
- else:
- slb_server_exists = False
-
- changed = False
- if operation == 'create':
- if slb_server_exists is False:
- result = axapi_call_v3(module, axapi_base_url + 'slb/server/', method='POST', body=json.dumps(json_post), signature=signature)
- if axapi_failure(result):
- module.fail_json(msg="failed to create the server: %s" % result['response']['err']['msg'])
- changed = True
- else:
- module.fail_json(msg="server already exists, use state='update' instead")
- changed = False
- # if we changed things, get the full info regarding result
- if changed:
- result = axapi_call_v3(module, axapi_base_url + 'slb/server/' + slb_server, method='GET', body='', signature=signature)
- else:
- result = slb_server_data
- elif operation == 'delete':
- if slb_server_exists:
- result = axapi_call_v3(module, axapi_base_url + 'slb/server/' + slb_server, method='DELETE', body='', signature=signature)
- if axapi_failure(result):
- module.fail_json(msg="failed to delete server: %s" % result['response']['err']['msg'])
- changed = True
- else:
- result = dict(msg="the server was not present")
- elif operation == 'update':
- if slb_server_exists:
- result = axapi_call_v3(module, axapi_base_url + 'slb/server/', method='PUT', body=json.dumps(json_post), signature=signature)
- if axapi_failure(result):
- module.fail_json(msg="failed to update server: %s" % result['response']['err']['msg'])
- changed = True
- else:
- result = dict(msg="the server was not present")
-
- # if the config has changed, save the config unless otherwise requested
- if changed and write_config:
- write_result = axapi_call_v3(module, axapi_base_url + 'write/memory/', method='POST', body='', signature=signature)
- if axapi_failure(write_result):
- module.fail_json(msg="failed to save the configuration: %s" % write_result['response']['err']['msg'])
-
- # log out gracefully and exit
- axapi_call_v3(module, axapi_base_url + 'logoff/', method='POST', body='', signature=signature)
- module.exit_json(changed=changed, content=result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/a10/a10_service_group.py b/plugins/modules/network/a10/a10_service_group.py
deleted file mode 100644
index cc05e03093..0000000000
--- a/plugins/modules/network/a10/a10_service_group.py
+++ /dev/null
@@ -1,338 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2014, Mischa Peters ,
-# Eric Chou
-#
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: a10_service_group
-short_description: Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' service groups.
-description:
- - Manage SLB (Server Load Balancing) service-group objects on A10 Networks devices via aXAPIv2.
-author:
- - Eric Chou (@ericchou1)
- - Mischa Peters (@mischapeters)
-notes:
- - Requires A10 Networks aXAPI 2.1.
- - When a server doesn't exist and is added to the service-group the server will be created.
-extends_documentation_fragment:
-- community.general.a10
-- url
-
-options:
- state:
- description:
- - If the specified service group should exists.
- default: present
- choices: ['present', 'absent']
- partition:
- description:
- - set active-partition
- service_group:
- description:
- - The SLB (Server Load Balancing) service-group name
- required: true
- aliases: ['service', 'pool', 'group']
- service_group_protocol:
- description:
- - The SLB service-group protocol of TCP or UDP.
- default: tcp
- aliases: ['proto', 'protocol']
- choices: ['tcp', 'udp']
- service_group_method:
- description:
- - The SLB service-group load balancing method, such as round-robin or weighted-rr.
- default: round-robin
- aliases: ['method']
- choices:
- - 'round-robin'
- - 'weighted-rr'
- - 'least-connection'
- - 'weighted-least-connection'
- - 'service-least-connection'
- - 'service-weighted-least-connection'
- - 'fastest-response'
- - 'least-request'
- - 'round-robin-strict'
- - 'src-ip-only-hash'
- - 'src-ip-hash'
- servers:
- description:
- - A list of servers to add to the service group. Each list item should be a
- dictionary which specifies the C(server:) and C(port:), but can also optionally
- specify the C(status:). See the examples below for details.
- aliases: ['server', 'member']
- validate_certs:
- description:
- - If C(no), SSL certificates will not be validated. This should only be used
- on personally controlled devices using self-signed certificates.
- type: bool
- default: 'yes'
-
-'''
-
-EXAMPLES = '''
-# Create a new service-group
-- a10_service_group:
- host: a10.mydomain.com
- username: myadmin
- password: mypassword
- partition: mypartition
- service_group: sg-80-tcp
- servers:
- - server: foo1.mydomain.com
- port: 8080
- - server: foo2.mydomain.com
- port: 8080
- - server: foo3.mydomain.com
- port: 8080
- - server: foo4.mydomain.com
- port: 8080
- status: disabled
-
-'''
-
-RETURN = '''
-content:
- description: the full info regarding the slb_service_group
- returned: success
- type: str
- sample: "mynewservicegroup"
-'''
-import json
-
-from ansible_collections.community.general.plugins.module_utils.network.a10.a10 import (axapi_call, a10_argument_spec, axapi_authenticate,
- axapi_failure, axapi_enabled_disabled)
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.urls import url_argument_spec
-
-
-VALID_SERVICE_GROUP_FIELDS = ['name', 'protocol', 'lb_method']
-VALID_SERVER_FIELDS = ['server', 'port', 'status']
-
-
-def validate_servers(module, servers):
- for item in servers:
- for key in item:
- if key not in VALID_SERVER_FIELDS:
- module.fail_json(msg="invalid server field (%s), must be one of: %s" % (key, ','.join(VALID_SERVER_FIELDS)))
-
- # validate the server name is present
- if 'server' not in item:
- module.fail_json(msg="server definitions must define the server field")
-
- # validate the port number is present and an integer
- if 'port' in item:
- try:
- item['port'] = int(item['port'])
- except Exception:
- module.fail_json(msg="server port definitions must be integers")
- else:
- module.fail_json(msg="server definitions must define the port field")
-
- # convert the status to the internal API integer value
- if 'status' in item:
- item['status'] = axapi_enabled_disabled(item['status'])
- else:
- item['status'] = 1
-
-
-def main():
- argument_spec = a10_argument_spec()
- argument_spec.update(url_argument_spec())
- argument_spec.update(
- dict(
- state=dict(type='str', default='present', choices=['present', 'absent']),
- service_group=dict(type='str', aliases=['service', 'pool', 'group'], required=True),
- service_group_protocol=dict(type='str', default='tcp', aliases=['proto', 'protocol'], choices=['tcp', 'udp']),
- service_group_method=dict(type='str', default='round-robin',
- aliases=['method'],
- choices=['round-robin',
- 'weighted-rr',
- 'least-connection',
- 'weighted-least-connection',
- 'service-least-connection',
- 'service-weighted-least-connection',
- 'fastest-response',
- 'least-request',
- 'round-robin-strict',
- 'src-ip-only-hash',
- 'src-ip-hash']),
- servers=dict(type='list', aliases=['server', 'member'], default=[]),
- partition=dict(type='str', default=[]),
- )
- )
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=False
- )
-
- host = module.params['host']
- username = module.params['username']
- password = module.params['password']
- partition = module.params['partition']
- state = module.params['state']
- write_config = module.params['write_config']
- slb_service_group = module.params['service_group']
- slb_service_group_proto = module.params['service_group_protocol']
- slb_service_group_method = module.params['service_group_method']
- slb_servers = module.params['servers']
-
- if slb_service_group is None:
- module.fail_json(msg='service_group is required')
-
- axapi_base_url = 'https://' + host + '/services/rest/V2.1/?format=json'
- load_balancing_methods = {'round-robin': 0,
- 'weighted-rr': 1,
- 'least-connection': 2,
- 'weighted-least-connection': 3,
- 'service-least-connection': 4,
- 'service-weighted-least-connection': 5,
- 'fastest-response': 6,
- 'least-request': 7,
- 'round-robin-strict': 8,
- 'src-ip-only-hash': 14,
- 'src-ip-hash': 15}
-
- if not slb_service_group_proto or slb_service_group_proto.lower() == 'tcp':
- protocol = 2
- else:
- protocol = 3
-
- # validate the server data list structure
- validate_servers(module, slb_servers)
-
- json_post = {
- 'service_group': {
- 'name': slb_service_group,
- 'protocol': protocol,
- 'lb_method': load_balancing_methods[slb_service_group_method],
- }
- }
-
- # first we authenticate to get a session id
- session_url = axapi_authenticate(module, axapi_base_url, username, password)
- # then we select the active-partition
- axapi_call(module, session_url + '&method=system.partition.active', json.dumps({'name': partition}))
- # then we check to see if the specified group exists
- slb_result = axapi_call(module, session_url + '&method=slb.service_group.search', json.dumps({'name': slb_service_group}))
- slb_service_group_exist = not axapi_failure(slb_result)
-
- changed = False
- if state == 'present':
- # before creating/updating we need to validate that servers
- # defined in the servers list exist to prevent errors
- checked_servers = []
- for server in slb_servers:
- result = axapi_call(module, session_url + '&method=slb.server.search', json.dumps({'name': server['server']}))
- if axapi_failure(result):
- module.fail_json(msg="the server %s specified in the servers list does not exist" % server['server'])
- checked_servers.append(server['server'])
-
- if not slb_service_group_exist:
- result = axapi_call(module, session_url + '&method=slb.service_group.create', json.dumps(json_post))
- if axapi_failure(result):
- module.fail_json(msg=result['response']['err']['msg'])
- changed = True
- else:
- # check to see if the service group definition without the
- # server members is different, and update that individually
- # if it needs it
- do_update = False
- for field in VALID_SERVICE_GROUP_FIELDS:
- if json_post['service_group'][field] != slb_result['service_group'][field]:
- do_update = True
- break
-
- if do_update:
- result = axapi_call(module, session_url + '&method=slb.service_group.update', json.dumps(json_post))
- if axapi_failure(result):
- module.fail_json(msg=result['response']['err']['msg'])
- changed = True
-
- # next we pull the defined list of servers out of the returned
- # results to make it a bit easier to iterate over
- defined_servers = slb_result.get('service_group', {}).get('member_list', [])
-
- # next we add/update new member servers from the user-specified
- # list if they're different or not on the target device
- for server in slb_servers:
- found = False
- different = False
- for def_server in defined_servers:
- if server['server'] == def_server['server']:
- found = True
- for valid_field in VALID_SERVER_FIELDS:
- if server[valid_field] != def_server[valid_field]:
- different = True
- break
- if found or different:
- break
- # add or update as required
- server_data = {
- "name": slb_service_group,
- "member": server,
- }
- if not found:
- result = axapi_call(module, session_url + '&method=slb.service_group.member.create', json.dumps(server_data))
- changed = True
- elif different:
- result = axapi_call(module, session_url + '&method=slb.service_group.member.update', json.dumps(server_data))
- changed = True
-
- # finally, remove any servers that are on the target
- # device but were not specified in the list given
- for server in defined_servers:
- found = False
- for slb_server in slb_servers:
- if server['server'] == slb_server['server']:
- found = True
- break
- # remove if not found
- server_data = {
- "name": slb_service_group,
- "member": server,
- }
- if not found:
- result = axapi_call(module, session_url + '&method=slb.service_group.member.delete', json.dumps(server_data))
- changed = True
-
- # if we changed things, get the full info regarding
- # the service group for the return data below
- if changed:
- result = axapi_call(module, session_url + '&method=slb.service_group.search', json.dumps({'name': slb_service_group}))
- else:
- result = slb_result
- elif state == 'absent':
- if slb_service_group_exist:
- result = axapi_call(module, session_url + '&method=slb.service_group.delete', json.dumps({'name': slb_service_group}))
- changed = True
- else:
- result = dict(msg="the service group was not present")
-
- # if the config has changed, save the config unless otherwise requested
- if changed and write_config:
- write_result = axapi_call(module, session_url + '&method=system.action.write_memory')
- if axapi_failure(write_result):
- module.fail_json(msg="failed to save the configuration: %s" % write_result['response']['err']['msg'])
-
- # log out of the session nicely and exit
- axapi_call(module, session_url + '&method=session.close')
- module.exit_json(changed=changed, content=result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/a10/a10_virtual_server.py b/plugins/modules/network/a10/a10_virtual_server.py
deleted file mode 100644
index 8f61788f04..0000000000
--- a/plugins/modules/network/a10/a10_virtual_server.py
+++ /dev/null
@@ -1,284 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2014, Mischa Peters ,
-# Eric Chou
-#
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: a10_virtual_server
-short_description: Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' virtual servers.
-description:
- - Manage SLB (Server Load Balancing) virtual server objects on A10 Networks devices via aXAPIv2.
-author:
- - Eric Chou (@ericchou1)
- - Mischa Peters (@mischapeters)
-notes:
- - Requires A10 Networks aXAPI 2.1.
-extends_documentation_fragment:
-- community.general.a10
-- url
-
-options:
- state:
- description:
- - If the specified virtual server should exist.
- choices: ['present', 'absent']
- default: present
- partition:
- description:
- - set active-partition
- virtual_server:
- description:
- - The SLB (Server Load Balancing) virtual server name.
- required: true
- aliases: ['vip', 'virtual']
- virtual_server_ip:
- description:
- - The SLB virtual server IPv4 address.
- aliases: ['ip', 'address']
- virtual_server_status:
- description:
- - The SLB virtual server status, such as enabled or disabled.
- default: enable
- aliases: ['status']
- choices: ['enabled', 'disabled']
- virtual_server_ports:
- description:
- - A list of ports to create for the virtual server. Each list item should be a
- dictionary which specifies the C(port:) and C(type:), but can also optionally
- specify the C(service_group:) as well as the C(status:). See the examples
- below for details. This parameter is required when C(state) is C(present).
- validate_certs:
- description:
- - If C(no), SSL certificates will not be validated. This should only be used
- on personally controlled devices using self-signed certificates.
- type: bool
- default: 'yes'
-
-'''
-
-
-EXAMPLES = '''
-# Create a new virtual server
-- a10_virtual_server:
- host: a10.mydomain.com
- username: myadmin
- password: mypassword
- partition: mypartition
- virtual_server: vserver1
- virtual_server_ip: 1.1.1.1
- virtual_server_ports:
- - port: 80
- protocol: TCP
- service_group: sg-80-tcp
- - port: 443
- protocol: HTTPS
- service_group: sg-443-https
- - port: 8080
- protocol: http
- status: disabled
-
-'''
-
-RETURN = '''
-content:
- description: the full info regarding the slb_virtual
- returned: success
- type: str
- sample: "mynewvirtualserver"
-'''
-import json
-
-from ansible_collections.community.general.plugins.module_utils.network.a10.a10 import (axapi_call, a10_argument_spec, axapi_authenticate, axapi_failure,
- axapi_enabled_disabled, axapi_get_vport_protocol,
- AXAPI_VPORT_PROTOCOLS)
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.urls import url_argument_spec
-
-
-VALID_PORT_FIELDS = ['port', 'protocol', 'service_group', 'status']
-
-
-def validate_ports(module, ports):
- for item in ports:
- for key in item:
- if key not in VALID_PORT_FIELDS:
- module.fail_json(msg="invalid port field (%s), must be one of: %s" % (key, ','.join(VALID_PORT_FIELDS)))
-
- # validate the port number is present and an integer
- if 'port' in item:
- try:
- item['port'] = int(item['port'])
- except Exception:
- module.fail_json(msg="port definitions must be integers")
- else:
- module.fail_json(msg="port definitions must define the port field")
-
- # validate the port protocol is present, and convert it to
- # the internal API integer value (and validate it)
- if 'protocol' in item:
- protocol = axapi_get_vport_protocol(item['protocol'])
- if not protocol:
- module.fail_json(msg="invalid port protocol, must be one of: %s" % ','.join(AXAPI_VPORT_PROTOCOLS))
- else:
- item['protocol'] = protocol
- else:
- module.fail_json(msg="port definitions must define the port protocol (%s)" % ','.join(AXAPI_VPORT_PROTOCOLS))
-
- # convert the status to the internal API integer value
- if 'status' in item:
- item['status'] = axapi_enabled_disabled(item['status'])
- else:
- item['status'] = 1
-
- # ensure the service_group field is at least present
- if 'service_group' not in item:
- item['service_group'] = ''
-
-
-def main():
- argument_spec = a10_argument_spec()
- argument_spec.update(url_argument_spec())
- argument_spec.update(
- dict(
- state=dict(type='str', default='present', choices=['present', 'absent']),
- virtual_server=dict(type='str', aliases=['vip', 'virtual'], required=True),
- virtual_server_ip=dict(type='str', aliases=['ip', 'address'], required=True),
- virtual_server_status=dict(type='str', default='enabled', aliases=['status'], choices=['enabled', 'disabled']),
- virtual_server_ports=dict(type='list', required=True),
- partition=dict(type='str', default=[]),
- )
- )
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=False
- )
-
- host = module.params['host']
- username = module.params['username']
- password = module.params['password']
- partition = module.params['partition']
- state = module.params['state']
- write_config = module.params['write_config']
- slb_virtual = module.params['virtual_server']
- slb_virtual_ip = module.params['virtual_server_ip']
- slb_virtual_status = module.params['virtual_server_status']
- slb_virtual_ports = module.params['virtual_server_ports']
-
- if slb_virtual is None:
- module.fail_json(msg='virtual_server is required')
-
- validate_ports(module, slb_virtual_ports)
-
- axapi_base_url = 'https://%s/services/rest/V2.1/?format=json' % host
- session_url = axapi_authenticate(module, axapi_base_url, username, password)
-
- axapi_call(module, session_url + '&method=system.partition.active', json.dumps({'name': partition}))
- slb_virtual_data = axapi_call(module, session_url + '&method=slb.virtual_server.search', json.dumps({'name': slb_virtual}))
- slb_virtual_exists = not axapi_failure(slb_virtual_data)
-
- changed = False
- if state == 'present':
- json_post = {
- 'virtual_server': {
- 'name': slb_virtual,
- 'address': slb_virtual_ip,
- 'status': axapi_enabled_disabled(slb_virtual_status),
- 'vport_list': slb_virtual_ports,
- }
- }
-
- # before creating/updating we need to validate that any
- # service groups defined in the ports list exist since
- # since the API will still create port definitions for
- # them while indicating a failure occurred
- checked_service_groups = []
- for port in slb_virtual_ports:
- if 'service_group' in port and port['service_group'] not in checked_service_groups:
- # skip blank service group entries
- if port['service_group'] == '':
- continue
- result = axapi_call(module, session_url + '&method=slb.service_group.search', json.dumps({'name': port['service_group']}))
- if axapi_failure(result):
- module.fail_json(msg="the service group %s specified in the ports list does not exist" % port['service_group'])
- checked_service_groups.append(port['service_group'])
-
- if not slb_virtual_exists:
- result = axapi_call(module, session_url + '&method=slb.virtual_server.create', json.dumps(json_post))
- if axapi_failure(result):
- module.fail_json(msg="failed to create the virtual server: %s" % result['response']['err']['msg'])
- changed = True
- else:
- def needs_update(src_ports, dst_ports):
- '''
- Checks to determine if the port definitions of the src_ports
- array are in or different from those in dst_ports. If there is
- a difference, this function returns true, otherwise false.
- '''
- for src_port in src_ports:
- found = False
- different = False
- for dst_port in dst_ports:
- if src_port['port'] == dst_port['port']:
- found = True
- for valid_field in VALID_PORT_FIELDS:
- if src_port[valid_field] != dst_port[valid_field]:
- different = True
- break
- if found or different:
- break
- if not found or different:
- return True
- # every port from the src exists in the dst, and none of them were different
- return False
-
- defined_ports = slb_virtual_data.get('virtual_server', {}).get('vport_list', [])
-
- # we check for a needed update both ways, in case ports
- # are missing from either the ones specified by the user
- # or from those on the device
- if needs_update(defined_ports, slb_virtual_ports) or needs_update(slb_virtual_ports, defined_ports):
- result = axapi_call(module, session_url + '&method=slb.virtual_server.update', json.dumps(json_post))
- if axapi_failure(result):
- module.fail_json(msg="failed to create the virtual server: %s" % result['response']['err']['msg'])
- changed = True
-
- # if we changed things, get the full info regarding
- # the service group for the return data below
- if changed:
- result = axapi_call(module, session_url + '&method=slb.virtual_server.search', json.dumps({'name': slb_virtual}))
- else:
- result = slb_virtual_data
- elif state == 'absent':
- if slb_virtual_exists:
- result = axapi_call(module, session_url + '&method=slb.virtual_server.delete', json.dumps({'name': slb_virtual}))
- changed = True
- else:
- result = dict(msg="the virtual server was not present")
-
- # if the config has changed, save the config unless otherwise requested
- if changed and write_config:
- write_result = axapi_call(module, session_url + '&method=system.action.write_memory')
- if axapi_failure(write_result):
- module.fail_json(msg="failed to save the configuration: %s" % write_result['response']['err']['msg'])
-
- # log out of the session nicely and exit
- axapi_call(module, session_url + '&method=session.close')
- module.exit_json(changed=changed, content=result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/aci/aci_interface_policy_fc.py b/plugins/modules/network/aci/aci_interface_policy_fc.py
deleted file mode 100644
index 7297b72479..0000000000
--- a/plugins/modules/network/aci/aci_interface_policy_fc.py
+++ /dev/null
@@ -1,239 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'certified'}
-
-DOCUMENTATION = r'''
----
-module: aci_interface_policy_fc
-short_description: Manage Fibre Channel interface policies (fc:IfPol)
-description:
-- Manage ACI Fiber Channel interface policies on Cisco ACI fabrics.
-options:
- fc_policy:
- description:
- - The name of the Fiber Channel interface policy.
- type: str
- required: yes
- aliases: [ name ]
- description:
- description:
- - The description of the Fiber Channel interface policy.
- type: str
- aliases: [ descr ]
- port_mode:
- description:
- - The Port Mode to use.
- - The APIC defaults to C(f) when unset during creation.
- type: str
- choices: [ f, np ]
- state:
- description:
- - Use C(present) or C(absent) for adding or removing.
- - Use C(query) for listing an object or multiple objects.
- type: str
- choices: [ absent, present, query ]
- default: present
- name_alias:
- description:
- - The alias for the current object. This relates to the nameAlias field in ACI.
- type: str
-extends_documentation_fragment:
-- cisco.aci.modules
-
-seealso:
-- name: APIC Management Information Model reference
- description: More information about the internal APIC class B(fc:IfPol).
- link: https://developer.cisco.com/docs/apic-mim-ref/
-author:
-- Dag Wieers (@dagwieers)
-'''
-
-EXAMPLES = r'''
-- aci_interface_policy_fc:
- host: '{{ hostname }}'
- username: '{{ username }}'
- password: '{{ password }}'
- fc_policy: '{{ fc_policy }}'
- port_mode: '{{ port_mode }}'
- description: '{{ description }}'
- state: present
- delegate_to: localhost
-'''
-
-RETURN = r'''
-current:
- description: The existing configuration from the APIC after the module has finished
- returned: success
- type: list
- sample:
- [
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment",
- "dn": "uni/tn-production",
- "name": "production",
- "nameAlias": "",
- "ownerKey": "",
- "ownerTag": ""
- }
- }
- }
- ]
-error:
- description: The error information as returned from the APIC
- returned: failure
- type: dict
- sample:
- {
- "code": "122",
- "text": "unknown managed object class foo"
- }
-raw:
- description: The raw output returned by the APIC REST API (xml or json)
- returned: parse error
- type: str
- sample: ''
-sent:
- description: The actual/minimal configuration pushed to the APIC
- returned: info
- type: list
- sample:
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment"
- }
- }
- }
-previous:
- description: The original configuration from the APIC before the module has started
- returned: info
- type: list
- sample:
- [
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production",
- "dn": "uni/tn-production",
- "name": "production",
- "nameAlias": "",
- "ownerKey": "",
- "ownerTag": ""
- }
- }
- }
- ]
-proposed:
- description: The assembled configuration from the user-provided parameters
- returned: info
- type: dict
- sample:
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment",
- "name": "production"
- }
- }
- }
-filter_string:
- description: The filter string used for the request
- returned: failure or debug
- type: str
- sample: ?rsp-prop-include=config-only
-method:
- description: The HTTP method used for the request to the APIC
- returned: failure or debug
- type: str
- sample: POST
-response:
- description: The HTTP response from the APIC
- returned: failure or debug
- type: str
- sample: OK (30 bytes)
-status:
- description: The HTTP status from the APIC
- returned: failure or debug
- type: int
- sample: 200
-url:
- description: The HTTP url used for the request to the APIC
- returned: failure or debug
- type: str
- sample: https://10.11.12.13/api/mo/uni/tn-production.json
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
-
-
-def main():
- argument_spec = aci_argument_spec()
- argument_spec.update(
- fc_policy=dict(type='str', aliases=['name']), # Not required for querying all objects
- description=dict(type='str', aliases=['descr']),
- port_mode=dict(type='str', choices=['f', 'np']), # No default provided on purpose
- state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
- name_alias=dict(type='str'),
- )
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- required_if=[
- ['state', 'absent', ['fc_policy']],
- ['state', 'present', ['fc_policy']],
- ],
- )
-
- fc_policy = module.params.get('fc_policy')
- port_mode = module.params.get('port_mode')
- description = module.params.get('description')
- state = module.params.get('state')
- name_alias = module.params.get('name_alias')
-
- aci = ACIModule(module)
- aci.construct_url(
- root_class=dict(
- aci_class='fcIfPol',
- aci_rn='infra/fcIfPol-{0}'.format(fc_policy),
- module_object=fc_policy,
- target_filter={'name': fc_policy},
- ),
- )
-
- aci.get_existing()
-
- if state == 'present':
- aci.payload(
- aci_class='fcIfPol',
- class_config=dict(
- name=fc_policy,
- descr=description,
- portMode=port_mode,
- nameAlias=name_alias,
- ),
- )
-
- aci.get_diff(aci_class='fcIfPol')
-
- aci.post_config()
-
- elif state == 'absent':
- aci.delete_config()
-
- aci.exit_json()
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/aci/aci_interface_policy_l2.py b/plugins/modules/network/aci/aci_interface_policy_l2.py
deleted file mode 100644
index d2ac475f27..0000000000
--- a/plugins/modules/network/aci/aci_interface_policy_l2.py
+++ /dev/null
@@ -1,264 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'certified'}
-
-DOCUMENTATION = r'''
----
-module: aci_interface_policy_l2
-short_description: Manage Layer 2 interface policies (l2:IfPol)
-description:
-- Manage Layer 2 interface policies on Cisco ACI fabrics.
-options:
- l2_policy:
- description:
- - The name of the Layer 2 interface policy.
- type: str
- required: yes
- aliases: [ name ]
- description:
- description:
- - The description of the Layer 2 interface policy.
- type: str
- aliases: [ descr ]
- qinq:
- description:
- - Determines if QinQ is disabled or if the port should be considered a core or edge port.
- - The APIC defaults to C(disabled) when unset during creation.
- type: str
- choices: [ core, disabled, edge ]
- vepa:
- description:
- - Determines if Virtual Ethernet Port Aggregator is disabled or enabled.
- - The APIC defaults to C(no) when unset during creation.
- type: bool
- vlan_scope:
- description:
- - The scope of the VLAN.
- - The APIC defaults to C(global) when unset during creation.
- type: str
- choices: [ global, portlocal ]
- state:
- description:
- - Use C(present) or C(absent) for adding or removing.
- - Use C(query) for listing an object or multiple objects.
- type: str
- choices: [ absent, present, query ]
- default: present
- name_alias:
- description:
- - The alias for the current object. This relates to the nameAlias field in ACI.
- type: str
-extends_documentation_fragment:
-- cisco.aci.modules
-
-seealso:
-- name: APIC Management Information Model reference
- description: More information about the internal APIC class B(l2:IfPol).
- link: https://developer.cisco.com/docs/apic-mim-ref/
-author:
-- Dag Wieers (@dagwieers)
-'''
-
-EXAMPLES = r'''
-- aci_interface_policy_l2:
- host: '{{ hostname }}'
- username: '{{ username }}'
- password: '{{ password }}'
- l2_policy: '{{ l2_policy }}'
- vlan_scope: '{{ vlan_policy }}'
- description: '{{ description }}'
- delegate_to: localhost
-'''
-
-RETURN = r'''
-current:
- description: The existing configuration from the APIC after the module has finished
- returned: success
- type: list
- sample:
- [
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment",
- "dn": "uni/tn-production",
- "name": "production",
- "nameAlias": "",
- "ownerKey": "",
- "ownerTag": ""
- }
- }
- }
- ]
-error:
- description: The error information as returned from the APIC
- returned: failure
- type: dict
- sample:
- {
- "code": "122",
- "text": "unknown managed object class foo"
- }
-raw:
- description: The raw output returned by the APIC REST API (xml or json)
- returned: parse error
- type: str
- sample: ''
-sent:
- description: The actual/minimal configuration pushed to the APIC
- returned: info
- type: list
- sample:
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment"
- }
- }
- }
-previous:
- description: The original configuration from the APIC before the module has started
- returned: info
- type: list
- sample:
- [
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production",
- "dn": "uni/tn-production",
- "name": "production",
- "nameAlias": "",
- "ownerKey": "",
- "ownerTag": ""
- }
- }
- }
- ]
-proposed:
- description: The assembled configuration from the user-provided parameters
- returned: info
- type: dict
- sample:
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment",
- "name": "production"
- }
- }
- }
-filter_string:
- description: The filter string used for the request
- returned: failure or debug
- type: str
- sample: ?rsp-prop-include=config-only
-method:
- description: The HTTP method used for the request to the APIC
- returned: failure or debug
- type: str
- sample: POST
-response:
- description: The HTTP response from the APIC
- returned: failure or debug
- type: str
- sample: OK (30 bytes)
-status:
- description: The HTTP status from the APIC
- returned: failure or debug
- type: int
- sample: 200
-url:
- description: The HTTP url used for the request to the APIC
- returned: failure or debug
- type: str
- sample: https://10.11.12.13/api/mo/uni/tn-production.json
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
-
-# Mapping dicts are used to normalize the proposed data to what the APIC expects, which will keep diffs accurate
-QINQ_MAPPING = dict(
- core='corePort',
- disabled='disabled',
- edge='edgePort',
-)
-
-
-def main():
- argument_spec = aci_argument_spec()
- argument_spec.update(
- l2_policy=dict(type='str', aliases=['name']), # Not required for querying all policies
- description=dict(type='str', aliases=['descr']),
- vlan_scope=dict(type='str', choices=['global', 'portlocal']), # No default provided on purpose
- qinq=dict(type='str', choices=['core', 'disabled', 'edge']),
- vepa=dict(type='bool'),
- state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
- name_alias=dict(type='str'),
- )
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- required_if=[
- ['state', 'absent', ['l2_policy']],
- ['state', 'present', ['l2_policy']],
- ],
- )
-
- aci = ACIModule(module)
-
- l2_policy = module.params.get('l2_policy')
- vlan_scope = module.params.get('vlan_scope')
- qinq = module.params.get('qinq')
- if qinq is not None:
- qinq = QINQ_MAPPING.get(qinq)
- vepa = aci.boolean(module.params.get('vepa'), 'enabled', 'disabled')
- description = module.params.get('description')
- state = module.params.get('state')
- name_alias = module.params.get('name_alias')
-
- aci.construct_url(
- root_class=dict(
- aci_class='l2IfPol',
- aci_rn='infra/l2IfP-{0}'.format(l2_policy),
- module_object=l2_policy,
- target_filter={'name': l2_policy},
- ),
- )
-
- aci.get_existing()
-
- if state == 'present':
- aci.payload(
- aci_class='l2IfPol',
- class_config=dict(
- name=l2_policy,
- descr=description,
- vlanScope=vlan_scope,
- qinq=qinq, vepa=vepa,
- nameAlias=name_alias,
- ),
- )
-
- aci.get_diff(aci_class='l2IfPol')
-
- aci.post_config()
-
- elif state == 'absent':
- aci.delete_config()
-
- aci.exit_json()
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/aci/aci_interface_policy_lldp.py b/plugins/modules/network/aci/aci_interface_policy_lldp.py
deleted file mode 100644
index baec7e29e3..0000000000
--- a/plugins/modules/network/aci/aci_interface_policy_lldp.py
+++ /dev/null
@@ -1,248 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'certified'}
-
-DOCUMENTATION = r'''
----
-module: aci_interface_policy_lldp
-short_description: Manage LLDP interface policies (lldp:IfPol)
-description:
-- Manage LLDP interface policies on Cisco ACI fabrics.
-options:
- lldp_policy:
- description:
- - The LLDP interface policy name.
- type: str
- required: yes
- aliases: [ name ]
- description:
- description:
- - The description for the LLDP interface policy name.
- type: str
- aliases: [ descr ]
- receive_state:
- description:
- - Enable or disable Receive state.
- - The APIC defaults to C(yes) when unset during creation.
- type: bool
- transmit_state:
- description:
- - Enable or Disable Transmit state.
- - The APIC defaults to C(yes) when unset during creation.
- type: bool
- state:
- description:
- - Use C(present) or C(absent) for adding or removing.
- - Use C(query) for listing an object or multiple objects.
- type: str
- choices: [ absent, present, query ]
- default: present
- name_alias:
- description:
- - The alias for the current object. This relates to the nameAlias field in ACI.
- type: str
-extends_documentation_fragment:
-- cisco.aci.modules
-
-seealso:
-- name: APIC Management Information Model reference
- description: More information about the internal APIC class B(lldp:IfPol).
- link: https://developer.cisco.com/docs/apic-mim-ref/
-author:
-- Dag Wieers (@dagwieers)
-'''
-
-# FIXME: Add more, better examples
-EXAMPLES = r'''
-- aci_interface_policy_lldp:
- host: '{{ hostname }}'
- username: '{{ username }}'
- password: '{{ password }}'
- lldp_policy: '{{ lldp_policy }}'
- description: '{{ description }}'
- receive_state: '{{ receive_state }}'
- transmit_state: '{{ transmit_state }}'
- delegate_to: localhost
-'''
-
-RETURN = r'''
-current:
- description: The existing configuration from the APIC after the module has finished
- returned: success
- type: list
- sample:
- [
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment",
- "dn": "uni/tn-production",
- "name": "production",
- "nameAlias": "",
- "ownerKey": "",
- "ownerTag": ""
- }
- }
- }
- ]
-error:
- description: The error information as returned from the APIC
- returned: failure
- type: dict
- sample:
- {
- "code": "122",
- "text": "unknown managed object class foo"
- }
-raw:
- description: The raw output returned by the APIC REST API (xml or json)
- returned: parse error
- type: str
- sample: ''
-sent:
- description: The actual/minimal configuration pushed to the APIC
- returned: info
- type: list
- sample:
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment"
- }
- }
- }
-previous:
- description: The original configuration from the APIC before the module has started
- returned: info
- type: list
- sample:
- [
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production",
- "dn": "uni/tn-production",
- "name": "production",
- "nameAlias": "",
- "ownerKey": "",
- "ownerTag": ""
- }
- }
- }
- ]
-proposed:
- description: The assembled configuration from the user-provided parameters
- returned: info
- type: dict
- sample:
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment",
- "name": "production"
- }
- }
- }
-filter_string:
- description: The filter string used for the request
- returned: failure or debug
- type: str
- sample: ?rsp-prop-include=config-only
-method:
- description: The HTTP method used for the request to the APIC
- returned: failure or debug
- type: str
- sample: POST
-response:
- description: The HTTP response from the APIC
- returned: failure or debug
- type: str
- sample: OK (30 bytes)
-status:
- description: The HTTP status from the APIC
- returned: failure or debug
- type: int
- sample: 200
-url:
- description: The HTTP url used for the request to the APIC
- returned: failure or debug
- type: str
- sample: https://10.11.12.13/api/mo/uni/tn-production.json
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
-
-
-def main():
- argument_spec = aci_argument_spec()
- argument_spec.update(
- lldp_policy=dict(type='str', aliases=['name']), # Not required for querying all objects
- description=dict(type='str', aliases=['descr']),
- receive_state=dict(type='bool'),
- transmit_state=dict(type='bool'),
- state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
- name_alias=dict(type='str'),
- )
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- required_if=[
- ['state', 'absent', ['lldp_policy']],
- ['state', 'present', ['lldp_policy']],
- ],
- )
-
- aci = ACIModule(module)
-
- lldp_policy = module.params.get('lldp_policy')
- description = module.params.get('description')
- receive_state = aci.boolean(module.params.get('receive_state'), 'enabled', 'disabled')
- transmit_state = aci.boolean(module.params.get('transmit_state'), 'enabled', 'disabled')
- state = module.params.get('state')
- name_alias = module.params.get('name_alias')
-
- aci.construct_url(
- root_class=dict(
- aci_class='lldpIfPol',
- aci_rn='infra/lldpIfP-{0}'.format(lldp_policy),
- module_object=lldp_policy,
- target_filter={'name': lldp_policy},
- ),
- )
-
- aci.get_existing()
-
- if state == 'present':
- aci.payload(
- aci_class='lldpIfPol',
- class_config=dict(
- name=lldp_policy,
- descr=description,
- adminRxSt=receive_state,
- adminTxSt=transmit_state,
- nameAlias=name_alias,
- ),
- )
-
- aci.get_diff(aci_class='lldpIfPol')
-
- aci.post_config()
-
- elif state == 'absent':
- aci.delete_config()
-
- aci.exit_json()
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/aci/aci_interface_policy_mcp.py b/plugins/modules/network/aci/aci_interface_policy_mcp.py
deleted file mode 100644
index 054b7d811e..0000000000
--- a/plugins/modules/network/aci/aci_interface_policy_mcp.py
+++ /dev/null
@@ -1,239 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'certified'}
-
-DOCUMENTATION = r'''
----
-module: aci_interface_policy_mcp
-short_description: Manage MCP interface policies (mcp:IfPol)
-description:
-- Manage MCP interface policies on Cisco ACI fabrics.
-options:
- mcp:
- description:
- - The name of the MCP interface.
- type: str
- required: yes
- aliases: [ mcp_interface, name ]
- description:
- description:
- - The description for the MCP interface.
- type: str
- aliases: [ descr ]
- admin_state:
- description:
- - Enable or disable admin state.
- - The APIC defaults to C(yes) when unset during creation.
- type: bool
- state:
- description:
- - Use C(present) or C(absent) for adding or removing.
- - Use C(query) for listing an object or multiple objects.
- type: str
- choices: [ absent, present, query ]
- default: present
- name_alias:
- description:
- - The alias for the current object. This relates to the nameAlias field in ACI.
- type: str
-extends_documentation_fragment:
-- cisco.aci.modules
-
-seealso:
-- name: APIC Management Information Model reference
- description: More information about the internal APIC class B(mcp:IfPol).
- link: https://developer.cisco.com/docs/apic-mim-ref/
-author:
-- Dag Wieers (@dagwieers)
-'''
-
-# FIXME: Add more, better examples
-EXAMPLES = r'''
-- aci_interface_policy_mcp:
- host: '{{ hostname }}'
- username: '{{ username }}'
- password: '{{ password }}'
- mcp: '{{ mcp }}'
- description: '{{ descr }}'
- admin_state: '{{ admin_state }}'
- delegate_to: localhost
-'''
-
-RETURN = r'''
-current:
- description: The existing configuration from the APIC after the module has finished
- returned: success
- type: list
- sample:
- [
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment",
- "dn": "uni/tn-production",
- "name": "production",
- "nameAlias": "",
- "ownerKey": "",
- "ownerTag": ""
- }
- }
- }
- ]
-error:
- description: The error information as returned from the APIC
- returned: failure
- type: dict
- sample:
- {
- "code": "122",
- "text": "unknown managed object class foo"
- }
-raw:
- description: The raw output returned by the APIC REST API (xml or json)
- returned: parse error
- type: str
- sample: ''
-sent:
- description: The actual/minimal configuration pushed to the APIC
- returned: info
- type: list
- sample:
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment"
- }
- }
- }
-previous:
- description: The original configuration from the APIC before the module has started
- returned: info
- type: list
- sample:
- [
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production",
- "dn": "uni/tn-production",
- "name": "production",
- "nameAlias": "",
- "ownerKey": "",
- "ownerTag": ""
- }
- }
- }
- ]
-proposed:
- description: The assembled configuration from the user-provided parameters
- returned: info
- type: dict
- sample:
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment",
- "name": "production"
- }
- }
- }
-filter_string:
- description: The filter string used for the request
- returned: failure or debug
- type: str
- sample: ?rsp-prop-include=config-only
-method:
- description: The HTTP method used for the request to the APIC
- returned: failure or debug
- type: str
- sample: POST
-response:
- description: The HTTP response from the APIC
- returned: failure or debug
- type: str
- sample: OK (30 bytes)
-status:
- description: The HTTP status from the APIC
- returned: failure or debug
- type: int
- sample: 200
-url:
- description: The HTTP url used for the request to the APIC
- returned: failure or debug
- type: str
- sample: https://10.11.12.13/api/mo/uni/tn-production.json
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
-
-
-def main():
- argument_spec = aci_argument_spec()
- argument_spec.update(
- mcp=dict(type='str', aliases=['mcp_interface', 'name']), # Not required for querying all objects
- description=dict(type='str', aliases=['descr']),
- admin_state=dict(type='bool'),
- state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
- name_alias=dict(type='str'),
- )
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- required_if=[
- ['state', 'absent', ['mcp']],
- ['state', 'present', ['mcp']],
- ],
- )
-
- aci = ACIModule(module)
-
- mcp = module.params.get('mcp')
- description = module.params.get('description')
- admin_state = aci.boolean(module.params.get('admin_state'), 'enabled', 'disabled')
- state = module.params.get('state')
- name_alias = module.params.get('name_alias')
-
- aci.construct_url(
- root_class=dict(
- aci_class='mcpIfPol',
- aci_rn='infra/mcpIfP-{0}'.format(mcp),
- module_object=mcp,
- target_filter={'name': mcp},
- ),
- )
-
- aci.get_existing()
-
- if state == 'present':
- aci.payload(
- aci_class='mcpIfPol',
- class_config=dict(
- name=mcp,
- descr=description,
- adminSt=admin_state,
- nameAlias=name_alias,
- ),
- )
-
- aci.get_diff(aci_class='mcpIfPol')
-
- aci.post_config()
-
- elif state == 'absent':
- aci.delete_config()
-
- aci.exit_json()
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/aci/aci_interface_policy_port_channel.py b/plugins/modules/network/aci/aci_interface_policy_port_channel.py
deleted file mode 100644
index 6700dd3fdf..0000000000
--- a/plugins/modules/network/aci/aci_interface_policy_port_channel.py
+++ /dev/null
@@ -1,321 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'certified'}
-
-DOCUMENTATION = r'''
----
-module: aci_interface_policy_port_channel
-short_description: Manage port channel interface policies (lacp:LagPol)
-description:
-- Manage port channel interface policies on Cisco ACI fabrics.
-options:
- port_channel:
- description:
- - Name of the port channel.
- type: str
- required: yes
- aliases: [ name ]
- description:
- description:
- - The description for the port channel.
- type: str
- aliases: [ descr ]
- max_links:
- description:
- - Maximum links.
- - Accepted values range between 1 and 16.
- - The APIC defaults to C(16) when unset during creation.
- type: int
- min_links:
- description:
- - Minimum links.
- - Accepted values range between 1 and 16.
- - The APIC defaults to C(1) when unset during creation.
- type: int
- mode:
- description:
- - Port channel interface policy mode.
- - Determines the LACP method to use for forming port-channels.
- - The APIC defaults to C(off) when unset during creation.
- type: str
- choices: [ active, mac-pin, mac-pin-nicload, 'off', passive ]
- fast_select:
- description:
- - Determines if Fast Select is enabled for Hot Standby Ports.
- - This makes up the LACP Policy Control Policy; if one setting is defined, then all other Control Properties
- left undefined or set to false will not exist after the task is ran.
- - The APIC defaults to C(yes) when unset during creation.
- type: bool
- graceful_convergence:
- description:
- - Determines if Graceful Convergence is enabled.
- - This makes up the LACP Policy Control Policy; if one setting is defined, then all other Control Properties
- left undefined or set to false will not exist after the task is ran.
- - The APIC defaults to C(yes) when unset during creation.
- type: bool
- load_defer:
- description:
- - Determines if Load Defer is enabled.
- - This makes up the LACP Policy Control Policy; if one setting is defined, then all other Control Properties
- left undefined or set to false will not exist after the task is ran.
- - The APIC defaults to C(no) when unset during creation.
- type: bool
- suspend_individual:
- description:
- - Determines if Suspend Individual is enabled.
- - This makes up the LACP Policy Control Policy; if one setting is defined, then all other Control Properties
- left undefined or set to false will not exist after the task is ran.
- - The APIC defaults to C(yes) when unset during creation.
- type: bool
- symmetric_hash:
- description:
- - Determines if Symmetric Hashing is enabled.
- - This makes up the LACP Policy Control Policy; if one setting is defined, then all other Control Properties
- left undefined or set to false will not exist after the task is ran.
- - The APIC defaults to C(no) when unset during creation.
- type: bool
- state:
- description:
- - Use C(present) or C(absent) for adding or removing.
- - Use C(query) for listing an object or multiple objects.
- type: str
- choices: [ absent, present, query ]
- default: present
- name_alias:
- description:
- - The alias for the current object. This relates to the nameAlias field in ACI.
- type: str
-extends_documentation_fragment:
-- cisco.aci.modules
-
-seealso:
-- name: APIC Management Information Model reference
- description: More information about the internal APIC class B(lacp:LagPol).
- link: https://developer.cisco.com/docs/apic-mim-ref/
-author:
-- Dag Wieers (@dagwieers)
-'''
-
-EXAMPLES = r'''
-- aci_interface_policy_port_channel:
- host: '{{ inventory_hostname }}'
- username: '{{ username }}'
- password: '{{ password }}'
- port_channel: '{{ port_channel }}'
- description: '{{ description }}'
- min_links: '{{ min_links }}'
- max_links: '{{ max_links }}'
- mode: '{{ mode }}'
- delegate_to: localhost
-'''
-
-RETURN = r'''
-current:
- description: The existing configuration from the APIC after the module has finished
- returned: success
- type: list
- sample:
- [
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment",
- "dn": "uni/tn-production",
- "name": "production",
- "nameAlias": "",
- "ownerKey": "",
- "ownerTag": ""
- }
- }
- }
- ]
-error:
- description: The error information as returned from the APIC
- returned: failure
- type: dict
- sample:
- {
- "code": "122",
- "text": "unknown managed object class foo"
- }
-raw:
- description: The raw output returned by the APIC REST API (xml or json)
- returned: parse error
- type: str
- sample: ''
-sent:
- description: The actual/minimal configuration pushed to the APIC
- returned: info
- type: list
- sample:
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment"
- }
- }
- }
-previous:
- description: The original configuration from the APIC before the module has started
- returned: info
- type: list
- sample:
- [
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production",
- "dn": "uni/tn-production",
- "name": "production",
- "nameAlias": "",
- "ownerKey": "",
- "ownerTag": ""
- }
- }
- }
- ]
-proposed:
- description: The assembled configuration from the user-provided parameters
- returned: info
- type: dict
- sample:
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment",
- "name": "production"
- }
- }
- }
-filter_string:
- description: The filter string used for the request
- returned: failure or debug
- type: str
- sample: ?rsp-prop-include=config-only
-method:
- description: The HTTP method used for the request to the APIC
- returned: failure or debug
- type: str
- sample: POST
-response:
- description: The HTTP response from the APIC
- returned: failure or debug
- type: str
- sample: OK (30 bytes)
-status:
- description: The HTTP status from the APIC
- returned: failure or debug
- type: int
- sample: 200
-url:
- description: The HTTP url used for the request to the APIC
- returned: failure or debug
- type: str
- sample: https://10.11.12.13/api/mo/uni/tn-production.json
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
-
-
-def main():
- argument_spec = aci_argument_spec()
- argument_spec.update(
- port_channel=dict(type='str', aliases=['name']), # Not required for querying all objects
- description=dict(type='str', aliases=['descr']),
- min_links=dict(type='int'),
- max_links=dict(type='int'),
- mode=dict(type='str', choices=['active', 'mac-pin', 'mac-pin-nicload', 'off', 'passive']),
- fast_select=dict(type='bool'),
- graceful_convergence=dict(type='bool'),
- load_defer=dict(type='bool'),
- suspend_individual=dict(type='bool'),
- symmetric_hash=dict(type='bool'),
- state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
- name_alias=dict(type='str'),
- )
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- required_if=[
- ['state', 'absent', ['port_channel']],
- ['state', 'present', ['port_channel']],
- ],
- )
-
- port_channel = module.params.get('port_channel')
- description = module.params.get('description')
- min_links = module.params.get('min_links')
- if min_links is not None and min_links not in range(1, 17):
- module.fail_json(msg='The "min_links" must be a value between 1 and 16')
- max_links = module.params.get('max_links')
- if max_links is not None and max_links not in range(1, 17):
- module.fail_json(msg='The "max_links" must be a value between 1 and 16')
- mode = module.params.get('mode')
- state = module.params.get('state')
- name_alias = module.params.get('name_alias')
-
- # Build ctrl value for request
- ctrl = []
- if module.params.get('fast_select') is True:
- ctrl.append('fast-sel-hot-stdby')
- if module.params.get('graceful_convergence') is True:
- ctrl.append('graceful-conv')
- if module.params.get('load_defer') is True:
- ctrl.append('load-defer')
- if module.params.get('suspend_individual') is True:
- ctrl.append('susp-individual')
- if module.params.get('symmetric_hash') is True:
- ctrl.append('symmetric-hash')
- if not ctrl:
- ctrl = None
- else:
- ctrl = ",".join(ctrl)
-
- aci = ACIModule(module)
- aci.construct_url(
- root_class=dict(
- aci_class='lacpLagPol',
- aci_rn='infra/lacplagp-{0}'.format(port_channel),
- module_object=port_channel,
- target_filter={'name': port_channel},
- ),
- )
-
- aci.get_existing()
-
- if state == 'present':
- aci.payload(
- aci_class='lacpLagPol',
- class_config=dict(
- name=port_channel,
- ctrl=ctrl,
- descr=description,
- minLinks=min_links,
- maxLinks=max_links,
- mode=mode,
- nameAlias=name_alias,
- ),
- )
-
- aci.get_diff(aci_class='lacpLagPol')
-
- aci.post_config()
-
- elif state == 'absent':
- aci.delete_config()
-
- aci.exit_json()
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/aci/aci_interface_policy_port_security.py b/plugins/modules/network/aci/aci_interface_policy_port_security.py
deleted file mode 100644
index 8434e7d1d6..0000000000
--- a/plugins/modules/network/aci/aci_interface_policy_port_security.py
+++ /dev/null
@@ -1,252 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'certified'}
-
-DOCUMENTATION = r'''
----
-module: aci_interface_policy_port_security
-short_description: Manage port security (l2:PortSecurityPol)
-description:
-- Manage port security on Cisco ACI fabrics.
-options:
- port_security:
- description:
- - The name of the port security.
- type: str
- required: yes
- aliases: [ name ]
- description:
- description:
- - The description for the contract.
- type: str
- aliases: [ descr ]
- max_end_points:
- description:
- - Maximum number of end points.
- - Accepted values range between C(0) and C(12000).
- - The APIC defaults to C(0) when unset during creation.
- type: int
- port_security_timeout:
- description:
- - The delay time in seconds before MAC learning is re-enabled
- - Accepted values range between C(60) and C(3600)
- - The APIC defaults to C(60) when unset during creation
- type: int
- state:
- description:
- - Use C(present) or C(absent) for adding or removing.
- - Use C(query) for listing an object or multiple objects.
- type: str
- choices: [ absent, present, query ]
- default: present
- name_alias:
- description:
- - The alias for the current object. This relates to the nameAlias field in ACI.
- type: str
-extends_documentation_fragment:
-- cisco.aci.modules
-
-seealso:
-- name: APIC Management Information Model reference
- description: More information about the internal APIC class B(l2:PortSecurityPol).
- link: https://developer.cisco.com/docs/apic-mim-ref/
-author:
-- Dag Wieers (@dagwieers)
-'''
-
-# FIXME: Add more, better examples
-EXAMPLES = r'''
-- aci_interface_policy_port_security:
- host: '{{ inventory_hostname }}'
- username: '{{ username }}'
- password: '{{ password }}'
- port_security: '{{ port_security }}'
- description: '{{ descr }}'
- max_end_points: '{{ max_end_points }}'
- port_security_timeout: '{{ port_security_timeout }}'
- delegate_to: localhost
-'''
-
-RETURN = r'''
-current:
- description: The existing configuration from the APIC after the module has finished
- returned: success
- type: list
- sample:
- [
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment",
- "dn": "uni/tn-production",
- "name": "production",
- "nameAlias": "",
- "ownerKey": "",
- "ownerTag": ""
- }
- }
- }
- ]
-error:
- description: The error information as returned from the APIC
- returned: failure
- type: dict
- sample:
- {
- "code": "122",
- "text": "unknown managed object class foo"
- }
-raw:
- description: The raw output returned by the APIC REST API (xml or json)
- returned: parse error
- type: str
- sample: ''
-sent:
- description: The actual/minimal configuration pushed to the APIC
- returned: info
- type: list
- sample:
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment"
- }
- }
- }
-previous:
- description: The original configuration from the APIC before the module has started
- returned: info
- type: list
- sample:
- [
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production",
- "dn": "uni/tn-production",
- "name": "production",
- "nameAlias": "",
- "ownerKey": "",
- "ownerTag": ""
- }
- }
- }
- ]
-proposed:
- description: The assembled configuration from the user-provided parameters
- returned: info
- type: dict
- sample:
- {
- "fvTenant": {
- "attributes": {
- "descr": "Production environment",
- "name": "production"
- }
- }
- }
-filter_string:
- description: The filter string used for the request
- returned: failure or debug
- type: str
- sample: ?rsp-prop-include=config-only
-method:
- description: The HTTP method used for the request to the APIC
- returned: failure or debug
- type: str
- sample: POST
-response:
- description: The HTTP response from the APIC
- returned: failure or debug
- type: str
- sample: OK (30 bytes)
-status:
- description: The HTTP status from the APIC
- returned: failure or debug
- type: int
- sample: 200
-url:
- description: The HTTP url used for the request to the APIC
- returned: failure or debug
- type: str
- sample: https://10.11.12.13/api/mo/uni/tn-production.json
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
-
-
-def main():
- argument_spec = aci_argument_spec()
- argument_spec.update(
- port_security=dict(type='str', aliases=['name']), # Not required for querying all objects
- description=dict(type='str', aliases=['descr']),
- max_end_points=dict(type='int'),
- port_security_timeout=dict(type='int'),
- state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
- name_alias=dict(type='str'),
- )
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- required_if=[
- ['state', 'absent', ['port_security']],
- ['state', 'present', ['port_security']],
- ],
- )
-
- port_security = module.params.get('port_security')
- description = module.params.get('description')
- max_end_points = module.params.get('max_end_points')
- port_security_timeout = module.params.get('port_security_timeout')
- name_alias = module.params.get('name_alias')
- if max_end_points is not None and max_end_points not in range(12001):
- module.fail_json(msg='The "max_end_points" must be between 0 and 12000')
- if port_security_timeout is not None and port_security_timeout not in range(60, 3601):
- module.fail_json(msg='The "port_security_timeout" must be between 60 and 3600')
- state = module.params.get('state')
-
- aci = ACIModule(module)
- aci.construct_url(
- root_class=dict(
- aci_class='l2PortSecurityPol',
- aci_rn='infra/portsecurityP-{0}'.format(port_security),
- module_object=port_security,
- target_filter={'name': port_security},
- ),
- )
-
- aci.get_existing()
-
- if state == 'present':
- aci.payload(
- aci_class='l2PortSecurityPol',
- class_config=dict(
- name=port_security,
- descr=description,
- maximum=max_end_points,
- nameAlias=name_alias,
- ),
- )
-
- aci.get_diff(aci_class='l2PortSecurityPol')
-
- aci.post_config()
-
- elif state == 'absent':
- aci.delete_config()
-
- aci.exit_json()
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/aci/aci_intf_policy_fc.py b/plugins/modules/network/aci/aci_intf_policy_fc.py
deleted file mode 120000
index 4f1118aa6d..0000000000
--- a/plugins/modules/network/aci/aci_intf_policy_fc.py
+++ /dev/null
@@ -1 +0,0 @@
-aci_interface_policy_fc.py
\ No newline at end of file
diff --git a/plugins/modules/network/aci/aci_intf_policy_l2.py b/plugins/modules/network/aci/aci_intf_policy_l2.py
deleted file mode 120000
index 924390568c..0000000000
--- a/plugins/modules/network/aci/aci_intf_policy_l2.py
+++ /dev/null
@@ -1 +0,0 @@
-aci_interface_policy_l2.py
\ No newline at end of file
diff --git a/plugins/modules/network/aci/aci_intf_policy_lldp.py b/plugins/modules/network/aci/aci_intf_policy_lldp.py
deleted file mode 120000
index 5d751deab3..0000000000
--- a/plugins/modules/network/aci/aci_intf_policy_lldp.py
+++ /dev/null
@@ -1 +0,0 @@
-aci_interface_policy_lldp.py
\ No newline at end of file
diff --git a/plugins/modules/network/aci/aci_intf_policy_mcp.py b/plugins/modules/network/aci/aci_intf_policy_mcp.py
deleted file mode 120000
index 89b6309246..0000000000
--- a/plugins/modules/network/aci/aci_intf_policy_mcp.py
+++ /dev/null
@@ -1 +0,0 @@
-aci_interface_policy_mcp.py
\ No newline at end of file
diff --git a/plugins/modules/network/aci/aci_intf_policy_port_channel.py b/plugins/modules/network/aci/aci_intf_policy_port_channel.py
deleted file mode 120000
index bed0d32886..0000000000
--- a/plugins/modules/network/aci/aci_intf_policy_port_channel.py
+++ /dev/null
@@ -1 +0,0 @@
-aci_interface_policy_port_channel.py
\ No newline at end of file
diff --git a/plugins/modules/network/aci/aci_intf_policy_port_security.py b/plugins/modules/network/aci/aci_intf_policy_port_security.py
deleted file mode 120000
index ff1bc0fdc7..0000000000
--- a/plugins/modules/network/aci/aci_intf_policy_port_security.py
+++ /dev/null
@@ -1 +0,0 @@
-aci_interface_policy_port_security.py
\ No newline at end of file
diff --git a/plugins/modules/network/aci/mso_schema_template_external_epg_contract.py b/plugins/modules/network/aci/mso_schema_template_external_epg_contract.py
deleted file mode 100644
index 679202b150..0000000000
--- a/plugins/modules/network/aci/mso_schema_template_external_epg_contract.py
+++ /dev/null
@@ -1,245 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: mso_schema_template_external_epg_contract
-short_description: Manage Extrnal EPG contracts in schema templates
-description:
-- Manage External EPG contracts in schema templates on Cisco ACI Multi-Site.
-author:
-- Devarshi Shah (@devarshishah3)
-options:
- schema:
- description:
- - The name of the schema.
- type: str
- required: yes
- template:
- description:
- - The name of the template to change.
- type: str
- required: yes
- external_epg:
- description:
- - The name of the EPG to manage.
- type: str
- required: yes
- contract:
- description:
- - A contract associated to this EPG.
- type: dict
- suboptions:
- name:
- description:
- - The name of the Contract to associate with.
- required: true
- type: str
- schema:
- description:
- - The schema that defines the referenced BD.
- - If this parameter is unspecified, it defaults to the current schema.
- type: str
- template:
- description:
- - The template that defines the referenced BD.
- type: str
- type:
- description:
- - The type of contract.
- type: str
- required: true
- choices: [ consumer, provider ]
- state:
- description:
- - Use C(present) or C(absent) for adding or removing.
- - Use C(query) for listing an object or multiple objects.
- type: str
- choices: [ absent, present, query ]
- default: present
-seealso:
-- module: cisco.mso.mso_schema_template_externalepg
-- module: cisco.mso.mso_schema_template_contract_filter
-extends_documentation_fragment:
-- cisco.mso.modules
-
-'''
-
-EXAMPLES = r'''
-- name: Add a contract to an EPG
- mso_schema_template_external_epg_contract:
- host: mso_host
- username: admin
- password: SomeSecretPassword
- schema: Schema 1
- template: Template 1
- epg: EPG 1
- contract:
- name: Contract 1
- type: consumer
- state: present
- delegate_to: localhost
-
-- name: Remove a Contract
- mso_schema_template_external_epg_contract:
- host: mso_host
- username: admin
- password: SomeSecretPassword
- schema: Schema 1
- template: Template 1
- epg: EPG 1
- contract:
- name: Contract 1
- state: absent
- delegate_to: localhost
-
-- name: Query a specific Contract
- mso_schema_template_external_epg_contract:
- host: mso_host
- username: admin
- password: SomeSecretPassword
- schema: Schema 1
- template: Template 1
- epg: EPG 1
- contract:
- name: Contract 1
- state: query
- delegate_to: localhost
- register: query_result
-
-- name: Query all Contracts
- mso_schema_template_external_epg_contract:
- host: mso_host
- username: admin
- password: SomeSecretPassword
- schema: Schema 1
- template: Template 1
- state: query
- delegate_to: localhost
- register: query_result
-'''
-
-RETURN = r'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.cisco.mso.plugins.module_utils.mso import MSOModule, mso_argument_spec, mso_contractref_spec, issubset
-
-
-def main():
- argument_spec = mso_argument_spec()
- argument_spec.update(
- schema=dict(type='str', required=True),
- template=dict(type='str', required=True),
- external_epg=dict(type='str', required=True),
- contract=dict(type='dict', options=mso_contractref_spec()),
- state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
- )
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- required_if=[
- ['state', 'absent', ['contract']],
- ['state', 'present', ['contract']],
- ],
- )
-
- schema = module.params['schema']
- template = module.params['template']
- external_epg = module.params['external_epg']
- contract = module.params['contract']
- state = module.params['state']
-
- mso = MSOModule(module)
-
- if contract:
- if contract.get('schema') is None:
- contract['schema'] = schema
- contract['schema_id'] = mso.lookup_schema(contract['schema'])
- if contract.get('template') is None:
- contract['template'] = template
-
- # Get schema_id
- schema_obj = mso.get_obj('schemas', displayName=schema)
- if schema_obj:
- schema_id = schema_obj['id']
- else:
- mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
-
- schema_path = 'schemas/{id}'.format(**schema_obj)
-
- # Get template
- templates = [t['name'] for t in schema_obj['templates']]
- if template not in templates:
- mso.fail_json(msg="Provided template '{0}' does not exist. Existing templates: {1}".format(template, ', '.join(templates)))
- template_idx = templates.index(template)
-
- # Get EPG
- epgs = [e['name'] for e in schema_obj['templates'][template_idx]['externalEpgs']]
- if external_epg not in epgs:
- mso.fail_json(msg="Provided epg '{epg}' does not exist. Existing epgs: {epgs}".format(epg=external_epg, epgs=', '.join(epgs)))
- epg_idx = epgs.index(external_epg)
-
- # Get Contract
- if contract:
- contracts = [(c['contractRef'],
- c['relationshipType']) for c in schema_obj['templates'][template_idx]['externalEpgs'][epg_idx]['contractRelationships']]
- contract_ref = mso.contract_ref(**contract)
- if (contract_ref, contract['type']) in contracts:
- contract_idx = contracts.index((contract_ref, contract['type']))
- contract_path = '/templates/{0}/externalEpgs/{1}/contractRelationships/{2}'.format(template, external_epg, contract)
- mso.existing = schema_obj['templates'][template_idx]['externalEpgs'][epg_idx]['contractRelationships'][contract_idx]
-
- if state == 'query':
- if not contract:
- mso.existing = schema_obj['templates'][template_idx]['externalEpgs'][epg_idx]['contractRelationships']
- elif not mso.existing:
- mso.fail_json(msg="Contract '{0}' not found".format(contract_ref))
- mso.exit_json()
-
- contracts_path = '/templates/{0}/externalEpgs/{1}/contractRelationships'.format(template, external_epg)
- ops = []
-
- mso.previous = mso.existing
- if state == 'absent':
- if mso.existing:
- mso.sent = mso.existing = {}
- ops.append(dict(op='remove', path=contract_path))
-
- elif state == 'present':
- payload = dict(
- relationshipType=contract['type'],
- contractRef=dict(
- contractName=contract['name'],
- templateName=contract['template'],
- schemaId=contract['schema_id'],
- ),
- )
-
- mso.sanitize(payload, collate=True)
-
- if mso.existing:
- ops.append(dict(op='replace', path=contract_path, value=mso.sent))
- else:
- ops.append(dict(op='add', path=contracts_path + '/-', value=mso.sent))
-
- mso.existing = mso.proposed
-
- if not module.check_mode:
- mso.request(schema_path, method='PATCH', data=ops)
-
- mso.exit_json()
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/aci/mso_schema_template_external_epg_subnet.py b/plugins/modules/network/aci/mso_schema_template_external_epg_subnet.py
deleted file mode 100644
index 1a736b96f5..0000000000
--- a/plugins/modules/network/aci/mso_schema_template_external_epg_subnet.py
+++ /dev/null
@@ -1,219 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: mso_schema_template_external_epg_subnet
-short_description: Manage External EPG subnets in schema templates
-description:
-- Manage External EPG subnets in schema templates on Cisco ACI Multi-Site.
-author:
-- Devarshi Shah (@devarshishah3)
-options:
- schema:
- description:
- - The name of the schema.
- type: str
- required: yes
- template:
- description:
- - The name of the template to change.
- type: str
- required: yes
- external_epg:
- description:
- - The name of the External EPG to manage.
- type: str
- required: yes
- subnet:
- description:
- - The IP range in CIDR notation.
- type: str
- required: true
- scope:
- description:
- - The scope of the subnet.
- type: list
- aggregate:
- description:
- - The aggregate option for the subnet.
- type: list
- state:
- description:
- - Use C(present) or C(absent) for adding or removing.
- - Use C(query) for listing an object or multiple objects.
- type: str
- choices: [ absent, present, query ]
- default: present
-notes:
-- Due to restrictions of the MSO REST API concurrent modifications to EPG subnets can be dangerous and corrupt data.
-extends_documentation_fragment:
-- cisco.mso.modules
-
-'''
-
-EXAMPLES = r'''
-- name: Add a new subnet to an External EPG
- mso_schema_template_external_epg_subnet:
- host: mso_host
- username: admin
- password: SomeSecretPassword
- schema: Schema 1
- template: Template 1
- external_epg: EPG 1
- subnet: 10.0.0.0/24
- state: present
- delegate_to: localhost
-
-- name: Remove a subnet from an External EPG
- mso_schema_template_external_epg_subnet:
- host: mso_host
- username: admin
- password: SomeSecretPassword
- schema: Schema 1
- template: Template 1
- external_epg: EPG 1
- subnet: 10.0.0.0/24
- state: absent
- delegate_to: localhost
-
-- name: Query a specific External EPG subnet
- mso_schema_template_external_epg_subnet:
- host: mso_host
- username: admin
- password: SomeSecretPassword
- schema: Schema 1
- template: Template 1
- external_epg: EPG 1
- subnet: 10.0.0.0/24
- state: query
- delegate_to: localhost
- register: query_result
-
-- name: Query all External EPGs subnets
- mso_schema_template_external_epg_subnet:
- host: mso_host
- username: admin
- password: SomeSecretPassword
- schema: Schema 1
- template: Template 1
- state: query
- delegate_to: localhost
- register: query_result
-'''
-
-RETURN = r'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.cisco.mso.plugins.module_utils.mso import MSOModule, mso_argument_spec, mso_reference_spec, mso_subnet_spec
-
-
-def main():
- argument_spec = mso_argument_spec()
- argument_spec.update(
- schema=dict(type='str', required=True),
- template=dict(type='str', required=True),
- external_epg=dict(type='str', required=True),
- state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
- subnet=dict(type='str', required=True),
- scope=dict(type='list', default=[]),
- aggregate=dict(type='list', default=[]),
- )
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- required_if=[
- ['state', 'absent', ['subnet']],
- ['state', 'present', ['subnet']],
- ],
- )
-
- schema = module.params['schema']
- template = module.params['template']
- external_epg = module.params['external_epg']
- subnet = module.params['subnet']
- scope = module.params['scope']
- aggregate = module.params['aggregate']
- state = module.params['state']
-
- mso = MSOModule(module)
-
- # Get schema
- schema_obj = mso.get_obj('schemas', displayName=schema)
- if not schema_obj:
- mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
-
- schema_path = 'schemas/{id}'.format(**schema_obj)
-
- # Get template
- templates = [t['name'] for t in schema_obj['templates']]
- if template not in templates:
- mso.fail_json(msg="Provided template '{template}' does not exist. Existing templates: {templates}".format(template=template,
- templates=', '.join(templates)))
- template_idx = templates.index(template)
-
- # Get EPG
- external_epgs = [e['name'] for e in schema_obj['templates'][template_idx]['externalEpgs']]
- if external_epg not in external_epgs:
- mso.fail_json(msg="Provided External EPG '{epg}' does not exist. Existing epgs: {epgs}".format(epg=external_epg, epgs=', '.join(external_epgs)))
- epg_idx = external_epgs.index(external_epg)
-
- # Get Subnet
- subnets = [s['ip'] for s in schema_obj['templates'][template_idx]['externalEpgs'][epg_idx]['subnets']]
- if subnet in subnets:
- subnet_idx = subnets.index(subnet)
- # FIXME: Changes based on index are DANGEROUS
- subnet_path = '/templates/{0}/externalEpgs/{1}/subnets/{2}'.format(template, external_epg, subnet_idx)
- mso.existing = schema_obj['templates'][template_idx]['externalEpgs'][epg_idx]['subnets'][subnet_idx]
-
- if state == 'query':
- if subnet is None:
- mso.existing = schema_obj['templates'][template_idx]['externalEpgs'][epg_idx]['subnets']
- elif not mso.existing:
- mso.fail_json(msg="Subnet '{subnet}' not found".format(subnet=subnet))
- mso.exit_json()
-
- subnets_path = '/templates/{0}/externalEpgs/{1}/subnets'.format(template, external_epg)
- ops = []
-
- mso.previous = mso.existing
- if state == 'absent':
- if mso.existing:
- mso.existing = {}
- ops.append(dict(op='remove', path=subnet_path))
-
- elif state == 'present':
- payload = dict(
- ip=subnet,
- scope=scope,
- aggregate=aggregate,
- )
-
- mso.sanitize(payload, collate=True)
-
- if mso.existing:
- ops.append(dict(op='replace', path=subnet_path, value=mso.sent))
- else:
- ops.append(dict(op='add', path=subnets_path + '/-', value=mso.sent))
-
- mso.existing = mso.proposed
-
- if not module.check_mode:
- mso.request(schema_path, method='PATCH', data=ops)
-
- mso.exit_json()
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/aireos/aireos_command.py b/plugins/modules/network/aireos/aireos_command.py
deleted file mode 100644
index da5da5155e..0000000000
--- a/plugins/modules/network/aireos/aireos_command.py
+++ /dev/null
@@ -1,218 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright: Ansible Team
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: aireos_command
-author: "James Mighion (@jmighion)"
-short_description: Run commands on remote devices running Cisco WLC
-description:
- - Sends arbitrary commands to an aireos node and returns the results
- read from the device. This module includes an
- argument that will cause the module to wait for a specific condition
- before returning or timing out if the condition is not met.
- - Commands run in configuration mode with this module are not
- idempotent. Please use M(aireos_config) to configure WLC devices.
-extends_documentation_fragment:
-- community.general.aireos
-
-options:
- commands:
- description:
- - List of commands to send to the remote aireos device over the
- configured provider. The resulting output from the command
- is returned. If the I(wait_for) argument is provided, the
- module is not returned until the condition is satisfied or
- the number of retries has expired.
- required: true
- wait_for:
- description:
- - List of conditions to evaluate against the output of the
- command. The task will wait for each condition to be true
- before moving forward. If the conditional is not true
- within the configured number of retries, the task fails.
- See examples.
- aliases: ['waitfor']
- match:
- description:
- - The I(match) argument is used in conjunction with the
- I(wait_for) argument to specify the match policy. Valid
- values are C(all) or C(any). If the value is set to C(all)
- then all conditionals in the wait_for must be satisfied. If
- the value is set to C(any) then only one of the values must be
- satisfied.
- default: all
- choices: ['any', 'all']
- retries:
- description:
- - Specifies the number of retries a command should by tried
- before it is considered failed. The command is run on the
- target device every retry and evaluated against the
- I(wait_for) conditions.
- default: 10
- interval:
- description:
- - Configures the interval in seconds to wait between retries
- of the command. If the command does not pass the specified
- conditions, the interval indicates how long to wait before
- trying the command again.
- default: 1
-'''
-
-EXAMPLES = """
-tasks:
- - name: run show sysinfo on remote devices
- aireos_command:
- commands: show sysinfo
-
- - name: run show sysinfo and check to see if output contains Cisco Controller
- aireos_command:
- commands: show sysinfo
- wait_for: result[0] contains 'Cisco Controller'
-
- - name: run multiple commands on remote nodes
- aireos_command:
- commands:
- - show sysinfo
- - show interface summary
-
- - name: run multiple commands and evaluate the output
- aireos_command:
- commands:
- - show sysinfo
- - show interface summary
- wait_for:
- - result[0] contains Cisco Controller
- - result[1] contains Loopback0
-"""
-
-RETURN = """
-stdout:
- description: The set of responses from the commands
- returned: always apart from low level errors (such as action plugin)
- type: list
- sample: ['...', '...']
-stdout_lines:
- description: The value of stdout split into a list
- returned: always apart from low level errors (such as action plugin)
- type: list
- sample: [['...', '...'], ['...'], ['...']]
-failed_conditions:
- description: The list of conditionals that have failed
- returned: failed
- type: list
- sample: ['...', '...']
-"""
-import time
-
-from ansible_collections.community.general.plugins.module_utils.network.aireos.aireos import run_commands
-from ansible_collections.community.general.plugins.module_utils.network.aireos.aireos import aireos_argument_spec, check_args
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ComplexList
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import Conditional
-from ansible.module_utils.six import string_types
-from ansible.module_utils._text import to_text
-
-
-def to_lines(stdout):
- for item in stdout:
- if isinstance(item, string_types):
- item = to_text(item, errors='surrogate_then_replace').split('\n')
- yield item
-
-
-def parse_commands(module, warnings):
- command = ComplexList(dict(
- command=dict(key=True),
- prompt=dict(),
- answer=dict()
- ), module)
- commands = command(module.params['commands'])
- for index, item in enumerate(commands):
- if module.check_mode and not item['command'].startswith('show'):
- warnings.append(
- 'only show commands are supported when using check mode, not '
- 'executing `%s`' % item['command']
- )
- elif item['command'].startswith('conf'):
- warnings.append(
- 'commands run in config mode with aireos_command are not '
- 'idempotent. Please use aireos_config instead'
- )
- return commands
-
-
-def main():
- """main entry point for module execution
- """
- argument_spec = dict(
- commands=dict(type='list', required=True),
-
- wait_for=dict(type='list', aliases=['waitfor']),
- match=dict(default='all', choices=['all', 'any']),
-
- retries=dict(default=10, type='int'),
- interval=dict(default=1, type='int')
- )
-
- argument_spec.update(aireos_argument_spec)
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- result = {'changed': False}
-
- warnings = list()
- check_args(module, warnings)
- commands = parse_commands(module, warnings)
- result['warnings'] = warnings
-
- wait_for = module.params['wait_for'] or list()
- conditionals = [Conditional(c) for c in wait_for]
-
- retries = module.params['retries']
- interval = module.params['interval']
- match = module.params['match']
-
- while retries > 0:
- responses = run_commands(module, commands)
-
- for item in list(conditionals):
- if item(responses):
- if match == 'any':
- conditionals = list()
- break
- conditionals.remove(item)
-
- if not conditionals:
- break
-
- time.sleep(interval)
- retries -= 1
-
- if conditionals:
- failed_conditions = [item.raw for item in conditionals]
- msg = 'One or more conditional statements have not been satisfied'
- module.fail_json(msg=msg, failed_conditions=failed_conditions)
-
- result.update({
- 'changed': False,
- 'stdout': responses,
- 'stdout_lines': list(to_lines(responses))
- })
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/aireos/aireos_config.py b/plugins/modules/network/aireos/aireos_config.py
deleted file mode 100644
index c2244db774..0000000000
--- a/plugins/modules/network/aireos/aireos_config.py
+++ /dev/null
@@ -1,357 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright: Ansible Team
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: aireos_config
-author: "James Mighion (@jmighion)"
-short_description: Manage Cisco WLC configurations
-description:
- - AireOS does not use a block indent file syntax, so there are no sections or parents.
- This module provides an implementation for working with AireOS configurations in
- a deterministic way.
-extends_documentation_fragment:
-- community.general.aireos
-
-options:
- lines:
- description:
- - The ordered set of commands that should be configured.
- The commands must be the exact same commands as found
- in the device run-config. Be sure to note the configuration
- command syntax as some commands are automatically modified by the
- device config parser.
- aliases: ['commands']
- src:
- description:
- - Specifies the source path to the file that contains the configuration
- or configuration template to load. The path to the source file can
- either be the full path on the Ansible control host or a relative
- path from the playbook or role root directory. This argument is mutually
- exclusive with I(lines).
- before:
- description:
- - The ordered set of commands to push on to the command stack if
- a change needs to be made. This allows the playbook designer
- the opportunity to perform configuration commands prior to pushing
- any changes without affecting how the set of commands are matched
- against the system.
- after:
- description:
- - The ordered set of commands to append to the end of the command
- stack if a change needs to be made. Just like with I(before) this
- allows the playbook designer to append a set of commands to be
- executed after the command set.
- match:
- description:
- - Instructs the module on the way to perform the matching of
- the set of commands against the current device config. If
- match is set to I(line), commands are matched line by line.
- If match is set to I(none), the module will not attempt to
- compare the source configuration with the running
- configuration on the remote device.
- default: line
- choices: ['line', 'none']
- backup:
- description:
- - This argument will cause the module to create a full backup of
- the current C(running-config) from the remote device before any
- changes are made. If the C(backup_options) value is not given,
- the backup file is written to the C(backup) folder in the playbook
- root directory. If the directory does not exist, it is created.
- type: bool
- default: 'no'
- running_config:
- description:
- - The module, by default, will connect to the remote device and
- retrieve the current running-config to use as a base for comparing
- against the contents of source. There are times when it is not
- desirable to have the task get the current running-config for
- every task in a playbook. The I(running_config) argument allows the
- implementer to pass in the configuration to use as the base
- config for comparison.
- aliases: ['config']
- save:
- description:
- - The C(save) argument instructs the module to save the
- running-config to startup-config. This operation is performed
- after any changes are made to the current running config. If
- no changes are made, the configuration is still saved to the
- startup config. This option will always cause the module to
- return changed. This argument is mutually exclusive with I(save_when).
- - This option is deprecated as of Ansible 2.7, use C(save_when)
- type: bool
- default: 'no'
- save_when:
- description:
- - When changes are made to the device running-configuration, the
- changes are not copied to non-volatile storage by default. Using
- this argument will change that. If the argument is set to
- I(always), then the running-config will always be copied to the
- startup-config and the module will always return as changed.
- If the argument is set to I(never), the running-config will never
- be copied to the startup-config. If the argument is set to I(changed),
- then the running-config will only be copied to the startup-config if
- the task has made a change.
- default: never
- choices: ['always', 'never', 'changed']
- diff_against:
- description:
- - When using the C(ansible-playbook --diff) command line argument
- the module can generate diffs against different sources.
- - When this option is configured as I(intended), the module will
- return the diff of the running-config against the configuration
- provided in the C(intended_config) argument.
- - When this option is configured as I(running), the module will
- return the before and after diff of the running-config with respect
- to any changes made to the device configuration.
- choices: ['intended', 'running']
- diff_ignore_lines:
- description:
- - Use this argument to specify one or more lines that should be
- ignored during the diff. This is used for lines in the configuration
- that are automatically updated by the system. This argument takes
- a list of regular expressions or exact line matches.
- intended_config:
- description:
- - The C(intended_config) provides the master configuration that
- the node should conform to and is used to check the final
- running-config against. This argument will not modify any settings
- on the remote device and is strictly used to check the compliance
- of the current device's configuration against. When specifying this
- argument, the task should also modify the C(diff_against) value and
- set it to I(intended).
- backup_options:
- description:
- - This is a dict object containing configurable options related to backup file path.
- The value of this option is read only when C(backup) is set to I(yes), if C(backup) is set
- to I(no) this option will be silently ignored.
- suboptions:
- filename:
- description:
- - The filename to be used to store the backup configuration. If the filename
- is not given it will be generated based on the hostname, current time and date
- in format defined by _config.@
- dir_path:
- description:
- - This option provides the path ending with directory name in which the backup
- configuration file will be stored. If the directory does not exist it will be first
- created and the filename is either the value of C(filename) or default filename
- as described in C(filename) options description. If the path value is not given
- in that case a I(backup) directory will be created in the current working directory
- and backup configuration will be copied in C(filename) within I(backup) directory.
- type: path
- type: dict
-'''
-
-EXAMPLES = """
-- name: configure configuration
- aireos_config:
- lines: sysname testDevice
-
-- name: diff the running-config against a provided config
- aireos_config:
- diff_against: intended
- intended: "{{ lookup('file', 'master.cfg') }}"
-
-- name: load new acl into device
- aireos_config:
- lines:
- - acl create testACL
- - acl rule protocol testACL 1 any
- - acl rule direction testACL 3 in
- before: acl delete testACL
-
-- name: configurable backup path
- aireos_config:
- backup: yes
- lines: sysname testDevice
- backup_options:
- filename: backup.cfg
- dir_path: /home/user
-"""
-
-RETURN = """
-commands:
- description: The set of commands that will be pushed to the remote device
- returned: always
- type: list
- sample: ['hostname foo', 'vlan 1', 'name default']
-updates:
- description: The set of commands that will be pushed to the remote device
- returned: always
- type: list
- sample: ['hostname foo', 'vlan 1', 'name default']
-backup_path:
- description: The full path to the backup file
- returned: when backup is yes
- type: str
- sample: /playbooks/ansible/backup/aireos_config.2016-07-16@22:28:34
-"""
-from ansible_collections.community.general.plugins.module_utils.network.aireos.aireos import run_commands, get_config, load_config
-from ansible_collections.community.general.plugins.module_utils.network.aireos.aireos import aireos_argument_spec
-from ansible_collections.community.general.plugins.module_utils.network.aireos.aireos import check_args as aireos_check_args
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, dumps
-
-
-def get_running_config(module, config=None):
- contents = module.params['running_config']
- if not contents:
- if config:
- contents = config
- else:
- contents = get_config(module)
- return NetworkConfig(indent=1, contents=contents)
-
-
-def get_candidate(module):
- candidate = NetworkConfig(indent=1)
-
- if module.params['src']:
- candidate.load(module.params['src'])
- elif module.params['lines']:
- candidate.add(module.params['lines'])
- return candidate
-
-
-def save_config(module, result):
- result['changed'] = True
- if not module.check_mode:
- command = {"command": "save config", "prompt": "Are you sure you want to save", "answer": "y"}
- run_commands(module, command)
- else:
- module.warn('Skipping command `save config` due to check_mode. Configuration not copied to '
- 'non-volatile storage')
-
-
-def main():
- """ main entry point for module execution
- """
- backup_spec = dict(
- filename=dict(),
- dir_path=dict(type='path')
- )
- argument_spec = dict(
- src=dict(type='path'),
-
- lines=dict(aliases=['commands'], type='list'),
-
- before=dict(type='list'),
- after=dict(type='list'),
-
- match=dict(default='line', choices=['line', 'none']),
-
- running_config=dict(aliases=['config']),
- intended_config=dict(),
-
- backup=dict(type='bool', default=False),
- backup_options=dict(type='dict', options=backup_spec),
-
- # save is deprecated as of 2.7, use save_when instead
- save=dict(type='bool', default=False, removed_in_version='2.11'),
- save_when=dict(choices=['always', 'never', 'changed'], default='never'),
-
- diff_against=dict(choices=['running', 'intended']),
- diff_ignore_lines=dict(type='list')
- )
-
- argument_spec.update(aireos_argument_spec)
-
- mutually_exclusive = [('lines', 'src'),
- ('save', 'save_when')]
-
- required_if = [('diff_against', 'intended', ['intended_config'])]
-
- module = AnsibleModule(argument_spec=argument_spec,
- mutually_exclusive=mutually_exclusive,
- required_if=required_if,
- supports_check_mode=True)
-
- warnings = list()
- aireos_check_args(module, warnings)
- result = {'changed': False, 'warnings': warnings}
-
- config = None
-
- if module.params['backup'] or (module._diff and module.params['diff_against'] == 'running'):
- contents = get_config(module)
- config = NetworkConfig(indent=1, contents=contents)
- if module.params['backup']:
- result['__backup__'] = contents
-
- if any((module.params['src'], module.params['lines'])):
- match = module.params['match']
-
- candidate = get_candidate(module)
-
- if match != 'none':
- config = get_running_config(module, config)
- configobjs = candidate.difference(config, match=match)
- else:
- configobjs = candidate.items
-
- if configobjs:
- commands = dumps(configobjs, 'commands').split('\n')
-
- if module.params['before']:
- commands[:0] = module.params['before']
-
- if module.params['after']:
- commands.extend(module.params['after'])
-
- result['commands'] = commands
- result['updates'] = commands
-
- if not module.check_mode:
- load_config(module, commands)
-
- result['changed'] = True
-
- diff_ignore_lines = module.params['diff_ignore_lines']
-
- if module.params['save_when'] == 'always' or module.params['save']:
- save_config(module, result)
- elif module.params['save_when'] == 'changed' and result['changed']:
- save_config(module, result)
-
- if module._diff:
- output = run_commands(module, 'show run-config commands')
- contents = output[0]
-
- # recreate the object in order to process diff_ignore_lines
- running_config = NetworkConfig(indent=1, contents=contents, ignore_lines=diff_ignore_lines)
-
- if module.params['diff_against'] == 'running':
- if module.check_mode:
- module.warn("unable to perform diff against running-config due to check mode")
- contents = None
- else:
- contents = config.config_text
- elif module.params['diff_against'] == 'intended':
- contents = module.params['intended_config']
-
- if contents is not None:
- base_config = NetworkConfig(indent=1, contents=contents, ignore_lines=diff_ignore_lines)
-
- if running_config.sha1 != base_config.sha1:
- result.update({
- 'changed': True,
- 'diff': {'before': str(base_config), 'after': str(running_config)}
- })
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/apconos/apconos_command.py b/plugins/modules/network/apconos/apconos_command.py
deleted file mode 100644
index dc14fa0eaf..0000000000
--- a/plugins/modules/network/apconos/apconos_command.py
+++ /dev/null
@@ -1,200 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2019 APCON.
-#
-# GNU General Public License v3.0+
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-# Module to execute apconos Commands on Apcon Switches.
-# Apcon Networking
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: apconos_command
-author: "David Lee (@davidlee-ap)"
-short_description: Run arbitrary commands on APCON devices
-description:
- - Sends arbitrary commands to an apcon device and returns the results
- read from the device. The module includes an argument that will
- cause the module to wait for a specific condition before returning
- or timing out if the condition is not met.
-notes:
- - Tested against apcon iis+ii
-options:
- commands:
- description:
- - List of commands to send to the remote device over the
- configured provider. The resulting output from the command
- is returned. If the I(wait_for) argument is provided, the
- module is not returned until the condition is satisfied or
- the number of retires as expired.
- required: true
- type: list
- wait_for:
- description:
- - List of conditions to evaluate against the output of the
- command. The task will wait for each condition to be true
- before moving forward. If the conditional is not true
- within the configured number of retries, the task fails.
- See examples.
- type: list
- match:
- description:
- - The I(match) argument is used in conjunction with the
- I(wait_for) argument to specify the match policy. Valid
- values are C(all) or C(any). If the value is set to C(all)
- then all conditionals in the wait_for must be satisfied. If
- the value is set to C(any) then only one of the values must be
- satisfied.
- default: all
- choices: ['any', 'all']
- type: str
- retries:
- description:
- - Specifies the number of retries a command should by tried
- before it is considered failed. The command is run on the
- target device every retry and evaluated against the
- I(wait_for) conditions.
- default: 10
- type: int
- interval:
- description:
- - Configures the interval in seconds to wait between retries
- of the command. If the command does not pass the specified
- conditions, the interval indicates how long to wait before
- trying the command again.
- default: 1
- type: int
-'''
-
-EXAMPLES = """
-- name: Basic Configuration
- apconos_command:
- commands:
- - show version
- - enable ssh
- register: result
-
-- name: Get output from single command
- apconos_command:
- commands: ['show version']
- register: result
-"""
-
-RETURN = """
-"""
-
-import time
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_lines
-from ansible_collections.community.general.plugins.module_utils.network.apconos.apconos import run_commands
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import Conditional
-
-
-def parse_commands(module, warnings):
-
- commands = module.params['commands']
-
- if module.check_mode:
- for item in list(commands):
- if not item.startswith('show'):
- warnings.append(
- 'Only show commands are supported when using check mode, not '
- 'executing %s' % item
- )
- commands.remove(item)
-
- return commands
-
-
-def main():
- spec = dict(
- commands=dict(type='list', required=True),
-
- wait_for=dict(type='list'),
- match=dict(default='all', choices=['all', 'any']),
-
- retries=dict(default=10, type='int'),
- interval=dict(default=1, type='int')
- )
-
- module = AnsibleModule(argument_spec=spec, supports_check_mode=False)
- warnings = list()
- result = {'changed': False, 'warnings': warnings}
-
- wait_for = module.params['wait_for'] or list()
- conditionals = [Conditional(c) for c in wait_for]
-
- commands = parse_commands(module, warnings)
- commands = module.params['commands']
- retries = module.params['retries']
- interval = module.params['interval']
- match = module.params['match']
-
- while retries > 0:
- responses = run_commands(module, commands)
-
- for item in list(conditionals):
- if item(responses):
- if match == 'any':
- conditionals = list()
- break
- conditionals.remove(item)
-
- if not conditionals:
- break
-
- time.sleep(interval)
- retries -= 1
-
- if conditionals:
- failed_conditions = [item.raw for item in conditionals]
- msg = 'One or more conditional statements have not been satisfied'
- module.fail_json(msg=msg, failed_conditions=failed_conditions)
-
- for item in responses:
- if len(item) == 0:
- if module.check_mode:
- result.update({
- 'changed': False,
- 'stdout': responses,
- 'stdout_lines': list(to_lines(responses))
- })
- else:
- result.update({
- 'changed': True,
- 'stdout': responses,
- 'stdout_lines': list(to_lines(responses))
- })
- elif 'ERROR' in item:
- result.update({
- 'failed': True,
- 'stdout': responses,
- 'stdout_lines': list(to_lines(responses))
- })
- else:
- result.update({
- 'stdout': item,
- 'stdout_lines': list(to_lines(responses))
- })
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/aruba/aruba_command.py b/plugins/modules/network/aruba/aruba_command.py
deleted file mode 100644
index d59756e2e9..0000000000
--- a/plugins/modules/network/aruba/aruba_command.py
+++ /dev/null
@@ -1,217 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright: Ansible Team
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: aruba_command
-author: "James Mighion (@jmighion)"
-short_description: Run commands on remote devices running Aruba Mobility Controller
-description:
- - Sends arbitrary commands to an aruba node and returns the results
- read from the device. This module includes an
- argument that will cause the module to wait for a specific condition
- before returning or timing out if the condition is not met.
- - This module does not support running commands in configuration mode.
- Please use M(aruba_config) to configure Aruba devices.
-extends_documentation_fragment:
-- community.general.aruba
-
-options:
- commands:
- description:
- - List of commands to send to the remote aruba device over the
- configured provider. The resulting output from the command
- is returned. If the I(wait_for) argument is provided, the
- module is not returned until the condition is satisfied or
- the number of retries has expired.
- required: true
- wait_for:
- description:
- - List of conditions to evaluate against the output of the
- command. The task will wait for each condition to be true
- before moving forward. If the conditional is not true
- within the configured number of retries, the task fails.
- See examples.
- aliases: ['waitfor']
- match:
- description:
- - The I(match) argument is used in conjunction with the
- I(wait_for) argument to specify the match policy. Valid
- values are C(all) or C(any). If the value is set to C(all)
- then all conditionals in the wait_for must be satisfied. If
- the value is set to C(any) then only one of the values must be
- satisfied.
- default: all
- choices: ['any', 'all']
- retries:
- description:
- - Specifies the number of retries a command should by tried
- before it is considered failed. The command is run on the
- target device every retry and evaluated against the
- I(wait_for) conditions.
- default: 10
- interval:
- description:
- - Configures the interval in seconds to wait between retries
- of the command. If the command does not pass the specified
- conditions, the interval indicates how long to wait before
- trying the command again.
- default: 1
-'''
-
-EXAMPLES = """
-tasks:
- - name: run show version on remote devices
- aruba_command:
- commands: show version
-
- - name: run show version and check to see if output contains Aruba
- aruba_command:
- commands: show version
- wait_for: result[0] contains Aruba
-
- - name: run multiple commands on remote nodes
- aruba_command:
- commands:
- - show version
- - show interfaces
-
- - name: run multiple commands and evaluate the output
- aruba_command:
- commands:
- - show version
- - show interfaces
- wait_for:
- - result[0] contains Aruba
- - result[1] contains Loopback0
-"""
-
-RETURN = """
-stdout:
- description: The set of responses from the commands
- returned: always
- type: list
- sample: ['...', '...']
-stdout_lines:
- description: The value of stdout split into a list
- returned: always
- type: list
- sample: [['...', '...'], ['...'], ['...']]
-failed_conditions:
- description: The list of conditionals that have failed
- returned: failed
- type: list
- sample: ['...', '...']
-"""
-import time
-
-from ansible_collections.community.general.plugins.module_utils.network.aruba.aruba import run_commands
-from ansible_collections.community.general.plugins.module_utils.network.aruba.aruba import aruba_argument_spec, check_args
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ComplexList
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import Conditional
-from ansible.module_utils.six import string_types
-
-
-def to_lines(stdout):
- for item in stdout:
- if isinstance(item, string_types):
- item = str(item).split('\n')
- yield item
-
-
-def parse_commands(module, warnings):
- command = ComplexList(dict(
- command=dict(key=True),
- prompt=dict(),
- answer=dict()
- ), module)
- commands = command(module.params['commands'])
- for index, item in enumerate(commands):
- if module.check_mode and not item['command'].startswith('show'):
- warnings.append(
- 'only show commands are supported when using check mode, not '
- 'executing `%s`' % item['command']
- )
- elif item['command'].startswith('conf'):
- module.fail_json(
- msg='aruba_command does not support running config mode '
- 'commands. Please use aruba_config instead'
- )
- return commands
-
-
-def main():
- """main entry point for module execution
- """
- argument_spec = dict(
- commands=dict(type='list', required=True),
-
- wait_for=dict(type='list', aliases=['waitfor']),
- match=dict(default='all', choices=['all', 'any']),
-
- retries=dict(default=10, type='int'),
- interval=dict(default=1, type='int')
- )
-
- argument_spec.update(aruba_argument_spec)
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- result = {'changed': False}
-
- warnings = list()
- check_args(module, warnings)
- commands = parse_commands(module, warnings)
- result['warnings'] = warnings
-
- wait_for = module.params['wait_for'] or list()
- conditionals = [Conditional(c) for c in wait_for]
-
- retries = module.params['retries']
- interval = module.params['interval']
- match = module.params['match']
-
- while retries > 0:
- responses = run_commands(module, commands)
-
- for item in list(conditionals):
- if item(responses):
- if match == 'any':
- conditionals = list()
- break
- conditionals.remove(item)
-
- if not conditionals:
- break
-
- time.sleep(interval)
- retries -= 1
-
- if conditionals:
- failed_conditions = [item.raw for item in conditionals]
- msg = 'One or more conditional statements have not been satisfied'
- module.fail_json(msg=msg, failed_conditions=failed_conditions)
-
- result.update({
- 'changed': False,
- 'stdout': responses,
- 'stdout_lines': list(to_lines(responses))
- })
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/aruba/aruba_config.py b/plugins/modules/network/aruba/aruba_config.py
deleted file mode 100644
index 4511ccd3dc..0000000000
--- a/plugins/modules/network/aruba/aruba_config.py
+++ /dev/null
@@ -1,424 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright: Ansible Team
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: aruba_config
-author: "James Mighion (@jmighion)"
-short_description: Manage Aruba configuration sections
-description:
- - Aruba configurations use a simple block indent file syntax
- for segmenting configuration into sections. This module provides
- an implementation for working with Aruba configuration sections in
- a deterministic way.
-extends_documentation_fragment:
-- community.general.aruba
-
-options:
- lines:
- description:
- - The ordered set of commands that should be configured in the
- section. The commands must be the exact same commands as found
- in the device running-config. Be sure to note the configuration
- command syntax as some commands are automatically modified by the
- device config parser.
- aliases: ['commands']
- parents:
- description:
- - The ordered set of parents that uniquely identify the section or hierarchy
- the commands should be checked against. If the parents argument
- is omitted, the commands are checked against the set of top
- level or global commands.
- src:
- description:
- - Specifies the source path to the file that contains the configuration
- or configuration template to load. The path to the source file can
- either be the full path on the Ansible control host or a relative
- path from the playbook or role root directory. This argument is mutually
- exclusive with I(lines), I(parents).
- before:
- description:
- - The ordered set of commands to push on to the command stack if
- a change needs to be made. This allows the playbook designer
- the opportunity to perform configuration commands prior to pushing
- any changes without affecting how the set of commands are matched
- against the system.
- after:
- description:
- - The ordered set of commands to append to the end of the command
- stack if a change needs to be made. Just like with I(before) this
- allows the playbook designer to append a set of commands to be
- executed after the command set.
- match:
- description:
- - Instructs the module on the way to perform the matching of
- the set of commands against the current device config. If
- match is set to I(line), commands are matched line by line. If
- match is set to I(strict), command lines are matched with respect
- to position. If match is set to I(exact), command lines
- must be an equal match. Finally, if match is set to I(none), the
- module will not attempt to compare the source configuration with
- the running configuration on the remote device.
- default: line
- choices: ['line', 'strict', 'exact', 'none']
- replace:
- description:
- - Instructs the module on the way to perform the configuration
- on the device. If the replace argument is set to I(line) then
- the modified lines are pushed to the device in configuration
- mode. If the replace argument is set to I(block) then the entire
- command block is pushed to the device in configuration mode if any
- line is not correct.
- default: line
- choices: ['line', 'block']
- backup:
- description:
- - This argument will cause the module to create a full backup of
- the current C(running-config) from the remote device before any
- changes are made. If the C(backup_options) value is not given,
- the backup file is written to the C(backup) folder in the playbook
- root directory. If the directory does not exist, it is created.
- type: bool
- default: 'no'
- running_config:
- description:
- - The module, by default, will connect to the remote device and
- retrieve the current running-config to use as a base for comparing
- against the contents of source. There are times when it is not
- desirable to have the task get the current running-config for
- every task in a playbook. The I(running_config) argument allows the
- implementer to pass in the configuration to use as the base
- config for comparison.
- aliases: ['config']
- save_when:
- description:
- - When changes are made to the device running-configuration, the
- changes are not copied to non-volatile storage by default. Using
- this argument will change that before. If the argument is set to
- I(always), then the running-config will always be copied to the
- startup configuration and the I(modified) flag will always be set to
- True. If the argument is set to I(modified), then the running-config
- will only be copied to the startup configuration if it has changed since
- the last save to startup configuration. If the argument is set to
- I(never), the running-config will never be copied to the
- startup configuration. If the argument is set to I(changed), then the running-config
- will only be copied to the startup configuration if the task has made a change.
- default: never
- choices: ['always', 'never', 'modified', 'changed']
- diff_against:
- description:
- - When using the C(ansible-playbook --diff) command line argument
- the module can generate diffs against different sources.
- - When this option is configure as I(startup), the module will return
- the diff of the running-config against the startup configuration.
- - When this option is configured as I(intended), the module will
- return the diff of the running-config against the configuration
- provided in the C(intended_config) argument.
- - When this option is configured as I(running), the module will
- return the before and after diff of the running-config with respect
- to any changes made to the device configuration.
- choices: ['startup', 'intended', 'running']
- diff_ignore_lines:
- description:
- - Use this argument to specify one or more lines that should be
- ignored during the diff. This is used for lines in the configuration
- that are automatically updated by the system. This argument takes
- a list of regular expressions or exact line matches.
- intended_config:
- description:
- - The C(intended_config) provides the master configuration that
- the node should conform to and is used to check the final
- running-config against. This argument will not modify any settings
- on the remote device and is strictly used to check the compliance
- of the current device's configuration against. When specifying this
- argument, the task should also modify the C(diff_against) value and
- set it to I(intended).
- encrypt:
- description:
- - This allows an Aruba controller's passwords and keys to be displayed in plain
- text when set to I(false) or encrypted when set to I(true).
- If set to I(false), the setting will re-encrypt at the end of the module run.
- Backups are still encrypted even when set to I(false).
- type: bool
- default: 'yes'
- backup_options:
- description:
- - This is a dict object containing configurable options related to backup file path.
- The value of this option is read only when C(backup) is set to I(yes), if C(backup) is set
- to I(no) this option will be silently ignored.
- suboptions:
- filename:
- description:
- - The filename to be used to store the backup configuration. If the filename
- is not given it will be generated based on the hostname, current time and date
- in format defined by _config.@
- dir_path:
- description:
- - This option provides the path ending with directory name in which the backup
- configuration file will be stored. If the directory does not exist it will be first
- created and the filename is either the value of C(filename) or default filename
- as described in C(filename) options description. If the path value is not given
- in that case a I(backup) directory will be created in the current working directory
- and backup configuration will be copied in C(filename) within I(backup) directory.
- type: path
- type: dict
-'''
-
-EXAMPLES = """
-- name: configure top level configuration
- aruba_config:
- lines: hostname {{ inventory_hostname }}
-
-- name: diff the running-config against a provided config
- aruba_config:
- diff_against: intended
- intended_config: "{{ lookup('file', 'master.cfg') }}"
-
-- name: configure interface settings
- aruba_config:
- lines:
- - description test interface
- - ip access-group 1 in
- parents: interface gigabitethernet 0/0/0
-
-- name: load new acl into device
- aruba_config:
- lines:
- - permit host 10.10.10.10
- - ipv6 permit host fda9:97d6:32a3:3e59::3333
- parents: ip access-list standard 1
- before: no ip access-list standard 1
- match: exact
-
-- name: configurable backup path
- aruba_config:
- backup: yes
- lines: hostname {{ inventory_hostname }}
- backup_options:
- filename: backup.cfg
- dir_path: /home/user
-"""
-
-RETURN = """
-commands:
- description: The set of commands that will be pushed to the remote device
- returned: always
- type: list
- sample: ['hostname foo', 'vlan 1', 'name default']
-updates:
- description: The set of commands that will be pushed to the remote device
- returned: always
- type: list
- sample: ['hostname foo', 'vlan 1', 'name default']
-backup_path:
- description: The full path to the backup file
- returned: when backup is yes
- type: str
- sample: /playbooks/ansible/backup/aruba_config.2016-07-16@22:28:34
-"""
-
-
-from ansible_collections.community.general.plugins.module_utils.network.aruba.aruba import run_commands, get_config, load_config
-from ansible_collections.community.general.plugins.module_utils.network.aruba.aruba import aruba_argument_spec
-from ansible_collections.community.general.plugins.module_utils.network.aruba.aruba import check_args as aruba_check_args
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, dumps
-
-
-def get_running_config(module, config=None):
- contents = module.params['running_config']
- if not contents:
- if config:
- contents = config
- else:
- contents = get_config(module)
- return NetworkConfig(contents=contents)
-
-
-def get_candidate(module):
- candidate = NetworkConfig()
-
- if module.params['src']:
- candidate.load(module.params['src'])
- elif module.params['lines']:
- parents = module.params['parents'] or list()
- candidate.add(module.params['lines'], parents=parents)
- return candidate
-
-
-def save_config(module, result):
- result['changed'] = True
- if not module.check_mode:
- run_commands(module, 'write memory')
- else:
- module.warn('Skipping command `write memory` '
- 'due to check_mode. Configuration not copied to '
- 'non-volatile storage')
-
-
-def main():
- """ main entry point for module execution
- """
- backup_spec = dict(
- filename=dict(),
- dir_path=dict(type='path')
- )
- argument_spec = dict(
- src=dict(type='path'),
-
- lines=dict(aliases=['commands'], type='list'),
- parents=dict(type='list'),
-
- before=dict(type='list'),
- after=dict(type='list'),
-
- match=dict(default='line', choices=['line', 'strict', 'exact', 'none']),
- replace=dict(default='line', choices=['line', 'block']),
-
- running_config=dict(aliases=['config']),
- intended_config=dict(),
-
- backup=dict(type='bool', default=False),
- backup_options=dict(type='dict', options=backup_spec),
-
- save_when=dict(choices=['always', 'never', 'modified', 'changed'], default='never'),
-
- diff_against=dict(choices=['running', 'startup', 'intended']),
- diff_ignore_lines=dict(type='list'),
-
- encrypt=dict(type='bool', default=True),
- )
-
- argument_spec.update(aruba_argument_spec)
-
- mutually_exclusive = [('lines', 'src'),
- ('parents', 'src')]
-
- required_if = [('match', 'strict', ['lines']),
- ('match', 'exact', ['lines']),
- ('replace', 'block', ['lines']),
- ('diff_against', 'intended', ['intended_config'])]
-
- module = AnsibleModule(argument_spec=argument_spec,
- mutually_exclusive=mutually_exclusive,
- required_if=required_if,
- supports_check_mode=True)
-
- warnings = list()
- aruba_check_args(module, warnings)
- result = {'changed': False, 'warnings': warnings}
-
- config = None
-
- if module.params['backup'] or (module._diff and module.params['diff_against'] == 'running'):
- contents = get_config(module)
- config = NetworkConfig(contents=contents)
- if module.params['backup']:
- result['__backup__'] = contents
-
- if not module.params['encrypt']:
- run_commands(module, 'encrypt disable')
-
- if any((module.params['src'], module.params['lines'])):
- match = module.params['match']
- replace = module.params['replace']
-
- candidate = get_candidate(module)
-
- if match != 'none':
- config = get_running_config(module, config)
- path = module.params['parents']
- configobjs = candidate.difference(config, match=match, replace=replace, path=path)
- else:
- configobjs = candidate.items
-
- if configobjs:
- commands = dumps(configobjs, 'commands').split('\n')
-
- if module.params['before']:
- commands[:0] = module.params['before']
-
- if module.params['after']:
- commands.extend(module.params['after'])
-
- result['commands'] = commands
- result['updates'] = commands
-
- if not module.check_mode:
- load_config(module, commands)
-
- result['changed'] = True
-
- running_config = None
- startup_config = None
-
- diff_ignore_lines = module.params['diff_ignore_lines']
-
- if module.params['save_when'] == 'always':
- save_config(module, result)
- elif module.params['save_when'] == 'modified':
- output = run_commands(module, ['show running-config', 'show configuration'])
-
- running_config = NetworkConfig(contents=output[0], ignore_lines=diff_ignore_lines)
- startup_config = NetworkConfig(contents=output[1], ignore_lines=diff_ignore_lines)
-
- if running_config.sha1 != startup_config.sha1:
- save_config(module, result)
- elif module.params['save_when'] == 'changed':
- if result['changed']:
- save_config(module, result)
-
- if module._diff:
- if not running_config:
- output = run_commands(module, 'show running-config')
- contents = output[0]
- else:
- contents = running_config.config_text
-
- # recreate the object in order to process diff_ignore_lines
- running_config = NetworkConfig(contents=contents, ignore_lines=diff_ignore_lines)
-
- if module.params['diff_against'] == 'running':
- if module.check_mode:
- module.warn("unable to perform diff against running-config due to check mode")
- contents = None
- else:
- contents = config.config_text
-
- elif module.params['diff_against'] == 'startup':
- if not startup_config:
- output = run_commands(module, 'show configuration')
- contents = output[0]
- else:
- contents = startup_config.config_text
-
- elif module.params['diff_against'] == 'intended':
- contents = module.params['intended_config']
-
- if contents is not None:
- base_config = NetworkConfig(contents=contents, ignore_lines=diff_ignore_lines)
-
- if running_config.sha1 != base_config.sha1:
- result.update({
- 'changed': True,
- 'diff': {'before': str(base_config), 'after': str(running_config)}
- })
-
- # make sure 'encrypt enable' is applied if it was ever disabled
- if not module.params['encrypt']:
- run_commands(module, 'encrypt enable')
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_actiongroupconfig.py b/plugins/modules/network/avi/avi_actiongroupconfig.py
deleted file mode 100644
index 9374845364..0000000000
--- a/plugins/modules/network/avi/avi_actiongroupconfig.py
+++ /dev/null
@@ -1,152 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_actiongroupconfig
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of ActionGroupConfig Avi RESTful Object
-description:
- - This module is used to configure ActionGroupConfig object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- action_script_config_ref:
- description:
- - Reference of the action script configuration to be used.
- - It is a reference to an object of type alertscriptconfig.
- autoscale_trigger_notification:
- description:
- - Trigger notification to autoscale manager.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- description:
- description:
- - User defined description for the object.
- email_config_ref:
- description:
- - Select the email notification configuration to use when sending alerts via email.
- - It is a reference to an object of type alertemailconfig.
- external_only:
- description:
- - Generate alert only to external destinations.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- required: true
- type: bool
- level:
- description:
- - When an alert is generated, mark its priority via the alert level.
- - Enum options - ALERT_LOW, ALERT_MEDIUM, ALERT_HIGH.
- - Default value when not specified in API or module is interpreted by Avi Controller as ALERT_LOW.
- required: true
- name:
- description:
- - Name of the object.
- required: true
- snmp_trap_profile_ref:
- description:
- - Select the snmp trap notification to use when sending alerts via snmp trap.
- - It is a reference to an object of type snmptrapprofile.
- syslog_config_ref:
- description:
- - Select the syslog notification configuration to use when sending alerts via syslog.
- - It is a reference to an object of type alertsyslogconfig.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create ActionGroupConfig object
- avi_actiongroupconfig:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_actiongroupconfig
-"""
-
-RETURN = '''
-obj:
- description: ActionGroupConfig (api/actiongroupconfig) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- action_script_config_ref=dict(type='str',),
- autoscale_trigger_notification=dict(type='bool',),
- description=dict(type='str',),
- email_config_ref=dict(type='str',),
- external_only=dict(type='bool', required=True),
- level=dict(type='str', required=True),
- name=dict(type='str', required=True),
- snmp_trap_profile_ref=dict(type='str',),
- syslog_config_ref=dict(type='str',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'actiongroupconfig',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_alertconfig.py b/plugins/modules/network/avi/avi_alertconfig.py
deleted file mode 100644
index b512195ba9..0000000000
--- a/plugins/modules/network/avi/avi_alertconfig.py
+++ /dev/null
@@ -1,226 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_alertconfig
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of AlertConfig Avi RESTful Object
-description:
- - This module is used to configure AlertConfig object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- action_group_ref:
- description:
- - The alert config will trigger the selected alert action, which can send notifications and execute a controlscript.
- - It is a reference to an object of type actiongroupconfig.
- alert_rule:
- description:
- - List of filters matching on events or client logs used for triggering alerts.
- required: true
- autoscale_alert:
- description:
- - This alert config applies to auto scale alerts.
- type: bool
- category:
- description:
- - Determines whether an alert is raised immediately when event occurs (realtime) or after specified number of events occurs within rolling time
- - window.
- - Enum options - REALTIME, ROLLINGWINDOW, WATERMARK.
- - Default value when not specified in API or module is interpreted by Avi Controller as REALTIME.
- required: true
- description:
- description:
- - A custom description field.
- enabled:
- description:
- - Enable or disable this alert config from generating new alerts.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- expiry_time:
- description:
- - An alert is expired and deleted after the expiry time has elapsed.
- - The original event triggering the alert remains in the event's log.
- - Allowed values are 1-31536000.
- - Default value when not specified in API or module is interpreted by Avi Controller as 86400.
- name:
- description:
- - Name of the alert configuration.
- required: true
- obj_uuid:
- description:
- - Uuid of the resource for which alert was raised.
- object_type:
- description:
- - The object type to which the alert config is associated with.
- - Valid object types are - virtual service, pool, service engine.
- - Enum options - VIRTUALSERVICE, POOL, HEALTHMONITOR, NETWORKPROFILE, APPLICATIONPROFILE, HTTPPOLICYSET, DNSPOLICY, SECURITYPOLICY, IPADDRGROUP,
- - STRINGGROUP, SSLPROFILE, SSLKEYANDCERTIFICATE, NETWORKSECURITYPOLICY, APPLICATIONPERSISTENCEPROFILE, ANALYTICSPROFILE, VSDATASCRIPTSET, TENANT,
- - PKIPROFILE, AUTHPROFILE, CLOUD, SERVERAUTOSCALEPOLICY, AUTOSCALELAUNCHCONFIG, MICROSERVICEGROUP, IPAMPROFILE, HARDWARESECURITYMODULEGROUP,
- - POOLGROUP, PRIORITYLABELS, POOLGROUPDEPLOYMENTPOLICY, GSLBSERVICE, GSLBSERVICERUNTIME, SCHEDULER, GSLBGEODBPROFILE,
- - GSLBAPPLICATIONPERSISTENCEPROFILE, TRAFFICCLONEPROFILE, VSVIP, WAFPOLICY, WAFPROFILE, ERRORPAGEPROFILE, ERRORPAGEBODY, L4POLICYSET,
- - GSLBSERVICERUNTIMEBATCH, WAFPOLICYPSMGROUP, PINGACCESSAGENT, SERVICEENGINEPOLICY, NATPOLICY, SSOPOLICY, PROTOCOLPARSER, SERVICEENGINE,
- - DEBUGSERVICEENGINE, DEBUGCONTROLLER, DEBUGVIRTUALSERVICE, SERVICEENGINEGROUP, SEPROPERTIES, NETWORK, CONTROLLERNODE, CONTROLLERPROPERTIES,
- - SYSTEMCONFIGURATION, VRFCONTEXT, USER, ALERTCONFIG, ALERTSYSLOGCONFIG, ALERTEMAILCONFIG, ALERTTYPECONFIG, APPLICATION, ROLE, CLOUDPROPERTIES,
- - SNMPTRAPPROFILE, ACTIONGROUPPROFILE, MICROSERVICE, ALERTPARAMS, ACTIONGROUPCONFIG, CLOUDCONNECTORUSER, GSLB, GSLBDNSUPDATE, GSLBSITEOPS,
- - GLBMGRWARMSTART, IPAMDNSRECORD, GSLBDNSGSSTATUS, GSLBDNSGEOFILEOPS, GSLBDNSGEOUPDATE, GSLBDNSGEOCLUSTEROPS, GSLBDNSCLEANUP, GSLBSITEOPSRESYNC,
- - IPAMDNSPROVIDERPROFILE, TCPSTATRUNTIME, UDPSTATRUNTIME, IPSTATRUNTIME, ARPSTATRUNTIME, MBSTATRUNTIME, IPSTKQSTATSRUNTIME, MALLOCSTATRUNTIME,
- - SHMALLOCSTATRUNTIME, CPUUSAGERUNTIME, L7GLOBALSTATSRUNTIME, L7VIRTUALSERVICESTATSRUNTIME, SEAGENTVNICDBRUNTIME, SEAGENTGRAPHDBRUNTIME,
- - SEAGENTSTATERUNTIME, INTERFACERUNTIME, ARPTABLERUNTIME, DISPATCHERSTATRUNTIME, DISPATCHERSTATCLEARRUNTIME, DISPATCHERTABLEDUMPRUNTIME,
- - DISPATCHERREMOTETIMERLISTDUMPRUNTIME, METRICSAGENTMESSAGE, HEALTHMONITORSTATRUNTIME, METRICSENTITYRUNTIME, PERSISTENCEINTERNAL,
- - HTTPPOLICYSETINTERNAL, DNSPOLICYINTERNAL, CONNECTIONDUMPRUNTIME, SHAREDDBSTATS, SHAREDDBSTATSCLEAR, ICMPSTATRUNTIME, ROUTETABLERUNTIME,
- - VIRTUALMACHINE, POOLSERVER, SEVSLIST, MEMINFORUNTIME, RTERINGSTATRUNTIME, ALGOSTATRUNTIME, HEALTHMONITORRUNTIME, CPUSTATRUNTIME, SEVM, HOST,
- - PORTGROUP, CLUSTER, DATACENTER, VCENTER, HTTPPOLICYSETSTATS, DNSPOLICYSTATS, METRICSSESTATS, RATELIMITERSTATRUNTIME, NETWORKSECURITYPOLICYSTATS,
- - TCPCONNRUNTIME, POOLSTATS, CONNPOOLINTERNAL, CONNPOOLSTATS, VSHASHSHOWRUNTIME, SELOGSTATSRUNTIME, NETWORKSECURITYPOLICYDETAIL, LICENSERUNTIME,
- - SERVERRUNTIME, METRICSRUNTIMESUMMARY, METRICSRUNTIMEDETAIL, DISPATCHERSEHMPROBETEMPDISABLERUNTIME, POOLDEBUG, VSLOGMGRMAP, SERUMINSERTIONSTATS,
- - HTTPCACHE, HTTPCACHESTATS, SEDOSSTATRUNTIME, VSDOSSTATRUNTIME, SERVERUPDATEREQ, VSSCALEOUTLIST, SEMEMDISTRUNTIME, TCPCONNRUNTIMEDETAIL,
- - SEUPGRADESTATUS, SEUPGRADEPREVIEW, SEFAULTINJECTEXHAUSTM, SEFAULTINJECTEXHAUSTMCL, SEFAULTINJECTEXHAUSTMCLSMALL, SEFAULTINJECTEXHAUSTCONN,
- - SEHEADLESSONLINEREQ, SEUPGRADE, SEUPGRADESTATUSDETAIL, SERESERVEDVS, SERESERVEDVSCLEAR, VSCANDIDATESEHOSTLIST, SEGROUPUPGRADE, REBALANCE,
- - SEGROUPREBALANCE, SEAUTHSTATSRUNTIME, AUTOSCALESTATE, VIRTUALSERVICEAUTHSTATS, NETWORKSECURITYPOLICYDOS, KEYVALINTERNAL, KEYVALSUMMARYINTERNAL,
- - SERVERSTATEUPDATEINFO, CLTRACKINTERNAL, CLTRACKSUMMARYINTERNAL, MICROSERVICERUNTIME, SEMICROSERVICE, VIRTUALSERVICEANALYSIS, CLIENTINTERNAL,
- - CLIENTSUMMARYINTERNAL, MICROSERVICEGROUPRUNTIME, BGPRUNTIME, REQUESTQUEUERUNTIME, MIGRATEALL, MIGRATEALLSTATUSSUMMARY, MIGRATEALLSTATUSDETAIL,
- - INTERFACESUMMARYRUNTIME, INTERFACELACPRUNTIME, DNSTABLE, GSLBSERVICEDETAIL, GSLBSERVICEINTERNAL, GSLBSERVICEHMONSTAT, SETROLESREQUEST,
- - TRAFFICCLONERUNTIME, GEOLOCATIONINFO, SEVSHBSTATRUNTIME, GEODBINTERNAL, GSLBSITEINTERNAL, WAFSTATS, USERDEFINEDDATASCRIPTCOUNTERS, LLDPRUNTIME,
- - VSESSHARINGPOOL, NDTABLERUNTIME, IP6STATRUNTIME, ICMP6STATRUNTIME, SEVSSPLACEMENT, L4POLICYSETSTATS, L4POLICYSETINTERNAL, BGPDEBUGINFO, SHARD,
- - CPUSTATRUNTIMEDETAIL, SEASSERTSTATRUNTIME, SEFAULTINJECTINFRA, SEAGENTASSERTSTATRUNTIME, SEDATASTORESTATUS, DIFFQUEUESTATUS, IP6ROUTETABLERUNTIME,
- - SECURITYMGRSTATE, VIRTUALSERVICESESCALEOUTSTATUS, SHARDSERVERSTATUS, SEAGENTSHARDCLIENTRESOURCEMAP, SEAGENTCONSISTENTHASH, SEAGENTVNICDBHISTORY,
- - SEAGENTSHARDCLIENTAPPMAP, SEAGENTSHARDCLIENTEVENTHISTORY, SENATSTATRUNTIME, SENATFLOWRUNTIME, SERESOURCEPROTO, SECONSUMERPROTO,
- - SECREATEPENDINGPROTO, PLACEMENTSTATS, SEVIPPROTO, RMVRFPROTO, VCENTERMAP, VIMGRVCENTERRUNTIME, INTERESTEDVMS, INTERESTEDHOSTS,
- - VCENTERSUPPORTEDCOUNTERS, ENTITYCOUNTERS, TRANSACTIONSTATS, SEVMCREATEPROGRESS, PLACEMENTSTATUS, VISUBFOLDERS, VIDATASTORE, VIHOSTRESOURCES,
- - CLOUDCONNECTOR, VINETWORKSUBNETVMS, VIDATASTORECONTENTS, VIMGRVCENTERCLOUDRUNTIME, VIVCENTERPORTGROUPS, VIVCENTERDATACENTERS, VIMGRHOSTRUNTIME,
- - PLACEMENTGLOBALS, APICCONFIGURATION, CIFTABLE, APICTRANSACTION, VIRTUALSERVICESTATEDBCACHESUMMARY, POOLSTATEDBCACHESUMMARY,
- - SERVERSTATEDBCACHESUMMARY, APICAGENTINTERNAL, APICTRANSACTIONFLAP, APICGRAPHINSTANCES, APICEPGS, APICEPGEPS, APICDEVICEPKGVER, APICTENANTS,
- - APICVMMDOMAINS, NSXCONFIGURATION, NSXSGTABLE, NSXAGENTINTERNAL, NSXSGINFO, NSXSGIPS, NSXAGENTINTERNALCLI, MAXOBJECTS.
- recommendation:
- description:
- - Recommendation of alertconfig.
- rolling_window:
- description:
- - Only if the number of events is reached or exceeded within the time window will an alert be generated.
- - Allowed values are 1-31536000.
- - Default value when not specified in API or module is interpreted by Avi Controller as 300.
- source:
- description:
- - Signifies system events or the type of client logsused in this alert configuration.
- - Enum options - CONN_LOGS, APP_LOGS, EVENT_LOGS, METRICS.
- required: true
- summary:
- description:
- - Summary of reason why alert is generated.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- threshold:
- description:
- - An alert is created only when the number of events meets or exceeds this number within the chosen time frame.
- - Allowed values are 1-65536.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.
- throttle:
- description:
- - Alerts are suppressed (throttled) for this duration of time since the last alert was raised for this alert config.
- - Allowed values are 0-31536000.
- - Default value when not specified in API or module is interpreted by Avi Controller as 600.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create AlertConfig object
- avi_alertconfig:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_alertconfig
-"""
-
-RETURN = '''
-obj:
- description: AlertConfig (api/alertconfig) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- action_group_ref=dict(type='str',),
- alert_rule=dict(type='dict', required=True),
- autoscale_alert=dict(type='bool',),
- category=dict(type='str', required=True),
- description=dict(type='str',),
- enabled=dict(type='bool',),
- expiry_time=dict(type='int',),
- name=dict(type='str', required=True),
- obj_uuid=dict(type='str',),
- object_type=dict(type='str',),
- recommendation=dict(type='str',),
- rolling_window=dict(type='int',),
- source=dict(type='str', required=True),
- summary=dict(type='str',),
- tenant_ref=dict(type='str',),
- threshold=dict(type='int',),
- throttle=dict(type='int',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'alertconfig',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_alertemailconfig.py b/plugins/modules/network/avi/avi_alertemailconfig.py
deleted file mode 100644
index 8ed5db1ad6..0000000000
--- a/plugins/modules/network/avi/avi_alertemailconfig.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_alertemailconfig
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of AlertEmailConfig Avi RESTful Object
-description:
- - This module is used to configure AlertEmailConfig object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- cc_emails:
- description:
- - Alerts are copied to the comma separated list of email recipients.
- description:
- description:
- - User defined description for the object.
- name:
- description:
- - A user-friendly name of the email notification service.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- to_emails:
- description:
- - Alerts are sent to the comma separated list of email recipients.
- required: true
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create AlertEmailConfig object
- avi_alertemailconfig:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_alertemailconfig
-"""
-
-RETURN = '''
-obj:
- description: AlertEmailConfig (api/alertemailconfig) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- cc_emails=dict(type='str',),
- description=dict(type='str',),
- name=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- to_emails=dict(type='str', required=True),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'alertemailconfig',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_alertscriptconfig.py b/plugins/modules/network/avi/avi_alertscriptconfig.py
deleted file mode 100644
index f616be8d6b..0000000000
--- a/plugins/modules/network/avi/avi_alertscriptconfig.py
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_alertscriptconfig
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of AlertScriptConfig Avi RESTful Object
-description:
- - This module is used to configure AlertScriptConfig object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- action_script:
- description:
- - User defined alert action script.
- - Please refer to kb.avinetworks.com for more information.
- name:
- description:
- - A user-friendly name of the script.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create Alert Script to perform AWS server autoscaling
- avi_alertscriptconfig:
- username: '{{ username }}'
- controller: '{{ controller }}'
- password: '{{ password }}'
- action_script: "echo Hello"
- name: AWS-Launch-Script
- tenant_ref: Demo
-"""
-
-RETURN = '''
-obj:
- description: AlertScriptConfig (api/alertscriptconfig) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- action_script=dict(type='str',),
- name=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'alertscriptconfig',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_alertsyslogconfig.py b/plugins/modules/network/avi/avi_alertsyslogconfig.py
deleted file mode 100644
index 1a71f3d587..0000000000
--- a/plugins/modules/network/avi/avi_alertsyslogconfig.py
+++ /dev/null
@@ -1,120 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_alertsyslogconfig
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of AlertSyslogConfig Avi RESTful Object
-description:
- - This module is used to configure AlertSyslogConfig object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- description:
- description:
- - User defined description for alert syslog config.
- name:
- description:
- - A user-friendly name of the syslog notification.
- required: true
- syslog_servers:
- description:
- - The list of syslog servers.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create Alert Syslog object to forward all events to external syslog server
- avi_alertsyslogconfig:
- controller: '{{ controller }}'
- name: Roberts-syslog
- password: '{{ password }}'
- syslog_servers:
- - syslog_server: 10.10.0.100
- syslog_server_port: 514
- udp: true
- tenant_ref: admin
- username: '{{ username }}'
-"""
-
-RETURN = '''
-obj:
- description: AlertSyslogConfig (api/alertsyslogconfig) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- description=dict(type='str',),
- name=dict(type='str', required=True),
- syslog_servers=dict(type='list',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'alertsyslogconfig',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_analyticsprofile.py b/plugins/modules/network/avi/avi_analyticsprofile.py
deleted file mode 100644
index 866ee9c306..0000000000
--- a/plugins/modules/network/avi/avi_analyticsprofile.py
+++ /dev/null
@@ -1,611 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_analyticsprofile
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of AnalyticsProfile Avi RESTful Object
-description:
- - This module is used to configure AnalyticsProfile object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- apdex_response_threshold:
- description:
- - If a client receives an http response in less than the satisfactory latency threshold, the request is considered satisfied.
- - It is considered tolerated if it is not satisfied and less than tolerated latency factor multiplied by the satisfactory latency threshold.
- - Greater than this number and the client's request is considered frustrated.
- - Allowed values are 1-30000.
- - Default value when not specified in API or module is interpreted by Avi Controller as 500.
- apdex_response_tolerated_factor:
- description:
- - Client tolerated response latency factor.
- - Client must receive a response within this factor times the satisfactory threshold (apdex_response_threshold) to be considered tolerated.
- - Allowed values are 1-1000.
- - Default value when not specified in API or module is interpreted by Avi Controller as 4.0.
- apdex_rtt_threshold:
- description:
- - Satisfactory client to avi round trip time(rtt).
- - Allowed values are 1-2000.
- - Default value when not specified in API or module is interpreted by Avi Controller as 250.
- apdex_rtt_tolerated_factor:
- description:
- - Tolerated client to avi round trip time(rtt) factor.
- - It is a multiple of apdex_rtt_tolerated_factor.
- - Allowed values are 1-1000.
- - Default value when not specified in API or module is interpreted by Avi Controller as 4.0.
- apdex_rum_threshold:
- description:
- - If a client is able to load a page in less than the satisfactory latency threshold, the pageload is considered satisfied.
- - It is considered tolerated if it is greater than satisfied but less than the tolerated latency multiplied by satisfied latency.
- - Greater than this number and the client's request is considered frustrated.
- - A pageload includes the time for dns lookup, download of all http objects, and page render time.
- - Allowed values are 1-30000.
- - Default value when not specified in API or module is interpreted by Avi Controller as 5000.
- apdex_rum_tolerated_factor:
- description:
- - Virtual service threshold factor for tolerated page load time (plt) as multiple of apdex_rum_threshold.
- - Allowed values are 1-1000.
- - Default value when not specified in API or module is interpreted by Avi Controller as 4.0.
- apdex_server_response_threshold:
- description:
- - A server http response is considered satisfied if latency is less than the satisfactory latency threshold.
- - The response is considered tolerated when it is greater than satisfied but less than the tolerated latency factor * s_latency.
- - Greater than this number and the server response is considered frustrated.
- - Allowed values are 1-30000.
- - Default value when not specified in API or module is interpreted by Avi Controller as 400.
- apdex_server_response_tolerated_factor:
- description:
- - Server tolerated response latency factor.
- - Servermust response within this factor times the satisfactory threshold (apdex_server_response_threshold) to be considered tolerated.
- - Allowed values are 1-1000.
- - Default value when not specified in API or module is interpreted by Avi Controller as 4.0.
- apdex_server_rtt_threshold:
- description:
- - Satisfactory client to avi round trip time(rtt).
- - Allowed values are 1-2000.
- - Default value when not specified in API or module is interpreted by Avi Controller as 125.
- apdex_server_rtt_tolerated_factor:
- description:
- - Tolerated client to avi round trip time(rtt) factor.
- - It is a multiple of apdex_rtt_tolerated_factor.
- - Allowed values are 1-1000.
- - Default value when not specified in API or module is interpreted by Avi Controller as 4.0.
- client_log_config:
- description:
- - Configure which logs are sent to the avi controller from ses and how they are processed.
- client_log_streaming_config:
- description:
- - Configure to stream logs to an external server.
- - Field introduced in 17.1.1.
- conn_lossy_ooo_threshold:
- description:
- - A connection between client and avi is considered lossy when more than this percentage of out of order packets are received.
- - Allowed values are 1-100.
- - Default value when not specified in API or module is interpreted by Avi Controller as 50.
- conn_lossy_timeo_rexmt_threshold:
- description:
- - A connection between client and avi is considered lossy when more than this percentage of packets are retransmitted due to timeout.
- - Allowed values are 1-100.
- - Default value when not specified in API or module is interpreted by Avi Controller as 20.
- conn_lossy_total_rexmt_threshold:
- description:
- - A connection between client and avi is considered lossy when more than this percentage of packets are retransmitted.
- - Allowed values are 1-100.
- - Default value when not specified in API or module is interpreted by Avi Controller as 50.
- conn_lossy_zero_win_size_event_threshold:
- description:
- - A client connection is considered lossy when percentage of times a packet could not be transmitted due to tcp zero window is above this threshold.
- - Allowed values are 0-100.
- - Default value when not specified in API or module is interpreted by Avi Controller as 2.
- conn_server_lossy_ooo_threshold:
- description:
- - A connection between avi and server is considered lossy when more than this percentage of out of order packets are received.
- - Allowed values are 1-100.
- - Default value when not specified in API or module is interpreted by Avi Controller as 50.
- conn_server_lossy_timeo_rexmt_threshold:
- description:
- - A connection between avi and server is considered lossy when more than this percentage of packets are retransmitted due to timeout.
- - Allowed values are 1-100.
- - Default value when not specified in API or module is interpreted by Avi Controller as 20.
- conn_server_lossy_total_rexmt_threshold:
- description:
- - A connection between avi and server is considered lossy when more than this percentage of packets are retransmitted.
- - Allowed values are 1-100.
- - Default value when not specified in API or module is interpreted by Avi Controller as 50.
- conn_server_lossy_zero_win_size_event_threshold:
- description:
- - A server connection is considered lossy when percentage of times a packet could not be transmitted due to tcp zero window is above this threshold.
- - Allowed values are 0-100.
- - Default value when not specified in API or module is interpreted by Avi Controller as 2.
- description:
- description:
- - User defined description for the object.
- disable_ondemand_metrics:
- description:
- - Virtual service (vs) metrics are processed only when there is live data traffic on the vs.
- - In case, vs is idle for a period of time as specified by ondemand_metrics_idle_timeout then metrics processing is suspended for that vs.
- - Field introduced in 18.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- disable_se_analytics:
- description:
- - Disable node (service engine) level analytics forvs metrics.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- disable_server_analytics:
- description:
- - Disable analytics on backend servers.
- - This may be desired in container environment when there are large number of ephemeral servers.
- - Additionally, no healthscore of servers is computed when server analytics is disabled.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- disable_vs_analytics:
- description:
- - Disable virtualservice (frontend) analytics.
- - This flag disables metrics and healthscore for virtualservice.
- - Field introduced in 18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- enable_advanced_analytics:
- description:
- - Enables advanced analytics features like anomaly detection.
- - If set to false, anomaly computation (and associated rules/events) for vs, pool and server metrics will be disabled.
- - However, setting it to false reduces cpu and memory requirements for analytics subsystem.
- - Field introduced in 17.2.13, 18.1.5, 18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- exclude_client_close_before_request_as_error:
- description:
- - Exclude client closed connection before an http request could be completed from being classified as an error.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- exclude_dns_policy_drop_as_significant:
- description:
- - Exclude dns policy drops from the list of errors.
- - Field introduced in 17.2.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- exclude_gs_down_as_error:
- description:
- - Exclude queries to gslb services that are operationally down from the list of errors.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- exclude_http_error_codes:
- description:
- - List of http status codes to be excluded from being classified as an error.
- - Error connections or responses impacts health score, are included as significant logs, and may be classified as part of a dos attack.
- exclude_invalid_dns_domain_as_error:
- description:
- - Exclude dns queries to domains outside the domains configured in the dns application profile from the list of errors.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- exclude_invalid_dns_query_as_error:
- description:
- - Exclude invalid dns queries from the list of errors.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- exclude_no_dns_record_as_error:
- description:
- - Exclude queries to domains that did not have configured services/records from the list of errors.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- exclude_no_valid_gs_member_as_error:
- description:
- - Exclude queries to gslb services that have no available members from the list of errors.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- exclude_persistence_change_as_error:
- description:
- - Exclude persistence server changed while load balancing' from the list of errors.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- exclude_server_dns_error_as_error:
- description:
- - Exclude server dns error response from the list of errors.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- exclude_server_tcp_reset_as_error:
- description:
- - Exclude server tcp reset from errors.
- - It is common for applications like ms exchange.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- exclude_sip_error_codes:
- description:
- - List of sip status codes to be excluded from being classified as an error.
- - Field introduced in 17.2.13, 18.1.5, 18.2.1.
- exclude_syn_retransmit_as_error:
- description:
- - Exclude 'server unanswered syns' from the list of errors.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- exclude_tcp_reset_as_error:
- description:
- - Exclude tcp resets by client from the list of potential errors.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- exclude_unsupported_dns_query_as_error:
- description:
- - Exclude unsupported dns queries from the list of errors.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- healthscore_max_server_limit:
- description:
- - Skips health score computation of pool servers when number of servers in a pool is more than this setting.
- - Allowed values are 0-5000.
- - Special values are 0- 'server health score is disabled'.
- - Field introduced in 17.2.13, 18.1.4.
- - Default value when not specified in API or module is interpreted by Avi Controller as 20.
- hs_event_throttle_window:
- description:
- - Time window (in secs) within which only unique health change events should occur.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1209600.
- hs_max_anomaly_penalty:
- description:
- - Maximum penalty that may be deducted from health score for anomalies.
- - Allowed values are 0-100.
- - Default value when not specified in API or module is interpreted by Avi Controller as 10.
- hs_max_resources_penalty:
- description:
- - Maximum penalty that may be deducted from health score for high resource utilization.
- - Allowed values are 0-100.
- - Default value when not specified in API or module is interpreted by Avi Controller as 25.
- hs_max_security_penalty:
- description:
- - Maximum penalty that may be deducted from health score based on security assessment.
- - Allowed values are 0-100.
- - Default value when not specified in API or module is interpreted by Avi Controller as 100.
- hs_min_dos_rate:
- description:
- - Dos connection rate below which the dos security assessment will not kick in.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1000.
- hs_performance_boost:
- description:
- - Adds free performance score credits to health score.
- - It can be used for compensating health score for known slow applications.
- - Allowed values are 0-100.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- hs_pscore_traffic_threshold_l4_client:
- description:
- - Threshold number of connections in 5min, below which apdexr, apdexc, rum_apdex, and other network quality metrics are not computed.
- - Default value when not specified in API or module is interpreted by Avi Controller as 10.0.
- hs_pscore_traffic_threshold_l4_server:
- description:
- - Threshold number of connections in 5min, below which apdexr, apdexc, rum_apdex, and other network quality metrics are not computed.
- - Default value when not specified in API or module is interpreted by Avi Controller as 10.0.
- hs_security_certscore_expired:
- description:
- - Score assigned when the certificate has expired.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.0.
- hs_security_certscore_gt30d:
- description:
- - Score assigned when the certificate expires in more than 30 days.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 5.0.
- hs_security_certscore_le07d:
- description:
- - Score assigned when the certificate expires in less than or equal to 7 days.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 2.0.
- hs_security_certscore_le30d:
- description:
- - Score assigned when the certificate expires in less than or equal to 30 days.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 4.0.
- hs_security_chain_invalidity_penalty:
- description:
- - Penalty for allowing certificates with invalid chain.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.0.
- hs_security_cipherscore_eq000b:
- description:
- - Score assigned when the minimum cipher strength is 0 bits.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.0.
- hs_security_cipherscore_ge128b:
- description:
- - Score assigned when the minimum cipher strength is greater than equal to 128 bits.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 5.0.
- hs_security_cipherscore_lt128b:
- description:
- - Score assigned when the minimum cipher strength is less than 128 bits.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 3.5.
- hs_security_encalgo_score_none:
- description:
- - Score assigned when no algorithm is used for encryption.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.0.
- hs_security_encalgo_score_rc4:
- description:
- - Score assigned when rc4 algorithm is used for encryption.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 2.5.
- hs_security_hsts_penalty:
- description:
- - Penalty for not enabling hsts.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.0.
- hs_security_nonpfs_penalty:
- description:
- - Penalty for allowing non-pfs handshakes.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.0.
- hs_security_selfsignedcert_penalty:
- description:
- - Deprecated.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.0.
- hs_security_ssl30_score:
- description:
- - Score assigned when supporting ssl3.0 encryption protocol.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 3.5.
- hs_security_tls10_score:
- description:
- - Score assigned when supporting tls1.0 encryption protocol.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 5.0.
- hs_security_tls11_score:
- description:
- - Score assigned when supporting tls1.1 encryption protocol.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 5.0.
- hs_security_tls12_score:
- description:
- - Score assigned when supporting tls1.2 encryption protocol.
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 5.0.
- hs_security_weak_signature_algo_penalty:
- description:
- - Penalty for allowing weak signature algorithm(s).
- - Allowed values are 0-5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.0.
- name:
- description:
- - The name of the analytics profile.
- required: true
- ondemand_metrics_idle_timeout:
- description:
- - This flag sets the time duration of no live data traffic after which virtual service metrics processing is suspended.
- - It is applicable only when disable_ondemand_metrics is set to false.
- - Field introduced in 18.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1800.
- ranges:
- description:
- - List of http status code ranges to be excluded from being classified as an error.
- resp_code_block:
- description:
- - Block of http response codes to be excluded from being classified as an error.
- - Enum options - AP_HTTP_RSP_4XX, AP_HTTP_RSP_5XX.
- sensitive_log_profile:
- description:
- - Rules applied to the http application log for filtering sensitive information.
- - Field introduced in 17.2.10, 18.1.2.
- sip_log_depth:
- description:
- - Maximum number of sip messages added in logs for a sip transaction.
- - By default, this value is 20.
- - Allowed values are 1-1000.
- - Field introduced in 17.2.13, 18.1.5, 18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 20.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the analytics profile.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create a custom Analytics profile object
- avi_analyticsprofile:
- controller: '{{ controller }}'
- username: '{{ username }}'
- password: '{{ password }}'
- apdex_response_threshold: 500
- apdex_response_tolerated_factor: 4.0
- apdex_rtt_threshold: 250
- apdex_rtt_tolerated_factor: 4.0
- apdex_rum_threshold: 5000
- apdex_rum_tolerated_factor: 4.0
- apdex_server_response_threshold: 400
- apdex_server_response_tolerated_factor: 4.0
- apdex_server_rtt_threshold: 125
- apdex_server_rtt_tolerated_factor: 4.0
- conn_lossy_ooo_threshold: 50
- conn_lossy_timeo_rexmt_threshold: 20
- conn_lossy_total_rexmt_threshold: 50
- conn_lossy_zero_win_size_event_threshold: 2
- conn_server_lossy_ooo_threshold: 50
- conn_server_lossy_timeo_rexmt_threshold: 20
- conn_server_lossy_total_rexmt_threshold: 50
- conn_server_lossy_zero_win_size_event_threshold: 2
- disable_se_analytics: false
- disable_server_analytics: false
- exclude_client_close_before_request_as_error: false
- exclude_persistence_change_as_error: false
- exclude_server_tcp_reset_as_error: false
- exclude_syn_retransmit_as_error: false
- exclude_tcp_reset_as_error: false
- hs_event_throttle_window: 1209600
- hs_max_anomaly_penalty: 10
- hs_max_resources_penalty: 25
- hs_max_security_penalty: 100
- hs_min_dos_rate: 1000
- hs_performance_boost: 20
- hs_pscore_traffic_threshold_l4_client: 10.0
- hs_pscore_traffic_threshold_l4_server: 10.0
- hs_security_certscore_expired: 0.0
- hs_security_certscore_gt30d: 5.0
- hs_security_certscore_le07d: 2.0
- hs_security_certscore_le30d: 4.0
- hs_security_chain_invalidity_penalty: 1.0
- hs_security_cipherscore_eq000b: 0.0
- hs_security_cipherscore_ge128b: 5.0
- hs_security_cipherscore_lt128b: 3.5
- hs_security_encalgo_score_none: 0.0
- hs_security_encalgo_score_rc4: 2.5
- hs_security_hsts_penalty: 0.0
- hs_security_nonpfs_penalty: 1.0
- hs_security_selfsignedcert_penalty: 1.0
- hs_security_ssl30_score: 3.5
- hs_security_tls10_score: 5.0
- hs_security_tls11_score: 5.0
- hs_security_tls12_score: 5.0
- hs_security_weak_signature_algo_penalty: 1.0
- name: jason-analytics-profile
- tenant_ref: Demo
-"""
-
-RETURN = '''
-obj:
- description: AnalyticsProfile (api/analyticsprofile) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- apdex_response_threshold=dict(type='int',),
- apdex_response_tolerated_factor=dict(type='float',),
- apdex_rtt_threshold=dict(type='int',),
- apdex_rtt_tolerated_factor=dict(type='float',),
- apdex_rum_threshold=dict(type='int',),
- apdex_rum_tolerated_factor=dict(type='float',),
- apdex_server_response_threshold=dict(type='int',),
- apdex_server_response_tolerated_factor=dict(type='float',),
- apdex_server_rtt_threshold=dict(type='int',),
- apdex_server_rtt_tolerated_factor=dict(type='float',),
- client_log_config=dict(type='dict',),
- client_log_streaming_config=dict(type='dict',),
- conn_lossy_ooo_threshold=dict(type='int',),
- conn_lossy_timeo_rexmt_threshold=dict(type='int',),
- conn_lossy_total_rexmt_threshold=dict(type='int',),
- conn_lossy_zero_win_size_event_threshold=dict(type='int',),
- conn_server_lossy_ooo_threshold=dict(type='int',),
- conn_server_lossy_timeo_rexmt_threshold=dict(type='int',),
- conn_server_lossy_total_rexmt_threshold=dict(type='int',),
- conn_server_lossy_zero_win_size_event_threshold=dict(type='int',),
- description=dict(type='str',),
- disable_ondemand_metrics=dict(type='bool',),
- disable_se_analytics=dict(type='bool',),
- disable_server_analytics=dict(type='bool',),
- disable_vs_analytics=dict(type='bool',),
- enable_advanced_analytics=dict(type='bool',),
- exclude_client_close_before_request_as_error=dict(type='bool',),
- exclude_dns_policy_drop_as_significant=dict(type='bool',),
- exclude_gs_down_as_error=dict(type='bool',),
- exclude_http_error_codes=dict(type='list',),
- exclude_invalid_dns_domain_as_error=dict(type='bool',),
- exclude_invalid_dns_query_as_error=dict(type='bool',),
- exclude_no_dns_record_as_error=dict(type='bool',),
- exclude_no_valid_gs_member_as_error=dict(type='bool',),
- exclude_persistence_change_as_error=dict(type='bool',),
- exclude_server_dns_error_as_error=dict(type='bool',),
- exclude_server_tcp_reset_as_error=dict(type='bool',),
- exclude_sip_error_codes=dict(type='list',),
- exclude_syn_retransmit_as_error=dict(type='bool',),
- exclude_tcp_reset_as_error=dict(type='bool',),
- exclude_unsupported_dns_query_as_error=dict(type='bool',),
- healthscore_max_server_limit=dict(type='int',),
- hs_event_throttle_window=dict(type='int',),
- hs_max_anomaly_penalty=dict(type='int',),
- hs_max_resources_penalty=dict(type='int',),
- hs_max_security_penalty=dict(type='int',),
- hs_min_dos_rate=dict(type='int',),
- hs_performance_boost=dict(type='int',),
- hs_pscore_traffic_threshold_l4_client=dict(type='float',),
- hs_pscore_traffic_threshold_l4_server=dict(type='float',),
- hs_security_certscore_expired=dict(type='float',),
- hs_security_certscore_gt30d=dict(type='float',),
- hs_security_certscore_le07d=dict(type='float',),
- hs_security_certscore_le30d=dict(type='float',),
- hs_security_chain_invalidity_penalty=dict(type='float',),
- hs_security_cipherscore_eq000b=dict(type='float',),
- hs_security_cipherscore_ge128b=dict(type='float',),
- hs_security_cipherscore_lt128b=dict(type='float',),
- hs_security_encalgo_score_none=dict(type='float',),
- hs_security_encalgo_score_rc4=dict(type='float',),
- hs_security_hsts_penalty=dict(type='float',),
- hs_security_nonpfs_penalty=dict(type='float',),
- hs_security_selfsignedcert_penalty=dict(type='float',),
- hs_security_ssl30_score=dict(type='float',),
- hs_security_tls10_score=dict(type='float',),
- hs_security_tls11_score=dict(type='float',),
- hs_security_tls12_score=dict(type='float',),
- hs_security_weak_signature_algo_penalty=dict(type='float',),
- name=dict(type='str', required=True),
- ondemand_metrics_idle_timeout=dict(type='int',),
- ranges=dict(type='list',),
- resp_code_block=dict(type='list',),
- sensitive_log_profile=dict(type='dict',),
- sip_log_depth=dict(type='int',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'analyticsprofile',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_api_session.py b/plugins/modules/network/avi/avi_api_session.py
deleted file mode 100644
index b46bb06fd4..0000000000
--- a/plugins/modules/network/avi/avi_api_session.py
+++ /dev/null
@@ -1,258 +0,0 @@
-#!/usr/bin/python
-"""
-# Created on Aug 12, 2016
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com) GitHub ID: grastogi23
-#
-# module_check: not supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-"""
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: avi_api_session
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Avi API Module
-description:
- - This module can be used for calling any resources defined in Avi REST API. U(https://avinetworks.com/)
- - This module is useful for invoking HTTP Patch methods and accessing resources that do not have an REST object associated with them.
-requirements: [ avisdk ]
-options:
- http_method:
- description:
- - Allowed HTTP methods for RESTful services and are supported by Avi Controller.
- choices: ["get", "put", "post", "patch", "delete"]
- required: true
- data:
- description:
- - HTTP body in YAML or JSON format.
- params:
- description:
- - Query parameters passed to the HTTP API.
- path:
- description:
- - 'Path for Avi API resource. For example, C(path: virtualservice) will translate to C(api/virtualserivce).'
- timeout:
- description:
- - Timeout (in seconds) for Avi API calls.
- default: 60
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = '''
-
- - name: Get Pool Information using avi_api_session
- avi_api_session:
- controller: "{{ controller }}"
- username: "{{ username }}"
- password: "{{ password }}"
- http_method: get
- path: pool
- params:
- name: "{{ pool_name }}"
- api_version: 16.4
- register: pool_results
-
- - name: Patch Pool with list of servers
- avi_api_session:
- controller: "{{ controller }}"
- username: "{{ username }}"
- password: "{{ password }}"
- http_method: patch
- path: "{{ pool_path }}"
- api_version: 16.4
- data:
- add:
- servers:
- - ip:
- addr: 10.10.10.10
- type: V4
- - ip:
- addr: 20.20.20.20
- type: V4
- register: updated_pool
-
- - name: Fetch Pool metrics bandwidth and connections rate
- avi_api_session:
- controller: "{{ controller }}"
- username: "{{ username }}"
- password: "{{ password }}"
- http_method: get
- path: analytics/metrics/pool
- api_version: 16.4
- params:
- name: "{{ pool_name }}"
- metric_id: l4_server.avg_bandwidth,l4_server.avg_complete_conns
- step: 300
- limit: 10
- register: pool_metrics
-
-'''
-
-
-RETURN = '''
-obj:
- description: Avi REST resource
- returned: success, changed
- type: dict
-'''
-
-
-import json
-import time
-from ansible.module_utils.basic import AnsibleModule
-from copy import deepcopy
-
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, ansible_return, avi_obj_cmp,
- cleanup_absent_fields, HAS_AVI)
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi_api import (
- ApiSession, AviCredentials)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- http_method=dict(required=True,
- choices=['get', 'put', 'post', 'patch',
- 'delete']),
- path=dict(type='str', required=True),
- params=dict(type='dict'),
- data=dict(type='jsonarg'),
- timeout=dict(type='int', default=60)
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(argument_spec=argument_specs)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- api_creds = AviCredentials()
- api_creds.update_from_ansible_module(module)
- api = ApiSession.get_session(
- api_creds.controller, api_creds.username, password=api_creds.password,
- timeout=api_creds.timeout, tenant=api_creds.tenant,
- tenant_uuid=api_creds.tenant_uuid, token=api_creds.token,
- port=api_creds.port)
-
- tenant_uuid = api_creds.tenant_uuid
- tenant = api_creds.tenant
- timeout = int(module.params.get('timeout'))
- # path is a required argument
- path = module.params.get('path', '')
- params = module.params.get('params', None)
- data = module.params.get('data', None)
- # Get the api_version from module.
- api_version = api_creds.api_version
- if data is not None:
- data = json.loads(data)
- method = module.params['http_method']
-
- existing_obj = None
- changed = method != 'get'
- gparams = deepcopy(params) if params else {}
- gparams.update({'include_refs': '', 'include_name': ''})
-
- # API methods not allowed
- api_get_not_allowed = ["cluster", "gslbsiteops"]
- api_post_not_allowed = ["alert", "fileservice"]
- api_put_not_allowed = ["backup"]
-
- if method == 'post' and not any(path.startswith(uri) for uri in api_post_not_allowed):
- # TODO: Above condition should be updated after AV-38981 is fixed
- # need to check if object already exists. In that case
- # change the method to be put
- try:
- using_collection = False
- if not any(path.startswith(uri) for uri in api_get_not_allowed):
- if 'name' in data:
- gparams['name'] = data['name']
- using_collection = True
- if not any(path.startswith(uri) for uri in api_get_not_allowed):
- rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid,
- params=gparams, api_version=api_version)
- existing_obj = rsp.json()
- if using_collection:
- existing_obj = existing_obj['results'][0]
- except (IndexError, KeyError):
- # object is not found
- pass
- else:
- if not any(path.startswith(uri) for uri in api_get_not_allowed):
- # object is present
- method = 'put'
- path += '/' + existing_obj['uuid']
-
- if method == 'put' and not any(path.startswith(uri) for uri in api_put_not_allowed):
- # put can happen with when full path is specified or it is put + post
- if existing_obj is None:
- using_collection = False
- if ((len(path.split('/')) == 1) and ('name' in data) and
- (not any(path.startswith(uri) for uri in api_get_not_allowed))):
- gparams['name'] = data['name']
- using_collection = True
- rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid,
- params=gparams, api_version=api_version)
- rsp_data = rsp.json()
- if using_collection:
- if rsp_data['results']:
- existing_obj = rsp_data['results'][0]
- path += '/' + existing_obj['uuid']
- else:
- method = 'post'
- else:
- if rsp.status_code == 404:
- method = 'post'
- else:
- existing_obj = rsp_data
- if existing_obj:
- changed = not avi_obj_cmp(data, existing_obj)
- cleanup_absent_fields(data)
- if method == 'patch':
- rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid,
- params=gparams, api_version=api_version)
- existing_obj = rsp.json()
-
- if (method == 'put' and changed) or (method != 'put'):
- fn = getattr(api, method)
- rsp = fn(path, tenant=tenant, tenant_uuid=tenant, timeout=timeout,
- params=params, data=data, api_version=api_version)
- else:
- rsp = None
- if method == 'delete' and rsp.status_code == 404:
- changed = False
- rsp.status_code = 200
- if method == 'patch' and existing_obj and rsp.status_code < 299:
- # Ideally the comparison should happen with the return values
- # from the patch API call. However, currently Avi API are
- # returning different hostname when GET is used vs Patch.
- # tracked as AV-12561
- if path.startswith('pool'):
- time.sleep(1)
- gparams = deepcopy(params) if params else {}
- gparams.update({'include_refs': '', 'include_name': ''})
- rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid,
- params=gparams, api_version=api_version)
- new_obj = rsp.json()
- changed = not avi_obj_cmp(new_obj, existing_obj)
- if rsp is None:
- return module.exit_json(changed=changed, obj=existing_obj)
- return ansible_return(module, rsp, changed, req=data)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_api_version.py b/plugins/modules/network/avi/avi_api_version.py
deleted file mode 100644
index b509483cc2..0000000000
--- a/plugins/modules/network/avi/avi_api_version.py
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/python
-"""
-# Created on July 24, 2017
-#
-# @author: Vilian Atmadzhov (vilian.atmadzhov@paddypowerbetfair.com) GitHub ID: vivobg
-#
-# module_check: not supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# Vilian Atmadzhov,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-"""
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: avi_api_version
-author: Vilian Atmadzhov (@vivobg)
-
-short_description: Avi API Version Module
-description:
- - This module can be used to obtain the version of the Avi REST API. U(https://avinetworks.com/)
-requirements: [ avisdk ]
-options: {}
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = '''
- - name: Get AVI API version
- avi_api_version:
- controller: ""
- username: ""
- password: ""
- tenant: ""
- register: avi_controller_version
-'''
-
-
-RETURN = '''
-obj:
- description: Avi REST resource
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, ansible_return, HAS_AVI)
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi_api import (
- ApiSession, AviCredentials)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict()
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(argument_spec=argument_specs)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- try:
- api_creds = AviCredentials()
- api_creds.update_from_ansible_module(module)
- api = ApiSession.get_session(
- api_creds.controller, api_creds.username,
- password=api_creds.password,
- timeout=api_creds.timeout, tenant=api_creds.tenant,
- tenant_uuid=api_creds.tenant_uuid, token=api_creds.token,
- port=api_creds.port)
-
- remote_api_version = api.remote_api_version
- remote = {}
- for key in remote_api_version.keys():
- remote[key.lower()] = remote_api_version[key]
- api.close()
- module.exit_json(changed=False, obj=remote)
- except Exception as e:
- module.fail_json(msg=("Unable to get an AVI session. %s" % e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_applicationpersistenceprofile.py b/plugins/modules/network/avi/avi_applicationpersistenceprofile.py
deleted file mode 100644
index 24072d0f4a..0000000000
--- a/plugins/modules/network/avi/avi_applicationpersistenceprofile.py
+++ /dev/null
@@ -1,165 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_applicationpersistenceprofile
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of ApplicationPersistenceProfile Avi RESTful Object
-description:
- - This module is used to configure ApplicationPersistenceProfile object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- app_cookie_persistence_profile:
- description:
- - Specifies the application cookie persistence profile parameters.
- description:
- description:
- - User defined description for the object.
- hdr_persistence_profile:
- description:
- - Specifies the custom http header persistence profile parameters.
- http_cookie_persistence_profile:
- description:
- - Specifies the http cookie persistence profile parameters.
- ip_persistence_profile:
- description:
- - Specifies the client ip persistence profile parameters.
- is_federated:
- description:
- - This field describes the object's replication scope.
- - If the field is set to false, then the object is visible within the controller-cluster and its associated service-engines.
- - If the field is set to true, then the object is replicated across the federation.
- - Field introduced in 17.1.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- name:
- description:
- - A user-friendly name for the persistence profile.
- required: true
- persistence_type:
- description:
- - Method used to persist clients to the same server for a duration of time or a session.
- - Enum options - PERSISTENCE_TYPE_CLIENT_IP_ADDRESS, PERSISTENCE_TYPE_HTTP_COOKIE, PERSISTENCE_TYPE_TLS, PERSISTENCE_TYPE_CLIENT_IPV6_ADDRESS,
- - PERSISTENCE_TYPE_CUSTOM_HTTP_HEADER, PERSISTENCE_TYPE_APP_COOKIE, PERSISTENCE_TYPE_GSLB_SITE.
- - Default value when not specified in API or module is interpreted by Avi Controller as PERSISTENCE_TYPE_CLIENT_IP_ADDRESS.
- required: true
- server_hm_down_recovery:
- description:
- - Specifies behavior when a persistent server has been marked down by a health monitor.
- - Enum options - HM_DOWN_PICK_NEW_SERVER, HM_DOWN_ABORT_CONNECTION, HM_DOWN_CONTINUE_PERSISTENT_SERVER.
- - Default value when not specified in API or module is interpreted by Avi Controller as HM_DOWN_PICK_NEW_SERVER.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the persistence profile.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create an Application Persistence setting using http cookie.
- avi_applicationpersistenceprofile:
- controller: '{{ controller }}'
- username: '{{ username }}'
- password: '{{ password }}'
- http_cookie_persistence_profile:
- always_send_cookie: false
- cookie_name: My-HTTP
- key:
- - aes_key: ShYGZdMks8j6Bpvm2sCvaXWzvXms2Z9ob+TTjRy46lQ=
- name: c1276819-550c-4adf-912d-59efa5fd7269
- - aes_key: OGsyVk84VCtyMENFOW0rMnRXVnNrb0RzdG5mT29oamJRb0dlbHZVSjR1az0=
- name: a080de57-77c3-4580-a3ea-e7a6493c14fd
- - aes_key: UVN0cU9HWmFUM2xOUzBVcmVXaHFXbnBLVUUxMU1VSktSVU5HWjJOWmVFMTBUMUV4UmxsNk4xQmFZejA9
- name: 60478846-33c6-484d-868d-bbc324fce4a5
- timeout: 15
- name: My-HTTP-Cookie
- persistence_type: PERSISTENCE_TYPE_HTTP_COOKIE
- server_hm_down_recovery: HM_DOWN_PICK_NEW_SERVER
- tenant_ref: Demo
-"""
-
-RETURN = '''
-obj:
- description: ApplicationPersistenceProfile (api/applicationpersistenceprofile) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- app_cookie_persistence_profile=dict(type='dict',),
- description=dict(type='str',),
- hdr_persistence_profile=dict(type='dict',),
- http_cookie_persistence_profile=dict(type='dict',),
- ip_persistence_profile=dict(type='dict',),
- is_federated=dict(type='bool',),
- name=dict(type='str', required=True),
- persistence_type=dict(type='str', required=True),
- server_hm_down_recovery=dict(type='str',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'applicationpersistenceprofile',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_applicationprofile.py b/plugins/modules/network/avi/avi_applicationprofile.py
deleted file mode 100644
index 10f8b0038f..0000000000
--- a/plugins/modules/network/avi/avi_applicationprofile.py
+++ /dev/null
@@ -1,218 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_applicationprofile
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of ApplicationProfile Avi RESTful Object
-description:
- - This module is used to configure ApplicationProfile object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- cloud_config_cksum:
- description:
- - Checksum of application profiles.
- - Internally set by cloud connector.
- - Field introduced in 17.2.14, 18.1.5, 18.2.1.
- created_by:
- description:
- - Name of the application profile creator.
- - Field introduced in 17.2.14, 18.1.5, 18.2.1.
- description:
- description:
- - User defined description for the object.
- dns_service_profile:
- description:
- - Specifies various dns service related controls for virtual service.
- dos_rl_profile:
- description:
- - Specifies various security related controls for virtual service.
- http_profile:
- description:
- - Specifies the http application proxy profile parameters.
- name:
- description:
- - The name of the application profile.
- required: true
- preserve_client_ip:
- description:
- - Specifies if client ip needs to be preserved for backend connection.
- - Not compatible with connection multiplexing.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- preserve_client_port:
- description:
- - Specifies if we need to preserve client port while preserving client ip for backend connections.
- - Field introduced in 17.2.7.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- sip_service_profile:
- description:
- - Specifies various sip service related controls for virtual service.
- - Field introduced in 17.2.8, 18.1.3, 18.2.1.
- tcp_app_profile:
- description:
- - Specifies the tcp application proxy profile parameters.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- type:
- description:
- - Specifies which application layer proxy is enabled for the virtual service.
- - Enum options - APPLICATION_PROFILE_TYPE_L4, APPLICATION_PROFILE_TYPE_HTTP, APPLICATION_PROFILE_TYPE_SYSLOG, APPLICATION_PROFILE_TYPE_DNS,
- - APPLICATION_PROFILE_TYPE_SSL, APPLICATION_PROFILE_TYPE_SIP.
- required: true
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the application profile.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create an Application Profile for HTTP application enabled for SSL traffic
- avi_applicationprofile:
- controller: '{{ controller }}'
- username: '{{ username }}'
- password: '{{ password }}'
- http_profile:
- cache_config:
- age_header: true
- aggressive: false
- date_header: true
- default_expire: 600
- enabled: false
- heuristic_expire: false
- max_cache_size: 0
- max_object_size: 4194304
- mime_types_group_refs:
- - admin:System-Cacheable-Resource-Types
- min_object_size: 100
- query_cacheable: false
- xcache_header: true
- client_body_timeout: 0
- client_header_timeout: 10000
- client_max_body_size: 0
- client_max_header_size: 12
- client_max_request_size: 48
- compression_profile:
- compressible_content_ref: admin:System-Compressible-Content-Types
- compression: false
- remove_accept_encoding_header: true
- type: AUTO_COMPRESSION
- connection_multiplexing_enabled: true
- hsts_enabled: false
- hsts_max_age: 365
- http_to_https: false
- httponly_enabled: false
- keepalive_header: false
- keepalive_timeout: 30000
- max_bad_rps_cip: 0
- max_bad_rps_cip_uri: 0
- max_bad_rps_uri: 0
- max_rps_cip: 0
- max_rps_cip_uri: 0
- max_rps_unknown_cip: 0
- max_rps_unknown_uri: 0
- max_rps_uri: 0
- post_accept_timeout: 30000
- secure_cookie_enabled: false
- server_side_redirect_to_https: false
- spdy_enabled: false
- spdy_fwd_proxy_mode: false
- ssl_client_certificate_mode: SSL_CLIENT_CERTIFICATE_NONE
- ssl_everywhere_enabled: false
- websockets_enabled: true
- x_forwarded_proto_enabled: false
- xff_alternate_name: X-Forwarded-For
- xff_enabled: true
- name: System-HTTP
- tenant_ref: admin
- type: APPLICATION_PROFILE_TYPE_HTTP
-"""
-
-RETURN = '''
-obj:
- description: ApplicationProfile (api/applicationprofile) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- cloud_config_cksum=dict(type='str',),
- created_by=dict(type='str',),
- description=dict(type='str',),
- dns_service_profile=dict(type='dict',),
- dos_rl_profile=dict(type='dict',),
- http_profile=dict(type='dict',),
- name=dict(type='str', required=True),
- preserve_client_ip=dict(type='bool',),
- preserve_client_port=dict(type='bool',),
- sip_service_profile=dict(type='dict',),
- tcp_app_profile=dict(type='dict',),
- tenant_ref=dict(type='str',),
- type=dict(type='str', required=True),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'applicationprofile',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_authprofile.py b/plugins/modules/network/avi/avi_authprofile.py
deleted file mode 100644
index dd5b2f3a0d..0000000000
--- a/plugins/modules/network/avi/avi_authprofile.py
+++ /dev/null
@@ -1,165 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_authprofile
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of AuthProfile Avi RESTful Object
-description:
- - This module is used to configure AuthProfile object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- description:
- description:
- - User defined description for the object.
- http:
- description:
- - Http user authentication params.
- ldap:
- description:
- - Ldap server and directory settings.
- name:
- description:
- - Name of the auth profile.
- required: true
- pa_agent_ref:
- description:
- - Pingaccessagent uuid.
- - It is a reference to an object of type pingaccessagent.
- - Field introduced in 18.2.3.
- saml:
- description:
- - Saml settings.
- - Field introduced in 17.2.3.
- tacacs_plus:
- description:
- - Tacacs+ settings.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- type:
- description:
- - Type of the auth profile.
- - Enum options - AUTH_PROFILE_LDAP, AUTH_PROFILE_TACACS_PLUS, AUTH_PROFILE_SAML, AUTH_PROFILE_PINGACCESS.
- required: true
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the auth profile.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create user authorization profile based on the LDAP
- avi_authprofile:
- controller: '{{ controller }}'
- password: '{{ password }}'
- username: '{{ username }}'
- http:
- cache_expiration_time: 5
- group_member_is_full_dn: false
- ldap:
- base_dn: dc=avi,dc=local
- bind_as_administrator: true
- port: 389
- security_mode: AUTH_LDAP_SECURE_NONE
- server:
- - 10.10.0.100
- settings:
- admin_bind_dn: user@avi.local
- group_filter: (objectClass=*)
- group_member_attribute: member
- group_member_is_full_dn: true
- group_search_dn: dc=avi,dc=local
- group_search_scope: AUTH_LDAP_SCOPE_SUBTREE
- ignore_referrals: true
- password: password
- user_id_attribute: samAccountname
- user_search_dn: dc=avi,dc=local
- user_search_scope: AUTH_LDAP_SCOPE_ONE
- name: ProdAuth
- tenant_ref: admin
- type: AUTH_PROFILE_LDAP
-"""
-
-RETURN = '''
-obj:
- description: AuthProfile (api/authprofile) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- description=dict(type='str',),
- http=dict(type='dict',),
- ldap=dict(type='dict',),
- name=dict(type='str', required=True),
- pa_agent_ref=dict(type='str',),
- saml=dict(type='dict',),
- tacacs_plus=dict(type='dict',),
- tenant_ref=dict(type='str',),
- type=dict(type='str', required=True),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'authprofile',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_autoscalelaunchconfig.py b/plugins/modules/network/avi/avi_autoscalelaunchconfig.py
deleted file mode 100644
index a1655f617d..0000000000
--- a/plugins/modules/network/avi/avi_autoscalelaunchconfig.py
+++ /dev/null
@@ -1,133 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_autoscalelaunchconfig
-author: Chaitanya Deshpande (@chaitanyaavi)
-
-short_description: Module for setup of AutoScaleLaunchConfig Avi RESTful Object
-description:
- - This module is used to configure AutoScaleLaunchConfig object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- description:
- description:
- - User defined description for the object.
- image_id:
- description:
- - Unique id of the amazon machine image (ami) or openstack vm id.
- mesos:
- description:
- - Autoscalemesossettings settings for autoscalelaunchconfig.
- name:
- description:
- - Name of the object.
- required: true
- openstack:
- description:
- - Autoscaleopenstacksettings settings for autoscalelaunchconfig.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- use_external_asg:
- description:
- - If set to true, serverautoscalepolicy will use the autoscaling group (external_autoscaling_groups) from pool to perform scale up and scale down.
- - Pool should have single autoscaling group configured.
- - Field introduced in 17.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create an Autoscale Launch configuration.
- avi_autoscalelaunchconfig:
- controller: '{{ controller }}'
- username: '{{ username }}'
- password: '{{ password }}'
- image_id: default
- name: default-autoscalelaunchconfig
- tenant_ref: admin
-"""
-
-RETURN = '''
-obj:
- description: AutoScaleLaunchConfig (api/autoscalelaunchconfig) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- description=dict(type='str',),
- image_id=dict(type='str',),
- mesos=dict(type='dict',),
- name=dict(type='str', required=True),
- openstack=dict(type='dict',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- use_external_asg=dict(type='bool',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'autoscalelaunchconfig',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_backup.py b/plugins/modules/network/avi/avi_backup.py
deleted file mode 100644
index 8935563b3a..0000000000
--- a/plugins/modules/network/avi/avi_backup.py
+++ /dev/null
@@ -1,131 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_backup
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of Backup Avi RESTful Object
-description:
- - This module is used to configure Backup object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- backup_config_ref:
- description:
- - Backupconfiguration information.
- - It is a reference to an object of type backupconfiguration.
- file_name:
- description:
- - The file name of backup.
- required: true
- local_file_url:
- description:
- - Url to download the backup file.
- remote_file_url:
- description:
- - Url to download the backup file.
- scheduler_ref:
- description:
- - Scheduler information.
- - It is a reference to an object of type scheduler.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- timestamp:
- description:
- - Unix timestamp of when the backup file is created.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create Backup object
- avi_backup:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_backup
-"""
-
-RETURN = '''
-obj:
- description: Backup (api/backup) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- backup_config_ref=dict(type='str',),
- file_name=dict(type='str', required=True),
- local_file_url=dict(type='str',),
- remote_file_url=dict(type='str',),
- scheduler_ref=dict(type='str',),
- tenant_ref=dict(type='str',),
- timestamp=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'backup',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_backupconfiguration.py b/plugins/modules/network/avi/avi_backupconfiguration.py
deleted file mode 100644
index 17f7a755fb..0000000000
--- a/plugins/modules/network/avi/avi_backupconfiguration.py
+++ /dev/null
@@ -1,167 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_backupconfiguration
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of BackupConfiguration Avi RESTful Object
-description:
- - This module is used to configure BackupConfiguration object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- aws_access_key:
- description:
- - Aws access key id.
- - Field introduced in 18.2.3.
- aws_bucket_id:
- description:
- - Aws bucket.
- - Field introduced in 18.2.3.
- aws_secret_access:
- description:
- - Aws secret access key.
- - Field introduced in 18.2.3.
- backup_file_prefix:
- description:
- - Prefix of the exported configuration file.
- - Field introduced in 17.1.1.
- backup_passphrase:
- description:
- - Passphrase of backup configuration.
- maximum_backups_stored:
- description:
- - Rotate the backup files based on this count.
- - Allowed values are 1-20.
- - Default value when not specified in API or module is interpreted by Avi Controller as 4.
- name:
- description:
- - Name of backup configuration.
- required: true
- remote_directory:
- description:
- - Directory at remote destination with write permission for ssh user.
- remote_hostname:
- description:
- - Remote destination.
- save_local:
- description:
- - Local backup.
- type: bool
- ssh_user_ref:
- description:
- - Access credentials for remote destination.
- - It is a reference to an object of type cloudconnectoruser.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- upload_to_remote_host:
- description:
- - Remote backup.
- type: bool
- upload_to_s3:
- description:
- - Cloud backup.
- - Field introduced in 18.2.3.
- type: bool
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create BackupConfiguration object
- avi_backupconfiguration:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_backupconfiguration
-"""
-
-RETURN = '''
-obj:
- description: BackupConfiguration (api/backupconfiguration) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- aws_access_key=dict(type='str', no_log=True,),
- aws_bucket_id=dict(type='str',),
- aws_secret_access=dict(type='str', no_log=True,),
- backup_file_prefix=dict(type='str',),
- backup_passphrase=dict(type='str', no_log=True,),
- maximum_backups_stored=dict(type='int',),
- name=dict(type='str', required=True),
- remote_directory=dict(type='str',),
- remote_hostname=dict(type='str',),
- save_local=dict(type='bool',),
- ssh_user_ref=dict(type='str',),
- tenant_ref=dict(type='str',),
- upload_to_remote_host=dict(type='bool',),
- upload_to_s3=dict(type='bool',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'backupconfiguration',
- set(['backup_passphrase', 'aws_access_key', 'aws_secret_access']))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_certificatemanagementprofile.py b/plugins/modules/network/avi/avi_certificatemanagementprofile.py
deleted file mode 100644
index b704c410cf..0000000000
--- a/plugins/modules/network/avi/avi_certificatemanagementprofile.py
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_certificatemanagementprofile
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of CertificateManagementProfile Avi RESTful Object
-description:
- - This module is used to configure CertificateManagementProfile object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- name:
- description:
- - Name of the pki profile.
- required: true
- script_params:
- description:
- - List of customparams.
- script_path:
- description:
- - Script_path of certificatemanagementprofile.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create CertificateManagementProfile object
- avi_certificatemanagementprofile:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_certificatemanagementprofile
-"""
-
-RETURN = '''
-obj:
- description: CertificateManagementProfile (api/certificatemanagementprofile) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- name=dict(type='str', required=True),
- script_params=dict(type='list',),
- script_path=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'certificatemanagementprofile',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_cloud.py b/plugins/modules/network/avi/avi_cloud.py
deleted file mode 100644
index a46b7e775b..0000000000
--- a/plugins/modules/network/avi/avi_cloud.py
+++ /dev/null
@@ -1,288 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_cloud
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of Cloud Avi RESTful Object
-description:
- - This module is used to configure Cloud object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- apic_configuration:
- description:
- - Apicconfiguration settings for cloud.
- apic_mode:
- description:
- - Boolean flag to set apic_mode.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- autoscale_polling_interval:
- description:
- - Cloudconnector polling interval for external autoscale groups.
- - Field introduced in 18.2.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 60.
- aws_configuration:
- description:
- - Awsconfiguration settings for cloud.
- azure_configuration:
- description:
- - Field introduced in 17.2.1.
- cloudstack_configuration:
- description:
- - Cloudstackconfiguration settings for cloud.
- custom_tags:
- description:
- - Custom tags for all avi created resources in the cloud infrastructure.
- - Field introduced in 17.1.5.
- dhcp_enabled:
- description:
- - Select the ip address management scheme.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- dns_provider_ref:
- description:
- - Dns profile for the cloud.
- - It is a reference to an object of type ipamdnsproviderprofile.
- docker_configuration:
- description:
- - Dockerconfiguration settings for cloud.
- east_west_dns_provider_ref:
- description:
- - Dns profile for east-west services.
- - It is a reference to an object of type ipamdnsproviderprofile.
- east_west_ipam_provider_ref:
- description:
- - Ipam profile for east-west services.
- - Warning - please use virtual subnets in this ipam profile that do not conflict with the underlay networks or any overlay networks in the cluster.
- - For example in aws and gcp, 169.254.0.0/16 is used for storing instance metadata.
- - Hence, it should not be used in this profile.
- - It is a reference to an object of type ipamdnsproviderprofile.
- enable_vip_static_routes:
- description:
- - Use static routes for vip side network resolution during virtualservice placement.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- gcp_configuration:
- description:
- - Google cloud platform configuration.
- - Field introduced in 18.2.1.
- ip6_autocfg_enabled:
- description:
- - Enable ipv6 auto configuration.
- - Field introduced in 18.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- ipam_provider_ref:
- description:
- - Ipam profile for the cloud.
- - It is a reference to an object of type ipamdnsproviderprofile.
- license_tier:
- description:
- - Specifies the default license tier which would be used by new se groups.
- - This field by default inherits the value from system configuration.
- - Enum options - ENTERPRISE_16, ENTERPRISE_18.
- - Field introduced in 17.2.5.
- license_type:
- description:
- - If no license type is specified then default license enforcement for the cloud type is chosen.
- - The default mappings are container cloud is max ses, openstack and vmware is cores and linux it is sockets.
- - Enum options - LIC_BACKEND_SERVERS, LIC_SOCKETS, LIC_CORES, LIC_HOSTS, LIC_SE_BANDWIDTH, LIC_METERED_SE_BANDWIDTH.
- linuxserver_configuration:
- description:
- - Linuxserverconfiguration settings for cloud.
- mesos_configuration:
- description:
- - Field deprecated in 18.2.2.
- mtu:
- description:
- - Mtu setting for the cloud.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1500.
- name:
- description:
- - Name of the object.
- required: true
- nsx_configuration:
- description:
- - Configuration parameters for nsx manager.
- - Field introduced in 17.1.1.
- obj_name_prefix:
- description:
- - Default prefix for all automatically created objects in this cloud.
- - This prefix can be overridden by the se-group template.
- openstack_configuration:
- description:
- - Openstackconfiguration settings for cloud.
- oshiftk8s_configuration:
- description:
- - Oshiftk8sconfiguration settings for cloud.
- prefer_static_routes:
- description:
- - Prefer static routes over interface routes during virtualservice placement.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- proxy_configuration:
- description:
- - Proxyconfiguration settings for cloud.
- rancher_configuration:
- description:
- - Rancherconfiguration settings for cloud.
- state_based_dns_registration:
- description:
- - Dns records for vips are added/deleted based on the operational state of the vips.
- - Field introduced in 17.1.12.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
- vca_configuration:
- description:
- - Vcloudairconfiguration settings for cloud.
- vcenter_configuration:
- description:
- - Vcenterconfiguration settings for cloud.
- vtype:
- description:
- - Cloud type.
- - Enum options - CLOUD_NONE, CLOUD_VCENTER, CLOUD_OPENSTACK, CLOUD_AWS, CLOUD_VCA, CLOUD_APIC, CLOUD_MESOS, CLOUD_LINUXSERVER, CLOUD_DOCKER_UCP,
- - CLOUD_RANCHER, CLOUD_OSHIFT_K8S, CLOUD_AZURE, CLOUD_GCP.
- - Default value when not specified in API or module is interpreted by Avi Controller as CLOUD_NONE.
- required: true
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create a VMware cloud with write access mode
- avi_cloud:
- username: '{{ username }}'
- controller: '{{ controller }}'
- password: '{{ password }}'
- apic_mode: false
- dhcp_enabled: true
- enable_vip_static_routes: false
- license_type: LIC_CORES
- mtu: 1500
- name: vCenter Cloud
- prefer_static_routes: false
- tenant_ref: admin
- vcenter_configuration:
- datacenter_ref: /api/vimgrdcruntime/datacenter-2-10.10.20.100
- management_network: /api/vimgrnwruntime/dvportgroup-103-10.10.20.100
- password: password
- privilege: WRITE_ACCESS
- username: user
- vcenter_url: 10.10.20.100
- vtype: CLOUD_VCENTER
-"""
-
-RETURN = '''
-obj:
- description: Cloud (api/cloud) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- apic_configuration=dict(type='dict',),
- apic_mode=dict(type='bool',),
- autoscale_polling_interval=dict(type='int',),
- aws_configuration=dict(type='dict',),
- azure_configuration=dict(type='dict',),
- cloudstack_configuration=dict(type='dict',),
- custom_tags=dict(type='list',),
- dhcp_enabled=dict(type='bool',),
- dns_provider_ref=dict(type='str',),
- docker_configuration=dict(type='dict',),
- east_west_dns_provider_ref=dict(type='str',),
- east_west_ipam_provider_ref=dict(type='str',),
- enable_vip_static_routes=dict(type='bool',),
- gcp_configuration=dict(type='dict',),
- ip6_autocfg_enabled=dict(type='bool',),
- ipam_provider_ref=dict(type='str',),
- license_tier=dict(type='str',),
- license_type=dict(type='str',),
- linuxserver_configuration=dict(type='dict',),
- mesos_configuration=dict(type='dict',),
- mtu=dict(type='int',),
- name=dict(type='str', required=True),
- nsx_configuration=dict(type='dict',),
- obj_name_prefix=dict(type='str',),
- openstack_configuration=dict(type='dict',),
- oshiftk8s_configuration=dict(type='dict',),
- prefer_static_routes=dict(type='bool',),
- proxy_configuration=dict(type='dict',),
- rancher_configuration=dict(type='dict',),
- state_based_dns_registration=dict(type='bool',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- vca_configuration=dict(type='dict',),
- vcenter_configuration=dict(type='dict',),
- vtype=dict(type='str', required=True),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'cloud',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_cloudconnectoruser.py b/plugins/modules/network/avi/avi_cloudconnectoruser.py
deleted file mode 100644
index 21082ecf96..0000000000
--- a/plugins/modules/network/avi/avi_cloudconnectoruser.py
+++ /dev/null
@@ -1,144 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_cloudconnectoruser
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of CloudConnectorUser Avi RESTful Object
-description:
- - This module is used to configure CloudConnectorUser object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- azure_serviceprincipal:
- description:
- - Field introduced in 17.2.1.
- azure_userpass:
- description:
- - Field introduced in 17.2.1.
- gcp_credentials:
- description:
- - Credentials for google cloud platform.
- - Field introduced in 18.2.1.
- name:
- description:
- - Name of the object.
- required: true
- oci_credentials:
- description:
- - Credentials for oracle cloud infrastructure.
- - Field introduced in 18.2.1,18.1.3.
- private_key:
- description:
- - Private_key of cloudconnectoruser.
- public_key:
- description:
- - Public_key of cloudconnectoruser.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- tencent_credentials:
- description:
- - Credentials for tencent cloud.
- - Field introduced in 18.2.3.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create a Cloud connector user that is used for integration into cloud platforms
- avi_cloudconnectoruser:
- controller: '{{ controller }}'
- name: root
- password: '{{ password }}'
- private_key: |
- -----BEGIN RSA PRIVATE KEY-----
- -----END RSA PRIVATE KEY-----'
- public_key: 'ssh-rsa ...'
- tenant_ref: admin
- username: '{{ username }}'
-"""
-
-RETURN = '''
-obj:
- description: CloudConnectorUser (api/cloudconnectoruser) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- azure_serviceprincipal=dict(type='dict',),
- azure_userpass=dict(type='dict',),
- gcp_credentials=dict(type='dict',),
- name=dict(type='str', required=True),
- oci_credentials=dict(type='dict',),
- private_key=dict(type='str', no_log=True,),
- public_key=dict(type='str',),
- tenant_ref=dict(type='str',),
- tencent_credentials=dict(type='dict',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'cloudconnectoruser',
- set(['private_key']))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_cloudproperties.py b/plugins/modules/network/avi/avi_cloudproperties.py
deleted file mode 100644
index 636aa23306..0000000000
--- a/plugins/modules/network/avi/avi_cloudproperties.py
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_cloudproperties
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of CloudProperties Avi RESTful Object
-description:
- - This module is used to configure CloudProperties object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- cc_props:
- description:
- - Cloudconnector properties.
- cc_vtypes:
- description:
- - Cloud types supported by cloudconnector.
- - Enum options - CLOUD_NONE, CLOUD_VCENTER, CLOUD_OPENSTACK, CLOUD_AWS, CLOUD_VCA, CLOUD_APIC, CLOUD_MESOS, CLOUD_LINUXSERVER, CLOUD_DOCKER_UCP,
- - CLOUD_RANCHER, CLOUD_OSHIFT_K8S, CLOUD_AZURE, CLOUD_GCP.
- hyp_props:
- description:
- - Hypervisor properties.
- info:
- description:
- - Properties specific to a cloud type.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create CloudProperties object
- avi_cloudproperties:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_cloudproperties
-"""
-
-RETURN = '''
-obj:
- description: CloudProperties (api/cloudproperties) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- cc_props=dict(type='dict',),
- cc_vtypes=dict(type='list',),
- hyp_props=dict(type='list',),
- info=dict(type='list',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'cloudproperties',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_cluster.py b/plugins/modules/network/avi/avi_cluster.py
deleted file mode 100644
index fe983d77ea..0000000000
--- a/plugins/modules/network/avi/avi_cluster.py
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_cluster
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of Cluster Avi RESTful Object
-description:
- - This module is used to configure Cluster object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- name:
- description:
- - Name of the object.
- required: true
- nodes:
- description:
- - List of clusternode.
- rejoin_nodes_automatically:
- description:
- - Re-join cluster nodes automatically in the event one of the node is reset to factory.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
- virtual_ip:
- description:
- - A virtual ip address.
- - This ip address will be dynamically reconfigured so that it always is the ip of the cluster leader.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create Cluster object
- avi_cluster:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_cluster
-"""
-
-RETURN = '''
-obj:
- description: Cluster (api/cluster) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- name=dict(type='str', required=True),
- nodes=dict(type='list',),
- rejoin_nodes_automatically=dict(type='bool',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- virtual_ip=dict(type='dict',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'cluster',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_clusterclouddetails.py b/plugins/modules/network/avi/avi_clusterclouddetails.py
deleted file mode 100644
index c7692d3181..0000000000
--- a/plugins/modules/network/avi/avi_clusterclouddetails.py
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_clusterclouddetails
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of ClusterCloudDetails Avi RESTful Object
-description:
- - This module is used to configure ClusterCloudDetails object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- azure_info:
- description:
- - Azure info to configure cluster_vip on the controller.
- - Field introduced in 17.2.5.
- name:
- description:
- - Field introduced in 17.2.5.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- - Field introduced in 17.2.5.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Field introduced in 17.2.5.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create ClusterCloudDetails object
- avi_clusterclouddetails:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_clusterclouddetails
-"""
-
-RETURN = '''
-obj:
- description: ClusterCloudDetails (api/clusterclouddetails) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- azure_info=dict(type='dict',),
- name=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'clusterclouddetails',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_controllerproperties.py b/plugins/modules/network/avi/avi_controllerproperties.py
deleted file mode 100644
index d5d3b6c42b..0000000000
--- a/plugins/modules/network/avi/avi_controllerproperties.py
+++ /dev/null
@@ -1,421 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.2
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_controllerproperties
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of ControllerProperties Avi RESTful Object
-description:
- - This module is used to configure ControllerProperties object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- allow_ip_forwarding:
- description:
- - Field introduced in 17.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- allow_unauthenticated_apis:
- description:
- - Allow unauthenticated access for special apis.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- allow_unauthenticated_nodes:
- description:
- - Boolean flag to set allow_unauthenticated_nodes.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- api_idle_timeout:
- description:
- - Allowed values are 0-1440.
- - Default value when not specified in API or module is interpreted by Avi Controller as 15.
- api_perf_logging_threshold:
- description:
- - Threshold to log request timing in portal_performance.log and server-timing response header.
- - Any stage taking longer than 1% of the threshold will be included in the server-timing header.
- - Field introduced in 18.1.4, 18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 10000.
- appviewx_compat_mode:
- description:
- - Export configuration in appviewx compatibility mode.
- - Field introduced in 17.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- attach_ip_retry_interval:
- description:
- - Number of attach_ip_retry_interval.
- - Default value when not specified in API or module is interpreted by Avi Controller as 360.
- attach_ip_retry_limit:
- description:
- - Number of attach_ip_retry_limit.
- - Default value when not specified in API or module is interpreted by Avi Controller as 4.
- bm_use_ansible:
- description:
- - Use ansible for se creation in baremetal.
- - Field introduced in 17.2.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- cleanup_expired_authtoken_timeout_period:
- description:
- - Period for auth token cleanup job.
- - Field introduced in 18.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 60.
- cleanup_sessions_timeout_period:
- description:
- - Period for sessions cleanup job.
- - Field introduced in 18.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 60.
- cloud_reconcile:
- description:
- - Enable/disable periodic reconcile for all the clouds.
- - Field introduced in 17.2.14,18.1.5,18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- cluster_ip_gratuitous_arp_period:
- description:
- - Period for cluster ip gratuitous arp job.
- - Default value when not specified in API or module is interpreted by Avi Controller as 60.
- consistency_check_timeout_period:
- description:
- - Period for consistency check job.
- - Field introduced in 18.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 60.
- crashed_se_reboot:
- description:
- - Number of crashed_se_reboot.
- - Default value when not specified in API or module is interpreted by Avi Controller as 900.
- dead_se_detection_timer:
- description:
- - Number of dead_se_detection_timer.
- - Default value when not specified in API or module is interpreted by Avi Controller as 360.
- dns_refresh_period:
- description:
- - Period for refresh pool and gslb dns job.
- - Default value when not specified in API or module is interpreted by Avi Controller as 60.
- dummy:
- description:
- - Number of dummy.
- enable_api_sharding:
- description:
- - This setting enables the controller leader to shard api requests to the followers (if any).
- - Field introduced in 18.1.5, 18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- enable_memory_balancer:
- description:
- - Enable/disable memory balancer.
- - Field introduced in 17.2.8.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- fatal_error_lease_time:
- description:
- - Number of fatal_error_lease_time.
- - Default value when not specified in API or module is interpreted by Avi Controller as 120.
- max_dead_se_in_grp:
- description:
- - Number of max_dead_se_in_grp.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.
- max_pcap_per_tenant:
- description:
- - Maximum number of pcap files stored per tenant.
- - Default value when not specified in API or module is interpreted by Avi Controller as 4.
- max_seq_attach_ip_failures:
- description:
- - Maximum number of consecutive attach ip failures that halts vs placement.
- - Field introduced in 17.2.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 3.
- max_seq_vnic_failures:
- description:
- - Number of max_seq_vnic_failures.
- - Default value when not specified in API or module is interpreted by Avi Controller as 3.
- persistence_key_rotate_period:
- description:
- - Period for rotate app persistence keys job.
- - Allowed values are 1-1051200.
- - Special values are 0 - 'disabled'.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- portal_token:
- description:
- - Token used for uploading tech-support to portal.
- - Field introduced in 16.4.6,17.1.2.
- process_locked_useraccounts_timeout_period:
- description:
- - Period for process locked user accounts job.
- - Field introduced in 18.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.
- process_pki_profile_timeout_period:
- description:
- - Period for process pki profile job.
- - Field introduced in 18.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1440.
- query_host_fail:
- description:
- - Number of query_host_fail.
- - Default value when not specified in API or module is interpreted by Avi Controller as 180.
- safenet_hsm_version:
- description:
- - Version of the safenet package installed on the controller.
- - Field introduced in 16.5.2,17.2.3.
- se_create_timeout:
- description:
- - Number of se_create_timeout.
- - Default value when not specified in API or module is interpreted by Avi Controller as 900.
- se_failover_attempt_interval:
- description:
- - Interval between attempting failovers to an se.
- - Default value when not specified in API or module is interpreted by Avi Controller as 300.
- se_from_marketplace:
- description:
- - This setting decides whether se is to be deployed from the cloud marketplace or to be created by the controller.
- - The setting is applicable only when byol license is selected.
- - Enum options - MARKETPLACE, IMAGE.
- - Field introduced in 18.1.4, 18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as IMAGE.
- se_offline_del:
- description:
- - Number of se_offline_del.
- - Default value when not specified in API or module is interpreted by Avi Controller as 172000.
- se_vnic_cooldown:
- description:
- - Number of se_vnic_cooldown.
- - Default value when not specified in API or module is interpreted by Avi Controller as 120.
- secure_channel_cleanup_timeout:
- description:
- - Period for secure channel cleanup job.
- - Default value when not specified in API or module is interpreted by Avi Controller as 60.
- secure_channel_controller_token_timeout:
- description:
- - Number of secure_channel_controller_token_timeout.
- - Default value when not specified in API or module is interpreted by Avi Controller as 60.
- secure_channel_se_token_timeout:
- description:
- - Number of secure_channel_se_token_timeout.
- - Default value when not specified in API or module is interpreted by Avi Controller as 60.
- seupgrade_fabric_pool_size:
- description:
- - Pool size used for all fabric commands during se upgrade.
- - Default value when not specified in API or module is interpreted by Avi Controller as 20.
- seupgrade_segroup_min_dead_timeout:
- description:
- - Time to wait before marking segroup upgrade as stuck.
- - Default value when not specified in API or module is interpreted by Avi Controller as 360.
- ssl_certificate_expiry_warning_days:
- description:
- - Number of days for ssl certificate expiry warning.
- unresponsive_se_reboot:
- description:
- - Number of unresponsive_se_reboot.
- - Default value when not specified in API or module is interpreted by Avi Controller as 300.
- upgrade_dns_ttl:
- description:
- - Time to account for dns ttl during upgrade.
- - This is in addition to vs_scalein_timeout_for_upgrade in se_group.
- - Field introduced in 17.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 5.
- upgrade_lease_time:
- description:
- - Number of upgrade_lease_time.
- - Default value when not specified in API or module is interpreted by Avi Controller as 360.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
- vnic_op_fail_time:
- description:
- - Number of vnic_op_fail_time.
- - Default value when not specified in API or module is interpreted by Avi Controller as 180.
- vs_apic_scaleout_timeout:
- description:
- - Time to wait for the scaled out se to become ready before marking the scaleout done, applies to apic configuration only.
- - Default value when not specified in API or module is interpreted by Avi Controller as 360.
- vs_awaiting_se_timeout:
- description:
- - Number of vs_awaiting_se_timeout.
- - Default value when not specified in API or module is interpreted by Avi Controller as 60.
- vs_key_rotate_period:
- description:
- - Period for rotate vs keys job.
- - Allowed values are 1-1051200.
- - Special values are 0 - 'disabled'.
- - Default value when not specified in API or module is interpreted by Avi Controller as 360.
- vs_scaleout_ready_check_interval:
- description:
- - Interval for checking scaleout_ready status while controller is waiting for scaleoutready rpc from the service engine.
- - Field introduced in 18.2.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 60.
- vs_se_attach_ip_fail:
- description:
- - Time to wait before marking attach ip operation on an se as failed.
- - Field introduced in 17.2.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 600.
- vs_se_bootup_fail:
- description:
- - Number of vs_se_bootup_fail.
- - Default value when not specified in API or module is interpreted by Avi Controller as 480.
- vs_se_create_fail:
- description:
- - Number of vs_se_create_fail.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1500.
- vs_se_ping_fail:
- description:
- - Number of vs_se_ping_fail.
- - Default value when not specified in API or module is interpreted by Avi Controller as 60.
- vs_se_vnic_fail:
- description:
- - Number of vs_se_vnic_fail.
- - Default value when not specified in API or module is interpreted by Avi Controller as 300.
- vs_se_vnic_ip_fail:
- description:
- - Number of vs_se_vnic_ip_fail.
- - Default value when not specified in API or module is interpreted by Avi Controller as 120.
- warmstart_se_reconnect_wait_time:
- description:
- - Number of warmstart_se_reconnect_wait_time.
- - Default value when not specified in API or module is interpreted by Avi Controller as 480.
- warmstart_vs_resync_wait_time:
- description:
- - Timeout for warmstart vs resync.
- - Field introduced in 18.1.4, 18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 300.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create ControllerProperties object
- avi_controllerproperties:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_controllerproperties
-"""
-
-RETURN = '''
-obj:
- description: ControllerProperties (api/controllerproperties) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- allow_ip_forwarding=dict(type='bool',),
- allow_unauthenticated_apis=dict(type='bool',),
- allow_unauthenticated_nodes=dict(type='bool',),
- api_idle_timeout=dict(type='int',),
- api_perf_logging_threshold=dict(type='int',),
- appviewx_compat_mode=dict(type='bool',),
- attach_ip_retry_interval=dict(type='int',),
- attach_ip_retry_limit=dict(type='int',),
- bm_use_ansible=dict(type='bool',),
- cleanup_expired_authtoken_timeout_period=dict(type='int',),
- cleanup_sessions_timeout_period=dict(type='int',),
- cloud_reconcile=dict(type='bool',),
- cluster_ip_gratuitous_arp_period=dict(type='int',),
- consistency_check_timeout_period=dict(type='int',),
- crashed_se_reboot=dict(type='int',),
- dead_se_detection_timer=dict(type='int',),
- dns_refresh_period=dict(type='int',),
- dummy=dict(type='int',),
- enable_api_sharding=dict(type='bool',),
- enable_memory_balancer=dict(type='bool',),
- fatal_error_lease_time=dict(type='int',),
- max_dead_se_in_grp=dict(type='int',),
- max_pcap_per_tenant=dict(type='int',),
- max_seq_attach_ip_failures=dict(type='int',),
- max_seq_vnic_failures=dict(type='int',),
- persistence_key_rotate_period=dict(type='int',),
- portal_token=dict(type='str', no_log=True,),
- process_locked_useraccounts_timeout_period=dict(type='int',),
- process_pki_profile_timeout_period=dict(type='int',),
- query_host_fail=dict(type='int',),
- safenet_hsm_version=dict(type='str',),
- se_create_timeout=dict(type='int',),
- se_failover_attempt_interval=dict(type='int',),
- se_from_marketplace=dict(type='str',),
- se_offline_del=dict(type='int',),
- se_vnic_cooldown=dict(type='int',),
- secure_channel_cleanup_timeout=dict(type='int',),
- secure_channel_controller_token_timeout=dict(type='int',),
- secure_channel_se_token_timeout=dict(type='int',),
- seupgrade_fabric_pool_size=dict(type='int',),
- seupgrade_segroup_min_dead_timeout=dict(type='int',),
- ssl_certificate_expiry_warning_days=dict(type='list',),
- unresponsive_se_reboot=dict(type='int',),
- upgrade_dns_ttl=dict(type='int',),
- upgrade_lease_time=dict(type='int',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- vnic_op_fail_time=dict(type='int',),
- vs_apic_scaleout_timeout=dict(type='int',),
- vs_awaiting_se_timeout=dict(type='int',),
- vs_key_rotate_period=dict(type='int',),
- vs_scaleout_ready_check_interval=dict(type='int',),
- vs_se_attach_ip_fail=dict(type='int',),
- vs_se_bootup_fail=dict(type='int',),
- vs_se_create_fail=dict(type='int',),
- vs_se_ping_fail=dict(type='int',),
- vs_se_vnic_fail=dict(type='int',),
- vs_se_vnic_ip_fail=dict(type='int',),
- warmstart_se_reconnect_wait_time=dict(type='int',),
- warmstart_vs_resync_wait_time=dict(type='int',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'controllerproperties',
- set(['portal_token']))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_customipamdnsprofile.py b/plugins/modules/network/avi/avi_customipamdnsprofile.py
deleted file mode 100644
index 05beed19a0..0000000000
--- a/plugins/modules/network/avi/avi_customipamdnsprofile.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_customipamdnsprofile
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of CustomIpamDnsProfile Avi RESTful Object
-description:
- - This module is used to configure CustomIpamDnsProfile object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- name:
- description:
- - Name of the custom ipam dns profile.
- - Field introduced in 17.1.1.
- required: true
- script_params:
- description:
- - Parameters that are always passed to the ipam/dns script.
- - Field introduced in 17.1.1.
- script_uri:
- description:
- - Script uri of form controller //ipamdnsscripts/.
- - Field introduced in 17.1.1.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- - Field introduced in 17.1.1.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Field introduced in 17.1.1.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create CustomIpamDnsProfile object
- avi_customipamdnsprofile:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_customipamdnsprofile
-"""
-
-RETURN = '''
-obj:
- description: CustomIpamDnsProfile (api/customipamdnsprofile) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- name=dict(type='str', required=True),
- script_params=dict(type='list',),
- script_uri=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'customipamdnsprofile',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_dnspolicy.py b/plugins/modules/network/avi/avi_dnspolicy.py
deleted file mode 100644
index 79b1bfc184..0000000000
--- a/plugins/modules/network/avi/avi_dnspolicy.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_dnspolicy
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of DnsPolicy Avi RESTful Object
-description:
- - This module is used to configure DnsPolicy object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- created_by:
- description:
- - Creator name.
- - Field introduced in 17.1.1.
- description:
- description:
- - Field introduced in 17.1.1.
- name:
- description:
- - Name of the dns policy.
- - Field introduced in 17.1.1.
- required: true
- rule:
- description:
- - Dns rules.
- - Field introduced in 17.1.1.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- - Field introduced in 17.1.1.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the dns policy.
- - Field introduced in 17.1.1.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create DnsPolicy object
- avi_dnspolicy:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_dnspolicy
-"""
-
-RETURN = '''
-obj:
- description: DnsPolicy (api/dnspolicy) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- created_by=dict(type='str',),
- description=dict(type='str',),
- name=dict(type='str', required=True),
- rule=dict(type='list',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'dnspolicy',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_errorpagebody.py b/plugins/modules/network/avi/avi_errorpagebody.py
deleted file mode 100644
index 2404c98a84..0000000000
--- a/plugins/modules/network/avi/avi_errorpagebody.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_errorpagebody
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of ErrorPageBody Avi RESTful Object
-description:
- - This module is used to configure ErrorPageBody object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- error_page_body:
- description:
- - Error page body sent to client when match.
- - Field introduced in 17.2.4.
- format:
- description:
- - Format of an error page body html or json.
- - Enum options - ERROR_PAGE_FORMAT_HTML, ERROR_PAGE_FORMAT_JSON.
- - Field introduced in 18.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as ERROR_PAGE_FORMAT_HTML.
- name:
- description:
- - Field introduced in 17.2.4.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- - Field introduced in 17.2.4.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Field introduced in 17.2.4.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create ErrorPageBody object
- avi_errorpagebody:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_errorpagebody
-"""
-
-RETURN = '''
-obj:
- description: ErrorPageBody (api/errorpagebody) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- error_page_body=dict(type='str',),
- format=dict(type='str',),
- name=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'errorpagebody',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_errorpageprofile.py b/plugins/modules/network/avi/avi_errorpageprofile.py
deleted file mode 100644
index 67cff153f2..0000000000
--- a/plugins/modules/network/avi/avi_errorpageprofile.py
+++ /dev/null
@@ -1,135 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_errorpageprofile
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of ErrorPageProfile Avi RESTful Object
-description:
- - This module is used to configure ErrorPageProfile object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- app_name:
- description:
- - Name of the virtual service which generated the error page.
- - Field deprecated in 18.1.1.
- - Field introduced in 17.2.4.
- - Default value when not specified in API or module is interpreted by Avi Controller as VS Name.
- company_name:
- description:
- - Name of the company to show in error page.
- - Field deprecated in 18.1.1.
- - Field introduced in 17.2.4.
- - Default value when not specified in API or module is interpreted by Avi Controller as Avi Networks.
- error_pages:
- description:
- - Defined error pages for http status codes.
- - Field introduced in 17.2.4.
- host_name:
- description:
- - Fully qualified domain name for which the error page is generated.
- - Field deprecated in 18.1.1.
- - Field introduced in 17.2.4.
- - Default value when not specified in API or module is interpreted by Avi Controller as Host Header.
- name:
- description:
- - Field introduced in 17.2.4.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- - Field introduced in 17.2.4.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Field introduced in 17.2.4.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create ErrorPageProfile object
- avi_errorpageprofile:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_errorpageprofile
-"""
-
-RETURN = '''
-obj:
- description: ErrorPageProfile (api/errorpageprofile) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- app_name=dict(type='str',),
- company_name=dict(type='str',),
- error_pages=dict(type='list',),
- host_name=dict(type='str',),
- name=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'errorpageprofile',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_gslb.py b/plugins/modules/network/avi/avi_gslb.py
deleted file mode 100644
index 186543e9b4..0000000000
--- a/plugins/modules/network/avi/avi_gslb.py
+++ /dev/null
@@ -1,354 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_gslb
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of Gslb Avi RESTful Object
-description:
- - This module is used to configure Gslb object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- async_interval:
- description:
- - Frequency with which messages are propagated to vs mgr.
- - Value of 0 disables async behavior and rpc are sent inline.
- - Allowed values are 0-5.
- - Field introduced in 18.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- clear_on_max_retries:
- description:
- - Max retries after which the remote site is treated as a fresh start.
- - In fresh start all the configs are downloaded.
- - Allowed values are 1-1024.
- - Default value when not specified in API or module is interpreted by Avi Controller as 20.
- client_ip_addr_group:
- description:
- - Group to specify if the client ip addresses are public or private.
- - Field introduced in 17.1.2.
- description:
- description:
- - User defined description for the object.
- dns_configs:
- description:
- - Sub domain configuration for the gslb.
- - Gslb service's fqdn must be a match one of these subdomains.
- is_federated:
- description:
- - This field indicates that this object is replicated across gslb federation.
- - Field introduced in 17.1.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- leader_cluster_uuid:
- description:
- - Mark this site as leader of gslb configuration.
- - This site is the one among the avi sites.
- required: true
- maintenance_mode:
- description:
- - This field disables the configuration operations on the leader for all federated objects.
- - Cud operations on gslb, gslbservice, gslbgeodbprofile and other federated objects will be rejected.
- - The rest-api disabling helps in upgrade scenarios where we don't want configuration sync operations to the gslb member when the member is being
- - upgraded.
- - This configuration programmatically blocks the leader from accepting new gslb configuration when member sites are undergoing upgrade.
- - Field introduced in 17.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- name:
- description:
- - Name for the gslb object.
- required: true
- send_interval:
- description:
- - Frequency with which group members communicate.
- - Allowed values are 1-3600.
- - Default value when not specified in API or module is interpreted by Avi Controller as 15.
- send_interval_prior_to_maintenance_mode:
- description:
- - The user can specify a send-interval while entering maintenance mode.
- - The validity of this 'maintenance send-interval' is only during maintenance mode.
- - When the user leaves maintenance mode, the original send-interval is reinstated.
- - This internal variable is used to store the original send-interval.
- - Field introduced in 18.2.3.
- sites:
- description:
- - Select avi site member belonging to this gslb.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- third_party_sites:
- description:
- - Third party site member belonging to this gslb.
- - Field introduced in 17.1.1.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the gslb object.
- view_id:
- description:
- - The view-id is used in change-leader mode to differentiate partitioned groups while they have the same gslb namespace.
- - Each partitioned group will be able to operate independently by using the view-id.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create Gslb object
- avi_gslb:
- name: "test-gslb"
- avi_credentials:
- username: '{{ username }}'
- password: '{{ password }}'
- controller: '{{ controller }}'
- sites:
- - name: "test-site1"
- username: "gslb_username"
- password: "gslb_password"
- ip_addresses:
- - type: "V4"
- addr: "10.10.28.83"
- enabled: True
- member_type: "GSLB_ACTIVE_MEMBER"
- port: 443
- cluster_uuid: "cluster-d4ee5fcc-3e0a-4d4f-9ae6-4182bc605829"
- - name: "test-site2"
- username: "gslb_username"
- password: "gslb_password"
- ip_addresses:
- - type: "V4"
- addr: "10.10.28.86"
- enabled: True
- member_type: "GSLB_ACTIVE_MEMBER"
- port: 443
- cluster_uuid: "cluster-0c37ae8d-ab62-410c-ad3e-06fa831950b1"
- dns_configs:
- - domain_name: "test1.com"
- - domain_name: "test2.com"
- leader_cluster_uuid: "cluster-d4ee5fcc-3e0a-4d4f-9ae6-4182bc605829"
-
-- name: Update Gslb site's configurations (Patch Add Operation)
- avi_gslb:
- avi_credentials:
- username: '{{ username }}'
- password: '{{ password }}'
- controller: '{{ controller }}'
- avi_api_update_method: patch
- avi_api_patch_op: add
- leader_cluster_uuid: "cluster-d4ee5fcc-3e0a-4d4f-9ae6-4182bc605829"
- name: "test-gslb"
- dns_configs:
- - domain_name: "temp1.com"
- - domain_name: "temp2.com"
- gslb_sites_config:
- - ip_addr: "10.10.28.83"
- dns_vses:
- - dns_vs_uuid: "virtualservice-f2a711cd-5e78-473f-8f47-d12de660fd62"
- domain_names:
- - "test1.com"
- - "test2.com"
- - ip_addr: "10.10.28.86"
- dns_vses:
- - dns_vs_uuid: "virtualservice-c1a63a16-f2a1-4f41-aab4-1e90f92a5e49"
- domain_names:
- - "temp1.com"
- - "temp2.com"
-
-- name: Update Gslb site's configurations (Patch Replace Operation)
- avi_gslb:
- avi_credentials:
- username: "{{ username }}"
- password: "{{ password }}"
- controller: "{{ controller }}"
- # On basis of cluster leader uuid dns_configs is set for that particular leader cluster
- leader_cluster_uuid: "cluster-84aa795f-8f09-42bb-97a4-5103f4a53da9"
- name: "test-gslb"
- avi_api_update_method: patch
- avi_api_patch_op: replace
- dns_configs:
- - domain_name: "test3.com"
- - domain_name: "temp3.com"
- gslb_sites_config:
- # Ip address is mapping key for dns_vses field update. For the given IP address,
- # dns_vses is updated.
- - ip_addr: "10.10.28.83"
- dns_vses:
- - dns_vs_uuid: "virtualservice-7c947ed4-77f3-4a52-909c-4f12afaf5bb0"
- domain_names:
- - "test3.com"
- - ip_addr: "10.10.28.86"
- dns_vses:
- - dns_vs_uuid: "virtualservice-799b2c6d-7f2d-4c3f-94c6-6e813b20b674"
- domain_names:
- - "temp3.com"
-
-- name: Update Gslb site's configurations (Patch Delete Operation)
- avi_gslb:
- avi_credentials:
- username: "{{ username }}"
- password: "{{ password }}"
- controller: "{{ controller }}"
- # On basis of cluster leader uuid dns_configs is set for that particular leader cluster
- leader_cluster_uuid: "cluster-84aa795f-8f09-42bb-97a4-5103f4a53da9"
- name: "test-gslb"
- avi_api_update_method: patch
- avi_api_patch_op: delete
- dns_configs:
- gslb_sites_config:
- - ip_addr: "10.10.28.83"
- - ip_addr: "10.10.28.86"
-"""
-
-RETURN = '''
-obj:
- description: Gslb (api/gslb) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi_api import ApiSession, AviCredentials
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- async_interval=dict(type='int',),
- clear_on_max_retries=dict(type='int',),
- client_ip_addr_group=dict(type='dict',),
- description=dict(type='str',),
- dns_configs=dict(type='list',),
- is_federated=dict(type='bool',),
- leader_cluster_uuid=dict(type='str', required=True),
- maintenance_mode=dict(type='bool',),
- name=dict(type='str', required=True),
- send_interval=dict(type='int',),
- send_interval_prior_to_maintenance_mode=dict(type='int',),
- sites=dict(type='list',),
- tenant_ref=dict(type='str',),
- third_party_sites=dict(type='list',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- view_id=dict(type='int',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- api_method = module.params['avi_api_update_method']
- if str(api_method).lower() == 'patch':
- patch_op = module.params['avi_api_patch_op']
- # Create controller session
- api_creds = AviCredentials()
- api_creds.update_from_ansible_module(module)
- api = ApiSession.get_session(
- api_creds.controller, api_creds.username, password=api_creds.password,
- timeout=api_creds.timeout, tenant=api_creds.tenant,
- tenant_uuid=api_creds.tenant_uuid, token=api_creds.token,
- port=api_creds.port)
- # Get existing gslb objects
- rsp = api.get('gslb', api_version=api_creds.api_version)
- existing_gslb = rsp.json()
- gslb = existing_gslb['results']
- sites = module.params['gslb_sites_config']
- for gslb_obj in gslb:
- # Update/Delete domain names in dns_configs fields in gslb object.
- if 'dns_configs' in module.params:
- if gslb_obj['leader_cluster_uuid'] == module.params['leader_cluster_uuid']:
- if str(patch_op).lower() == 'delete':
- gslb_obj['dns_configs'] = []
- elif str(patch_op).lower() == 'add':
- if module.params['dns_configs'] not in gslb_obj['dns_configs']:
- gslb_obj['dns_configs'].extend(module.params['dns_configs'])
- else:
- gslb_obj['dns_configs'] = module.params['dns_configs']
- # Update/Delete sites configuration
- if sites:
- for site_obj in gslb_obj['sites']:
- dns_vses = site_obj.get('dns_vses', [])
- for obj in sites:
- config_for = obj.get('ip_addr', None)
- if not config_for:
- return module.fail_json(msg=(
- "ip_addr of site in a configuration is mandatory. "
- "Please provide ip_addr i.e. gslb site's ip."))
- if config_for == site_obj['ip_addresses'][0]['addr']:
- if str(patch_op).lower() == 'delete':
- site_obj['dns_vses'] = []
- else:
- # Modify existing gslb sites object
- for key, val in obj.items():
- if key == 'dns_vses' and str(patch_op).lower() == 'add':
- found = False
- # Check dns_vses field already exists on the controller
- for v in dns_vses:
- if val[0]['dns_vs_uuid'] != v['dns_vs_uuid']:
- found = True
- break
- if not found:
- dns_vses.extend(val)
- else:
- site_obj[key] = val
- if str(patch_op).lower() == 'add':
- site_obj['dns_vses'] = dns_vses
- uni_dns_configs = [dict(tupleized) for tupleized in set(tuple(item.items())
- for item in gslb_obj['dns_configs'])]
- gslb_obj['dns_configs'] = uni_dns_configs
- module.params.update(gslb_obj)
- module.params.update(
- {
- 'avi_api_update_method': 'put',
- 'state': 'present'
- }
- )
- return avi_ansible_api(module, 'gslb',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_gslbgeodbprofile.py b/plugins/modules/network/avi/avi_gslbgeodbprofile.py
deleted file mode 100644
index 8db544ff2c..0000000000
--- a/plugins/modules/network/avi/avi_gslbgeodbprofile.py
+++ /dev/null
@@ -1,129 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.2
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_gslbgeodbprofile
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of GslbGeoDbProfile Avi RESTful Object
-description:
- - This module is used to configure GslbGeoDbProfile object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- description:
- description:
- - Field introduced in 17.1.1.
- entries:
- description:
- - List of geodb entries.
- - An entry can either be a geodb file or an ip address group with geo properties.
- - Field introduced in 17.1.1.
- is_federated:
- description:
- - This field indicates that this object is replicated across gslb federation.
- - Field introduced in 17.1.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- name:
- description:
- - A user-friendly name for the geodb profile.
- - Field introduced in 17.1.1.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- - Field introduced in 17.1.1.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the geodb profile.
- - Field introduced in 17.1.1.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create GslbGeoDbProfile object
- avi_gslbgeodbprofile:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_gslbgeodbprofile
-"""
-
-RETURN = '''
-obj:
- description: GslbGeoDbProfile (api/gslbgeodbprofile) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- description=dict(type='str',),
- entries=dict(type='list',),
- is_federated=dict(type='bool',),
- name=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'gslbgeodbprofile',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_gslbservice.py b/plugins/modules/network/avi/avi_gslbservice.py
deleted file mode 100644
index 71de354626..0000000000
--- a/plugins/modules/network/avi/avi_gslbservice.py
+++ /dev/null
@@ -1,230 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_gslbservice
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of GslbService Avi RESTful Object
-description:
- - This module is used to configure GslbService object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- application_persistence_profile_ref:
- description:
- - The federated application persistence associated with gslbservice site persistence functionality.
- - It is a reference to an object of type applicationpersistenceprofile.
- - Field introduced in 17.2.1.
- controller_health_status_enabled:
- description:
- - Gs member's overall health status is derived based on a combination of controller and datapath health-status inputs.
- - Note that the datapath status is determined by the association of health monitor profiles.
- - Only the controller provided status is determined through this configuration.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- created_by:
- description:
- - Creator name.
- - Field introduced in 17.1.2.
- description:
- description:
- - User defined description for the object.
- domain_names:
- description:
- - Fully qualified domain name of the gslb service.
- down_response:
- description:
- - Response to the client query when the gslb service is down.
- enabled:
- description:
- - Enable or disable the gslb service.
- - If the gslb service is enabled, then the vips are sent in the dns responses based on reachability and configured algorithm.
- - If the gslb service is disabled, then the vips are no longer available in the dns response.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- groups:
- description:
- - Select list of pools belonging to this gslb service.
- health_monitor_refs:
- description:
- - Verify vs health by applying one or more health monitors.
- - Active monitors generate synthetic traffic from dns service engine and to mark a vs up or down based on the response.
- - It is a reference to an object of type healthmonitor.
- health_monitor_scope:
- description:
- - Health monitor probe can be executed for all the members or it can be executed only for third-party members.
- - This operational mode is useful to reduce the number of health monitor probes in case of a hybrid scenario.
- - In such a case, avi members can have controller derived status while non-avi members can be probed by via health monitor probes in dataplane.
- - Enum options - GSLB_SERVICE_HEALTH_MONITOR_ALL_MEMBERS, GSLB_SERVICE_HEALTH_MONITOR_ONLY_NON_AVI_MEMBERS.
- - Default value when not specified in API or module is interpreted by Avi Controller as GSLB_SERVICE_HEALTH_MONITOR_ALL_MEMBERS.
- hm_off:
- description:
- - This field is an internal field and is used in se.
- - Field introduced in 18.2.2.
- type: bool
- is_federated:
- description:
- - This field indicates that this object is replicated across gslb federation.
- - Field introduced in 17.1.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- min_members:
- description:
- - The minimum number of members to distribute traffic to.
- - Allowed values are 1-65535.
- - Special values are 0 - 'disable'.
- - Field introduced in 17.2.4.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- name:
- description:
- - Name for the gslb service.
- required: true
- num_dns_ip:
- description:
- - Number of ip addresses of this gslb service to be returned by the dns service.
- - Enter 0 to return all ip addresses.
- - Allowed values are 1-20.
- - Special values are 0- 'return all ip addresses'.
- pool_algorithm:
- description:
- - The load balancing algorithm will pick a gslb pool within the gslb service list of available pools.
- - Enum options - GSLB_SERVICE_ALGORITHM_PRIORITY, GSLB_SERVICE_ALGORITHM_GEO.
- - Field introduced in 17.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as GSLB_SERVICE_ALGORITHM_PRIORITY.
- site_persistence_enabled:
- description:
- - Enable site-persistence for the gslbservice.
- - Field introduced in 17.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- ttl:
- description:
- - Ttl value (in seconds) for records served for this gslb service by the dns service.
- - Allowed values are 0-86400.
- url:
- description:
- - Avi controller URL of the object.
- use_edns_client_subnet:
- description:
- - Use the client ip subnet from the edns option as source ipaddress for client geo-location and consistent hash algorithm.
- - Default is true.
- - Field introduced in 17.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- uuid:
- description:
- - Uuid of the gslb service.
- wildcard_match:
- description:
- - Enable wild-card match of fqdn if an exact match is not found in the dns table, the longest match is chosen by wild-carding the fqdn in the dns
- - request.
- - Default is false.
- - Field introduced in 17.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create GslbService object
- avi_gslbservice:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_gslbservice
-"""
-
-RETURN = '''
-obj:
- description: GslbService (api/gslbservice) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- application_persistence_profile_ref=dict(type='str',),
- controller_health_status_enabled=dict(type='bool',),
- created_by=dict(type='str',),
- description=dict(type='str',),
- domain_names=dict(type='list',),
- down_response=dict(type='dict',),
- enabled=dict(type='bool',),
- groups=dict(type='list',),
- health_monitor_refs=dict(type='list',),
- health_monitor_scope=dict(type='str',),
- hm_off=dict(type='bool',),
- is_federated=dict(type='bool',),
- min_members=dict(type='int',),
- name=dict(type='str', required=True),
- num_dns_ip=dict(type='int',),
- pool_algorithm=dict(type='str',),
- site_persistence_enabled=dict(type='bool',),
- tenant_ref=dict(type='str',),
- ttl=dict(type='int',),
- url=dict(type='str',),
- use_edns_client_subnet=dict(type='bool',),
- uuid=dict(type='str',),
- wildcard_match=dict(type='bool',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'gslbservice',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_gslbservice_patch_member.py b/plugins/modules/network/avi/avi_gslbservice_patch_member.py
deleted file mode 100644
index eb23ded793..0000000000
--- a/plugins/modules/network/avi/avi_gslbservice_patch_member.py
+++ /dev/null
@@ -1,294 +0,0 @@
-#!/usr/bin/python
-"""
-# Created on Aug 12, 2016
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com) GitHub ID: grastogi23
-#
-# module_check: supported
-#
-# Copyright: (c) 2016 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-"""
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: avi_gslbservice_patch_member
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Avi API Module
-description:
- - This module can be used for calling any resources defined in Avi REST API. U(https://avinetworks.com/)
- - This module is useful for invoking HTTP Patch methods and accessing resources that do not have an REST object associated with them.
-requirements: [ avisdk ]
-options:
- data:
- description:
- - HTTP body of GSLB Service Member in YAML or JSON format.
- params:
- description:
- - Query parameters passed to the HTTP API.
- name:
- description:
- - Name of the GSLB Service
- required: true
- state:
- description:
- - The state that should be applied to the member. Member is
- - identified using field member.ip.addr.
- default: present
- choices: ["absent","present"]
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = '''
- - name: Patch GSLB Service to add a new member and group
- avi_gslbservice_patch_member:
- controller: "{{ controller }}"
- username: "{{ username }}"
- password: "{{ password }}"
- name: gs-3
- api_version: 17.2.1
- data:
- group:
- name: newfoo
- priority: 60
- members:
- - enabled: true
- ip:
- addr: 10.30.10.66
- type: V4
- ratio: 3
- - name: Patch GSLB Service to delete an existing member
- avi_gslbservice_patch_member:
- controller: "{{ controller }}"
- username: "{{ username }}"
- password: "{{ password }}"
- name: gs-3
- state: absent
- api_version: 17.2.1
- data:
- group:
- name: newfoo
- members:
- - enabled: true
- ip:
- addr: 10.30.10.68
- type: V4
- ratio: 3
- - name: Update priority of GSLB Service Pool
- avi_gslbservice_patch_member:
- controller: ""
- username: ""
- password: ""
- name: gs-3
- state: present
- api_version: 17.2.1
- data:
- group:
- name: newfoo
- priority: 42
-'''
-
-
-RETURN = '''
-obj:
- description: Avi REST resource
- returned: success, changed
- type: dict
-'''
-
-import json
-import time
-from ansible.module_utils.basic import AnsibleModule
-from copy import deepcopy
-
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_obj_cmp, cleanup_absent_fields,
- ansible_return, AviCheckModeResponse, HAS_AVI)
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi_api import (
- ApiSession, AviCredentials)
-except ImportError:
- HAS_AVI = False
-
-
-def delete_member(module, check_mode, api, tenant, tenant_uuid,
- existing_obj, data, api_version):
- members = data.get('group', {}).get('members', [])
- patched_member_ids = set([m['ip']['addr'] for m in members if 'fqdn' not in m])
- patched_member_fqdns = set([m['fqdn'] for m in members if 'fqdn' in m])
-
- changed = False
- rsp = None
-
- if existing_obj and (patched_member_ids or patched_member_fqdns):
- groups = [group for group in existing_obj.get('groups', [])
- if group['name'] == data['group']['name']]
- if groups:
- changed = any(
- [(lambda g: g['ip']['addr'] in patched_member_ids)(m)
- for m in groups[0].get('members', []) if 'fqdn' not in m])
- changed = changed or any(
- [(lambda g: g['fqdn'] in patched_member_fqdns)(m)
- for m in groups[0].get('members', []) if 'fqdn' in m])
- if check_mode or not changed:
- return changed, rsp
- # should not come here if not found
- group = groups[0]
- new_members = []
- for m in group.get('members', []):
- if 'fqdn' in m:
- if m['fqdn'] not in patched_member_fqdns:
- new_members.append(m)
- elif 'ip' in m:
- if m['ip']['addr'] not in patched_member_ids:
- new_members.append(m)
- group['members'] = new_members
- if not group['members']:
- # Delete this group from the existing objects if it is empty.
- # Controller also does not allow empty group.
- existing_obj['groups'] = [
- grp for grp in existing_obj.get('groups', []) if
- grp['name'] != data['group']['name']]
- # remove the members that are part of the list
- # update the object
- # added api version for AVI api call.
- rsp = api.put('gslbservice/%s' % existing_obj['uuid'], data=existing_obj,
- tenant=tenant, tenant_uuid=tenant_uuid, api_version=api_version)
- return changed, rsp
-
-
-def add_member(module, check_mode, api, tenant, tenant_uuid,
- existing_obj, data, name, api_version):
- rsp = None
- if not existing_obj:
- # create the object
- changed = True
- if check_mode:
- rsp = AviCheckModeResponse(obj=None)
- else:
- # creates group with single member
- req = {'name': name,
- 'groups': [data['group']]
- }
- # added api version for AVI api call.
- rsp = api.post('gslbservice', data=req, tenant=tenant,
- tenant_uuid=tenant_uuid, api_version=api_version)
- else:
- # found GSLB object
- req = deepcopy(existing_obj)
- if 'groups' not in req:
- req['groups'] = []
- groups = [group for group in req['groups']
- if group['name'] == data['group']['name']]
- if not groups:
- # did not find the group
- req['groups'].append(data['group'])
- else:
- # just update the existing group with members
- group = groups[0]
- group_info_wo_members = deepcopy(data['group'])
- group_info_wo_members.pop('members', None)
- group.update(group_info_wo_members)
- if 'members' not in group:
- group['members'] = []
- new_members = []
- for patch_member in data['group'].get('members', []):
- found = False
- for m in group['members']:
- if 'fqdn' in patch_member and m.get('fqdn', '') == patch_member['fqdn']:
- found = True
- break
- elif m['ip']['addr'] == patch_member['ip']['addr']:
- found = True
- break
- if not found:
- new_members.append(patch_member)
- else:
- m.update(patch_member)
- # add any new members
- group['members'].extend(new_members)
- cleanup_absent_fields(req)
- changed = not avi_obj_cmp(req, existing_obj)
- if changed and not check_mode:
- obj_path = '%s/%s' % ('gslbservice', existing_obj['uuid'])
- # added api version for AVI api call.
- rsp = api.put(obj_path, data=req, tenant=tenant,
- tenant_uuid=tenant_uuid, api_version=api_version)
- return changed, rsp
-
-
-def main():
- argument_specs = dict(
- params=dict(type='dict'),
- data=dict(type='dict'),
- name=dict(type='str', required=True),
- state=dict(default='present',
- choices=['absent', 'present'])
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(argument_spec=argument_specs)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or ansible>=2.8 is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- api_creds = AviCredentials()
- api_creds.update_from_ansible_module(module)
- api = ApiSession.get_session(
- api_creds.controller, api_creds.username, password=api_creds.password,
- timeout=api_creds.timeout, tenant=api_creds.tenant,
- tenant_uuid=api_creds.tenant_uuid, token=api_creds.token,
- port=api_creds.port)
-
- tenant = api_creds.tenant
- tenant_uuid = api_creds.tenant_uuid
- params = module.params.get('params', None)
- data = module.params.get('data', None)
- gparams = deepcopy(params) if params else {}
- gparams.update({'include_refs': '', 'include_name': ''})
- name = module.params.get('name', '')
- state = module.params['state']
- # Get the api version from module.
- api_version = api_creds.api_version
- """
- state: present
- 1. Check if the GSLB service is present
- 2. If not then create the GSLB service with the member
- 3. Check if the group exists
- 4. if not then create the group with the member
- 5. Check if the member is present
- if not then add the member
- state: absent
- 1. check if GSLB service is present if not then exit
- 2. check if group is present. if not then exit
- 3. check if member is present. if present then remove it.
- """
- obj_type = 'gslbservice'
- # Added api version to call
- existing_obj = api.get_object_by_name(
- obj_type, name, tenant=tenant, tenant_uuid=tenant_uuid,
- params={'include_refs': '', 'include_name': ''}, api_version=api_version)
- check_mode = module.check_mode
- if state == 'absent':
- # Added api version to call
- changed, rsp = delete_member(module, check_mode, api, tenant,
- tenant_uuid, existing_obj, data, api_version)
- else:
- # Added api version to call
- changed, rsp = add_member(module, check_mode, api, tenant, tenant_uuid,
- existing_obj, data, name, api_version)
- if check_mode or not changed:
- return module.exit_json(changed=changed, obj=existing_obj)
- return ansible_return(module, rsp, changed, req=data)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_hardwaresecuritymodulegroup.py b/plugins/modules/network/avi/avi_hardwaresecuritymodulegroup.py
deleted file mode 100644
index e8502187bb..0000000000
--- a/plugins/modules/network/avi/avi_hardwaresecuritymodulegroup.py
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_hardwaresecuritymodulegroup
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of HardwareSecurityModuleGroup Avi RESTful Object
-description:
- - This module is used to configure HardwareSecurityModuleGroup object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- hsm:
- description:
- - Hardware security module configuration.
- required: true
- name:
- description:
- - Name of the hsm group configuration object.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the hsm group configuration object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create HardwareSecurityModuleGroup object
- avi_hardwaresecuritymodulegroup:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_hardwaresecuritymodulegroup
-"""
-
-RETURN = '''
-obj:
- description: HardwareSecurityModuleGroup (api/hardwaresecuritymodulegroup) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- hsm=dict(type='dict', required=True),
- name=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'hardwaresecuritymodulegroup',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_healthmonitor.py b/plugins/modules/network/avi/avi_healthmonitor.py
deleted file mode 100644
index de273fe1de..0000000000
--- a/plugins/modules/network/avi/avi_healthmonitor.py
+++ /dev/null
@@ -1,205 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_healthmonitor
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of HealthMonitor Avi RESTful Object
-description:
- - This module is used to configure HealthMonitor object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- description:
- description:
- - User defined description for the object.
- dns_monitor:
- description:
- - Healthmonitordns settings for healthmonitor.
- external_monitor:
- description:
- - Healthmonitorexternal settings for healthmonitor.
- failed_checks:
- description:
- - Number of continuous failed health checks before the server is marked down.
- - Allowed values are 1-50.
- - Default value when not specified in API or module is interpreted by Avi Controller as 2.
- http_monitor:
- description:
- - Healthmonitorhttp settings for healthmonitor.
- https_monitor:
- description:
- - Healthmonitorhttp settings for healthmonitor.
- is_federated:
- description:
- - This field describes the object's replication scope.
- - If the field is set to false, then the object is visible within the controller-cluster and its associated service-engines.
- - If the field is set to true, then the object is replicated across the federation.
- - Field introduced in 17.1.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- monitor_port:
- description:
- - Use this port instead of the port defined for the server in the pool.
- - If the monitor succeeds to this port, the load balanced traffic will still be sent to the port of the server defined within the pool.
- - Allowed values are 1-65535.
- - Special values are 0 - 'use server port'.
- name:
- description:
- - A user friendly name for this health monitor.
- required: true
- radius_monitor:
- description:
- - Health monitor for radius.
- - Field introduced in 18.2.3.
- receive_timeout:
- description:
- - A valid response from the server is expected within the receive timeout window.
- - This timeout must be less than the send interval.
- - If server status is regularly flapping up and down, consider increasing this value.
- - Allowed values are 1-2400.
- - Default value when not specified in API or module is interpreted by Avi Controller as 4.
- send_interval:
- description:
- - Frequency, in seconds, that monitors are sent to a server.
- - Allowed values are 1-3600.
- - Default value when not specified in API or module is interpreted by Avi Controller as 10.
- sip_monitor:
- description:
- - Health monitor for sip.
- - Field introduced in 17.2.8, 18.1.3, 18.2.1.
- successful_checks:
- description:
- - Number of continuous successful health checks before server is marked up.
- - Allowed values are 1-50.
- - Default value when not specified in API or module is interpreted by Avi Controller as 2.
- tcp_monitor:
- description:
- - Healthmonitortcp settings for healthmonitor.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- type:
- description:
- - Type of the health monitor.
- - Enum options - HEALTH_MONITOR_PING, HEALTH_MONITOR_TCP, HEALTH_MONITOR_HTTP, HEALTH_MONITOR_HTTPS, HEALTH_MONITOR_EXTERNAL, HEALTH_MONITOR_UDP,
- - HEALTH_MONITOR_DNS, HEALTH_MONITOR_GSLB, HEALTH_MONITOR_SIP, HEALTH_MONITOR_RADIUS.
- required: true
- udp_monitor:
- description:
- - Healthmonitorudp settings for healthmonitor.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the health monitor.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Create a HTTPS health monitor
- avi_healthmonitor:
- controller: 10.10.27.90
- username: admin
- password: AviNetworks123!
- https_monitor:
- http_request: HEAD / HTTP/1.0
- http_response_code:
- - HTTP_2XX
- - HTTP_3XX
- receive_timeout: 4
- failed_checks: 3
- send_interval: 10
- successful_checks: 3
- type: HEALTH_MONITOR_HTTPS
- name: MyWebsite-HTTPS
-"""
-
-RETURN = '''
-obj:
- description: HealthMonitor (api/healthmonitor) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- description=dict(type='str',),
- dns_monitor=dict(type='dict',),
- external_monitor=dict(type='dict',),
- failed_checks=dict(type='int',),
- http_monitor=dict(type='dict',),
- https_monitor=dict(type='dict',),
- is_federated=dict(type='bool',),
- monitor_port=dict(type='int',),
- name=dict(type='str', required=True),
- radius_monitor=dict(type='dict',),
- receive_timeout=dict(type='int',),
- send_interval=dict(type='int',),
- sip_monitor=dict(type='dict',),
- successful_checks=dict(type='int',),
- tcp_monitor=dict(type='dict',),
- tenant_ref=dict(type='str',),
- type=dict(type='str', required=True),
- udp_monitor=dict(type='dict',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'healthmonitor',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_httppolicyset.py b/plugins/modules/network/avi/avi_httppolicyset.py
deleted file mode 100644
index 9bc047927a..0000000000
--- a/plugins/modules/network/avi/avi_httppolicyset.py
+++ /dev/null
@@ -1,169 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_httppolicyset
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of HTTPPolicySet Avi RESTful Object
-description:
- - This module is used to configure HTTPPolicySet object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- cloud_config_cksum:
- description:
- - Checksum of cloud configuration for pool.
- - Internally set by cloud connector.
- created_by:
- description:
- - Creator name.
- description:
- description:
- - User defined description for the object.
- http_request_policy:
- description:
- - Http request policy for the virtual service.
- http_response_policy:
- description:
- - Http response policy for the virtual service.
- http_security_policy:
- description:
- - Http security policy for the virtual service.
- is_internal_policy:
- description:
- - Boolean flag to set is_internal_policy.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- name:
- description:
- - Name of the http policy set.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the http policy set.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Create a HTTP Policy set two switch between testpool1 and testpool2
- avi_httppolicyset:
- controller: 10.10.27.90
- username: admin
- password: AviNetworks123!
- name: test-HTTP-Policy-Set
- tenant_ref: admin
- http_request_policy:
- rules:
- - index: 1
- enable: true
- name: test-test1
- match:
- path:
- match_case: INSENSITIVE
- match_str:
- - /test1
- match_criteria: EQUALS
- switching_action:
- action: HTTP_SWITCHING_SELECT_POOL
- status_code: HTTP_LOCAL_RESPONSE_STATUS_CODE_200
- pool_ref: "/api/pool?name=testpool1"
- - index: 2
- enable: true
- name: test-test2
- match:
- path:
- match_case: INSENSITIVE
- match_str:
- - /test2
- match_criteria: CONTAINS
- switching_action:
- action: HTTP_SWITCHING_SELECT_POOL
- status_code: HTTP_LOCAL_RESPONSE_STATUS_CODE_200
- pool_ref: "/api/pool?name=testpool2"
- is_internal_policy: false
-"""
-
-RETURN = '''
-obj:
- description: HTTPPolicySet (api/httppolicyset) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- cloud_config_cksum=dict(type='str',),
- created_by=dict(type='str',),
- description=dict(type='str',),
- http_request_policy=dict(type='dict',),
- http_response_policy=dict(type='dict',),
- http_security_policy=dict(type='dict',),
- is_internal_policy=dict(type='bool',),
- name=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'httppolicyset',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_ipaddrgroup.py b/plugins/modules/network/avi/avi_ipaddrgroup.py
deleted file mode 100644
index b9f73a9321..0000000000
--- a/plugins/modules/network/avi/avi_ipaddrgroup.py
+++ /dev/null
@@ -1,159 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_ipaddrgroup
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of IpAddrGroup Avi RESTful Object
-description:
- - This module is used to configure IpAddrGroup object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- addrs:
- description:
- - Configure ip address(es).
- apic_epg_name:
- description:
- - Populate ip addresses from members of this cisco apic epg.
- country_codes:
- description:
- - Populate the ip address ranges from the geo database for this country.
- description:
- description:
- - User defined description for the object.
- ip_ports:
- description:
- - Configure (ip address, port) tuple(s).
- marathon_app_name:
- description:
- - Populate ip addresses from tasks of this marathon app.
- marathon_service_port:
- description:
- - Task port associated with marathon service port.
- - If marathon app has multiple service ports, this is required.
- - Else, the first task port is used.
- name:
- description:
- - Name of the ip address group.
- required: true
- prefixes:
- description:
- - Configure ip address prefix(es).
- ranges:
- description:
- - Configure ip address range(s).
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the ip address group.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create an IP Address Group configuration
- avi_ipaddrgroup:
- controller: '{{ controller }}'
- username: '{{ username }}'
- password: '{{ password }}'
- name: Client-Source-Block
- prefixes:
- - ip_addr:
- addr: 10.0.0.0
- type: V4
- mask: 8
- - ip_addr:
- addr: 172.16.0.0
- type: V4
- mask: 12
- - ip_addr:
- addr: 192.168.0.0
- type: V4
- mask: 16
-"""
-
-RETURN = '''
-obj:
- description: IpAddrGroup (api/ipaddrgroup) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- addrs=dict(type='list',),
- apic_epg_name=dict(type='str',),
- country_codes=dict(type='list',),
- description=dict(type='str',),
- ip_ports=dict(type='list',),
- marathon_app_name=dict(type='str',),
- marathon_service_port=dict(type='int',),
- name=dict(type='str', required=True),
- prefixes=dict(type='list',),
- ranges=dict(type='list',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'ipaddrgroup',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_ipamdnsproviderprofile.py b/plugins/modules/network/avi/avi_ipamdnsproviderprofile.py
deleted file mode 100644
index cfa0ad34bb..0000000000
--- a/plugins/modules/network/avi/avi_ipamdnsproviderprofile.py
+++ /dev/null
@@ -1,180 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_ipamdnsproviderprofile
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of IpamDnsProviderProfile Avi RESTful Object
-description:
- - This module is used to configure IpamDnsProviderProfile object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- allocate_ip_in_vrf:
- description:
- - If this flag is set, only allocate ip from networks in the virtual service vrf.
- - Applicable for avi vantage ipam only.
- - Field introduced in 17.2.4.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- aws_profile:
- description:
- - Provider details if type is aws.
- azure_profile:
- description:
- - Provider details if type is microsoft azure.
- - Field introduced in 17.2.1.
- custom_profile:
- description:
- - Provider details if type is custom.
- - Field introduced in 17.1.1.
- gcp_profile:
- description:
- - Provider details if type is google cloud.
- infoblox_profile:
- description:
- - Provider details if type is infoblox.
- internal_profile:
- description:
- - Provider details if type is avi.
- name:
- description:
- - Name for the ipam/dns provider profile.
- required: true
- oci_profile:
- description:
- - Provider details for oracle cloud.
- - Field introduced in 18.2.1,18.1.3.
- openstack_profile:
- description:
- - Provider details if type is openstack.
- proxy_configuration:
- description:
- - Field introduced in 17.1.1.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- tencent_profile:
- description:
- - Provider details for tencent cloud.
- - Field introduced in 18.2.3.
- type:
- description:
- - Provider type for the ipam/dns provider profile.
- - Enum options - IPAMDNS_TYPE_INFOBLOX, IPAMDNS_TYPE_AWS, IPAMDNS_TYPE_OPENSTACK, IPAMDNS_TYPE_GCP, IPAMDNS_TYPE_INFOBLOX_DNS, IPAMDNS_TYPE_CUSTOM,
- - IPAMDNS_TYPE_CUSTOM_DNS, IPAMDNS_TYPE_AZURE, IPAMDNS_TYPE_OCI, IPAMDNS_TYPE_TENCENT, IPAMDNS_TYPE_INTERNAL, IPAMDNS_TYPE_INTERNAL_DNS,
- - IPAMDNS_TYPE_AWS_DNS, IPAMDNS_TYPE_AZURE_DNS.
- required: true
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the ipam/dns provider profile.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create IPAM DNS provider setting
- avi_ipamdnsproviderprofile:
- controller: '{{ controller }}'
- username: '{{ username }}'
- password: '{{ password }}'
- internal_profile:
- dns_service_domain:
- - domain_name: ashish.local
- num_dns_ip: 1
- pass_through: true
- record_ttl: 100
- - domain_name: guru.local
- num_dns_ip: 1
- pass_through: true
- record_ttl: 200
- ttl: 300
- name: Ashish-DNS
- tenant_ref: Demo
- type: IPAMDNS_TYPE_INTERNAL
-"""
-
-RETURN = '''
-obj:
- description: IpamDnsProviderProfile (api/ipamdnsproviderprofile) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- allocate_ip_in_vrf=dict(type='bool',),
- aws_profile=dict(type='dict',),
- azure_profile=dict(type='dict',),
- custom_profile=dict(type='dict',),
- gcp_profile=dict(type='dict',),
- infoblox_profile=dict(type='dict',),
- internal_profile=dict(type='dict',),
- name=dict(type='str', required=True),
- oci_profile=dict(type='dict',),
- openstack_profile=dict(type='dict',),
- proxy_configuration=dict(type='dict',),
- tenant_ref=dict(type='str',),
- tencent_profile=dict(type='dict',),
- type=dict(type='str', required=True),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'ipamdnsproviderprofile',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_l4policyset.py b/plugins/modules/network/avi/avi_l4policyset.py
deleted file mode 100644
index e4d069a97b..0000000000
--- a/plugins/modules/network/avi/avi_l4policyset.py
+++ /dev/null
@@ -1,131 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_l4policyset
-author: Chaitanya Deshpande (@chaitanyaavi)
-
-short_description: Module for setup of L4PolicySet Avi RESTful Object
-description:
- - This module is used to configure L4PolicySet object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- created_by:
- description:
- - Creator name.
- - Field introduced in 17.2.7.
- description:
- description:
- - Field introduced in 17.2.7.
- is_internal_policy:
- description:
- - Field introduced in 17.2.7.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- l4_connection_policy:
- description:
- - Policy to apply when a new transport connection is setup.
- - Field introduced in 17.2.7.
- name:
- description:
- - Name of the l4 policy set.
- - Field introduced in 17.2.7.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- - Field introduced in 17.2.7.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Id of the l4 policy set.
- - Field introduced in 17.2.7.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create L4PolicySet object
- avi_l4policyset:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_l4policyset
-"""
-
-RETURN = '''
-obj:
- description: L4PolicySet (api/l4policyset) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- created_by=dict(type='str',),
- description=dict(type='str',),
- is_internal_policy=dict(type='bool',),
- l4_connection_policy=dict(type='dict',),
- name=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'l4policyset',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_microservicegroup.py b/plugins/modules/network/avi/avi_microservicegroup.py
deleted file mode 100644
index c1cb187e2d..0000000000
--- a/plugins/modules/network/avi/avi_microservicegroup.py
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_microservicegroup
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of MicroServiceGroup Avi RESTful Object
-description:
- - This module is used to configure MicroServiceGroup object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- created_by:
- description:
- - Creator name.
- description:
- description:
- - User defined description for the object.
- name:
- description:
- - Name of the microservice group.
- required: true
- service_refs:
- description:
- - Configure microservice(es).
- - It is a reference to an object of type microservice.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the microservice group.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create a Microservice Group that can be used for setting up Network security policy
- avi_microservicegroup:
- controller: '{{ controller }}'
- username: '{{ username }}'
- password: '{{ password }}'
- description: Group created by my Secure My App UI.
- name: vs-msg-marketing
- tenant_ref: admin
-"""
-
-RETURN = '''
-obj:
- description: MicroServiceGroup (api/microservicegroup) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- created_by=dict(type='str',),
- description=dict(type='str',),
- name=dict(type='str', required=True),
- service_refs=dict(type='list',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'microservicegroup',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_network.py b/plugins/modules/network/avi/avi_network.py
deleted file mode 100644
index b52d665caf..0000000000
--- a/plugins/modules/network/avi/avi_network.py
+++ /dev/null
@@ -1,156 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_network
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of Network Avi RESTful Object
-description:
- - This module is used to configure Network object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- cloud_ref:
- description:
- - It is a reference to an object of type cloud.
- configured_subnets:
- description:
- - List of subnet.
- dhcp_enabled:
- description:
- - Select the ip address management scheme for this network.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- exclude_discovered_subnets:
- description:
- - When selected, excludes all discovered subnets in this network from consideration for virtual service placement.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- ip6_autocfg_enabled:
- description:
- - Enable ipv6 auto configuration.
- - Field introduced in 18.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- name:
- description:
- - Name of the object.
- required: true
- synced_from_se:
- description:
- - Boolean flag to set synced_from_se.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
- vcenter_dvs:
- description:
- - Boolean flag to set vcenter_dvs.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- vimgrnw_ref:
- description:
- - It is a reference to an object of type vimgrnwruntime.
- vrf_context_ref:
- description:
- - It is a reference to an object of type vrfcontext.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create Network object
- avi_network:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_network
-"""
-
-RETURN = '''
-obj:
- description: Network (api/network) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- cloud_ref=dict(type='str',),
- configured_subnets=dict(type='list',),
- dhcp_enabled=dict(type='bool',),
- exclude_discovered_subnets=dict(type='bool',),
- ip6_autocfg_enabled=dict(type='bool',),
- name=dict(type='str', required=True),
- synced_from_se=dict(type='bool',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- vcenter_dvs=dict(type='bool',),
- vimgrnw_ref=dict(type='str',),
- vrf_context_ref=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'network',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_networkprofile.py b/plugins/modules/network/avi/avi_networkprofile.py
deleted file mode 100644
index b71db84733..0000000000
--- a/plugins/modules/network/avi/avi_networkprofile.py
+++ /dev/null
@@ -1,132 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_networkprofile
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of NetworkProfile Avi RESTful Object
-description:
- - This module is used to configure NetworkProfile object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- connection_mirror:
- description:
- - When enabled, avi mirrors all tcp fastpath connections to standby.
- - Applicable only in legacy ha mode.
- - Field introduced in 18.1.3,18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- description:
- description:
- - User defined description for the object.
- name:
- description:
- - The name of the network profile.
- required: true
- profile:
- description:
- - Networkprofileunion settings for networkprofile.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the network profile.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create a network profile for an UDP application
- avi_networkprofile:
- controller: '{{ controller }}'
- username: '{{ username }}'
- password: '{{ password }}'
- name: System-UDP-Fast-Path
- profile:
- type: PROTOCOL_TYPE_UDP_FAST_PATH
- udp_fast_path_profile:
- per_pkt_loadbalance: false
- session_idle_timeout: 10
- snat: true
- tenant_ref: admin
-"""
-
-RETURN = '''
-obj:
- description: NetworkProfile (api/networkprofile) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- connection_mirror=dict(type='bool',),
- description=dict(type='str',),
- name=dict(type='str', required=True),
- profile=dict(type='dict', required=True),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'networkprofile',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_networksecuritypolicy.py b/plugins/modules/network/avi/avi_networksecuritypolicy.py
deleted file mode 100644
index 781e9f6a5c..0000000000
--- a/plugins/modules/network/avi/avi_networksecuritypolicy.py
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_networksecuritypolicy
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of NetworkSecurityPolicy Avi RESTful Object
-description:
- - This module is used to configure NetworkSecurityPolicy object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- cloud_config_cksum:
- description:
- - Checksum of cloud configuration for network sec policy.
- - Internally set by cloud connector.
- created_by:
- description:
- - Creator name.
- description:
- description:
- - User defined description for the object.
- name:
- description:
- - Name of the object.
- rules:
- description:
- - List of networksecurityrule.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create a network security policy to block clients represented by ip group known_attackers
- avi_networksecuritypolicy:
- controller: '{{ controller }}'
- username: '{{ username }}'
- password: '{{ password }}'
- name: vs-gurutest-ns
- rules:
- - action: NETWORK_SECURITY_POLICY_ACTION_TYPE_DENY
- age: 0
- enable: true
- index: 1
- log: false
- match:
- client_ip:
- group_refs:
- - Demo:known_attackers
- match_criteria: IS_IN
- name: Rule 1
- tenant_ref: Demo
-"""
-
-RETURN = '''
-obj:
- description: NetworkSecurityPolicy (api/networksecuritypolicy) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- cloud_config_cksum=dict(type='str',),
- created_by=dict(type='str',),
- description=dict(type='str',),
- name=dict(type='str',),
- rules=dict(type='list',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'networksecuritypolicy',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_pkiprofile.py b/plugins/modules/network/avi/avi_pkiprofile.py
deleted file mode 100644
index 2b19ebd4d4..0000000000
--- a/plugins/modules/network/avi/avi_pkiprofile.py
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_pkiprofile
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of PKIProfile Avi RESTful Object
-description:
- - This module is used to configure PKIProfile object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- ca_certs:
- description:
- - List of certificate authorities (root and intermediate) trusted that is used for certificate validation.
- created_by:
- description:
- - Creator name.
- crl_check:
- description:
- - When enabled, avi will verify via crl checks that certificates in the trust chain have not been revoked.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- crls:
- description:
- - Certificate revocation lists.
- ignore_peer_chain:
- description:
- - When enabled, avi will not trust intermediate and root certs presented by a client.
- - Instead, only the chain certs configured in the certificate authority section will be used to verify trust of the client's cert.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- is_federated:
- description:
- - This field describes the object's replication scope.
- - If the field is set to false, then the object is visible within the controller-cluster and its associated service-engines.
- - If the field is set to true, then the object is replicated across the federation.
- - Field introduced in 17.1.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- name:
- description:
- - Name of the pki profile.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
- validate_only_leaf_crl:
- description:
- - When enabled, avi will only validate the revocation status of the leaf certificate using crl.
- - To enable validation for the entire chain, disable this option and provide all the relevant crls.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create PKIProfile object
- avi_pkiprofile:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_pkiprofile
-"""
-
-RETURN = '''
-obj:
- description: PKIProfile (api/pkiprofile) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- ca_certs=dict(type='list',),
- created_by=dict(type='str',),
- crl_check=dict(type='bool',),
- crls=dict(type='list',),
- ignore_peer_chain=dict(type='bool',),
- is_federated=dict(type='bool',),
- name=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- validate_only_leaf_crl=dict(type='bool',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'pkiprofile',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_pool.py b/plugins/modules/network/avi/avi_pool.py
deleted file mode 100644
index fb51aed329..0000000000
--- a/plugins/modules/network/avi/avi_pool.py
+++ /dev/null
@@ -1,498 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_pool
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of Pool Avi RESTful Object
-description:
- - This module is used to configure Pool object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- a_pool:
- description:
- - Name of container cloud application that constitutes a pool in a a-b pool configuration, if different from vs app.
- - Field deprecated in 18.1.2.
- ab_pool:
- description:
- - A/b pool configuration.
- - Field deprecated in 18.1.2.
- ab_priority:
- description:
- - Priority of this pool in a a-b pool pair.
- - Internally used.
- - Field deprecated in 18.1.2.
- analytics_policy:
- description:
- - Determines analytics settings for the pool.
- - Field introduced in 18.1.5, 18.2.1.
- analytics_profile_ref:
- description:
- - Specifies settings related to analytics.
- - It is a reference to an object of type analyticsprofile.
- - Field introduced in 18.1.4,18.2.1.
- apic_epg_name:
- description:
- - Synchronize cisco apic epg members with pool servers.
- application_persistence_profile_ref:
- description:
- - Persistence will ensure the same user sticks to the same server for a desired duration of time.
- - It is a reference to an object of type applicationpersistenceprofile.
- autoscale_launch_config_ref:
- description:
- - If configured then avi will trigger orchestration of pool server creation and deletion.
- - It is only supported for container clouds like mesos, openshift, kubernetes, docker, etc.
- - It is a reference to an object of type autoscalelaunchconfig.
- autoscale_networks:
- description:
- - Network ids for the launch configuration.
- autoscale_policy_ref:
- description:
- - Reference to server autoscale policy.
- - It is a reference to an object of type serverautoscalepolicy.
- capacity_estimation:
- description:
- - Inline estimation of capacity of servers.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- capacity_estimation_ttfb_thresh:
- description:
- - The maximum time-to-first-byte of a server.
- - Allowed values are 1-5000.
- - Special values are 0 - 'automatic'.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- cloud_config_cksum:
- description:
- - Checksum of cloud configuration for pool.
- - Internally set by cloud connector.
- cloud_ref:
- description:
- - It is a reference to an object of type cloud.
- conn_pool_properties:
- description:
- - Connection pool properties.
- - Field introduced in 18.2.1.
- connection_ramp_duration:
- description:
- - Duration for which new connections will be gradually ramped up to a server recently brought online.
- - Useful for lb algorithms that are least connection based.
- - Allowed values are 1-300.
- - Special values are 0 - 'immediate'.
- - Default value when not specified in API or module is interpreted by Avi Controller as 10.
- created_by:
- description:
- - Creator name.
- default_server_port:
- description:
- - Traffic sent to servers will use this destination server port unless overridden by the server's specific port attribute.
- - The ssl checkbox enables avi to server encryption.
- - Allowed values are 1-65535.
- - Default value when not specified in API or module is interpreted by Avi Controller as 80.
- delete_server_on_dns_refresh:
- description:
- - Indicates whether existing ips are disabled(false) or deleted(true) on dns hostname refreshdetail -- on a dns refresh, some ips set on pool may
- - no longer be returned by the resolver.
- - These ips are deleted from the pool when this knob is set to true.
- - They are disabled, if the knob is set to false.
- - Field introduced in 18.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- description:
- description:
- - A description of the pool.
- domain_name:
- description:
- - Comma separated list of domain names which will be used to verify the common names or subject alternative names presented by server certificates.
- - It is performed only when common name check host_check_enabled is enabled.
- east_west:
- description:
- - Inherited config from virtualservice.
- type: bool
- enabled:
- description:
- - Enable or disable the pool.
- - Disabling will terminate all open connections and pause health monitors.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- external_autoscale_groups:
- description:
- - Names of external auto-scale groups for pool servers.
- - Currently available only for aws and azure.
- - Field introduced in 17.1.2.
- fail_action:
- description:
- - Enable an action - close connection, http redirect or local http response - when a pool failure happens.
- - By default, a connection will be closed, in case the pool experiences a failure.
- fewest_tasks_feedback_delay:
- description:
- - Periodicity of feedback for fewest tasks server selection algorithm.
- - Allowed values are 1-300.
- - Default value when not specified in API or module is interpreted by Avi Controller as 10.
- graceful_disable_timeout:
- description:
- - Used to gracefully disable a server.
- - Virtual service waits for the specified time before terminating the existing connections to the servers that are disabled.
- - Allowed values are 1-7200.
- - Special values are 0 - 'immediate', -1 - 'infinite'.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.
- gslb_sp_enabled:
- description:
- - Indicates if the pool is a site-persistence pool.
- - Field introduced in 17.2.1.
- type: bool
- health_monitor_refs:
- description:
- - Verify server health by applying one or more health monitors.
- - Active monitors generate synthetic traffic from each service engine and mark a server up or down based on the response.
- - The passive monitor listens only to client to server communication.
- - It raises or lowers the ratio of traffic destined to a server based on successful responses.
- - It is a reference to an object of type healthmonitor.
- host_check_enabled:
- description:
- - Enable common name check for server certificate.
- - If enabled and no explicit domain name is specified, avi will use the incoming host header to do the match.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- inline_health_monitor:
- description:
- - The passive monitor will monitor client to server connections and requests and adjust traffic load to servers based on successful responses.
- - This may alter the expected behavior of the lb method, such as round robin.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- ipaddrgroup_ref:
- description:
- - Use list of servers from ip address group.
- - It is a reference to an object of type ipaddrgroup.
- lb_algorithm:
- description:
- - The load balancing algorithm will pick a server within the pool's list of available servers.
- - Enum options - LB_ALGORITHM_LEAST_CONNECTIONS, LB_ALGORITHM_ROUND_ROBIN, LB_ALGORITHM_FASTEST_RESPONSE, LB_ALGORITHM_CONSISTENT_HASH,
- - LB_ALGORITHM_LEAST_LOAD, LB_ALGORITHM_FEWEST_SERVERS, LB_ALGORITHM_RANDOM, LB_ALGORITHM_FEWEST_TASKS, LB_ALGORITHM_NEAREST_SERVER,
- - LB_ALGORITHM_CORE_AFFINITY, LB_ALGORITHM_TOPOLOGY.
- - Default value when not specified in API or module is interpreted by Avi Controller as LB_ALGORITHM_LEAST_CONNECTIONS.
- lb_algorithm_consistent_hash_hdr:
- description:
- - Http header name to be used for the hash key.
- lb_algorithm_core_nonaffinity:
- description:
- - Degree of non-affinity for core affinity based server selection.
- - Allowed values are 1-65535.
- - Field introduced in 17.1.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as 2.
- lb_algorithm_hash:
- description:
- - Criteria used as a key for determining the hash between the client and server.
- - Enum options - LB_ALGORITHM_CONSISTENT_HASH_SOURCE_IP_ADDRESS, LB_ALGORITHM_CONSISTENT_HASH_SOURCE_IP_ADDRESS_AND_PORT,
- - LB_ALGORITHM_CONSISTENT_HASH_URI, LB_ALGORITHM_CONSISTENT_HASH_CUSTOM_HEADER, LB_ALGORITHM_CONSISTENT_HASH_CUSTOM_STRING,
- - LB_ALGORITHM_CONSISTENT_HASH_CALLID.
- - Default value when not specified in API or module is interpreted by Avi Controller as LB_ALGORITHM_CONSISTENT_HASH_SOURCE_IP_ADDRESS.
- lookup_server_by_name:
- description:
- - Allow server lookup by name.
- - Field introduced in 17.1.11,17.2.4.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- max_concurrent_connections_per_server:
- description:
- - The maximum number of concurrent connections allowed to each server within the pool.
- - Note applied value will be no less than the number of service engines that the pool is placed on.
- - If set to 0, no limit is applied.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- max_conn_rate_per_server:
- description:
- - Rate limit connections to each server.
- min_health_monitors_up:
- description:
- - Minimum number of health monitors in up state to mark server up.
- - Field introduced in 18.2.1, 17.2.12.
- min_servers_up:
- description:
- - Minimum number of servers in up state for marking the pool up.
- - Field introduced in 18.2.1, 17.2.12.
- name:
- description:
- - The name of the pool.
- required: true
- networks:
- description:
- - (internal-use) networks designated as containing servers for this pool.
- - The servers may be further narrowed down by a filter.
- - This field is used internally by avi, not editable by the user.
- nsx_securitygroup:
- description:
- - A list of nsx service groups where the servers for the pool are created.
- - Field introduced in 17.1.1.
- pki_profile_ref:
- description:
- - Avi will validate the ssl certificate present by a server against the selected pki profile.
- - It is a reference to an object of type pkiprofile.
- placement_networks:
- description:
- - Manually select the networks and subnets used to provide reachability to the pool's servers.
- - Specify the subnet using the following syntax 10-1-1-0/24.
- - Use static routes in vrf configuration when pool servers are not directly connected butroutable from the service engine.
- prst_hdr_name:
- description:
- - Header name for custom header persistence.
- - Field deprecated in 18.1.2.
- request_queue_depth:
- description:
- - Minimum number of requests to be queued when pool is full.
- - Default value when not specified in API or module is interpreted by Avi Controller as 128.
- request_queue_enabled:
- description:
- - Enable request queue when pool is full.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- rewrite_host_header_to_server_name:
- description:
- - Rewrite incoming host header to server name of the server to which the request is proxied.
- - Enabling this feature rewrites host header for requests to all servers in the pool.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- rewrite_host_header_to_sni:
- description:
- - If sni server name is specified, rewrite incoming host header to the sni server name.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- server_auto_scale:
- description:
- - Server autoscale.
- - Not used anymore.
- - Field deprecated in 18.1.2.
- type: bool
- server_count:
- description:
- - Field deprecated in 18.2.1.
- server_name:
- description:
- - Fully qualified dns hostname which will be used in the tls sni extension in server connections if sni is enabled.
- - If no value is specified, avi will use the incoming host header instead.
- server_reselect:
- description:
- - Server reselect configuration for http requests.
- server_timeout:
- description:
- - Server timeout value specifies the time within which a server connection needs to be established and a request-response exchange completes
- - between avi and the server.
- - Value of 0 results in using default timeout of 60 minutes.
- - Allowed values are 0-3600000.
- - Field introduced in 18.1.5,18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- servers:
- description:
- - The pool directs load balanced traffic to this list of destination servers.
- - The servers can be configured by ip address, name, network or via ip address group.
- service_metadata:
- description:
- - Metadata pertaining to the service provided by this pool.
- - In openshift/kubernetes environments, app metadata info is stored.
- - Any user input to this field will be overwritten by avi vantage.
- - Field introduced in 17.2.14,18.1.5,18.2.1.
- sni_enabled:
- description:
- - Enable tls sni for server connections.
- - If disabled, avi will not send the sni extension as part of the handshake.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- ssl_key_and_certificate_ref:
- description:
- - Service engines will present a client ssl certificate to the server.
- - It is a reference to an object of type sslkeyandcertificate.
- ssl_profile_ref:
- description:
- - When enabled, avi re-encrypts traffic to the backend servers.
- - The specific ssl profile defines which ciphers and ssl versions will be supported.
- - It is a reference to an object of type sslprofile.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- use_service_port:
- description:
- - Do not translate the client's destination port when sending the connection to the server.
- - The pool or servers specified service port will still be used for health monitoring.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- uuid:
- description:
- - Uuid of the pool.
- vrf_ref:
- description:
- - Virtual routing context that the pool is bound to.
- - This is used to provide the isolation of the set of networks the pool is attached to.
- - The pool inherits the virtual routing context of the virtual service, and this field is used only internally, and is set by pb-transform.
- - It is a reference to an object of type vrfcontext.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Create a Pool with two servers and HTTP monitor
- avi_pool:
- controller: 10.10.1.20
- username: avi_user
- password: avi_password
- name: testpool1
- description: testpool1
- state: present
- health_monitor_refs:
- - '/api/healthmonitor?name=System-HTTP'
- servers:
- - ip:
- addr: 10.10.2.20
- type: V4
- - ip:
- addr: 10.10.2.21
- type: V4
-
-- name: Patch pool with a single server using patch op and avi_credentials
- avi_pool:
- avi_api_update_method: patch
- avi_api_patch_op: delete
- avi_credentials: "{{avi_credentials}}"
- name: test-pool
- servers:
- - ip:
- addr: 10.90.64.13
- type: 'V4'
- register: pool
- when:
- - state | default("present") == "present"
-"""
-
-RETURN = '''
-obj:
- description: Pool (api/pool) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- a_pool=dict(type='str',),
- ab_pool=dict(type='dict',),
- ab_priority=dict(type='int',),
- analytics_policy=dict(type='dict',),
- analytics_profile_ref=dict(type='str',),
- apic_epg_name=dict(type='str',),
- application_persistence_profile_ref=dict(type='str',),
- autoscale_launch_config_ref=dict(type='str',),
- autoscale_networks=dict(type='list',),
- autoscale_policy_ref=dict(type='str',),
- capacity_estimation=dict(type='bool',),
- capacity_estimation_ttfb_thresh=dict(type='int',),
- cloud_config_cksum=dict(type='str',),
- cloud_ref=dict(type='str',),
- conn_pool_properties=dict(type='dict',),
- connection_ramp_duration=dict(type='int',),
- created_by=dict(type='str',),
- default_server_port=dict(type='int',),
- delete_server_on_dns_refresh=dict(type='bool',),
- description=dict(type='str',),
- domain_name=dict(type='list',),
- east_west=dict(type='bool',),
- enabled=dict(type='bool',),
- external_autoscale_groups=dict(type='list',),
- fail_action=dict(type='dict',),
- fewest_tasks_feedback_delay=dict(type='int',),
- graceful_disable_timeout=dict(type='int',),
- gslb_sp_enabled=dict(type='bool',),
- health_monitor_refs=dict(type='list',),
- host_check_enabled=dict(type='bool',),
- inline_health_monitor=dict(type='bool',),
- ipaddrgroup_ref=dict(type='str',),
- lb_algorithm=dict(type='str',),
- lb_algorithm_consistent_hash_hdr=dict(type='str',),
- lb_algorithm_core_nonaffinity=dict(type='int',),
- lb_algorithm_hash=dict(type='str',),
- lookup_server_by_name=dict(type='bool',),
- max_concurrent_connections_per_server=dict(type='int',),
- max_conn_rate_per_server=dict(type='dict',),
- min_health_monitors_up=dict(type='int',),
- min_servers_up=dict(type='int',),
- name=dict(type='str', required=True),
- networks=dict(type='list',),
- nsx_securitygroup=dict(type='list',),
- pki_profile_ref=dict(type='str',),
- placement_networks=dict(type='list',),
- prst_hdr_name=dict(type='str',),
- request_queue_depth=dict(type='int',),
- request_queue_enabled=dict(type='bool',),
- rewrite_host_header_to_server_name=dict(type='bool',),
- rewrite_host_header_to_sni=dict(type='bool',),
- server_auto_scale=dict(type='bool',),
- server_count=dict(type='int',),
- server_name=dict(type='str',),
- server_reselect=dict(type='dict',),
- server_timeout=dict(type='int',),
- servers=dict(type='list',),
- service_metadata=dict(type='str',),
- sni_enabled=dict(type='bool',),
- ssl_key_and_certificate_ref=dict(type='str',),
- ssl_profile_ref=dict(type='str',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- use_service_port=dict(type='bool',),
- uuid=dict(type='str',),
- vrf_ref=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'pool',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_poolgroup.py b/plugins/modules/network/avi/avi_poolgroup.py
deleted file mode 100644
index 8cf97197fe..0000000000
--- a/plugins/modules/network/avi/avi_poolgroup.py
+++ /dev/null
@@ -1,167 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_poolgroup
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of PoolGroup Avi RESTful Object
-description:
- - This module is used to configure PoolGroup object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- cloud_config_cksum:
- description:
- - Checksum of cloud configuration for poolgroup.
- - Internally set by cloud connector.
- cloud_ref:
- description:
- - It is a reference to an object of type cloud.
- created_by:
- description:
- - Name of the user who created the object.
- deployment_policy_ref:
- description:
- - When setup autoscale manager will automatically promote new pools into production when deployment goals are met.
- - It is a reference to an object of type poolgroupdeploymentpolicy.
- description:
- description:
- - Description of pool group.
- fail_action:
- description:
- - Enable an action - close connection, http redirect, or local http response - when a pool group failure happens.
- - By default, a connection will be closed, in case the pool group experiences a failure.
- implicit_priority_labels:
- description:
- - Whether an implicit set of priority labels is generated.
- - Field introduced in 17.1.9,17.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- members:
- description:
- - List of pool group members object of type poolgroupmember.
- min_servers:
- description:
- - The minimum number of servers to distribute traffic to.
- - Allowed values are 1-65535.
- - Special values are 0 - 'disable'.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- name:
- description:
- - The name of the pool group.
- required: true
- priority_labels_ref:
- description:
- - Uuid of the priority labels.
- - If not provided, pool group member priority label will be interpreted as a number with a larger number considered higher priority.
- - It is a reference to an object of type prioritylabels.
- service_metadata:
- description:
- - Metadata pertaining to the service provided by this poolgroup.
- - In openshift/kubernetes environments, app metadata info is stored.
- - Any user input to this field will be overwritten by avi vantage.
- - Field introduced in 17.2.14,18.1.5,18.2.1.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the pool group.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create PoolGroup object
- avi_poolgroup:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_poolgroup
-"""
-
-RETURN = '''
-obj:
- description: PoolGroup (api/poolgroup) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- cloud_config_cksum=dict(type='str',),
- cloud_ref=dict(type='str',),
- created_by=dict(type='str',),
- deployment_policy_ref=dict(type='str',),
- description=dict(type='str',),
- fail_action=dict(type='dict',),
- implicit_priority_labels=dict(type='bool',),
- members=dict(type='list',),
- min_servers=dict(type='int',),
- name=dict(type='str', required=True),
- priority_labels_ref=dict(type='str',),
- service_metadata=dict(type='str',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'poolgroup',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_poolgroupdeploymentpolicy.py b/plugins/modules/network/avi/avi_poolgroupdeploymentpolicy.py
deleted file mode 100644
index c52400466c..0000000000
--- a/plugins/modules/network/avi/avi_poolgroupdeploymentpolicy.py
+++ /dev/null
@@ -1,154 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_poolgroupdeploymentpolicy
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of PoolGroupDeploymentPolicy Avi RESTful Object
-description:
- - This module is used to configure PoolGroupDeploymentPolicy object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- auto_disable_old_prod_pools:
- description:
- - It will automatically disable old production pools once there is a new production candidate.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- description:
- description:
- - User defined description for the object.
- evaluation_duration:
- description:
- - Duration of evaluation period for automatic deployment.
- - Allowed values are 60-86400.
- - Default value when not specified in API or module is interpreted by Avi Controller as 300.
- name:
- description:
- - The name of the pool group deployment policy.
- required: true
- rules:
- description:
- - List of pgdeploymentrule.
- scheme:
- description:
- - Deployment scheme.
- - Enum options - BLUE_GREEN, CANARY.
- - Default value when not specified in API or module is interpreted by Avi Controller as BLUE_GREEN.
- target_test_traffic_ratio:
- description:
- - Target traffic ratio before pool is made production.
- - Allowed values are 1-100.
- - Default value when not specified in API or module is interpreted by Avi Controller as 100.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- test_traffic_ratio_rampup:
- description:
- - Ratio of the traffic that is sent to the pool under test.
- - Test ratio of 100 means blue green.
- - Allowed values are 1-100.
- - Default value when not specified in API or module is interpreted by Avi Controller as 100.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the pool group deployment policy.
- webhook_ref:
- description:
- - Webhook configured with url that avi controller will pass back information about pool group, old and new pool information and current deployment
- - rule results.
- - It is a reference to an object of type webhook.
- - Field introduced in 17.1.1.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create PoolGroupDeploymentPolicy object
- avi_poolgroupdeploymentpolicy:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_poolgroupdeploymentpolicy
-"""
-
-RETURN = '''
-obj:
- description: PoolGroupDeploymentPolicy (api/poolgroupdeploymentpolicy) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- auto_disable_old_prod_pools=dict(type='bool',),
- description=dict(type='str',),
- evaluation_duration=dict(type='int',),
- name=dict(type='str', required=True),
- rules=dict(type='list',),
- scheme=dict(type='str',),
- target_test_traffic_ratio=dict(type='int',),
- tenant_ref=dict(type='str',),
- test_traffic_ratio_rampup=dict(type='int',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- webhook_ref=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'poolgroupdeploymentpolicy',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_prioritylabels.py b/plugins/modules/network/avi/avi_prioritylabels.py
deleted file mode 100644
index 2ecbaf42c4..0000000000
--- a/plugins/modules/network/avi/avi_prioritylabels.py
+++ /dev/null
@@ -1,120 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_prioritylabels
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of PriorityLabels Avi RESTful Object
-description:
- - This module is used to configure PriorityLabels object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- cloud_ref:
- description:
- - It is a reference to an object of type cloud.
- description:
- description:
- - A description of the priority labels.
- equivalent_labels:
- description:
- - Equivalent priority labels in descending order.
- name:
- description:
- - The name of the priority labels.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the priority labels.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create PriorityLabels object
- avi_prioritylabels:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_prioritylabels
-"""
-
-RETURN = '''
-obj:
- description: PriorityLabels (api/prioritylabels) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- cloud_ref=dict(type='str',),
- description=dict(type='str',),
- equivalent_labels=dict(type='list',),
- name=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'prioritylabels',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_role.py b/plugins/modules/network/avi/avi_role.py
deleted file mode 100644
index 4184fce498..0000000000
--- a/plugins/modules/network/avi/avi_role.py
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_role
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of Role Avi RESTful Object
-description:
- - This module is used to configure Role object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- name:
- description:
- - Name of the object.
- required: true
- privileges:
- description:
- - List of permission.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create Role object
- avi_role:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_role
-"""
-
-RETURN = '''
-obj:
- description: Role (api/role) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- name=dict(type='str', required=True),
- privileges=dict(type='list',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'role',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_scheduler.py b/plugins/modules/network/avi/avi_scheduler.py
deleted file mode 100644
index c79fabd785..0000000000
--- a/plugins/modules/network/avi/avi_scheduler.py
+++ /dev/null
@@ -1,154 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_scheduler
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of Scheduler Avi RESTful Object
-description:
- - This module is used to configure Scheduler object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- backup_config_ref:
- description:
- - Backup configuration to be executed by this scheduler.
- - It is a reference to an object of type backupconfiguration.
- enabled:
- description:
- - Boolean flag to set enabled.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- end_date_time:
- description:
- - Scheduler end date and time.
- frequency:
- description:
- - Frequency at which custom scheduler will run.
- - Allowed values are 0-60.
- frequency_unit:
- description:
- - Unit at which custom scheduler will run.
- - Enum options - SCHEDULER_FREQUENCY_UNIT_MIN, SCHEDULER_FREQUENCY_UNIT_HOUR, SCHEDULER_FREQUENCY_UNIT_DAY, SCHEDULER_FREQUENCY_UNIT_WEEK,
- - SCHEDULER_FREQUENCY_UNIT_MONTH.
- name:
- description:
- - Name of scheduler.
- required: true
- run_mode:
- description:
- - Scheduler run mode.
- - Enum options - RUN_MODE_PERIODIC, RUN_MODE_AT, RUN_MODE_NOW.
- run_script_ref:
- description:
- - Control script to be executed by this scheduler.
- - It is a reference to an object of type alertscriptconfig.
- scheduler_action:
- description:
- - Define scheduler action.
- - Enum options - SCHEDULER_ACTION_RUN_A_SCRIPT, SCHEDULER_ACTION_BACKUP.
- - Default value when not specified in API or module is interpreted by Avi Controller as SCHEDULER_ACTION_BACKUP.
- start_date_time:
- description:
- - Scheduler start date and time.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create Scheduler object
- avi_scheduler:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_scheduler
-"""
-
-RETURN = '''
-obj:
- description: Scheduler (api/scheduler) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- backup_config_ref=dict(type='str',),
- enabled=dict(type='bool',),
- end_date_time=dict(type='str',),
- frequency=dict(type='int',),
- frequency_unit=dict(type='str',),
- name=dict(type='str', required=True),
- run_mode=dict(type='str',),
- run_script_ref=dict(type='str',),
- scheduler_action=dict(type='str',),
- start_date_time=dict(type='str',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'scheduler',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_seproperties.py b/plugins/modules/network/avi/avi_seproperties.py
deleted file mode 100644
index 0eb92eeec6..0000000000
--- a/plugins/modules/network/avi/avi_seproperties.py
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_seproperties
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of SeProperties Avi RESTful Object
-description:
- - This module is used to configure SeProperties object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- se_agent_properties:
- description:
- - Seagentproperties settings for seproperties.
- se_bootup_properties:
- description:
- - Sebootupproperties settings for seproperties.
- se_runtime_properties:
- description:
- - Seruntimeproperties settings for seproperties.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
- - Default value when not specified in API or module is interpreted by Avi Controller as default.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create SeProperties object
- avi_seproperties:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_seproperties
-"""
-
-RETURN = '''
-obj:
- description: SeProperties (api/seproperties) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- se_agent_properties=dict(type='dict',),
- se_bootup_properties=dict(type='dict',),
- se_runtime_properties=dict(type='dict',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'seproperties',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_serverautoscalepolicy.py b/plugins/modules/network/avi/avi_serverautoscalepolicy.py
deleted file mode 100644
index 640258a3e6..0000000000
--- a/plugins/modules/network/avi/avi_serverautoscalepolicy.py
+++ /dev/null
@@ -1,180 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_serverautoscalepolicy
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of ServerAutoScalePolicy Avi RESTful Object
-description:
- - This module is used to configure ServerAutoScalePolicy object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- description:
- description:
- - User defined description for the object.
- intelligent_autoscale:
- description:
- - Use avi intelligent autoscale algorithm where autoscale is performed by comparing load on the pool against estimated capacity of all the servers.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- intelligent_scalein_margin:
- description:
- - Maximum extra capacity as percentage of load used by the intelligent scheme.
- - Scalein is triggered when available capacity is more than this margin.
- - Allowed values are 1-99.
- - Default value when not specified in API or module is interpreted by Avi Controller as 40.
- intelligent_scaleout_margin:
- description:
- - Minimum extra capacity as percentage of load used by the intelligent scheme.
- - Scaleout is triggered when available capacity is less than this margin.
- - Allowed values are 1-99.
- - Default value when not specified in API or module is interpreted by Avi Controller as 20.
- max_scalein_adjustment_step:
- description:
- - Maximum number of servers to scalein simultaneously.
- - The actual number of servers to scalein is chosen such that target number of servers is always more than or equal to the min_size.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.
- max_scaleout_adjustment_step:
- description:
- - Maximum number of servers to scaleout simultaneously.
- - The actual number of servers to scaleout is chosen such that target number of servers is always less than or equal to the max_size.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.
- max_size:
- description:
- - Maximum number of servers after scaleout.
- - Allowed values are 0-400.
- min_size:
- description:
- - No scale-in happens once number of operationally up servers reach min_servers.
- - Allowed values are 0-400.
- name:
- description:
- - Name of the object.
- required: true
- scalein_alertconfig_refs:
- description:
- - Trigger scalein when alerts due to any of these alert configurations are raised.
- - It is a reference to an object of type alertconfig.
- scalein_cooldown:
- description:
- - Cooldown period during which no new scalein is triggered to allow previous scalein to successfully complete.
- - Default value when not specified in API or module is interpreted by Avi Controller as 300.
- scaleout_alertconfig_refs:
- description:
- - Trigger scaleout when alerts due to any of these alert configurations are raised.
- - It is a reference to an object of type alertconfig.
- scaleout_cooldown:
- description:
- - Cooldown period during which no new scaleout is triggered to allow previous scaleout to successfully complete.
- - Default value when not specified in API or module is interpreted by Avi Controller as 300.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- use_predicted_load:
- description:
- - Use predicted load rather than current load.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create ServerAutoScalePolicy object
- avi_serverautoscalepolicy:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_serverautoscalepolicy
-"""
-
-RETURN = '''
-obj:
- description: ServerAutoScalePolicy (api/serverautoscalepolicy) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- description=dict(type='str',),
- intelligent_autoscale=dict(type='bool',),
- intelligent_scalein_margin=dict(type='int',),
- intelligent_scaleout_margin=dict(type='int',),
- max_scalein_adjustment_step=dict(type='int',),
- max_scaleout_adjustment_step=dict(type='int',),
- max_size=dict(type='int',),
- min_size=dict(type='int',),
- name=dict(type='str', required=True),
- scalein_alertconfig_refs=dict(type='list',),
- scalein_cooldown=dict(type='int',),
- scaleout_alertconfig_refs=dict(type='list',),
- scaleout_cooldown=dict(type='int',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- use_predicted_load=dict(type='bool',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'serverautoscalepolicy',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_serviceengine.py b/plugins/modules/network/avi/avi_serviceengine.py
deleted file mode 100644
index e70722be81..0000000000
--- a/plugins/modules/network/avi/avi_serviceengine.py
+++ /dev/null
@@ -1,171 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_serviceengine
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of ServiceEngine Avi RESTful Object
-description:
- - This module is used to configure ServiceEngine object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- availability_zone:
- description:
- - Availability_zone of serviceengine.
- cloud_ref:
- description:
- - It is a reference to an object of type cloud.
- container_mode:
- description:
- - Boolean flag to set container_mode.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- container_type:
- description:
- - Enum options - container_type_bridge, container_type_host, container_type_host_dpdk.
- - Default value when not specified in API or module is interpreted by Avi Controller as CONTAINER_TYPE_HOST.
- controller_created:
- description:
- - Boolean flag to set controller_created.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- controller_ip:
- description:
- - Controller_ip of serviceengine.
- data_vnics:
- description:
- - List of vnic.
- enable_state:
- description:
- - Inorder to disable se set this field appropriately.
- - Enum options - SE_STATE_ENABLED, SE_STATE_DISABLED_FOR_PLACEMENT, SE_STATE_DISABLED, SE_STATE_DISABLED_FORCE.
- - Default value when not specified in API or module is interpreted by Avi Controller as SE_STATE_ENABLED.
- flavor:
- description:
- - Flavor of serviceengine.
- host_ref:
- description:
- - It is a reference to an object of type vimgrhostruntime.
- hypervisor:
- description:
- - Enum options - default, vmware_esx, kvm, vmware_vsan, xen.
- mgmt_vnic:
- description:
- - Vnic settings for serviceengine.
- name:
- description:
- - Name of the object.
- - Default value when not specified in API or module is interpreted by Avi Controller as VM name unknown.
- resources:
- description:
- - Seresources settings for serviceengine.
- se_group_ref:
- description:
- - It is a reference to an object of type serviceenginegroup.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create ServiceEngine object
- avi_serviceengine:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_serviceengine
-"""
-
-RETURN = '''
-obj:
- description: ServiceEngine (api/serviceengine) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- availability_zone=dict(type='str',),
- cloud_ref=dict(type='str',),
- container_mode=dict(type='bool',),
- container_type=dict(type='str',),
- controller_created=dict(type='bool',),
- controller_ip=dict(type='str',),
- data_vnics=dict(type='list',),
- enable_state=dict(type='str',),
- flavor=dict(type='str',),
- host_ref=dict(type='str',),
- hypervisor=dict(type='str',),
- mgmt_vnic=dict(type='dict',),
- name=dict(type='str',),
- resources=dict(type='dict',),
- se_group_ref=dict(type='str',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'serviceengine',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_serviceenginegroup.py b/plugins/modules/network/avi/avi_serviceenginegroup.py
deleted file mode 100644
index e0739777c5..0000000000
--- a/plugins/modules/network/avi/avi_serviceenginegroup.py
+++ /dev/null
@@ -1,1076 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_serviceenginegroup
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of ServiceEngineGroup Avi RESTful Object
-description:
- - This module is used to configure ServiceEngineGroup object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- accelerated_networking:
- description:
- - Enable accelerated networking option for azure se.
- - Accelerated networking enables single root i/o virtualization (sr-iov) to a se vm.
- - This improves networking performance.
- - Field introduced in 17.2.14,18.1.5,18.2.1.
- type: bool
- active_standby:
- description:
- - Service engines in active/standby mode for ha failover.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- additional_config_memory:
- description:
- - Indicates the percent of config memory used for config updates.
- - Allowed values are 0-90.
- - Field deprecated in 18.1.2.
- - Field introduced in 18.1.1.
- advertise_backend_networks:
- description:
- - Advertise reach-ability of backend server networks via adc through bgp for default gateway feature.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- aggressive_failure_detection:
- description:
- - Enable aggressive failover configuration for ha.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- algo:
- description:
- - In compact placement, virtual services are placed on existing ses until max_vs_per_se limit is reached.
- - Enum options - PLACEMENT_ALGO_PACKED, PLACEMENT_ALGO_DISTRIBUTED.
- - Default value when not specified in API or module is interpreted by Avi Controller as PLACEMENT_ALGO_PACKED.
- allow_burst:
- description:
- - Allow ses to be created using burst license.
- - Field introduced in 17.2.5.
- type: bool
- app_cache_percent:
- description:
- - A percent value of total se memory reserved for application caching.
- - This is an se bootup property and requires se restart.
- - Allowed values are 0 - 100.
- - Special values are 0- 'disable'.
- - Field introduced in 18.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- app_learning_memory_percent:
- description:
- - A percent value of total se memory reserved for application learning.
- - This is an se bootup property and requires se restart.
- - Allowed values are 0 - 10.
- - Field introduced in 18.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- archive_shm_limit:
- description:
- - Amount of se memory in gb until which shared memory is collected in core archive.
- - Field introduced in 17.1.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as 8.
- async_ssl:
- description:
- - Ssl handshakes will be handled by dedicated ssl threads.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- async_ssl_threads:
- description:
- - Number of async ssl threads per se_dp.
- - Allowed values are 1-16.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.
- auto_rebalance:
- description:
- - If set, virtual services will be automatically migrated when load on an se is less than minimum or more than maximum thresholds.
- - Only alerts are generated when the auto_rebalance is not set.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- auto_rebalance_capacity_per_se:
- description:
- - Capacities of se for auto rebalance for each criteria.
- - Field introduced in 17.2.4.
- auto_rebalance_criteria:
- description:
- - Set of criteria for se auto rebalance.
- - Enum options - SE_AUTO_REBALANCE_CPU, SE_AUTO_REBALANCE_PPS, SE_AUTO_REBALANCE_MBPS, SE_AUTO_REBALANCE_OPEN_CONNS, SE_AUTO_REBALANCE_CPS.
- - Field introduced in 17.2.3.
- auto_rebalance_interval:
- description:
- - Frequency of rebalance, if 'auto rebalance' is enabled.
- - Default value when not specified in API or module is interpreted by Avi Controller as 300.
- auto_redistribute_active_standby_load:
- description:
- - Redistribution of virtual services from the takeover se to the replacement se can cause momentary traffic loss.
- - If the auto-redistribute load option is left in its default off state, any desired rebalancing requires calls to rest api.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- bgp_state_update_interval:
- description:
- - Bgp peer state update interval.
- - Allowed values are 5-100.
- - Field introduced in 17.2.14,18.1.5,18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 10.
- buffer_se:
- description:
- - Excess service engine capacity provisioned for ha failover.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.
- cloud_ref:
- description:
- - It is a reference to an object of type cloud.
- config_debugs_on_all_cores:
- description:
- - Enable config debugs on all cores of se.
- - Field introduced in 17.2.13,18.1.5,18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- connection_memory_percentage:
- description:
- - Percentage of memory for connection state.
- - This will come at the expense of memory used for http in-memory cache.
- - Allowed values are 10-90.
- - Default value when not specified in API or module is interpreted by Avi Controller as 50.
- cpu_reserve:
- description:
- - Boolean flag to set cpu_reserve.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- cpu_socket_affinity:
- description:
- - Allocate all the cpu cores for the service engine virtual machines on the same cpu socket.
- - Applicable only for vcenter cloud.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- custom_securitygroups_data:
- description:
- - Custom security groups to be associated with data vnics for se instances in openstack and aws clouds.
- - Field introduced in 17.1.3.
- custom_securitygroups_mgmt:
- description:
- - Custom security groups to be associated with management vnic for se instances in openstack and aws clouds.
- - Field introduced in 17.1.3.
- custom_tag:
- description:
- - Custom tag will be used to create the tags for se instance in aws.
- - Note this is not the same as the prefix for se name.
- data_network_id:
- description:
- - Subnet used to spin up the data nic for service engines, used only for azure cloud.
- - Overrides the cloud level setting for service engine subnet.
- - Field introduced in 18.2.3.
- datascript_timeout:
- description:
- - Number of instructions before datascript times out.
- - Allowed values are 0-100000000.
- - Field introduced in 18.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1000000.
- dedicated_dispatcher_core:
- description:
- - Dedicate the core that handles packet receive/transmit from the network to just the dispatching function.
- - Don't use it for tcp/ip and ssl functions.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- description:
- description:
- - User defined description for the object.
- disable_avi_securitygroups:
- description:
- - By default, avi creates and manages security groups along with custom sg provided by user.
- - Set this to true to disallow avi to create and manage new security groups.
- - Avi will only make use of custom security groups provided by user.
- - This option is only supported for aws cloud type.
- - Field introduced in 17.2.13,18.1.4,18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- disable_csum_offloads:
- description:
- - Stop using tcp/udp and ip checksum offload features of nics.
- - Field introduced in 17.1.14, 17.2.5, 18.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- disable_gro:
- description:
- - Disable generic receive offload (gro) in dpdk poll-mode driver packet receive path.
- - Gro is on by default on nics that do not support lro (large receive offload) or do not gain performance boost from lro.
- - Field introduced in 17.2.5, 18.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- disable_se_memory_check:
- description:
- - If set, disable the config memory check done in service engine.
- - Field introduced in 18.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- disable_tso:
- description:
- - Disable tcp segmentation offload (tso) in dpdk poll-mode driver packet transmit path.
- - Tso is on by default on nics that support it.
- - Field introduced in 17.2.5, 18.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- disk_per_se:
- description:
- - Amount of disk space for each of the service engine virtual machines.
- - Default value when not specified in API or module is interpreted by Avi Controller as 10.
- distribute_load_active_standby:
- description:
- - Use both the active and standby service engines for virtual service placement in the legacy active standby ha mode.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- distribute_queues:
- description:
- - Distributes queue ownership among cores so multiple cores handle dispatcher duties.
- - Field introduced in 17.2.8.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- enable_hsm_priming:
- description:
- - (this is a beta feature).
- - Enable hsm key priming.
- - If enabled, key handles on the hsm will be synced to se before processing client connections.
- - Field introduced in 17.2.7, 18.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- enable_multi_lb:
- description:
- - Applicable only for azure cloud with basic sku lb.
- - If set, additional azure lbs will be automatically created if resources in existing lb are exhausted.
- - Field introduced in 17.2.10, 18.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- enable_routing:
- description:
- - Enable routing for this serviceenginegroup .
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- enable_vip_on_all_interfaces:
- description:
- - Enable vip on all interfaces of se.
- - Field introduced in 17.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- enable_vmac:
- description:
- - Use virtual mac address for interfaces on which floating interface ips are placed.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- ephemeral_portrange_end:
- description:
- - End local ephemeral port number for outbound connections.
- - Field introduced in 17.2.13, 18.1.5, 18.2.1.
- ephemeral_portrange_start:
- description:
- - Start local ephemeral port number for outbound connections.
- - Field introduced in 17.2.13, 18.1.5, 18.2.1.
- extra_config_multiplier:
- description:
- - Multiplier for extra config to support large vs/pool config.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.0.
- extra_shared_config_memory:
- description:
- - Extra config memory to support large geo db configuration.
- - Field introduced in 17.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- floating_intf_ip:
- description:
- - If serviceenginegroup is configured for legacy 1+1 active standby ha mode, floating ip's will be advertised only by the active se in the pair.
- - Virtual services in this group must be disabled/enabled for any changes to the floating ip's to take effect.
- - Only active se hosting vs tagged with active standby se 1 tag will advertise this floating ip when manual load distribution is enabled.
- floating_intf_ip_se_2:
- description:
- - If serviceenginegroup is configured for legacy 1+1 active standby ha mode, floating ip's will be advertised only by the active se in the pair.
- - Virtual services in this group must be disabled/enabled for any changes to the floating ip's to take effect.
- - Only active se hosting vs tagged with active standby se 2 tag will advertise this floating ip when manual load distribution is enabled.
- flow_table_new_syn_max_entries:
- description:
- - Maximum number of flow table entries that have not completed tcp three-way handshake yet.
- - Field introduced in 17.2.5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- free_list_size:
- description:
- - Number of entries in the free list.
- - Field introduced in 17.2.10, 18.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1024.
- ha_mode:
- description:
- - High availability mode for all the virtual services using this service engine group.
- - Enum options - HA_MODE_SHARED_PAIR, HA_MODE_SHARED, HA_MODE_LEGACY_ACTIVE_STANDBY.
- - Default value when not specified in API or module is interpreted by Avi Controller as HA_MODE_SHARED.
- hardwaresecuritymodulegroup_ref:
- description:
- - It is a reference to an object of type hardwaresecuritymodulegroup.
- heap_minimum_config_memory:
- description:
- - Minimum required heap memory to apply any configuration.
- - Allowed values are 0-100.
- - Field introduced in 18.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 8.
- hm_on_standby:
- description:
- - Enable active health monitoring from the standby se for all placed virtual services.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- host_attribute_key:
- description:
- - Key of a (key, value) pair identifying a label for a set of nodes usually in container clouds.
- - Needs to be specified together with host_attribute_value.
- - Ses can be configured differently including ha modes across different se groups.
- - May also be used for isolation between different classes of virtualservices.
- - Virtualservices' se group may be specified via annotations/labels.
- - A openshift/kubernetes namespace maybe annotated with a matching se group label as openshift.io/node-selector apptype=prod.
- - When multiple se groups are used in a cloud with host attributes specified,just a single se group can exist as a match-all se group without a
- - host_attribute_key.
- host_attribute_value:
- description:
- - Value of a (key, value) pair identifying a label for a set of nodes usually in container clouds.
- - Needs to be specified together with host_attribute_key.
- host_gateway_monitor:
- description:
- - Enable the host gateway monitor when service engine is deployed as docker container.
- - Disabled by default.
- - Field introduced in 17.2.4.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- hypervisor:
- description:
- - Override default hypervisor.
- - Enum options - DEFAULT, VMWARE_ESX, KVM, VMWARE_VSAN, XEN.
- ignore_rtt_threshold:
- description:
- - Ignore rtt samples if it is above threshold.
- - Field introduced in 17.1.6,17.2.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 5000.
- ingress_access_data:
- description:
- - Program se security group ingress rules to allow vip data access from remote cidr type.
- - Enum options - SG_INGRESS_ACCESS_NONE, SG_INGRESS_ACCESS_ALL, SG_INGRESS_ACCESS_VPC.
- - Field introduced in 17.1.5.
- - Default value when not specified in API or module is interpreted by Avi Controller as SG_INGRESS_ACCESS_ALL.
- ingress_access_mgmt:
- description:
- - Program se security group ingress rules to allow ssh/icmp management access from remote cidr type.
- - Enum options - SG_INGRESS_ACCESS_NONE, SG_INGRESS_ACCESS_ALL, SG_INGRESS_ACCESS_VPC.
- - Field introduced in 17.1.5.
- - Default value when not specified in API or module is interpreted by Avi Controller as SG_INGRESS_ACCESS_ALL.
- instance_flavor:
- description:
- - Instance/flavor name for se instance.
- iptables:
- description:
- - Iptables rules.
- least_load_core_selection:
- description:
- - Select core with least load for new flow.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- license_tier:
- description:
- - Specifies the license tier which would be used.
- - This field by default inherits the value from cloud.
- - Enum options - ENTERPRISE_16, ENTERPRISE_18.
- - Field introduced in 17.2.5.
- license_type:
- description:
- - If no license type is specified then default license enforcement for the cloud type is chosen.
- - Enum options - LIC_BACKEND_SERVERS, LIC_SOCKETS, LIC_CORES, LIC_HOSTS, LIC_SE_BANDWIDTH, LIC_METERED_SE_BANDWIDTH.
- - Field introduced in 17.2.5.
- log_disksz:
- description:
- - Maximum disk capacity (in mb) to be allocated to an se.
- - This is exclusively used for debug and log data.
- - Default value when not specified in API or module is interpreted by Avi Controller as 10000.
- max_cpu_usage:
- description:
- - When cpu usage on an se exceeds this threshold, virtual services hosted on this se may be rebalanced to other ses to reduce load.
- - A new se may be created as part of this process.
- - Allowed values are 40-90.
- - Default value when not specified in API or module is interpreted by Avi Controller as 80.
- max_memory_per_mempool:
- description:
- - Max bytes that can be allocated in a single mempool.
- - Field introduced in 18.1.5.
- - Default value when not specified in API or module is interpreted by Avi Controller as 64.
- max_public_ips_per_lb:
- description:
- - Applicable to azure platform only.
- - Maximum number of public ips per azure lb.
- - Field introduced in 17.2.12, 18.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 30.
- max_rules_per_lb:
- description:
- - Applicable to azure platform only.
- - Maximum number of rules per azure lb.
- - Field introduced in 17.2.12, 18.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 150.
- max_scaleout_per_vs:
- description:
- - Maximum number of active service engines for the virtual service.
- - Allowed values are 1-64.
- - Default value when not specified in API or module is interpreted by Avi Controller as 4.
- max_se:
- description:
- - Maximum number of services engines in this group.
- - Allowed values are 0-1000.
- - Default value when not specified in API or module is interpreted by Avi Controller as 10.
- max_vs_per_se:
- description:
- - Maximum number of virtual services that can be placed on a single service engine.
- - East west virtual services are excluded from this limit.
- - Allowed values are 1-1000.
- - Default value when not specified in API or module is interpreted by Avi Controller as 10.
- mem_reserve:
- description:
- - Boolean flag to set mem_reserve.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- memory_for_config_update:
- description:
- - Indicates the percent of memory reserved for config updates.
- - Allowed values are 0-100.
- - Field introduced in 18.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 15.
- memory_per_se:
- description:
- - Amount of memory for each of the service engine virtual machines.
- - Default value when not specified in API or module is interpreted by Avi Controller as 2048.
- mgmt_network_ref:
- description:
- - Management network to use for avi service engines.
- - It is a reference to an object of type network.
- mgmt_subnet:
- description:
- - Management subnet to use for avi service engines.
- min_cpu_usage:
- description:
- - When cpu usage on an se falls below the minimum threshold, virtual services hosted on the se may be consolidated onto other underutilized ses.
- - After consolidation, unused service engines may then be eligible for deletion.
- - Allowed values are 20-60.
- - Default value when not specified in API or module is interpreted by Avi Controller as 30.
- min_scaleout_per_vs:
- description:
- - Minimum number of active service engines for the virtual service.
- - Allowed values are 1-64.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.
- min_se:
- description:
- - Minimum number of services engines in this group (relevant for se autorebalance only).
- - Allowed values are 0-1000.
- - Field introduced in 17.2.13,18.1.3,18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.
- minimum_connection_memory:
- description:
- - Indicates the percent of memory reserved for connections.
- - Allowed values are 0-100.
- - Field introduced in 18.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 20.
- minimum_required_config_memory:
- description:
- - Required available config memory to apply any configuration.
- - Allowed values are 0-90.
- - Field deprecated in 18.1.2.
- - Field introduced in 18.1.1.
- n_log_streaming_threads:
- description:
- - Number of threads to use for log streaming.
- - Allowed values are 1-100.
- - Field introduced in 17.2.12, 18.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.
- name:
- description:
- - Name of the object.
- required: true
- non_significant_log_throttle:
- description:
- - This setting limits the number of non-significant logs generated per second per core on this se.
- - Default is 100 logs per second.
- - Set it to zero (0) to disable throttling.
- - Field introduced in 17.1.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as 100.
- num_dispatcher_cores:
- description:
- - Number of dispatcher cores (0,1,2,4,8 or 16).
- - If set to 0, then number of dispatcher cores is deduced automatically.
- - Allowed values are 0,1,2,4,8,16.
- - Field introduced in 17.2.12, 18.1.3, 18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- num_flow_cores_sum_changes_to_ignore:
- description:
- - Number of changes in num flow cores sum to ignore.
- - Default value when not specified in API or module is interpreted by Avi Controller as 8.
- openstack_availability_zone:
- description:
- - Field deprecated in 17.1.1.
- openstack_availability_zones:
- description:
- - Field introduced in 17.1.1.
- openstack_mgmt_network_name:
- description:
- - Avi management network name.
- openstack_mgmt_network_uuid:
- description:
- - Management network uuid.
- os_reserved_memory:
- description:
- - Amount of extra memory to be reserved for use by the operating system on a service engine.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- per_app:
- description:
- - Per-app se mode is designed for deploying dedicated load balancers per app (vs).
- - In this mode, each se is limited to a max of 2 vss.
- - Vcpus in per-app ses count towards licensing usage at 25% rate.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- placement_mode:
- description:
- - If placement mode is 'auto', virtual services are automatically placed on service engines.
- - Enum options - PLACEMENT_MODE_AUTO.
- - Default value when not specified in API or module is interpreted by Avi Controller as PLACEMENT_MODE_AUTO.
- realtime_se_metrics:
- description:
- - Enable or disable real time se metrics.
- reboot_on_stop:
- description:
- - Reboot the system if the se is stopped.
- - Field introduced in 17.2.16,18.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- se_bandwidth_type:
- description:
- - Select the se bandwidth for the bandwidth license.
- - Enum options - SE_BANDWIDTH_UNLIMITED, SE_BANDWIDTH_25M, SE_BANDWIDTH_200M, SE_BANDWIDTH_1000M, SE_BANDWIDTH_10000M.
- - Field introduced in 17.2.5.
- se_deprovision_delay:
- description:
- - Duration to preserve unused service engine virtual machines before deleting them.
- - If traffic to a virtual service were to spike up abruptly, this se would still be available to be utilized again rather than creating a new se.
- - If this value is set to 0, controller will never delete any ses and administrator has to manually cleanup unused ses.
- - Allowed values are 0-525600.
- - Default value when not specified in API or module is interpreted by Avi Controller as 120.
- se_dos_profile:
- description:
- - Dosthresholdprofile settings for serviceenginegroup.
- se_dpdk_pmd:
- description:
- - Determines if dpdk pool mode driver should be used or not 0 automatically determine based on hypervisor/nic type 1 unconditionally use dpdk
- - poll mode driver 2 don't use dpdk poll mode driver.
- - Allowed values are 0-2.
- - Field introduced in 18.1.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- se_flow_probe_retries:
- description:
- - Flow probe retry count if no replies are received.
- - Allowed values are 0-5.
- - Field introduced in 18.1.4, 18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 2.
- se_flow_probe_timer:
- description:
- - Timeout in milliseconds for flow probe entries.
- - Allowed values are 10-200.
- - Field introduced in 18.1.4, 18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 100.
- se_ipc_udp_port:
- description:
- - Udp port for se_dp ipc in docker bridge mode.
- - Field introduced in 17.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1500.
- se_name_prefix:
- description:
- - Prefix to use for virtual machine name of service engines.
- - Default value when not specified in API or module is interpreted by Avi Controller as Avi.
- se_pcap_lookahead:
- description:
- - Enables lookahead mode of packet receive in pcap mode.
- - Introduced to overcome an issue with hv_netvsc driver.
- - Lookahead mode attempts to ensure that application and kernel's view of the receive rings are consistent.
- - Field introduced in 18.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- se_pcap_reinit_frequency:
- description:
- - Frequency in seconds at which periodically a pcap reinit check is triggered.
- - May be used in conjunction with the configuration pcap_reinit_threshold.
- - (valid range 15 mins - 12 hours, 0 - disables).
- - Allowed values are 900-43200.
- - Special values are 0- 'disable'.
- - Field introduced in 17.2.13, 18.1.3, 18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- se_pcap_reinit_threshold:
- description:
- - Threshold for input packet receive errors in pcap mode exceeding which a pcap reinit is triggered.
- - If not set, an unconditional reinit is performed.
- - This value is checked every pcap_reinit_frequency interval.
- - Field introduced in 17.2.13, 18.1.3, 18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- se_probe_port:
- description:
- - Tcp port on se where echo service will be run.
- - Field introduced in 17.2.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 7.
- se_remote_punt_udp_port:
- description:
- - Udp port for punted packets in docker bridge mode.
- - Field introduced in 17.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1501.
- se_routing:
- description:
- - Enable routing via service engine datapath.
- - When disabled, routing is done by the linux kernel.
- - Ip routing needs to be enabled in service engine group for se routing to be effective.
- - Field introduced in 18.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- se_sb_dedicated_core:
- description:
- - Sideband traffic will be handled by a dedicated core.
- - Field introduced in 16.5.2, 17.1.9, 17.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- se_sb_threads:
- description:
- - Number of sideband threads per se.
- - Allowed values are 1-128.
- - Field introduced in 16.5.2, 17.1.9, 17.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.
- se_thread_multiplier:
- description:
- - Multiplier for se threads based on vcpu.
- - Allowed values are 1-10.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.
- se_tracert_port_range:
- description:
- - Traceroute port range.
- - Field introduced in 17.2.8.
- se_tunnel_mode:
- description:
- - Determines if dsr from secondary se is active or not 0 automatically determine based on hypervisor type.
- - 1 disable dsr unconditionally.
- - 2 enable dsr unconditionally.
- - Allowed values are 0-2.
- - Field introduced in 17.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- se_tunnel_udp_port:
- description:
- - Udp port for tunneled packets from secondary to primary se in docker bridge mode.
- - Field introduced in 17.1.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1550.
- se_udp_encap_ipc:
- description:
- - Determines if se-se ipc messages are encapsulated in a udp header 0 automatically determine based on hypervisor type.
- - 1 use udp encap unconditionally.
- - Allowed values are 0-1.
- - Field introduced in 17.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- se_use_dpdk:
- description:
- - Determines if dpdk library should be used or not 0 automatically determine based on hypervisor type 1 use dpdk if pcap is not enabled 2
- - don't use dpdk.
- - Allowed values are 0-2.
- - Field introduced in 18.1.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- se_vs_hb_max_pkts_in_batch:
- description:
- - Maximum number of aggregated vs heartbeat packets to send in a batch.
- - Allowed values are 1-256.
- - Field introduced in 17.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 64.
- se_vs_hb_max_vs_in_pkt:
- description:
- - Maximum number of virtualservices for which heartbeat messages are aggregated in one packet.
- - Allowed values are 1-1024.
- - Field introduced in 17.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 256.
- self_se_election:
- description:
- - Enable ses to elect a primary amongst themselves in the absence of a connectivity to controller.
- - Field introduced in 18.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- service_ip6_subnets:
- description:
- - Ipv6 subnets assigned to the se group.
- - Required for vs group placement.
- - Field introduced in 18.1.1.
- service_ip_subnets:
- description:
- - Subnets assigned to the se group.
- - Required for vs group placement.
- - Field introduced in 17.1.1.
- shm_minimum_config_memory:
- description:
- - Minimum required shared memory to apply any configuration.
- - Allowed values are 0-100.
- - Field introduced in 18.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 4.
- significant_log_throttle:
- description:
- - This setting limits the number of significant logs generated per second per core on this se.
- - Default is 100 logs per second.
- - Set it to zero (0) to disable throttling.
- - Field introduced in 17.1.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as 100.
- ssl_preprocess_sni_hostname:
- description:
- - (beta) preprocess ssl client hello for sni hostname extension.if set to true, this will apply sni child's ssl protocol(s), if they are different
- - from sni parent's allowed ssl protocol(s).
- - Field introduced in 17.2.12, 18.1.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- udf_log_throttle:
- description:
- - This setting limits the number of udf logs generated per second per core on this se.
- - Udf logs are generated due to the configured client log filters or the rules with logging enabled.
- - Default is 100 logs per second.
- - Set it to zero (0) to disable throttling.
- - Field introduced in 17.1.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as 100.
- url:
- description:
- - Avi controller URL of the object.
- use_standard_alb:
- description:
- - Use standard sku azure load balancer.
- - By default cloud level flag is set.
- - If not set, it inherits/uses the use_standard_alb flag from the cloud.
- - Field introduced in 18.2.3.
- type: bool
- uuid:
- description:
- - Unique object identifier of the object.
- vcenter_clusters:
- description:
- - Vcenterclusters settings for serviceenginegroup.
- vcenter_datastore_mode:
- description:
- - Enum options - vcenter_datastore_any, vcenter_datastore_local, vcenter_datastore_shared.
- - Default value when not specified in API or module is interpreted by Avi Controller as VCENTER_DATASTORE_ANY.
- vcenter_datastores:
- description:
- - List of vcenterdatastore.
- vcenter_datastores_include:
- description:
- - Boolean flag to set vcenter_datastores_include.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- vcenter_folder:
- description:
- - Folder to place all the service engine virtual machines in vcenter.
- - Default value when not specified in API or module is interpreted by Avi Controller as AviSeFolder.
- vcenter_hosts:
- description:
- - Vcenterhosts settings for serviceenginegroup.
- vcpus_per_se:
- description:
- - Number of vcpus for each of the service engine virtual machines.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.
- vip_asg:
- description:
- - When vip_asg is set, vip configuration will be managed by avi.user will be able to configure vip_asg or vips individually at the time of create.
- - Field introduced in 17.2.12, 18.1.2.
- vs_host_redundancy:
- description:
- - Ensure primary and secondary service engines are deployed on different physical hosts.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- vs_scalein_timeout:
- description:
- - Time to wait for the scaled in se to drain existing flows before marking the scalein done.
- - Default value when not specified in API or module is interpreted by Avi Controller as 30.
- vs_scalein_timeout_for_upgrade:
- description:
- - During se upgrade, time to wait for the scaled-in se to drain existing flows before marking the scalein done.
- - Default value when not specified in API or module is interpreted by Avi Controller as 30.
- vs_scaleout_timeout:
- description:
- - Time to wait for the scaled out se to become ready before marking the scaleout done.
- - Default value when not specified in API or module is interpreted by Avi Controller as 600.
- vs_se_scaleout_additional_wait_time:
- description:
- - Wait time for sending scaleout ready notification after virtual service is marked up.
- - In certain deployments, there may be an additional delay to accept traffic.
- - For example, for bgp, some time is needed for route advertisement.
- - Allowed values are 0-20.
- - Field introduced in 18.1.5,18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- vs_se_scaleout_ready_timeout:
- description:
- - Timeout in seconds for service engine to sendscaleout ready notification of a virtual service.
- - Allowed values are 0-60.
- - Field introduced in 18.1.5,18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 25.
- vs_switchover_timeout:
- description:
- - During se upgrade in a legacy active/standby segroup, time to wait for the new primary se to accept flows before marking the switchover done.
- - Field introduced in 17.2.13,18.1.4,18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as 300.
- vss_placement:
- description:
- - Parameters to place virtual services on only a subset of the cores of an se.
- - Field introduced in 17.2.5.
- vss_placement_enabled:
- description:
- - If set, virtual services will be placed on only a subset of the cores of an se.
- - Field introduced in 18.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- waf_learning_interval:
- description:
- - Frequency with which se publishes waf learning.
- - Allowed values are 1-43200.
- - Field deprecated in 18.2.3.
- - Field introduced in 18.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 10.
- waf_learning_memory:
- description:
- - Amount of memory reserved on se for waf learning.
- - Cannot exceed 5% of se memory.
- - Field deprecated in 18.2.3.
- - Field introduced in 18.1.2.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- waf_mempool:
- description:
- - Enable memory pool for waf.
- - Field introduced in 17.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- waf_mempool_size:
- description:
- - Memory pool size used for waf.
- - Field introduced in 17.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as 64.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create ServiceEngineGroup object
- avi_serviceenginegroup:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_serviceenginegroup
-"""
-
-RETURN = '''
-obj:
- description: ServiceEngineGroup (api/serviceenginegroup) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- accelerated_networking=dict(type='bool',),
- active_standby=dict(type='bool',),
- additional_config_memory=dict(type='int',),
- advertise_backend_networks=dict(type='bool',),
- aggressive_failure_detection=dict(type='bool',),
- algo=dict(type='str',),
- allow_burst=dict(type='bool',),
- app_cache_percent=dict(type='int',),
- app_learning_memory_percent=dict(type='int',),
- archive_shm_limit=dict(type='int',),
- async_ssl=dict(type='bool',),
- async_ssl_threads=dict(type='int',),
- auto_rebalance=dict(type='bool',),
- auto_rebalance_capacity_per_se=dict(type='list',),
- auto_rebalance_criteria=dict(type='list',),
- auto_rebalance_interval=dict(type='int',),
- auto_redistribute_active_standby_load=dict(type='bool',),
- bgp_state_update_interval=dict(type='int',),
- buffer_se=dict(type='int',),
- cloud_ref=dict(type='str',),
- config_debugs_on_all_cores=dict(type='bool',),
- connection_memory_percentage=dict(type='int',),
- cpu_reserve=dict(type='bool',),
- cpu_socket_affinity=dict(type='bool',),
- custom_securitygroups_data=dict(type='list',),
- custom_securitygroups_mgmt=dict(type='list',),
- custom_tag=dict(type='list',),
- data_network_id=dict(type='str',),
- datascript_timeout=dict(type='int',),
- dedicated_dispatcher_core=dict(type='bool',),
- description=dict(type='str',),
- disable_avi_securitygroups=dict(type='bool',),
- disable_csum_offloads=dict(type='bool',),
- disable_gro=dict(type='bool',),
- disable_se_memory_check=dict(type='bool',),
- disable_tso=dict(type='bool',),
- disk_per_se=dict(type='int',),
- distribute_load_active_standby=dict(type='bool',),
- distribute_queues=dict(type='bool',),
- enable_hsm_priming=dict(type='bool',),
- enable_multi_lb=dict(type='bool',),
- enable_routing=dict(type='bool',),
- enable_vip_on_all_interfaces=dict(type='bool',),
- enable_vmac=dict(type='bool',),
- ephemeral_portrange_end=dict(type='int',),
- ephemeral_portrange_start=dict(type='int',),
- extra_config_multiplier=dict(type='float',),
- extra_shared_config_memory=dict(type='int',),
- floating_intf_ip=dict(type='list',),
- floating_intf_ip_se_2=dict(type='list',),
- flow_table_new_syn_max_entries=dict(type='int',),
- free_list_size=dict(type='int',),
- ha_mode=dict(type='str',),
- hardwaresecuritymodulegroup_ref=dict(type='str',),
- heap_minimum_config_memory=dict(type='int',),
- hm_on_standby=dict(type='bool',),
- host_attribute_key=dict(type='str',),
- host_attribute_value=dict(type='str',),
- host_gateway_monitor=dict(type='bool',),
- hypervisor=dict(type='str',),
- ignore_rtt_threshold=dict(type='int',),
- ingress_access_data=dict(type='str',),
- ingress_access_mgmt=dict(type='str',),
- instance_flavor=dict(type='str',),
- iptables=dict(type='list',),
- least_load_core_selection=dict(type='bool',),
- license_tier=dict(type='str',),
- license_type=dict(type='str',),
- log_disksz=dict(type='int',),
- max_cpu_usage=dict(type='int',),
- max_memory_per_mempool=dict(type='int',),
- max_public_ips_per_lb=dict(type='int',),
- max_rules_per_lb=dict(type='int',),
- max_scaleout_per_vs=dict(type='int',),
- max_se=dict(type='int',),
- max_vs_per_se=dict(type='int',),
- mem_reserve=dict(type='bool',),
- memory_for_config_update=dict(type='int',),
- memory_per_se=dict(type='int',),
- mgmt_network_ref=dict(type='str',),
- mgmt_subnet=dict(type='dict',),
- min_cpu_usage=dict(type='int',),
- min_scaleout_per_vs=dict(type='int',),
- min_se=dict(type='int',),
- minimum_connection_memory=dict(type='int',),
- minimum_required_config_memory=dict(type='int',),
- n_log_streaming_threads=dict(type='int',),
- name=dict(type='str', required=True),
- non_significant_log_throttle=dict(type='int',),
- num_dispatcher_cores=dict(type='int',),
- num_flow_cores_sum_changes_to_ignore=dict(type='int',),
- openstack_availability_zone=dict(type='str',),
- openstack_availability_zones=dict(type='list',),
- openstack_mgmt_network_name=dict(type='str',),
- openstack_mgmt_network_uuid=dict(type='str',),
- os_reserved_memory=dict(type='int',),
- per_app=dict(type='bool',),
- placement_mode=dict(type='str',),
- realtime_se_metrics=dict(type='dict',),
- reboot_on_stop=dict(type='bool',),
- se_bandwidth_type=dict(type='str',),
- se_deprovision_delay=dict(type='int',),
- se_dos_profile=dict(type='dict',),
- se_dpdk_pmd=dict(type='int',),
- se_flow_probe_retries=dict(type='int',),
- se_flow_probe_timer=dict(type='int',),
- se_ipc_udp_port=dict(type='int',),
- se_name_prefix=dict(type='str',),
- se_pcap_lookahead=dict(type='bool',),
- se_pcap_reinit_frequency=dict(type='int',),
- se_pcap_reinit_threshold=dict(type='int',),
- se_probe_port=dict(type='int',),
- se_remote_punt_udp_port=dict(type='int',),
- se_routing=dict(type='bool',),
- se_sb_dedicated_core=dict(type='bool',),
- se_sb_threads=dict(type='int',),
- se_thread_multiplier=dict(type='int',),
- se_tracert_port_range=dict(type='dict',),
- se_tunnel_mode=dict(type='int',),
- se_tunnel_udp_port=dict(type='int',),
- se_udp_encap_ipc=dict(type='int',),
- se_use_dpdk=dict(type='int',),
- se_vs_hb_max_pkts_in_batch=dict(type='int',),
- se_vs_hb_max_vs_in_pkt=dict(type='int',),
- self_se_election=dict(type='bool',),
- service_ip6_subnets=dict(type='list',),
- service_ip_subnets=dict(type='list',),
- shm_minimum_config_memory=dict(type='int',),
- significant_log_throttle=dict(type='int',),
- ssl_preprocess_sni_hostname=dict(type='bool',),
- tenant_ref=dict(type='str',),
- udf_log_throttle=dict(type='int',),
- url=dict(type='str',),
- use_standard_alb=dict(type='bool',),
- uuid=dict(type='str',),
- vcenter_clusters=dict(type='dict',),
- vcenter_datastore_mode=dict(type='str',),
- vcenter_datastores=dict(type='list',),
- vcenter_datastores_include=dict(type='bool',),
- vcenter_folder=dict(type='str',),
- vcenter_hosts=dict(type='dict',),
- vcpus_per_se=dict(type='int',),
- vip_asg=dict(type='dict',),
- vs_host_redundancy=dict(type='bool',),
- vs_scalein_timeout=dict(type='int',),
- vs_scalein_timeout_for_upgrade=dict(type='int',),
- vs_scaleout_timeout=dict(type='int',),
- vs_se_scaleout_additional_wait_time=dict(type='int',),
- vs_se_scaleout_ready_timeout=dict(type='int',),
- vs_switchover_timeout=dict(type='int',),
- vss_placement=dict(type='dict',),
- vss_placement_enabled=dict(type='bool',),
- waf_learning_interval=dict(type='int',),
- waf_learning_memory=dict(type='int',),
- waf_mempool=dict(type='bool',),
- waf_mempool_size=dict(type='int',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'serviceenginegroup',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_snmptrapprofile.py b/plugins/modules/network/avi/avi_snmptrapprofile.py
deleted file mode 100644
index eb10fe16a1..0000000000
--- a/plugins/modules/network/avi/avi_snmptrapprofile.py
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_snmptrapprofile
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of SnmpTrapProfile Avi RESTful Object
-description:
- - This module is used to configure SnmpTrapProfile object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- name:
- description:
- - A user-friendly name of the snmp trap configuration.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- trap_servers:
- description:
- - The ip address or hostname of the snmp trap destination server.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the snmp trap profile object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create SnmpTrapProfile object
- avi_snmptrapprofile:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_snmptrapprofile
-"""
-
-RETURN = '''
-obj:
- description: SnmpTrapProfile (api/snmptrapprofile) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- name=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- trap_servers=dict(type='list',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'snmptrapprofile',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_sslkeyandcertificate.py b/plugins/modules/network/avi/avi_sslkeyandcertificate.py
deleted file mode 100644
index 6a2dd12c22..0000000000
--- a/plugins/modules/network/avi/avi_sslkeyandcertificate.py
+++ /dev/null
@@ -1,197 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_sslkeyandcertificate
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of SSLKeyAndCertificate Avi RESTful Object
-description:
- - This module is used to configure SSLKeyAndCertificate object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- ca_certs:
- description:
- - Ca certificates in certificate chain.
- certificate:
- description:
- - Sslcertificate settings for sslkeyandcertificate.
- required: true
- certificate_base64:
- description:
- - States if the certificate is base64 encoded.
- - Field introduced in 18.1.2, 18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- certificate_management_profile_ref:
- description:
- - It is a reference to an object of type certificatemanagementprofile.
- created_by:
- description:
- - Creator name.
- dynamic_params:
- description:
- - Dynamic parameters needed for certificate management profile.
- enckey_base64:
- description:
- - Encrypted private key corresponding to the private key (e.g.
- - Those generated by an hsm such as thales nshield).
- enckey_name:
- description:
- - Name of the encrypted private key (e.g.
- - Those generated by an hsm such as thales nshield).
- format:
- description:
- - Format of the key/certificate file.
- - Enum options - SSL_PEM, SSL_PKCS12.
- - Field introduced in 18.1.2, 18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as SSL_PEM.
- hardwaresecuritymodulegroup_ref:
- description:
- - It is a reference to an object of type hardwaresecuritymodulegroup.
- key:
- description:
- - Private key.
- key_base64:
- description:
- - States if the private key is base64 encoded.
- - Field introduced in 18.1.2, 18.2.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- key_params:
- description:
- - Sslkeyparams settings for sslkeyandcertificate.
- key_passphrase:
- description:
- - Passphrase used to encrypt the private key.
- - Field introduced in 18.1.2, 18.2.1.
- name:
- description:
- - Name of the object.
- required: true
- status:
- description:
- - Enum options - ssl_certificate_finished, ssl_certificate_pending.
- - Default value when not specified in API or module is interpreted by Avi Controller as SSL_CERTIFICATE_FINISHED.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- type:
- description:
- - Enum options - ssl_certificate_type_virtualservice, ssl_certificate_type_system, ssl_certificate_type_ca.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Create a SSL Key and Certificate
- avi_sslkeyandcertificate:
- controller: 10.10.27.90
- username: admin
- password: AviNetworks123!
- key: |
- -----BEGIN PRIVATE KEY-----
- ....
- -----END PRIVATE KEY-----
- certificate:
- self_signed: true
- certificate: |
- -----BEGIN CERTIFICATE-----
- ....
- -----END CERTIFICATE-----
- type: SSL_CERTIFICATE_TYPE_VIRTUALSERVICE
- name: MyTestCert
-"""
-
-RETURN = '''
-obj:
- description: SSLKeyAndCertificate (api/sslkeyandcertificate) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- ca_certs=dict(type='list',),
- certificate=dict(type='dict', required=True),
- certificate_base64=dict(type='bool',),
- certificate_management_profile_ref=dict(type='str',),
- created_by=dict(type='str',),
- dynamic_params=dict(type='list',),
- enckey_base64=dict(type='str',),
- enckey_name=dict(type='str',),
- format=dict(type='str',),
- hardwaresecuritymodulegroup_ref=dict(type='str',),
- key=dict(type='str', no_log=True,),
- key_base64=dict(type='bool',),
- key_params=dict(type='dict',),
- key_passphrase=dict(type='str', no_log=True,),
- name=dict(type='str', required=True),
- status=dict(type='str',),
- tenant_ref=dict(type='str',),
- type=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'sslkeyandcertificate',
- set(['key_passphrase', 'key']))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_sslprofile.py b/plugins/modules/network/avi/avi_sslprofile.py
deleted file mode 100644
index 574d2fa855..0000000000
--- a/plugins/modules/network/avi/avi_sslprofile.py
+++ /dev/null
@@ -1,209 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_sslprofile
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of SSLProfile Avi RESTful Object
-description:
- - This module is used to configure SSLProfile object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- accepted_ciphers:
- description:
- - Ciphers suites represented as defined by U(http://www.openssl.org/docs/apps/ciphers.html).
- - Default value when not specified in API or module is interpreted by Avi Controller as AES:3DES:RC4.
- accepted_versions:
- description:
- - Set of versions accepted by the server.
- cipher_enums:
- description:
- - Enum options - tls_ecdhe_ecdsa_with_aes_128_gcm_sha256, tls_ecdhe_ecdsa_with_aes_256_gcm_sha384, tls_ecdhe_rsa_with_aes_128_gcm_sha256,
- - tls_ecdhe_rsa_with_aes_256_gcm_sha384, tls_ecdhe_ecdsa_with_aes_128_cbc_sha256, tls_ecdhe_ecdsa_with_aes_256_cbc_sha384,
- - tls_ecdhe_rsa_with_aes_128_cbc_sha256, tls_ecdhe_rsa_with_aes_256_cbc_sha384, tls_rsa_with_aes_128_gcm_sha256, tls_rsa_with_aes_256_gcm_sha384,
- - tls_rsa_with_aes_128_cbc_sha256, tls_rsa_with_aes_256_cbc_sha256, tls_ecdhe_ecdsa_with_aes_128_cbc_sha, tls_ecdhe_ecdsa_with_aes_256_cbc_sha,
- - tls_ecdhe_rsa_with_aes_128_cbc_sha, tls_ecdhe_rsa_with_aes_256_cbc_sha, tls_rsa_with_aes_128_cbc_sha, tls_rsa_with_aes_256_cbc_sha,
- - tls_rsa_with_3des_ede_cbc_sha, tls_rsa_with_rc4_128_sha.
- description:
- description:
- - User defined description for the object.
- dhparam:
- description:
- - Dh parameters used in ssl.
- - At this time, it is not configurable and is set to 2048 bits.
- enable_ssl_session_reuse:
- description:
- - Enable ssl session re-use.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- name:
- description:
- - Name of the object.
- required: true
- prefer_client_cipher_ordering:
- description:
- - Prefer the ssl cipher ordering presented by the client during the ssl handshake over the one specified in the ssl profile.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- send_close_notify:
- description:
- - Send 'close notify' alert message for a clean shutdown of the ssl connection.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- ssl_rating:
- description:
- - Sslrating settings for sslprofile.
- ssl_session_timeout:
- description:
- - The amount of time in seconds before an ssl session expires.
- - Default value when not specified in API or module is interpreted by Avi Controller as 86400.
- tags:
- description:
- - List of tag.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- type:
- description:
- - Ssl profile type.
- - Enum options - SSL_PROFILE_TYPE_APPLICATION, SSL_PROFILE_TYPE_SYSTEM.
- - Field introduced in 17.2.8.
- - Default value when not specified in API or module is interpreted by Avi Controller as SSL_PROFILE_TYPE_APPLICATION.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create SSL profile with list of allowed ciphers
- avi_sslprofile:
- controller: '{{ controller }}'
- username: '{{ username }}'
- password: '{{ password }}'
- accepted_ciphers: >
- ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:
- ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:
- AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:
- AES256-SHA:DES-CBC3-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:
- ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA
- accepted_versions:
- - type: SSL_VERSION_TLS1
- - type: SSL_VERSION_TLS1_1
- - type: SSL_VERSION_TLS1_2
- cipher_enums:
- - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
- - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
- - TLS_RSA_WITH_AES_128_GCM_SHA256
- - TLS_RSA_WITH_AES_256_GCM_SHA384
- - TLS_RSA_WITH_AES_128_CBC_SHA256
- - TLS_RSA_WITH_AES_256_CBC_SHA256
- - TLS_RSA_WITH_AES_128_CBC_SHA
- - TLS_RSA_WITH_AES_256_CBC_SHA
- - TLS_RSA_WITH_3DES_EDE_CBC_SHA
- - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
- - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- name: PFS-BOTH-RSA-EC
- send_close_notify: true
- ssl_rating:
- compatibility_rating: SSL_SCORE_EXCELLENT
- performance_rating: SSL_SCORE_EXCELLENT
- security_score: '100.0'
- tenant_ref: Demo
-"""
-
-RETURN = '''
-obj:
- description: SSLProfile (api/sslprofile) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- accepted_ciphers=dict(type='str',),
- accepted_versions=dict(type='list',),
- cipher_enums=dict(type='list',),
- description=dict(type='str',),
- dhparam=dict(type='str',),
- enable_ssl_session_reuse=dict(type='bool',),
- name=dict(type='str', required=True),
- prefer_client_cipher_ordering=dict(type='bool',),
- send_close_notify=dict(type='bool',),
- ssl_rating=dict(type='dict',),
- ssl_session_timeout=dict(type='int',),
- tags=dict(type='list',),
- tenant_ref=dict(type='str',),
- type=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'sslprofile',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_stringgroup.py b/plugins/modules/network/avi/avi_stringgroup.py
deleted file mode 100644
index bf494cf841..0000000000
--- a/plugins/modules/network/avi/avi_stringgroup.py
+++ /dev/null
@@ -1,135 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_stringgroup
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of StringGroup Avi RESTful Object
-description:
- - This module is used to configure StringGroup object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- description:
- description:
- - User defined description for the object.
- kv:
- description:
- - Configure key value in the string group.
- name:
- description:
- - Name of the string group.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- type:
- description:
- - Type of stringgroup.
- - Enum options - SG_TYPE_STRING, SG_TYPE_KEYVAL.
- - Default value when not specified in API or module is interpreted by Avi Controller as SG_TYPE_STRING.
- required: true
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the string group.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create a string group configuration
- avi_stringgroup:
- controller: '{{ controller }}'
- password: '{{ password }}'
- username: '{{ username }}'
- kv:
- - key: text/html
- - key: text/xml
- - key: text/plain
- - key: text/css
- - key: text/javascript
- - key: application/javascript
- - key: application/x-javascript
- - key: application/xml
- - key: application/pdf
- name: System-Compressible-Content-Types
- tenant_ref: admin
- type: SG_TYPE_STRING
-"""
-
-RETURN = '''
-obj:
- description: StringGroup (api/stringgroup) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- description=dict(type='str',),
- kv=dict(type='list',),
- name=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- type=dict(type='str', required=True),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'stringgroup',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_systemconfiguration.py b/plugins/modules/network/avi/avi_systemconfiguration.py
deleted file mode 100644
index b338720fec..0000000000
--- a/plugins/modules/network/avi/avi_systemconfiguration.py
+++ /dev/null
@@ -1,182 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_systemconfiguration
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of SystemConfiguration Avi RESTful Object
-description:
- - This module is used to configure SystemConfiguration object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- admin_auth_configuration:
- description:
- - Adminauthconfiguration settings for systemconfiguration.
- default_license_tier:
- description:
- - Specifies the default license tier which would be used by new clouds.
- - Enum options - ENTERPRISE_16, ENTERPRISE_18.
- - Field introduced in 17.2.5.
- - Default value when not specified in API or module is interpreted by Avi Controller as ENTERPRISE_18.
- dns_configuration:
- description:
- - Dnsconfiguration settings for systemconfiguration.
- dns_virtualservice_refs:
- description:
- - Dns virtualservices hosting fqdn records for applications across avi vantage.
- - If no virtualservices are provided, avi vantage will provide dns services for configured applications.
- - Switching back to avi vantage from dns virtualservices is not allowed.
- - It is a reference to an object of type virtualservice.
- docker_mode:
- description:
- - Boolean flag to set docker_mode.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- email_configuration:
- description:
- - Emailconfiguration settings for systemconfiguration.
- global_tenant_config:
- description:
- - Tenantconfiguration settings for systemconfiguration.
- linux_configuration:
- description:
- - Linuxconfiguration settings for systemconfiguration.
- mgmt_ip_access_control:
- description:
- - Configure ip access control for controller to restrict open access.
- ntp_configuration:
- description:
- - Ntpconfiguration settings for systemconfiguration.
- portal_configuration:
- description:
- - Portalconfiguration settings for systemconfiguration.
- proxy_configuration:
- description:
- - Proxyconfiguration settings for systemconfiguration.
- secure_channel_configuration:
- description:
- - Configure secure channel properties.
- - Field introduced in 18.1.4, 18.2.1.
- snmp_configuration:
- description:
- - Snmpconfiguration settings for systemconfiguration.
- ssh_ciphers:
- description:
- - Allowed ciphers list for ssh to the management interface on the controller and service engines.
- - If this is not specified, all the default ciphers are allowed.
- ssh_hmacs:
- description:
- - Allowed hmac list for ssh to the management interface on the controller and service engines.
- - If this is not specified, all the default hmacs are allowed.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
- welcome_workflow_complete:
- description:
- - This flag is set once the initial controller setup workflow is complete.
- - Field introduced in 18.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create SystemConfiguration object
- avi_systemconfiguration:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_systemconfiguration
-"""
-
-RETURN = '''
-obj:
- description: SystemConfiguration (api/systemconfiguration) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- admin_auth_configuration=dict(type='dict',),
- default_license_tier=dict(type='str',),
- dns_configuration=dict(type='dict',),
- dns_virtualservice_refs=dict(type='list',),
- docker_mode=dict(type='bool',),
- email_configuration=dict(type='dict',),
- global_tenant_config=dict(type='dict',),
- linux_configuration=dict(type='dict',),
- mgmt_ip_access_control=dict(type='dict',),
- ntp_configuration=dict(type='dict',),
- portal_configuration=dict(type='dict',),
- proxy_configuration=dict(type='dict',),
- secure_channel_configuration=dict(type='dict',),
- snmp_configuration=dict(type='dict',),
- ssh_ciphers=dict(type='list',),
- ssh_hmacs=dict(type='list',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- welcome_workflow_complete=dict(type='bool',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'systemconfiguration',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_tenant.py b/plugins/modules/network/avi/avi_tenant.py
deleted file mode 100644
index 3828f09e35..0000000000
--- a/plugins/modules/network/avi/avi_tenant.py
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_tenant
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of Tenant Avi RESTful Object
-description:
- - This module is used to configure Tenant object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- config_settings:
- description:
- - Tenantconfiguration settings for tenant.
- created_by:
- description:
- - Creator of this tenant.
- description:
- description:
- - User defined description for the object.
- local:
- description:
- - Boolean flag to set local.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- name:
- description:
- - Name of the object.
- required: true
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
- - name: Create Tenant using Service Engines in provider mode
- avi_tenant:
- controller: '{{ controller }}'
- password: '{{ password }}'
- username: '{{ username }}'
- config_settings:
- se_in_provider_context: false
- tenant_access_to_provider_se: true
- tenant_vrf: false
- description: VCenter, Open Stack, AWS Virtual services
- local: true
- name: Demo
-"""
-
-RETURN = '''
-obj:
- description: Tenant (api/tenant) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- config_settings=dict(type='dict',),
- created_by=dict(type='str',),
- description=dict(type='str',),
- local=dict(type='bool',),
- name=dict(type='str', required=True),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'tenant',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_trafficcloneprofile.py b/plugins/modules/network/avi/avi_trafficcloneprofile.py
deleted file mode 100644
index 10b24c24fc..0000000000
--- a/plugins/modules/network/avi/avi_trafficcloneprofile.py
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_trafficcloneprofile
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of TrafficCloneProfile Avi RESTful Object
-description:
- - This module is used to configure TrafficCloneProfile object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- clone_servers:
- description:
- - Field introduced in 17.1.1.
- cloud_ref:
- description:
- - It is a reference to an object of type cloud.
- - Field introduced in 17.1.1.
- name:
- description:
- - Name for the traffic clone profile.
- - Field introduced in 17.1.1.
- required: true
- preserve_client_ip:
- description:
- - Specifies if client ip needs to be preserved to clone destination.
- - Field introduced in 17.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- - Field introduced in 17.1.1.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the traffic clone profile.
- - Field introduced in 17.1.1.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create TrafficCloneProfile object
- avi_trafficcloneprofile:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_trafficcloneprofile
-"""
-
-RETURN = '''
-obj:
- description: TrafficCloneProfile (api/trafficcloneprofile) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- clone_servers=dict(type='list',),
- cloud_ref=dict(type='str',),
- name=dict(type='str', required=True),
- preserve_client_ip=dict(type='bool',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'trafficcloneprofile',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_user.py b/plugins/modules/network/avi/avi_user.py
deleted file mode 100644
index f87bb5345f..0000000000
--- a/plugins/modules/network/avi/avi_user.py
+++ /dev/null
@@ -1,193 +0,0 @@
-#!/usr/bin/python
-"""
-# Created on Aug 2, 2018
-#
-# @author: Shrikant Chaudhari (shrikant.chaudhari@avinetworks.com) GitHub ID: gitshrikant
-#
-# module_check: supported
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_user
-author: Shrikant Chaudhari (@gitshrikant)
-short_description: Avi User Module
-description:
- - This module can be used for creation, updation and deletion of a user.
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- type: str
- name:
- description:
- - Full name of the user.
- required: true
- type: str
- obj_username:
- description:
- - Name that the user will supply when signing into Avi Vantage, such as jdoe or jdoe@avinetworks.com.
- required: true
- type: str
- obj_password:
- description:
- - You may either enter a case-sensitive password in this field for the new or existing user.
- required: true
- type: str
- email:
- description:
- - Email address of the user. This field is used when a user loses their password and requests to have it reset. See Password Recovery.
- type: str
- access:
- description:
- - Access settings (write, read, or no access) for each type of resource within Vantage.
- type: list
- is_superuser:
- description:
- - If the user will need to have the same privileges as the admin account, set it to true.
- type: bool
- is_active:
- description:
- - Activates the current user account.
- type: bool
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["post", "put", "patch"]
- type: str
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- type: str
- user_profile_ref:
- description:
- - Refer user profile.
- - This can also be full URI same as it comes in response payload
- type: str
- default_tenant_ref:
- description:
- - Default tenant reference.
- - This can also be full URI same as it comes in response payload
- default: /api/tenant?name=admin
- type: str
-
-
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = '''
- - name: user creation
- avi_user:
- controller: ""
- username: ""
- password: ""
- api_version: ""
- name: "testuser"
- obj_username: "testuser"
- obj_password: "test123"
- email: "test@abc.test"
- access:
- - role_ref: "/api/role?name=Tenant-Admin"
- tenant_ref: "/api/tenant/admin#admin"
- user_profile_ref: "/api/useraccountprofile?name=Default-User-Account-Profile"
- is_active: true
- is_superuser: true
- default_tenant_ref: "/api/tenant?name=admin"
-
- - name: user creation
- avi_user:
- controller: ""
- username: ""
- password: ""
- api_version: ""
- name: "testuser"
- obj_username: "testuser2"
- obj_password: "password"
- email: "testuser2@abc.test"
- access:
- - role_ref: "https://192.0.2.10/api/role?name=Tenant-Admin"
- tenant_ref: "https://192.0.2.10/api/tenant/admin#admin"
- user_profile_ref: "https://192.0.2.10/api/useraccountprofile?name=Default-User-Account-Profile"
- is_active: true
- is_superuser: true
- default_tenant_ref: "https://192.0.2.10/api/tenant?name=admin"
-'''
-
-RETURN = '''
-obj:
- description: Avi REST resource
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, ansible_return, HAS_AVI)
- from ansible_collections.community.general.plugins.module_utils.network.avi.ansible_utils import (
- avi_ansible_api)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- name=dict(type='str', required=True),
- obj_username=dict(type='str', required=True),
- obj_password=dict(type='str', required=True, no_log=True),
- access=dict(type='list',),
- email=dict(type='str',),
- is_superuser=dict(type='bool',),
- is_active=dict(type='bool',),
- avi_api_update_method=dict(default='put',
- choices=['post', 'put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- user_profile_ref=dict(type='str',),
- default_tenant_ref=dict(type='str', default='/api/tenant?name=admin'),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'user',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_useraccount.py b/plugins/modules/network/avi/avi_useraccount.py
deleted file mode 100644
index 98cfc68c38..0000000000
--- a/plugins/modules/network/avi/avi_useraccount.py
+++ /dev/null
@@ -1,152 +0,0 @@
-#!/usr/bin/python
-"""
-# Created on Aug 12, 2016
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com) GitHub ID: grastogi23
-#
-# module_check: not supported
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-"""
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_useraccount
-author: Chaitanya Deshpande (@chaitanyaavi)
-short_description: Avi UserAccount Module
-description:
- - This module can be used for updating the password of a user.
- - This module is useful for setting up admin password for Controller bootstrap.
-requirements: [ avisdk ]
-options:
- old_password:
- description:
- - Old password for update password or default password for bootstrap.
- force_change:
- description:
- - If specifically set to true then old password is tried first for controller and then the new password is
- tried. If not specified this flag then the new password is tried first.
-
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = '''
- - name: Update user password
- avi_useraccount:
- controller: ""
- username: ""
- password: new_password
- old_password: ""
- api_version: ""
- force_change: false
-
- - name: Update user password using avi_credentials
- avi_useraccount:
- avi_credentials: ""
- old_password: ""
- force_change: false
-'''
-
-RETURN = '''
-obj:
- description: Avi REST resource
- returned: success, changed
- type: dict
-'''
-
-import json
-import time
-from ansible.module_utils.basic import AnsibleModule
-from copy import deepcopy
-
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, ansible_return, avi_obj_cmp,
- cleanup_absent_fields, HAS_AVI)
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi_api import (
- ApiSession, AviCredentials)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- old_password=dict(type='str', required=True, no_log=True),
- # Flag to specify priority of old/new password while establishing session with controller.
- # To handle both Saas and conventional (Entire state in playbook) scenario.
- force_change=dict(type='bool', default=False)
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(argument_spec=argument_specs)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- api_creds = AviCredentials()
- api_creds.update_from_ansible_module(module)
- old_password = module.params.get('old_password')
- force_change = module.params.get('force_change', False)
- data = {
- 'old_password': old_password,
- 'password': api_creds.password
- }
- # First try old password if 'force_change' is set to true
- if force_change:
- first_pwd = old_password
- second_pwd = api_creds.password
- # First try new password if 'force_change' is set to false or not specified in playbook.
- else:
- first_pwd = api_creds.password
- second_pwd = old_password
- password_changed = False
- try:
- api = ApiSession.get_session(
- api_creds.controller, api_creds.username,
- password=first_pwd, timeout=api_creds.timeout,
- tenant=api_creds.tenant, tenant_uuid=api_creds.tenant_uuid,
- token=api_creds.token, port=api_creds.port)
- if force_change:
- rsp = api.put('useraccount', data=data)
- if rsp:
- password_changed = True
- except Exception:
- pass
- if not password_changed:
- api = ApiSession.get_session(
- api_creds.controller, api_creds.username, password=second_pwd,
- timeout=api_creds.timeout, tenant=api_creds.tenant,
- tenant_uuid=api_creds.tenant_uuid, token=api_creds.token,
- port=api_creds.port)
- if not force_change:
- rsp = api.put('useraccount', data=data)
- if rsp:
- password_changed = True
- if password_changed:
- return ansible_return(module, rsp, True, req=data)
- else:
- return ansible_return(module, rsp, False, req=data)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_useraccountprofile.py b/plugins/modules/network/avi/avi_useraccountprofile.py
deleted file mode 100644
index 6786777945..0000000000
--- a/plugins/modules/network/avi/avi_useraccountprofile.py
+++ /dev/null
@@ -1,135 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_useraccountprofile
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of UserAccountProfile Avi RESTful Object
-description:
- - This module is used to configure UserAccountProfile object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- account_lock_timeout:
- description:
- - Lock timeout period (in minutes).
- - Default is 30 minutes.
- - Default value when not specified in API or module is interpreted by Avi Controller as 30.
- credentials_timeout_threshold:
- description:
- - The time period after which credentials expire.
- - Default is 180 days.
- - Default value when not specified in API or module is interpreted by Avi Controller as 180.
- max_concurrent_sessions:
- description:
- - Maximum number of concurrent sessions allowed.
- - There are unlimited sessions by default.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- max_login_failure_count:
- description:
- - Number of login attempts before lockout.
- - Default is 3 attempts.
- - Default value when not specified in API or module is interpreted by Avi Controller as 3.
- max_password_history_count:
- description:
- - Maximum number of passwords to be maintained in the password history.
- - Default is 4 passwords.
- - Default value when not specified in API or module is interpreted by Avi Controller as 4.
- name:
- description:
- - Name of the object.
- required: true
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create UserAccountProfile object
- avi_useraccountprofile:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_useraccountprofile
-"""
-
-RETURN = '''
-obj:
- description: UserAccountProfile (api/useraccountprofile) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- account_lock_timeout=dict(type='int',),
- credentials_timeout_threshold=dict(type='int',),
- max_concurrent_sessions=dict(type='int',),
- max_login_failure_count=dict(type='int',),
- max_password_history_count=dict(type='int',),
- name=dict(type='str', required=True),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'useraccountprofile',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_virtualservice.py b/plugins/modules/network/avi/avi_virtualservice.py
deleted file mode 100644
index 026855920c..0000000000
--- a/plugins/modules/network/avi/avi_virtualservice.py
+++ /dev/null
@@ -1,653 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_virtualservice
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of VirtualService Avi RESTful Object
-description:
- - This module is used to configure VirtualService object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- active_standby_se_tag:
- description:
- - This configuration only applies if the virtualservice is in legacy active standby ha mode and load distribution among active standby is enabled.
- - This field is used to tag the virtualservice so that virtualservices with the same tag will share the same active serviceengine.
- - Virtualservices with different tags will have different active serviceengines.
- - If one of the serviceengine's in the serviceenginegroup fails, all virtualservices will end up using the same active serviceengine.
- - Redistribution of the virtualservices can be either manual or automated when the failed serviceengine recovers.
- - Redistribution is based on the auto redistribute property of the serviceenginegroup.
- - Enum options - ACTIVE_STANDBY_SE_1, ACTIVE_STANDBY_SE_2.
- - Default value when not specified in API or module is interpreted by Avi Controller as ACTIVE_STANDBY_SE_1.
- allow_invalid_client_cert:
- description:
- - Process request even if invalid client certificate is presented.
- - Datascript apis need to be used for processing of such requests.
- - Field introduced in 18.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- analytics_policy:
- description:
- - Determines analytics settings for the application.
- analytics_profile_ref:
- description:
- - Specifies settings related to analytics.
- - It is a reference to an object of type analyticsprofile.
- apic_contract_graph:
- description:
- - The name of the contract/graph associated with the virtual service.
- - Should be in the format.
- - This is applicable only for service integration mode with cisco apic controller.
- - Field introduced in 17.2.12,18.1.2.
- application_profile_ref:
- description:
- - Enable application layer specific features for the virtual service.
- - It is a reference to an object of type applicationprofile.
- auto_allocate_floating_ip:
- description:
- - Auto-allocate floating/elastic ip from the cloud infrastructure.
- - Field deprecated in 17.1.1.
- type: bool
- auto_allocate_ip:
- description:
- - Auto-allocate vip from the provided subnet.
- - Field deprecated in 17.1.1.
- type: bool
- availability_zone:
- description:
- - Availability-zone to place the virtual service.
- - Field deprecated in 17.1.1.
- avi_allocated_fip:
- description:
- - (internal-use) fip allocated by avi in the cloud infrastructure.
- - Field deprecated in 17.1.1.
- type: bool
- avi_allocated_vip:
- description:
- - (internal-use) vip allocated by avi in the cloud infrastructure.
- - Field deprecated in 17.1.1.
- type: bool
- azure_availability_set:
- description:
- - (internal-use)applicable for azure only.
- - Azure availability set to which this vs is associated.
- - Internally set by the cloud connector.
- - Field introduced in 17.2.12, 18.1.2.
- bulk_sync_kvcache:
- description:
- - (this is a beta feature).
- - Sync key-value cache to the new ses when vs is scaled out.
- - For ex ssl sessions are stored using vs's key-value cache.
- - When the vs is scaled out, the ssl session information is synced to the new se, allowing existing ssl sessions to be reused on the new se.
- - Field introduced in 17.2.7, 18.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- client_auth:
- description:
- - Http authentication configuration for protected resources.
- close_client_conn_on_config_update:
- description:
- - Close client connection on vs config update.
- - Field introduced in 17.2.4.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- cloud_config_cksum:
- description:
- - Checksum of cloud configuration for vs.
- - Internally set by cloud connector.
- cloud_ref:
- description:
- - It is a reference to an object of type cloud.
- cloud_type:
- description:
- - Enum options - cloud_none, cloud_vcenter, cloud_openstack, cloud_aws, cloud_vca, cloud_apic, cloud_mesos, cloud_linuxserver, cloud_docker_ucp,
- - cloud_rancher, cloud_oshift_k8s, cloud_azure, cloud_gcp.
- - Default value when not specified in API or module is interpreted by Avi Controller as CLOUD_NONE.
- connections_rate_limit:
- description:
- - Rate limit the incoming connections to this virtual service.
- content_rewrite:
- description:
- - Profile used to match and rewrite strings in request and/or response body.
- created_by:
- description:
- - Creator name.
- delay_fairness:
- description:
- - Select the algorithm for qos fairness.
- - This determines how multiple virtual services sharing the same service engines will prioritize traffic over a congested network.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- description:
- description:
- - User defined description for the object.
- discovered_network_ref:
- description:
- - (internal-use) discovered networks providing reachability for client facing virtual service ip.
- - This field is deprecated.
- - It is a reference to an object of type network.
- - Field deprecated in 17.1.1.
- discovered_networks:
- description:
- - (internal-use) discovered networks providing reachability for client facing virtual service ip.
- - This field is used internally by avi, not editable by the user.
- - Field deprecated in 17.1.1.
- discovered_subnet:
- description:
- - (internal-use) discovered subnets providing reachability for client facing virtual service ip.
- - This field is deprecated.
- - Field deprecated in 17.1.1.
- dns_info:
- description:
- - Service discovery specific data including fully qualified domain name, type and time-to-live of the dns record.
- - Note that only one of fqdn and dns_info setting is allowed.
- dns_policies:
- description:
- - Dns policies applied on the dns traffic of the virtual service.
- - Field introduced in 17.1.1.
- east_west_placement:
- description:
- - Force placement on all se's in service group (mesos mode only).
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- enable_autogw:
- description:
- - Response traffic to clients will be sent back to the source mac address of the connection, rather than statically sent to a default gateway.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- enable_rhi:
- description:
- - Enable route health injection using the bgp config in the vrf context.
- type: bool
- enable_rhi_snat:
- description:
- - Enable route health injection for source nat'ted floating ip address using the bgp config in the vrf context.
- type: bool
- enabled:
- description:
- - Enable or disable the virtual service.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- error_page_profile_ref:
- description:
- - Error page profile to be used for this virtualservice.this profile is used to send the custom error page to the client generated by the proxy.
- - It is a reference to an object of type errorpageprofile.
- - Field introduced in 17.2.4.
- floating_ip:
- description:
- - Floating ip to associate with this virtual service.
- - Field deprecated in 17.1.1.
- floating_subnet_uuid:
- description:
- - If auto_allocate_floating_ip is true and more than one floating-ip subnets exist, then the subnet for the floating ip address allocation.
- - This field is applicable only if the virtualservice belongs to an openstack or aws cloud.
- - In openstack or aws cloud it is required when auto_allocate_floating_ip is selected.
- - Field deprecated in 17.1.1.
- flow_dist:
- description:
- - Criteria for flow distribution among ses.
- - Enum options - LOAD_AWARE, CONSISTENT_HASH_SOURCE_IP_ADDRESS, CONSISTENT_HASH_SOURCE_IP_ADDRESS_AND_PORT.
- - Default value when not specified in API or module is interpreted by Avi Controller as LOAD_AWARE.
- flow_label_type:
- description:
- - Criteria for flow labelling.
- - Enum options - NO_LABEL, APPLICATION_LABEL, SERVICE_LABEL.
- - Default value when not specified in API or module is interpreted by Avi Controller as NO_LABEL.
- fqdn:
- description:
- - Dns resolvable, fully qualified domain name of the virtualservice.
- - Only one of 'fqdn' and 'dns_info' configuration is allowed.
- host_name_xlate:
- description:
- - Translate the host name sent to the servers to this value.
- - Translate the host name sent from servers back to the value used by the client.
- http_policies:
- description:
- - Http policies applied on the data traffic of the virtual service.
- ign_pool_net_reach:
- description:
- - Ignore pool servers network reachability constraints for virtual service placement.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- ip_address:
- description:
- - Ip address of the virtual service.
- - Field deprecated in 17.1.1.
- ipam_network_subnet:
- description:
- - Subnet and/or network for allocating virtualservice ip by ipam provider module.
- - Field deprecated in 17.1.1.
- l4_policies:
- description:
- - L4 policies applied to the data traffic of the virtual service.
- - Field introduced in 17.2.7.
- limit_doser:
- description:
- - Limit potential dos attackers who exceed max_cps_per_client significantly to a fraction of max_cps_per_client for a while.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- max_cps_per_client:
- description:
- - Maximum connections per second per client ip.
- - Allowed values are 10-1000.
- - Special values are 0- 'unlimited'.
- - Default value when not specified in API or module is interpreted by Avi Controller as 0.
- microservice_ref:
- description:
- - Microservice representing the virtual service.
- - It is a reference to an object of type microservice.
- min_pools_up:
- description:
- - Minimum number of up pools to mark vs up.
- - Field introduced in 18.2.1, 17.2.12.
- name:
- description:
- - Name for the virtual service.
- required: true
- network_profile_ref:
- description:
- - Determines network settings such as protocol, tcp or udp, and related options for the protocol.
- - It is a reference to an object of type networkprofile.
- network_ref:
- description:
- - Manually override the network on which the virtual service is placed.
- - It is a reference to an object of type network.
- - Field deprecated in 17.1.1.
- network_security_policy_ref:
- description:
- - Network security policies for the virtual service.
- - It is a reference to an object of type networksecuritypolicy.
- nsx_securitygroup:
- description:
- - A list of nsx service groups representing the clients which can access the virtual ip of the virtual service.
- - Field introduced in 17.1.1.
- performance_limits:
- description:
- - Optional settings that determine performance limits like max connections or bandwidth etc.
- pool_group_ref:
- description:
- - The pool group is an object that contains pools.
- - It is a reference to an object of type poolgroup.
- pool_ref:
- description:
- - The pool is an object that contains destination servers and related attributes such as load-balancing and persistence.
- - It is a reference to an object of type pool.
- port_uuid:
- description:
- - (internal-use) network port assigned to the virtual service ip address.
- - Field deprecated in 17.1.1.
- remove_listening_port_on_vs_down:
- description:
- - Remove listening port if virtualservice is down.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- requests_rate_limit:
- description:
- - Rate limit the incoming requests to this virtual service.
- saml_sp_config:
- description:
- - Application-specific saml config.
- - Field introduced in 18.2.3.
- scaleout_ecmp:
- description:
- - Disable re-distribution of flows across service engines for a virtual service.
- - Enable if the network itself performs flow hashing with ecmp in environments such as gcp.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- se_group_ref:
- description:
- - The service engine group to use for this virtual service.
- - Moving to a new se group is disruptive to existing connections for this vs.
- - It is a reference to an object of type serviceenginegroup.
- security_policy_ref:
- description:
- - Security policy applied on the traffic of the virtual service.
- - This policy is used to perform security actions such as distributed denial of service (ddos) attack mitigation, etc.
- - It is a reference to an object of type securitypolicy.
- - Field introduced in 18.2.1.
- server_network_profile_ref:
- description:
- - Determines the network settings profile for the server side of tcp proxied connections.
- - Leave blank to use the same settings as the client to vs side of the connection.
- - It is a reference to an object of type networkprofile.
- service_metadata:
- description:
- - Metadata pertaining to the service provided by this virtual service.
- - In openshift/kubernetes environments, egress pod info is stored.
- - Any user input to this field will be overwritten by avi vantage.
- service_pool_select:
- description:
- - Select pool based on destination port.
- services:
- description:
- - List of services defined for this virtual service.
- sideband_profile:
- description:
- - Sideband configuration to be used for this virtualservice.it can be used for sending traffic to sideband vips for external inspection etc.
- snat_ip:
- description:
- - Nat'ted floating source ip address(es) for upstream connection to servers.
- sp_pool_refs:
- description:
- - Gslb pools used to manage site-persistence functionality.
- - Each site-persistence pool contains the virtualservices in all the other sites, that is auto-generated by the gslb manager.
- - This is a read-only field for the user.
- - It is a reference to an object of type pool.
- - Field introduced in 17.2.2.
- ssl_key_and_certificate_refs:
- description:
- - Select or create one or two certificates, ec and/or rsa, that will be presented to ssl/tls terminated connections.
- - It is a reference to an object of type sslkeyandcertificate.
- ssl_profile_ref:
- description:
- - Determines the set of ssl versions and ciphers to accept for ssl/tls terminated connections.
- - It is a reference to an object of type sslprofile.
- ssl_profile_selectors:
- description:
- - Select ssl profile based on client ip address match.
- - Field introduced in 18.2.3.
- ssl_sess_cache_avg_size:
- description:
- - Expected number of ssl session cache entries (may be exceeded).
- - Allowed values are 1024-16383.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1024.
- sso_policy:
- description:
- - Client authentication and authorization policy for the virtualservice.
- - Field deprecated in 18.2.3.
- - Field introduced in 18.2.1.
- sso_policy_ref:
- description:
- - The sso policy attached to the virtualservice.
- - It is a reference to an object of type ssopolicy.
- - Field introduced in 18.2.3.
- static_dns_records:
- description:
- - List of static dns records applied to this virtual service.
- - These are static entries and no health monitoring is performed against the ip addresses.
- subnet:
- description:
- - Subnet providing reachability for client facing virtual service ip.
- - Field deprecated in 17.1.1.
- subnet_uuid:
- description:
- - It represents subnet for the virtual service ip address allocation when auto_allocate_ip is true.it is only applicable in openstack or aws cloud.
- - This field is required if auto_allocate_ip is true.
- - Field deprecated in 17.1.1.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- topology_policies:
- description:
- - Topology policies applied on the dns traffic of the virtual service based ongslb topology algorithm.
- - Field introduced in 18.2.3.
- traffic_clone_profile_ref:
- description:
- - Server network or list of servers for cloning traffic.
- - It is a reference to an object of type trafficcloneprofile.
- - Field introduced in 17.1.1.
- traffic_enabled:
- description:
- - Knob to enable the virtual service traffic on its assigned service engines.
- - This setting is effective only when the enabled flag is set to true.
- - Field introduced in 17.2.8.
- - Default value when not specified in API or module is interpreted by Avi Controller as True.
- type: bool
- type:
- description:
- - Specify if this is a normal virtual service, or if it is the parent or child of an sni-enabled virtual hosted virtual service.
- - Enum options - VS_TYPE_NORMAL, VS_TYPE_VH_PARENT, VS_TYPE_VH_CHILD.
- - Default value when not specified in API or module is interpreted by Avi Controller as VS_TYPE_NORMAL.
- url:
- description:
- - Avi controller URL of the object.
- use_bridge_ip_as_vip:
- description:
- - Use bridge ip as vip on each host in mesos deployments.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- use_vip_as_snat:
- description:
- - Use the virtual ip as the snat ip for health monitoring and sending traffic to the backend servers instead of the service engine interface ip.
- - The caveat of enabling this option is that the virtualservice cannot be configued in an active-active ha mode.
- - Dns based multi vip solution has to be used for ha & non-disruptive upgrade purposes.
- - Field introduced in 17.1.9,17.2.3.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- uuid:
- description:
- - Uuid of the virtualservice.
- vh_domain_name:
- description:
- - The exact name requested from the client's sni-enabled tls hello domain name field.
- - If this is a match, the parent vs will forward the connection to this child vs.
- vh_parent_vs_uuid:
- description:
- - Specifies the virtual service acting as virtual hosting (sni) parent.
- vip:
- description:
- - List of virtual service ips.
- - While creating a 'shared vs',please use vsvip_ref to point to the shared entities.
- - Field introduced in 17.1.1.
- vrf_context_ref:
- description:
- - Virtual routing context that the virtual service is bound to.
- - This is used to provide the isolation of the set of networks the application is attached to.
- - It is a reference to an object of type vrfcontext.
- vs_datascripts:
- description:
- - Datascripts applied on the data traffic of the virtual service.
- vsvip_cloud_config_cksum:
- description:
- - Checksum of cloud configuration for vsvip.
- - Internally set by cloud connector.
- - Field introduced in 17.2.9, 18.1.2.
- vsvip_ref:
- description:
- - Mostly used during the creation of shared vs, this field refers to entities that can be shared across virtual services.
- - It is a reference to an object of type vsvip.
- - Field introduced in 17.1.1.
- waf_policy_ref:
- description:
- - Waf policy for the virtual service.
- - It is a reference to an object of type wafpolicy.
- - Field introduced in 17.2.1.
- weight:
- description:
- - The quality of service weight to assign to traffic transmitted from this virtual service.
- - A higher weight will prioritize traffic versus other virtual services sharing the same service engines.
- - Allowed values are 1-128.
- - Default value when not specified in API or module is interpreted by Avi Controller as 1.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Create SSL Virtual Service using Pool testpool2
- avi_virtualservice:
- controller: 10.10.27.90
- username: admin
- password: AviNetworks123!
- name: newtestvs
- state: present
- performance_limits:
- max_concurrent_connections: 1000
- services:
- - port: 443
- enable_ssl: true
- - port: 80
- ssl_profile_ref: '/api/sslprofile?name=System-Standard'
- application_profile_ref: '/api/applicationprofile?name=System-Secure-HTTP'
- ssl_key_and_certificate_refs:
- - '/api/sslkeyandcertificate?name=System-Default-Cert'
- ip_address:
- addr: 10.90.131.103
- type: V4
- pool_ref: '/api/pool?name=testpool2'
-"""
-
-RETURN = '''
-obj:
- description: VirtualService (api/virtualservice) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- active_standby_se_tag=dict(type='str',),
- allow_invalid_client_cert=dict(type='bool',),
- analytics_policy=dict(type='dict',),
- analytics_profile_ref=dict(type='str',),
- apic_contract_graph=dict(type='str',),
- application_profile_ref=dict(type='str',),
- auto_allocate_floating_ip=dict(type='bool',),
- auto_allocate_ip=dict(type='bool',),
- availability_zone=dict(type='str',),
- avi_allocated_fip=dict(type='bool',),
- avi_allocated_vip=dict(type='bool',),
- azure_availability_set=dict(type='str',),
- bulk_sync_kvcache=dict(type='bool',),
- client_auth=dict(type='dict',),
- close_client_conn_on_config_update=dict(type='bool',),
- cloud_config_cksum=dict(type='str',),
- cloud_ref=dict(type='str',),
- cloud_type=dict(type='str',),
- connections_rate_limit=dict(type='dict',),
- content_rewrite=dict(type='dict',),
- created_by=dict(type='str',),
- delay_fairness=dict(type='bool',),
- description=dict(type='str',),
- discovered_network_ref=dict(type='list',),
- discovered_networks=dict(type='list',),
- discovered_subnet=dict(type='list',),
- dns_info=dict(type='list',),
- dns_policies=dict(type='list',),
- east_west_placement=dict(type='bool',),
- enable_autogw=dict(type='bool',),
- enable_rhi=dict(type='bool',),
- enable_rhi_snat=dict(type='bool',),
- enabled=dict(type='bool',),
- error_page_profile_ref=dict(type='str',),
- floating_ip=dict(type='dict',),
- floating_subnet_uuid=dict(type='str',),
- flow_dist=dict(type='str',),
- flow_label_type=dict(type='str',),
- fqdn=dict(type='str',),
- host_name_xlate=dict(type='str',),
- http_policies=dict(type='list',),
- ign_pool_net_reach=dict(type='bool',),
- ip_address=dict(type='dict',),
- ipam_network_subnet=dict(type='dict',),
- l4_policies=dict(type='list',),
- limit_doser=dict(type='bool',),
- max_cps_per_client=dict(type='int',),
- microservice_ref=dict(type='str',),
- min_pools_up=dict(type='int',),
- name=dict(type='str', required=True),
- network_profile_ref=dict(type='str',),
- network_ref=dict(type='str',),
- network_security_policy_ref=dict(type='str',),
- nsx_securitygroup=dict(type='list',),
- performance_limits=dict(type='dict',),
- pool_group_ref=dict(type='str',),
- pool_ref=dict(type='str',),
- port_uuid=dict(type='str',),
- remove_listening_port_on_vs_down=dict(type='bool',),
- requests_rate_limit=dict(type='dict',),
- saml_sp_config=dict(type='dict',),
- scaleout_ecmp=dict(type='bool',),
- se_group_ref=dict(type='str',),
- security_policy_ref=dict(type='str',),
- server_network_profile_ref=dict(type='str',),
- service_metadata=dict(type='str',),
- service_pool_select=dict(type='list',),
- services=dict(type='list',),
- sideband_profile=dict(type='dict',),
- snat_ip=dict(type='list',),
- sp_pool_refs=dict(type='list',),
- ssl_key_and_certificate_refs=dict(type='list',),
- ssl_profile_ref=dict(type='str',),
- ssl_profile_selectors=dict(type='list',),
- ssl_sess_cache_avg_size=dict(type='int',),
- sso_policy=dict(type='dict',),
- sso_policy_ref=dict(type='str',),
- static_dns_records=dict(type='list',),
- subnet=dict(type='dict',),
- subnet_uuid=dict(type='str',),
- tenant_ref=dict(type='str',),
- topology_policies=dict(type='list',),
- traffic_clone_profile_ref=dict(type='str',),
- traffic_enabled=dict(type='bool',),
- type=dict(type='str',),
- url=dict(type='str',),
- use_bridge_ip_as_vip=dict(type='bool',),
- use_vip_as_snat=dict(type='bool',),
- uuid=dict(type='str',),
- vh_domain_name=dict(type='list',),
- vh_parent_vs_uuid=dict(type='str',),
- vip=dict(type='list',),
- vrf_context_ref=dict(type='str',),
- vs_datascripts=dict(type='list',),
- vsvip_cloud_config_cksum=dict(type='str',),
- vsvip_ref=dict(type='str',),
- waf_policy_ref=dict(type='str',),
- weight=dict(type='int',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'virtualservice',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_vrfcontext.py b/plugins/modules/network/avi/avi_vrfcontext.py
deleted file mode 100644
index 2f57f0399c..0000000000
--- a/plugins/modules/network/avi/avi_vrfcontext.py
+++ /dev/null
@@ -1,145 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.2
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_vrfcontext
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of VrfContext Avi RESTful Object
-description:
- - This module is used to configure VrfContext object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- bgp_profile:
- description:
- - Bgp local and peer info.
- cloud_ref:
- description:
- - It is a reference to an object of type cloud.
- debugvrfcontext:
- description:
- - Configure debug flags for vrf.
- - Field introduced in 17.1.1.
- description:
- description:
- - User defined description for the object.
- gateway_mon:
- description:
- - Configure ping based heartbeat check for gateway in service engines of vrf.
- internal_gateway_monitor:
- description:
- - Configure ping based heartbeat check for all default gateways in service engines of vrf.
- - Field introduced in 17.1.1.
- name:
- description:
- - Name of the object.
- required: true
- static_routes:
- description:
- - List of staticroute.
- system_default:
- description:
- - Boolean flag to set system_default.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Unique object identifier of the object.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create VrfContext object
- avi_vrfcontext:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_vrfcontext
-"""
-
-RETURN = '''
-obj:
- description: VrfContext (api/vrfcontext) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- bgp_profile=dict(type='dict',),
- cloud_ref=dict(type='str',),
- debugvrfcontext=dict(type='dict',),
- description=dict(type='str',),
- gateway_mon=dict(type='list',),
- internal_gateway_monitor=dict(type='dict',),
- name=dict(type='str', required=True),
- static_routes=dict(type='list',),
- system_default=dict(type='bool',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'vrfcontext',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_vsdatascriptset.py b/plugins/modules/network/avi/avi_vsdatascriptset.py
deleted file mode 100644
index 07115c2c11..0000000000
--- a/plugins/modules/network/avi/avi_vsdatascriptset.py
+++ /dev/null
@@ -1,148 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.1
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_vsdatascriptset
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of VSDataScriptSet Avi RESTful Object
-description:
- - This module is used to configure VSDataScriptSet object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- created_by:
- description:
- - Creator name.
- - Field introduced in 17.1.11,17.2.4.
- datascript:
- description:
- - Datascripts to execute.
- description:
- description:
- - User defined description for the object.
- ipgroup_refs:
- description:
- - Uuid of ip groups that could be referred by vsdatascriptset objects.
- - It is a reference to an object of type ipaddrgroup.
- name:
- description:
- - Name for the virtual service datascript collection.
- required: true
- pool_group_refs:
- description:
- - Uuid of pool groups that could be referred by vsdatascriptset objects.
- - It is a reference to an object of type poolgroup.
- pool_refs:
- description:
- - Uuid of pools that could be referred by vsdatascriptset objects.
- - It is a reference to an object of type pool.
- protocol_parser_refs:
- description:
- - List of protocol parsers that could be referred by vsdatascriptset objects.
- - It is a reference to an object of type protocolparser.
- - Field introduced in 18.2.3.
- string_group_refs:
- description:
- - Uuid of string groups that could be referred by vsdatascriptset objects.
- - It is a reference to an object of type stringgroup.
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the virtual service datascript collection.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create VSDataScriptSet object
- avi_vsdatascriptset:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_vsdatascriptset
-"""
-
-RETURN = '''
-obj:
- description: VSDataScriptSet (api/vsdatascriptset) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- created_by=dict(type='str',),
- datascript=dict(type='list',),
- description=dict(type='str',),
- ipgroup_refs=dict(type='list',),
- name=dict(type='str', required=True),
- pool_group_refs=dict(type='list',),
- pool_refs=dict(type='list',),
- protocol_parser_refs=dict(type='list',),
- string_group_refs=dict(type='list',),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'vsdatascriptset',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_vsvip.py b/plugins/modules/network/avi/avi_vsvip.py
deleted file mode 100644
index fc54b3f11b..0000000000
--- a/plugins/modules/network/avi/avi_vsvip.py
+++ /dev/null
@@ -1,155 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-# Avi Version: 17.1.2
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_vsvip
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of VsVip Avi RESTful Object
-description:
- - This module is used to configure VsVip object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- cloud_ref:
- description:
- - It is a reference to an object of type cloud.
- - Field introduced in 17.1.1.
- dns_info:
- description:
- - Service discovery specific data including fully qualified domain name, type and time-to-live of the dns record.
- - Field introduced in 17.1.1.
- east_west_placement:
- description:
- - Force placement on all service engines in the service engine group (container clouds only).
- - Field introduced in 17.1.1.
- - Default value when not specified in API or module is interpreted by Avi Controller as False.
- type: bool
- name:
- description:
- - Name for the vsvip object.
- - Field introduced in 17.1.1.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- - Field introduced in 17.1.1.
- url:
- description:
- - Avi controller URL of the object.
- use_standard_alb:
- description:
- - This overrides the cloud level default and needs to match the se group value in which it will be used if the se group use_standard_alb value is
- - set.
- - This is only used when fip is used for vs on azure cloud.
- - Field introduced in 18.2.3.
- type: bool
- uuid:
- description:
- - Uuid of the vsvip object.
- - Field introduced in 17.1.1.
- vip:
- description:
- - List of virtual service ips and other shareable entities.
- - Field introduced in 17.1.1.
- vrf_context_ref:
- description:
- - Virtual routing context that the virtual service is bound to.
- - This is used to provide the isolation of the set of networks the application is attached to.
- - It is a reference to an object of type vrfcontext.
- - Field introduced in 17.1.1.
- vsvip_cloud_config_cksum:
- description:
- - Checksum of cloud configuration for vsvip.
- - Internally set by cloud connector.
- - Field introduced in 17.2.9, 18.1.2.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create VsVip object
- avi_vsvip:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_vsvip
-"""
-
-RETURN = '''
-obj:
- description: VsVip (api/vsvip) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- cloud_ref=dict(type='str',),
- dns_info=dict(type='list',),
- east_west_placement=dict(type='bool',),
- name=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- use_standard_alb=dict(type='bool',),
- uuid=dict(type='str',),
- vip=dict(type='list',),
- vrf_context_ref=dict(type='str',),
- vsvip_cloud_config_cksum=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'vsvip',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/avi/avi_webhook.py b/plugins/modules/network/avi/avi_webhook.py
deleted file mode 100644
index e42b8a5cbf..0000000000
--- a/plugins/modules/network/avi/avi_webhook.py
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/usr/bin/python
-#
-# @author: Gaurav Rastogi (grastogi@avinetworks.com)
-# Eric Anderson (eanderson@avinetworks.com)
-# module_check: supported
-#
-# Copyright: (c) 2017 Gaurav Rastogi,
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: avi_webhook
-author: Gaurav Rastogi (@grastogi23)
-
-short_description: Module for setup of Webhook Avi RESTful Object
-description:
- - This module is used to configure Webhook object
- - more examples at U(https://github.com/avinetworks/devops)
-requirements: [ avisdk ]
-options:
- state:
- description:
- - The state that should be applied on the entity.
- default: present
- choices: ["absent", "present"]
- avi_api_update_method:
- description:
- - Default method for object update is HTTP PUT.
- - Setting to patch will override that behavior to use HTTP PATCH.
- default: put
- choices: ["put", "patch"]
- avi_api_patch_op:
- description:
- - Patch operation to use when using avi_api_update_method as patch.
- choices: ["add", "replace", "delete"]
- callback_url:
- description:
- - Callback url for the webhook.
- - Field introduced in 17.1.1.
- description:
- description:
- - Field introduced in 17.1.1.
- name:
- description:
- - The name of the webhook profile.
- - Field introduced in 17.1.1.
- required: true
- tenant_ref:
- description:
- - It is a reference to an object of type tenant.
- - Field introduced in 17.1.1.
- url:
- description:
- - Avi controller URL of the object.
- uuid:
- description:
- - Uuid of the webhook profile.
- - Field introduced in 17.1.1.
- verification_token:
- description:
- - Verification token sent back with the callback asquery parameters.
- - Field introduced in 17.1.1.
-extends_documentation_fragment:
-- community.general.avi
-
-'''
-
-EXAMPLES = """
-- name: Example to create Webhook object
- avi_webhook:
- controller: 10.10.25.42
- username: admin
- password: something
- state: present
- name: sample_webhook
-"""
-
-RETURN = '''
-obj:
- description: Webhook (api/webhook) object
- returned: success, changed
- type: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-try:
- from ansible_collections.community.general.plugins.module_utils.network.avi.avi import (
- avi_common_argument_spec, avi_ansible_api, HAS_AVI)
-except ImportError:
- HAS_AVI = False
-
-
-def main():
- argument_specs = dict(
- state=dict(default='present',
- choices=['absent', 'present']),
- avi_api_update_method=dict(default='put',
- choices=['put', 'patch']),
- avi_api_patch_op=dict(choices=['add', 'replace', 'delete']),
- callback_url=dict(type='str',),
- description=dict(type='str',),
- name=dict(type='str', required=True),
- tenant_ref=dict(type='str',),
- url=dict(type='str',),
- uuid=dict(type='str',),
- verification_token=dict(type='str',),
- )
- argument_specs.update(avi_common_argument_spec())
- module = AnsibleModule(
- argument_spec=argument_specs, supports_check_mode=True)
- if not HAS_AVI:
- return module.fail_json(msg=(
- 'Avi python API SDK (avisdk>=17.1) or requests is not installed. '
- 'For more details visit https://github.com/avinetworks/sdk.'))
- return avi_ansible_api(module, 'webhook',
- set([]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/bigswitch/bcf_switch.py b/plugins/modules/network/bigswitch/bcf_switch.py
deleted file mode 100644
index dedabc8cce..0000000000
--- a/plugins/modules/network/bigswitch/bcf_switch.py
+++ /dev/null
@@ -1,161 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Ted Elhourani
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: bcf_switch
-author: "Ted (@tedelhourani)"
-short_description: Create and remove a bcf switch.
-description:
- - Create and remove a Big Cloud Fabric switch.
-options:
- name:
- description:
- - The name of the switch.
- required: true
- fabric_role:
- description:
- - Fabric role of the switch.
- choices: ['spine', 'leaf']
- required: true
- leaf_group:
- description:
- - The leaf group of the switch if the switch is a leaf.
- required: false
- mac:
- description:
- - The MAC address of the switch.
- required: true
- state:
- description:
- - Whether the switch should be present or absent.
- default: present
- choices: ['present', 'absent']
- controller:
- description:
- - The controller IP address.
- required: true
- validate_certs:
- description:
- - If C(false), SSL certificates will not be validated. This should only be used
- on personally controlled devices using self-signed certificates.
- required: false
- default: true
- type: bool
- access_token:
- description:
- - Big Cloud Fabric access token. If this isn't set then the environment variable C(BIGSWITCH_ACCESS_TOKEN) is used.
-'''
-
-
-EXAMPLES = '''
-- name: bcf leaf switch
- bcf_switch:
- name: Rack1Leaf1
- fabric_role: leaf
- leaf_group: R1
- mac: 00:00:00:02:00:02
- controller: '{{ inventory_hostname }}'
- state: present
- validate_certs: false
-'''
-
-
-RETURN = ''' # '''
-
-import os
-import traceback
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.bigswitch.bigswitch import Rest
-from ansible.module_utils._text import to_native
-
-
-def switch(module, check_mode):
- try:
- access_token = module.params['access_token'] or os.environ['BIGSWITCH_ACCESS_TOKEN']
- except KeyError as e:
- module.fail_json(msg='Unable to load %s' % e.message, exception=traceback.format_exc())
-
- name = module.params['name']
- fabric_role = module.params['fabric_role']
- leaf_group = module.params['leaf_group']
- dpid = '00:00:' + module.params['mac']
- state = module.params['state']
- controller = module.params['controller']
-
- rest = Rest(module,
- {'content-type': 'application/json', 'Cookie': 'session_cookie=' + access_token},
- 'https://' + controller + ':8443/api/v1/data/controller/core')
-
- response = rest.get('switch-config', data={})
- if response.status_code != 200:
- module.fail_json(msg="failed to obtain existing switch config: {0}".format(response.json['description']))
-
- config_present = False
- for switch in response.json:
- if all((switch['name'] == name,
- switch['fabric-role'] == fabric_role,
- switch['dpid'] == dpid)):
- config_present = switch.get('leaf-group', None) == leaf_group
- if config_present:
- break
-
- if state in ('present') and config_present:
- module.exit_json(changed=False)
-
- if state in ('absent') and not config_present:
- module.exit_json(changed=False)
-
- if check_mode:
- module.exit_json(changed=True)
-
- if state in ('present'):
- data = {'name': name, 'fabric-role': fabric_role, 'leaf-group': leaf_group, 'dpid': dpid}
- response = rest.put('switch-config[name="%s"]' % name, data)
- if response.status_code == 204:
- module.exit_json(changed=True)
- else:
- module.fail_json(msg="error configuring switch '{0}': {1}".format(name, response.json['description']))
-
- if state in ('absent'):
- response = rest.delete('switch-config[name="%s"]' % name, data={})
- if response.status_code == 204:
- module.exit_json(changed=True)
- else:
- module.fail_json(msg="error deleting switch '{0}': {1}".format(name, response.json['description']))
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- name=dict(type='str', required=True),
- fabric_role=dict(choices=['spine', 'leaf'], required=True),
- leaf_group=dict(type='str', required=False),
- mac=dict(type='str', required=True),
- controller=dict(type='str', required=True),
- state=dict(choices=['present', 'absent'], default='present'),
- validate_certs=dict(type='bool', default='True'),
- access_token=dict(type='str', no_log=True)
- ),
- supports_check_mode=True,
- )
-
- try:
- switch(module, check_mode=module.check_mode)
- except Exception as e:
- module.fail_json(msg=to_native(e), exception=traceback.format_exc())
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/bigswitch/bigmon_chain.py b/plugins/modules/network/bigswitch/bigmon_chain.py
deleted file mode 100644
index 67428b257c..0000000000
--- a/plugins/modules/network/bigswitch/bigmon_chain.py
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2016, Ted Elhourani
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# Ansible module to manage Big Monitoring Fabric service chains
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: bigmon_chain
-author: "Ted (@tedelhourani)"
-short_description: Create and remove a bigmon inline service chain.
-description:
- - Create and remove a bigmon inline service chain.
-options:
- name:
- description:
- - The name of the chain.
- required: true
- state:
- description:
- - Whether the service chain should be present or absent.
- default: present
- choices: ['present', 'absent']
- controller:
- description:
- - The controller IP address.
- required: true
- validate_certs:
- description:
- - If C(false), SSL certificates will not be validated. This should only be used
- on personally controlled devices using self-signed certificates.
- required: false
- default: true
- type: bool
- access_token:
- description:
- - Bigmon access token. If this isn't set, the environment variable C(BIGSWITCH_ACCESS_TOKEN) is used.
-'''
-
-
-EXAMPLES = '''
-- name: bigmon inline service chain
- bigmon_chain:
- name: MyChain
- controller: '{{ inventory_hostname }}'
- state: present
- validate_certs: false
-'''
-
-
-RETURN = ''' # '''
-
-import os
-import traceback
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.bigswitch.bigswitch import Rest
-from ansible.module_utils._text import to_native
-
-
-def chain(module):
- try:
- access_token = module.params['access_token'] or os.environ['BIGSWITCH_ACCESS_TOKEN']
- except KeyError as e:
- module.fail_json(msg='Unable to load %s' % e.message, exception=traceback.format_exc())
-
- name = module.params['name']
- state = module.params['state']
- controller = module.params['controller']
-
- rest = Rest(module,
- {'content-type': 'application/json', 'Cookie': 'session_cookie=' + access_token},
- 'https://' + controller + ':8443/api/v1/data/controller/applications/bigchain')
-
- if None in (name, state, controller):
- module.fail_json(msg='parameter `name` is missing')
-
- response = rest.get('chain?config=true', data={})
- if response.status_code != 200:
- module.fail_json(msg="failed to obtain existing chain config: {0}".format(response.json['description']))
-
- config_present = False
- matching = [chain for chain in response.json if chain['name'] == name]
- if matching:
- config_present = True
-
- if state in ('present') and config_present:
- module.exit_json(changed=False)
-
- if state in ('absent') and not config_present:
- module.exit_json(changed=False)
-
- if state in ('present'):
- response = rest.put('chain[name="%s"]' % name, data={'name': name})
- if response.status_code == 204:
- module.exit_json(changed=True)
- else:
- module.fail_json(msg="error creating chain '{0}': {1}".format(name, response.json['description']))
-
- if state in ('absent'):
- response = rest.delete('chain[name="%s"]' % name, data={})
- if response.status_code == 204:
- module.exit_json(changed=True)
- else:
- module.fail_json(msg="error deleting chain '{0}': {1}".format(name, response.json['description']))
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- name=dict(type='str', required=True),
- controller=dict(type='str', required=True),
- state=dict(choices=['present', 'absent'], default='present'),
- validate_certs=dict(type='bool', default='True'),
- access_token=dict(type='str', no_log=True)
- )
- )
-
- try:
- chain(module)
- except Exception as e:
- module.fail_json(msg=to_native(e), exception=traceback.format_exc())
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/bigswitch/bigmon_policy.py b/plugins/modules/network/bigswitch/bigmon_policy.py
deleted file mode 100644
index 421c76f225..0000000000
--- a/plugins/modules/network/bigswitch/bigmon_policy.py
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2016, Ted Elhourani
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# Ansible module to manage Big Monitoring Fabric service chains
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: bigmon_policy
-author: "Ted (@tedelhourani)"
-short_description: Create and remove a bigmon out-of-band policy.
-description:
- - Create and remove a bigmon out-of-band policy.
-options:
- name:
- description:
- - The name of the policy.
- required: true
- policy_description:
- description:
- - Description of policy.
- action:
- description:
- - Forward matching packets to delivery interfaces, Drop is for measure rate of matching packets,
- but do not forward to delivery interfaces, capture packets and write to a PCAP file, or enable NetFlow generation.
- default: forward
- choices: ['forward', 'drop', 'flow-gen']
- priority:
- description:
- - A priority associated with this policy. The higher priority policy takes precedence over a lower priority.
- default: 100
- duration:
- description:
- - Run policy for duration duration or until delivery_packet_count packets are delivered, whichever comes first.
- default: 0
- start_time:
- description:
- - Date the policy becomes active
- default: ansible_date_time.iso8601
- delivery_packet_count:
- description:
- - Run policy until delivery_packet_count packets are delivered.
- default: 0
- state:
- description:
- - Whether the policy should be present or absent.
- default: present
- choices: ['present', 'absent']
- controller:
- description:
- - The controller address.
- required: true
- validate_certs:
- description:
- - If C(false), SSL certificates will not be validated. This should only be used
- on personally controlled devices using self-signed certificates.
- required: false
- default: true
- type: bool
- access_token:
- description:
- - Bigmon access token. If this isn't set, the environment variable C(BIGSWITCH_ACCESS_TOKEN) is used.
-
-'''
-
-EXAMPLES = '''
-- name: policy to aggregate filter and deliver data center (DC) 1 traffic
- bigmon_policy:
- name: policy1
- policy_description: DC 1 traffic policy
- action: drop
- controller: '{{ inventory_hostname }}'
- state: present
- validate_certs: false
-'''
-
-RETURN = ''' # '''
-
-import datetime
-import os
-import traceback
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.bigswitch.bigswitch import Rest
-from ansible.module_utils._text import to_native
-
-
-def policy(module):
- try:
- access_token = module.params['access_token'] or os.environ['BIGSWITCH_ACCESS_TOKEN']
- except KeyError as e:
- module.fail_json(msg='Unable to load %s' % e.message, exception=traceback.format_exc())
-
- name = module.params['name']
- policy_description = module.params['policy_description']
- action = module.params['action']
- priority = module.params['priority']
- duration = module.params['duration']
- start_time = module.params['start_time']
- delivery_packet_count = module.params['delivery_packet_count']
- state = module.params['state']
- controller = module.params['controller']
-
- rest = Rest(module,
- {'content-type': 'application/json', 'Cookie': 'session_cookie=' + access_token},
- 'https://' + controller + ':8443/api/v1/data/controller/applications/bigtap')
-
- if name is None:
- module.fail_json(msg='parameter `name` is missing')
-
- response = rest.get('policy?config=true', data={})
- if response.status_code != 200:
- module.fail_json(msg="failed to obtain existing policy config: {0}".format(response.json['description']))
-
- config_present = False
-
- matching = [policy for policy in response.json
- if policy['name'] == name and
- policy['duration'] == duration and
- policy['delivery-packet-count'] == delivery_packet_count and
- policy['policy-description'] == policy_description and
- policy['action'] == action and
- policy['priority'] == priority]
-
- if matching:
- config_present = True
-
- if state in ('present') and config_present:
- module.exit_json(changed=False)
-
- if state in ('absent') and not config_present:
- module.exit_json(changed=False)
-
- if state in ('present'):
- data = {'name': name, 'action': action, 'policy-description': policy_description,
- 'priority': priority, 'duration': duration, 'start-time': start_time,
- 'delivery-packet-count': delivery_packet_count}
-
- response = rest.put('policy[name="%s"]' % name, data=data)
- if response.status_code == 204:
- module.exit_json(changed=True)
- else:
- module.fail_json(msg="error creating policy '{0}': {1}".format(name, response.json['description']))
-
- if state in ('absent'):
- response = rest.delete('policy[name="%s"]' % name, data={})
- if response.status_code == 204:
- module.exit_json(changed=True)
- else:
- module.fail_json(msg="error deleting policy '{0}': {1}".format(name, response.json['description']))
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- name=dict(type='str', required=True),
- policy_description=dict(type='str', default=''),
- action=dict(choices=['forward', 'drop', 'capture', 'flow-gen'], default='forward'),
- priority=dict(type='int', default=100),
- duration=dict(type='int', default=0),
- start_time=dict(type='str', default=datetime.datetime.now().isoformat() + '+00:00'),
- delivery_packet_count=dict(type='int', default=0),
- controller=dict(type='str', required=True),
- state=dict(choices=['present', 'absent'], default='present'),
- validate_certs=dict(type='bool', default='True'),
- access_token=dict(type='str', no_log=True)
- )
- )
-
- try:
- policy(module)
- except Exception as e:
- module.fail_json(msg=to_native(e), exception=traceback.format_exc())
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/check_point/checkpoint_access_layer_facts.py b/plugins/modules/network/check_point/checkpoint_access_layer_facts.py
deleted file mode 100644
index c18de677e8..0000000000
--- a/plugins/modules/network/check_point/checkpoint_access_layer_facts.py
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'network'}
-
-
-DOCUMENTATION = '''
----
-module: checkpoint_access_layer_facts
-short_description: Get access layer facts on Check Point over Web Services API
-description:
- - Get access layer facts on Check Point devices.
- All operations are performed over Web Services API.
-author: "Ansible by Red Hat (@rcarrillocruz)"
-options:
- uid:
- description:
- - UID of access layer object.
- type: str
- name:
- description:
- - Name of the access layer object.
- type: str
-'''
-
-EXAMPLES = """
-- name: Get object facts
- checkpoint_access_layer_facts:
-"""
-
-RETURN = """
-ansible_facts:
- description: The checkpoint access layer facts.
- returned: always.
- type: list
-"""
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-
-
-def get_access_layer(module, connection):
- uid = module.params['uid']
- name = module.params['name']
-
- payload = {}
-
- if uid:
- payload = {'uid': uid}
- code, result = connection.send_request('/web_api/show-access-layer', payload)
- elif name:
- payload = {'name': name}
- code, result = connection.send_request('/web_api/show-access-layer', payload)
- else:
- code, result = connection.send_request('/web_api/show-access-layers', payload)
-
- return code, result
-
-
-def main():
- argument_spec = dict(
- uid=dict(type='str', default=None),
- name=dict(type='str', default=None)
- )
-
- module = AnsibleModule(argument_spec=argument_spec)
- connection = Connection(module._socket_path)
-
- code, response = get_access_layer(module, connection)
-
- if code == 200:
- module.exit_json(ansible_facts=dict(checkpoint_access_layers=response))
- else:
- module.fail_json(msg='Check Point device returned error {0} with message {1}'.format(code, response))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/check_point/checkpoint_access_rule.py b/plugins/modules/network/check_point/checkpoint_access_rule.py
deleted file mode 100644
index c081734173..0000000000
--- a/plugins/modules/network/check_point/checkpoint_access_rule.py
+++ /dev/null
@@ -1,274 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'network'}
-
-
-DOCUMENTATION = '''
----
-module: checkpoint_access_rule
-short_description: Manages access rules on Check Point over Web Services API
-description:
- - Manages access rules on Check Point devices including creating, updating, removing access rules objects,
- All operations are performed over Web Services API.
-author: "Ansible by Red Hat (@rcarrillocruz)"
-options:
- name:
- description:
- - Name of the access rule.
- type: str
- layer:
- description:
- - Layer to attach the access rule to.
- required: True
- type: str
- position:
- description:
- - Position of the access rule.
- type: str
- source:
- description:
- - Source object of the access rule.
- type: str
- destination:
- description:
- - Destination object of the access rule.
- type: str
- action:
- description:
- - Action of the access rule (accept, drop, inform, etc).
- type: str
- default: drop
- enabled:
- description:
- - Enabled or disabled flag.
- type: bool
- default: True
- state:
- description:
- - State of the access rule (present or absent). Defaults to present.
- type: str
- default: present
- auto_publish_session:
- description:
- - Publish the current session if changes have been performed
- after task completes.
- type: bool
- default: 'yes'
- auto_install_policy:
- description:
- - Install the package policy if changes have been performed
- after the task completes.
- type: bool
- default: 'yes'
- policy_package:
- description:
- - Package policy name to be installed.
- type: str
- default: 'standard'
- targets:
- description:
- - Targets to install the package policy on.
- type: list
-'''
-
-EXAMPLES = """
-- name: Create access rule
- checkpoint_access_rule:
- layer: Network
- name: "Drop attacker"
- position: top
- source: attacker
- destination: Any
- action: Drop
-
-- name: Delete access rule
- checkpoint_access_rule:
- layer: Network
- name: "Drop attacker"
-"""
-
-RETURN = """
-checkpoint_access_rules:
- description: The checkpoint access rule object created or updated.
- returned: always, except when deleting the access rule.
- type: list
-"""
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.check_point.mgmt.plugins.module_utils.checkpoint import checkpoint_argument_spec, publish, install_policy
-
-
-def get_access_rule(module, connection):
- name = module.params['name']
- layer = module.params['layer']
-
- payload = {'name': name, 'layer': layer}
-
- code, response = connection.send_request('/web_api/show-access-rule', payload)
-
- return code, response
-
-
-def create_access_rule(module, connection):
- name = module.params['name']
- layer = module.params['layer']
- position = module.params['position']
- source = module.params['source']
- destination = module.params['destination']
- action = module.params['action']
-
- payload = {'name': name,
- 'layer': layer,
- 'position': position,
- 'source': source,
- 'destination': destination,
- 'action': action}
-
- code, response = connection.send_request('/web_api/add-access-rule', payload)
-
- return code, response
-
-
-def update_access_rule(module, connection):
- name = module.params['name']
- layer = module.params['layer']
- position = module.params['position']
- source = module.params['source']
- destination = module.params['destination']
- action = module.params['action']
- enabled = module.params['enabled']
-
- payload = {'name': name,
- 'layer': layer,
- 'position': position,
- 'source': source,
- 'destination': destination,
- 'action': action,
- 'enabled': enabled}
-
- code, response = connection.send_request('/web_api/set-access-rule', payload)
-
- return code, response
-
-
-def delete_access_rule(module, connection):
- name = module.params['name']
- layer = module.params['layer']
-
- payload = {'name': name,
- 'layer': layer,
- }
-
- code, response = connection.send_request('/web_api/delete-access-rule', payload)
-
- return code, response
-
-
-def needs_update(module, access_rule):
- res = False
-
- if module.params['source'] and module.params['source'] != access_rule['source'][0]['name']:
- res = True
- if module.params['destination'] and module.params['destination'] != access_rule['destination'][0]['name']:
- res = True
- if module.params['action'] != access_rule['action']['name']:
- res = True
- if module.params['enabled'] != access_rule['enabled']:
- res = True
-
- return res
-
-
-def main():
- argument_spec = dict(
- name=dict(type='str', required=True),
- layer=dict(type='str'),
- position=dict(type='str'),
- source=dict(type='str'),
- destination=dict(type='str'),
- action=dict(type='str', default='drop'),
- enabled=dict(type='bool', default=True),
- state=dict(type='str', default='present')
- )
- argument_spec.update(checkpoint_argument_spec)
-
- required_if = [('state', 'present', ('layer', 'position'))]
- module = AnsibleModule(argument_spec=argument_spec, required_if=required_if)
- connection = Connection(module._socket_path)
- code, response = get_access_rule(module, connection)
- result = {'changed': False}
-
- if module.params['state'] == 'present':
- if code == 200:
- if needs_update(module, response):
- code, response = update_access_rule(module, connection)
- if code != 200:
- module.fail_json(msg=response)
- if module.params['auto_publish_session']:
- publish(connection)
-
- if module.params['auto_install_policy']:
- install_policy(connection, module.params['policy_package'], module.params['targets'])
-
- result['changed'] = True
- result['checkpoint_access_rules'] = response
- else:
- pass
- elif code == 404:
- code, response = create_access_rule(module, connection)
- if code != 200:
- module.fail_json(msg=response)
- if module.params['auto_publish_session']:
- publish(connection)
-
- if module.params['auto_install_policy']:
- install_policy(connection, module.params['policy_package'], module.params['targets'])
-
- result['changed'] = True
- result['checkpoint_access_rules'] = response
- else:
- if code == 200:
- code, response = delete_access_rule(module, connection)
- if code != 200:
- module.fail_json(msg=response)
- if module.params['auto_publish_session']:
- publish(connection)
-
- if module.params['auto_install_policy']:
- install_policy(connection, module.params['policy_package'], module.params['targets'])
-
- result['changed'] = True
- result['checkpoint_access_rules'] = response
- elif code == 404:
- pass
-
- result['checkpoint_session_uid'] = connection.get_session_uid()
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/check_point/checkpoint_access_rule_facts.py b/plugins/modules/network/check_point/checkpoint_access_rule_facts.py
deleted file mode 100644
index a477bd407e..0000000000
--- a/plugins/modules/network/check_point/checkpoint_access_rule_facts.py
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'network'}
-
-
-DOCUMENTATION = '''
----
-module: checkpoint_access_rule_facts
-short_description: Get access rules objects facts on Check Point over Web Services API
-description:
- - Get access rules objects facts on Check Point devices.
- All operations are performed over Web Services API.
-author: "Ansible by Red Hat (@rcarrillocruz)"
-options:
- name:
- description:
- - Name of the access rule. If not provided, UID is required.
- type: str
- uid:
- description:
- - UID of the access rule. If not provided, name is required.
- type: str
- layer:
- description:
- - Layer the access rule is attached to.
- required: True
- type: str
-'''
-
-EXAMPLES = """
-- name: Get access rule facts
- checkpoint_access_rule_facts:
- layer: Network
- name: "Drop attacker"
-"""
-
-RETURN = """
-ansible_facts:
- description: The checkpoint access rule object facts.
- returned: always.
- type: list
-"""
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-
-
-def get_access_rule(module, connection):
- name = module.params['name']
- uid = module.params['uid']
- layer = module.params['layer']
-
- if uid:
- payload = {'uid': uid, 'layer': layer}
- elif name:
- payload = {'name': name, 'layer': layer}
-
- code, response = connection.send_request('/web_api/show-access-rule', payload)
-
- return code, response
-
-
-def main():
- argument_spec = dict(
- name=dict(type='str'),
- uid=dict(type='str'),
- layer=dict(type='str', required=True),
- )
-
- module = AnsibleModule(argument_spec=argument_spec)
- connection = Connection(module._socket_path)
- code, response = get_access_rule(module, connection)
- if code == 200:
- module.exit_json(ansible_facts=dict(checkpoint_access_rules=response))
- else:
- module.fail_json(msg='Checkpoint device returned error {0} with message {1}'.format(code, response))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/check_point/checkpoint_host.py b/plugins/modules/network/check_point/checkpoint_host.py
deleted file mode 100644
index 5d651c3007..0000000000
--- a/plugins/modules/network/check_point/checkpoint_host.py
+++ /dev/null
@@ -1,215 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'network'}
-
-
-DOCUMENTATION = '''
----
-module: checkpoint_host
-short_description: Manages host objects on Check Point over Web Services API
-description:
- - Manages host objects on Check Point devices including creating, updating, removing access rules objects.
- All operations are performed over Web Services API.
-author: "Ansible by Red Hat (@rcarrillocruz)"
-options:
- name:
- description:
- - Name of the access rule.
- type: str
- required: True
- ip_address:
- description:
- - IP address of the host object.
- type: str
- state:
- description:
- - State of the access rule (present or absent). Defaults to present.
- type: str
- default: present
- auto_publish_session:
- description:
- - Publish the current session if changes have been performed
- after task completes.
- type: bool
- default: 'yes'
- auto_install_policy:
- description:
- - Install the package policy if changes have been performed
- after the task completes.
- type: bool
- default: 'yes'
- policy_package:
- description:
- - Package policy name to be installed.
- type: str
- default: 'standard'
- targets:
- description:
- - Targets to install the package policy on.
- type: list
-'''
-
-EXAMPLES = """
-- name: Create host object
- checkpoint_host:
- name: attacker
- ip_address: 192.168.0.15
-
-- name: Delete host object
- checkpoint_host:
- name: attacker
- state: absent
-"""
-
-RETURN = """
-checkpoint_hosts:
- description: The checkpoint host object created or updated.
- returned: always, except when deleting the host.
- type: list
-"""
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.check_point.mgmt.plugins.module_utils.checkpoint import checkpoint_argument_spec, publish, install_policy
-
-
-def get_host(module, connection):
- name = module.params['name']
-
- payload = {'name': name}
-
- code, response = connection.send_request('/web_api/show-host', payload)
-
- return code, response
-
-
-def create_host(module, connection):
- name = module.params['name']
- ip_address = module.params['ip_address']
-
- payload = {'name': name,
- 'ip-address': ip_address}
-
- code, response = connection.send_request('/web_api/add-host', payload)
-
- return code, response
-
-
-def update_host(module, connection):
- name = module.params['name']
- ip_address = module.params['ip_address']
-
- payload = {'name': name,
- 'ip-address': ip_address}
-
- code, response = connection.send_request('/web_api/set-host', payload)
-
- return code, response
-
-
-def delete_host(module, connection):
- name = module.params['name']
-
- payload = {'name': name}
-
- code, response = connection.send_request('/web_api/delete-host', payload)
-
- return code, response
-
-
-def needs_update(module, host):
- res = False
-
- if module.params['ip_address'] != host['ipv4-address']:
- res = True
-
- return res
-
-
-def main():
- argument_spec = dict(
- name=dict(type='str', required=True),
- ip_address=dict(type='str'),
- state=dict(type='str', default='present')
- )
- argument_spec.update(checkpoint_argument_spec)
-
- module = AnsibleModule(argument_spec=argument_spec)
- connection = Connection(module._socket_path)
- code, response = get_host(module, connection)
- result = {'changed': False}
-
- if module.params['state'] == 'present':
- if code == 200:
- if needs_update(module, response):
- code, response = update_host(module, connection)
- if code != 200:
- module.fail_json(msg=response)
- if module.params['auto_publish_session']:
- publish(connection)
-
- if module.params['auto_install_policy']:
- install_policy(connection, module.params['policy_package'], module.params['targets'])
-
- result['changed'] = True
- result['checkpoint_hosts'] = response
- else:
- pass
- elif code == 404:
- code, response = create_host(module, connection)
- if code != 200:
- module.fail_json(msg=response)
- if module.params['auto_publish_session']:
- publish(connection)
-
- if module.params['auto_install_policy']:
- install_policy(connection, module.params['policy_package'], module.params['targets'])
-
- result['changed'] = True
- result['checkpoint_hosts'] = response
- else:
- if code == 200:
- # Handle deletion
- code, response = delete_host(module, connection)
- if code != 200:
- module.fail_json(msg=response)
- if module.params['auto_publish_session']:
- publish(connection)
-
- if module.params['auto_install_policy']:
- install_policy(connection, module.params['policy_package'], module.params['targets'])
-
- result['changed'] = True
- result['checkpoint_hosts'] = response
- elif code == 404:
- pass
-
- result['checkpoint_session_uid'] = connection.get_session_uid()
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/check_point/checkpoint_host_facts.py b/plugins/modules/network/check_point/checkpoint_host_facts.py
deleted file mode 100644
index c8a8d8aa38..0000000000
--- a/plugins/modules/network/check_point/checkpoint_host_facts.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'network'}
-
-
-DOCUMENTATION = '''
----
-module: checkpoint_host_facts
-short_description: Get host objects facts on Check Point over Web Services API
-description:
- - Get host objects facts on Check Point devices.
- All operations are performed over Web Services API.
-author: "Ansible by Red Hat (@rcarrillocruz)"
-options:
- name:
- description:
- - Name of the host object. If name is not provided, UID is required.
- type: str
- uid:
- description:
- - UID of the host object. If UID is not provided, name is required.
- type: str
-'''
-
-EXAMPLES = """
-- name: Get host object facts
- checkpoint_host_facts:
- name: attacker
-"""
-
-RETURN = """
-ansible_hosts:
- description: The checkpoint host object facts.
- returned: always.
- type: list
-"""
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-
-
-def get_host(module, connection):
- name = module.params['name']
- uid = module.params['uid']
-
- if uid:
- payload = {'uid': uid}
- elif name:
- payload = {'name': name}
-
- code, result = connection.send_request('/web_api/show-host', payload)
-
- return code, result
-
-
-def main():
- argument_spec = dict(
- name=dict(type='str'),
- uid=dict(type='str'),
- )
-
- required_one_of = [('name', 'uid')]
- module = AnsibleModule(argument_spec=argument_spec, required_one_of=required_one_of)
- connection = Connection(module._socket_path)
-
- code, response = get_host(module, connection)
-
- if code == 200:
- module.exit_json(ansible_facts=dict(checkpoint_hosts=response))
- else:
- module.fail_json(msg='Checkpoint device returned error {0} with message {1}'.format(code, response))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/check_point/checkpoint_object_facts.py b/plugins/modules/network/check_point/checkpoint_object_facts.py
deleted file mode 100644
index 96d0145126..0000000000
--- a/plugins/modules/network/check_point/checkpoint_object_facts.py
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'network'}
-
-
-DOCUMENTATION = '''
----
-module: checkpoint_object_facts
-short_description: Get object facts on Check Point over Web Services API
-description:
- - Get object facts on Check Point devices.
- All operations are performed over Web Services API.
-author: "Ansible by Red Hat (@rcarrillocruz)"
-options:
- uid:
- description:
- - UID of the object. If UID is not provided, it will do a full search
- which can be filtered with the filter argument.
- object_filter:
- description:
- - Filter expression for search. It accepts AND/OR logical operators and performs a textual
- and IP address search. To search only by IP address, set ip_only argument to True.
- which can be filtered with the filter argument.
- ip_only:
- description:
- - Filter only by IP address.
- type: bool
- default: false
- object_type:
- description:
- - Type of the object to search. Must be a valid API resource name
- type: str
-'''
-
-EXAMPLES = """
-- name: Get object facts
- checkpoint_object_facts:
- object_filter: 192.168.30.30
- ip_only: yes
-"""
-
-RETURN = """
-ansible_hosts:
- description: The checkpoint object facts.
- returned: always.
- type: list
-"""
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-
-
-def get_object(module, connection):
- uid = module.params['uid']
- object_filter = module.params['object_filter']
- ip_only = module.params['ip_only']
- object_type = module.params['object_type']
-
- if uid:
- payload = {'uid': uid}
- code, result = connection.send_request('/web_api/show-object', payload)
- else:
- payload = {'filter': object_filter, 'ip-only': ip_only, 'type': object_type}
- code, result = connection.send_request('/web_api/show-objects', payload)
-
- return code, result
-
-
-def main():
- argument_spec = dict(
- uid=dict(type='str', default=None),
- object_filter=dict(type='str', default=None),
- ip_only=dict(type='bool', default=False),
- object_type=dict(type='str', default=None)
- )
-
- module = AnsibleModule(argument_spec=argument_spec)
- connection = Connection(module._socket_path)
-
- code, response = get_object(module, connection)
-
- if code == 200:
- module.exit_json(ansible_facts=dict(checkpoint_objects=response))
- else:
- module.fail_json(msg='Check Point device returned error {0} with message {1}'.format(code, response))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/check_point/checkpoint_run_script.py b/plugins/modules/network/check_point/checkpoint_run_script.py
deleted file mode 100644
index abee6b5093..0000000000
--- a/plugins/modules/network/check_point/checkpoint_run_script.py
+++ /dev/null
@@ -1,110 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'network'}
-
-
-DOCUMENTATION = '''
----
-module: checkpoint_run_script
-short_description: Run scripts on Check Point devices over Web Services API
-description:
- - Run scripts on Check Point devices.
- All operations are performed over Web Services API.
-author: "Ansible by Red Hat (@rcarrillocruz)"
-options:
- script_name:
- description:
- - Name of the script.
- type: str
- required: True
- script:
- description:
- - Script body contents.
- type: str
- required: True
- targets:
- description:
- - Targets the script should be run against. Can reference either name or UID.
- type: list
- required: True
-'''
-
-EXAMPLES = """
-- name: Run script
- checkpoint_run_script:
- script_name: "List root"
- script: ls -l /
- targets:
- - mycheckpointgw
-"""
-
-RETURN = """
-checkpoint_run_script:
- description: The checkpoint run script output.
- returned: always.
- type: list
-"""
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-
-
-def run_script(module, connection):
- script_name = module.params['script_name']
- script = module.params['script']
- targets = module.params['targets']
-
- payload = {'script-name': script_name,
- 'script': script,
- 'targets': targets}
-
- code, response = connection.send_request('/web_api/run-script', payload)
-
- return code, response
-
-
-def main():
- argument_spec = dict(
- script_name=dict(type='str', required=True),
- script=dict(type='str', required=True),
- targets=dict(type='list', required=True)
- )
-
- module = AnsibleModule(argument_spec=argument_spec)
- connection = Connection(module._socket_path)
- code, response = run_script(module, connection)
- result = {'changed': True}
-
- if code == 200:
- result['checkpoint_run_script'] = response
- else:
- module.fail_json(msg='Checkpoint device returned error {0} with message {1}'.format(code, response))
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/check_point/checkpoint_session.py b/plugins/modules/network/check_point/checkpoint_session.py
deleted file mode 100644
index e1d45cd03c..0000000000
--- a/plugins/modules/network/check_point/checkpoint_session.py
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'network'}
-
-
-DOCUMENTATION = '''
----
-module: checkpoint_session
-short_description: Manages session objects on Check Point over Web Services API
-description:
- - Manages session objects on Check Point devices performing actions like publish and discard.
- All operations are performed over Web Services API.
-author: "Ansible by Red Hat (@rcarrillocruz)"
-options:
- uid:
- description:
- - UID of the session.
- type: str
- required: True
- state:
- description:
- - Action to perform on the session object. Valid choices are published and discarded.
- type: str
- choices: ['published', 'discarded']
- default: published
-'''
-
-EXAMPLES = """
-- name: Publish session
- checkpoint_session:
- uid: 7a13a360-9b24-40d7-acd3-5b50247be33e
- state: published
-
-- name: Discard session
- checkpoint_session:
- uid: 7a13a360-9b24-40d7-acd3-5b50247be33e
- state: discarded
-"""
-
-RETURN = """
-checkpoint_session:
- description: The checkpoint session output per return from API. It will differ depending on action.
- returned: always.
- type: list
-"""
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-
-
-def get_session(module, connection):
- payload = {'uid': module.params['uid']}
-
- code, result = connection.send_request('/web_api/show-session', payload)
-
- return code, result
-
-
-def main():
- argument_spec = dict(
- uid=dict(type='str', default=None),
- state=dict(type='str', default='published', choices=['published', 'discarded'])
- )
-
- module = AnsibleModule(argument_spec=argument_spec)
- connection = Connection(module._socket_path)
- code, response = get_session(module, connection)
- result = {'changed': False}
-
- if code == 200:
- result['changed'] = True
- payload = None
-
- if module.params['uid']:
- payload = {'uid': module.params['uid']}
-
- if module.params['state'] == 'published':
- code, response = connection.send_request('/web_api/publish', payload)
- else:
- code, response = connection.send_request('/web_api/discard', payload)
- if code != 200:
- module.fail_json(msg=response)
- result['checkpoint_session'] = response
- else:
- module.fail_json(msg='Check Point device returned error {0} with message {1}'.format(code, response))
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/check_point/checkpoint_task_facts.py b/plugins/modules/network/check_point/checkpoint_task_facts.py
deleted file mode 100644
index 632113a534..0000000000
--- a/plugins/modules/network/check_point/checkpoint_task_facts.py
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'network'}
-
-
-DOCUMENTATION = '''
----
-module: checkpoint_task_facts
-short_description: Get task objects facts on Check Point over Web Services API
-description:
- - Get task objects facts on Check Point devices.
- All operations are performed over Web Services API.
-author: "Ansible by Red Hat (@rcarrillocruz)"
-options:
- task_id:
- description:
- - ID of the task object.
- type: str
- required: True
-'''
-
-EXAMPLES = """
-- name: Get task facts
- checkpoint_task_facts:
- task_id: 2eec70e5-78a8-4bdb-9a76-cfb5601d0bcb
-"""
-
-RETURN = """
-ansible_facts:
- description: The checkpoint task facts.
- returned: always.
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-
-
-def get_task(module, connection):
- task_id = module.params['task_id']
-
- if task_id:
- payload = {'task-id': task_id,
- 'details-level': 'full'}
-
- code, response = connection.send_request('/web_api/show-task', payload)
- else:
- code, response = connection.send_request('/web_api/show-tasks', None)
-
- return code, response
-
-
-def main():
- argument_spec = dict(
- task_id=dict(type='str'),
- )
-
- module = AnsibleModule(argument_spec=argument_spec)
- connection = Connection(module._socket_path)
- code, response = get_task(module, connection)
- if code == 200:
- module.exit_json(ansible_facts=dict(checkpoint_tasks=response))
- else:
- module.fail_json(msg='Checkpoint device returned error {0} with message {1}'.format(code, response))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/check_point/cp_publish.py b/plugins/modules/network/check_point/cp_publish.py
deleted file mode 100644
index cece9ee0d4..0000000000
--- a/plugins/modules/network/check_point/cp_publish.py
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Ansible module to manage Check Point Firewall (c) 2019
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: cp_publish
-short_description: All the changes done by this user will be seen by all users only after publish is called.
-description:
- - All the changes done by this user will be seen by all users only after publish is called.
- All operations are performed over Web Services API.
-author: "Or Soffer (@chkp-orso)"
-options:
- uid:
- description:
- - Session unique identifier. Specify it to publish a different session than the one you currently use.
- type: str
-extends_documentation_fragment:
-- check_point.mgmt.checkpoint_commands
-
-'''
-
-EXAMPLES = """
-- name: publish
- cp_publish:
-"""
-
-RETURN = """
-cp_publish:
- description: The checkpoint publish output.
- returned: always.
- type: dict
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.check_point.mgmt.plugins.module_utils.checkpoint import checkpoint_argument_spec_for_commands, api_command
-
-
-def main():
- argument_spec = dict(
- uid=dict(type='str')
- )
- argument_spec.update(checkpoint_argument_spec_for_commands)
-
- module = AnsibleModule(argument_spec=argument_spec)
-
- command = "publish"
-
- result = api_command(module, command)
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_aaa_server.py b/plugins/modules/network/cloudengine/ce_aaa_server.py
deleted file mode 100644
index c7da3fdeb3..0000000000
--- a/plugins/modules/network/cloudengine/ce_aaa_server.py
+++ /dev/null
@@ -1,2180 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: ce_aaa_server
-short_description: Manages AAA server global configuration on HUAWEI CloudEngine switches.
-description:
- - Manages AAA server global configuration on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- state:
- description:
- - Specify desired state of the resource.
- type: str
- choices: [ absent, present ]
- default: present
- authen_scheme_name:
- description:
- - Name of an authentication scheme.
- The value is a string of 1 to 32 characters.
- type: str
- first_authen_mode:
- description:
- - Preferred authentication mode.
- type: str
- choices: ['invalid', 'local', 'hwtacacs', 'radius', 'none']
- default: local
- author_scheme_name:
- description:
- - Name of an authorization scheme.
- The value is a string of 1 to 32 characters.
- type: str
- first_author_mode:
- description:
- - Preferred authorization mode.
- type: str
- choices: ['invalid', 'local', 'hwtacacs', 'if-authenticated', 'none']
- default: local
- acct_scheme_name:
- description:
- - Accounting scheme name.
- The value is a string of 1 to 32 characters.
- type: str
- accounting_mode:
- description:
- - Accounting Mode.
- type: str
- choices: ['invalid', 'hwtacacs', 'radius', 'none']
- default: none
- domain_name:
- description:
- - Name of a domain.
- The value is a string of 1 to 64 characters.
- type: str
- radius_server_group:
- description:
- - RADIUS server group's name.
- The value is a string of 1 to 32 case-insensitive characters.
- type: str
- hwtacas_template:
- description:
- - Name of a HWTACACS template.
- The value is a string of 1 to 32 case-insensitive characters.
- type: str
- local_user_group:
- description:
- - Name of the user group where the user belongs. The user inherits all the rights of the user group.
- The value is a string of 1 to 32 characters.
- type: str
-'''
-
-EXAMPLES = r'''
-
-- name: AAA server test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Radius authentication Server Basic settings"
- ce_aaa_server:
- state: present
- authen_scheme_name: test1
- first_authen_mode: radius
- radius_server_group: test2
- provider: "{{ cli }}"
-
- - name: "Undo radius authentication Server Basic settings"
- ce_aaa_server:
- state: absent
- authen_scheme_name: test1
- first_authen_mode: radius
- radius_server_group: test2
- provider: "{{ cli }}"
-
- - name: "Hwtacacs accounting Server Basic settings"
- ce_aaa_server:
- state: present
- acct_scheme_name: test1
- accounting_mode: hwtacacs
- hwtacas_template: test2
- provider: "{{ cli }}"
-
- - name: "Undo hwtacacs accounting Server Basic settings"
- ce_aaa_server:
- state: absent
- acct_scheme_name: test1
- accounting_mode: hwtacacs
- hwtacas_template: test2
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"accounting_mode": "hwtacacs", "acct_scheme_name": "test1",
- "hwtacas_template": "test2", "state": "present"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {"accounting scheme": [["hwtacacs"], ["default"]],
- "hwtacacs template": ["huawei"]}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"accounting scheme": [["hwtacacs", "test1"]],
- "hwtacacs template": ["huawei", "test2"]}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["accounting-scheme test1",
- "accounting-mode hwtacacs",
- "hwtacacs server template test2",
- "hwtacacs enable"]
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-
-SUCCESS = """success"""
-FAILED = """failed"""
-
-INVALID_SCHEME_CHAR = [' ', '/', '\\', ':', '*', '?', '"', '|', '<', '>']
-INVALID_DOMAIN_CHAR = [' ', '*', '?', '"', '\'']
-INVALID_GROUP_CHAR = ['/', '\\', ':', '*', '?', '"', '|', '<', '>']
-
-
-# get authentication scheme
-CE_GET_AUTHENTICATION_SCHEME = """
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge authentication scheme
-CE_MERGE_AUTHENTICATION_SCHEME = """
-
-
-
-
- %s
- %s
- invalid
-
-
-
-
-"""
-
-# create authentication scheme
-CE_CREATE_AUTHENTICATION_SCHEME = """
-
-
-
-
- %s
- %s
- invalid
-
-
-
-
-"""
-
-# delete authentication scheme
-CE_DELETE_AUTHENTICATION_SCHEME = """
-
-
-
-
- %s
- %s
- invalid
-
-
-
-
-"""
-
-# get authorization scheme
-CE_GET_AUTHORIZATION_SCHEME = """
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge authorization scheme
-CE_MERGE_AUTHORIZATION_SCHEME = """
-
-
-
-
- %s
- %s
- invalid
-
-
-
-
-"""
-
-# create authorization scheme
-CE_CREATE_AUTHORIZATION_SCHEME = """
-
-
-
-
- %s
- %s
- invalid
-
-
-
-
-"""
-
-# delete authorization scheme
-CE_DELETE_AUTHORIZATION_SCHEME = """
-
-
-
-
- %s
- %s
- invalid
-
-
-
-
-"""
-
-# get accounting scheme
-CE_GET_ACCOUNTING_SCHEME = """
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge accounting scheme
-CE_MERGE_ACCOUNTING_SCHEME = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-# create accounting scheme
-CE_CREATE_ACCOUNTING_SCHEME = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-# delete accounting scheme
-CE_DELETE_ACCOUNTING_SCHEME = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-# get authentication domain
-CE_GET_AUTHENTICATION_DOMAIN = """
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge authentication domain
-CE_MERGE_AUTHENTICATION_DOMAIN = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-# create authentication domain
-CE_CREATE_AUTHENTICATION_DOMAIN = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-# delete authentication domain
-CE_DELETE_AUTHENTICATION_DOMAIN = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-# get authorization domain
-CE_GET_AUTHORIZATION_DOMAIN = """
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge authorization domain
-CE_MERGE_AUTHORIZATION_DOMAIN = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-# create authorization domain
-CE_CREATE_AUTHORIZATION_DOMAIN = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-# delete authorization domain
-CE_DELETE_AUTHORIZATION_DOMAIN = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-# get accounting domain
-CE_GET_ACCOUNTING_DOMAIN = """
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge accounting domain
-CE_MERGE_ACCOUNTING_DOMAIN = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-# create accounting domain
-CE_CREATE_ACCOUNTING_DOMAIN = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-# delete accounting domain
-CE_DELETE_ACCOUNTING_DOMAIN = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-# get radius template
-CE_GET_RADIUS_TEMPLATE = """
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge radius template
-CE_MERGE_RADIUS_TEMPLATE = """
-
-
-
-
- %s
- 3
- 5
-
-
-
-
-"""
-
-# create radius template
-CE_CREATE_RADIUS_TEMPLATE = """
-
-
-
-
- %s
- 3
- 5
-
-
-
-
-"""
-
-# delete radius template
-CE_DELETE_RADIUS_TEMPLATE = """
-
-
-
-
- %s
- 3
- 5
-
-
-
-
-"""
-
-# get hwtacacs template
-CE_GET_HWTACACS_TEMPLATE = """
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge hwtacacs template
-CE_MERGE_HWTACACS_TEMPLATE = """
-
-
-
-
- %s
- true
- 5
-
-
-
-
-"""
-
-# create hwtacacs template
-CE_CREATE_HWTACACS_TEMPLATE = """
-
-
-
-
- %s
- true
- 5
-
-
-
-
-"""
-
-# delete hwtacacs template
-CE_DELETE_HWTACACS_TEMPLATE = """
-
-
-
-
- %s
-
-
-
-
-"""
-
-# get radius client
-CE_GET_RADIUS_CLIENT = """
-
-
-
-
-
-
-
-
-
-"""
-
-# merge radius client
-CE_MERGE_RADIUS_CLIENT = """
-
-
-
- %s
-
-
-
-"""
-
-# get hwtacacs global config
-CE_GET_HWTACACS_GLOBAL_CFG = """
-
-
-
-
-
-
-
-
-
-"""
-
-# merge hwtacacs global config
-CE_MERGE_HWTACACS_GLOBAL_CFG = """
-
-
-
- %s
-
-
-
-"""
-
-# get local user group
-CE_GET_LOCAL_USER_GROUP = """
-
-
-
-
-
-
-
-
-
-"""
-# merge local user group
-CE_MERGE_LOCAL_USER_GROUP = """
-
-
-
-
- %s
-
-
-
-
-"""
-# delete local user group
-CE_DELETE_LOCAL_USER_GROUP = """
-
-
-
-
- %s
-
-
-
-
-"""
-
-
-class AaaServer(object):
- """ Manages aaa configuration """
-
- def netconf_get_config(self, **kwargs):
- """ Get configure by netconf """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- xml_str = get_nc_config(module, conf_str)
-
- return xml_str
-
- def netconf_set_config(self, **kwargs):
- """ Set configure by netconf """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- recv_xml = set_nc_config(module, conf_str)
-
- return recv_xml
-
- def get_authentication_scheme(self, **kwargs):
- """ Get scheme of authentication """
-
- module = kwargs["module"]
- conf_str = CE_GET_AUTHENTICATION_SCHEME
-
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(
- r'.*(.*).*\s*'
- r'(.*).*\s*'
- r'(.*).*\s*', xml_str)
-
- if re_find:
- return re_find
- else:
- return result
-
- def get_authentication_domain(self, **kwargs):
- """ Get domain of authentication """
-
- module = kwargs["module"]
- conf_str = CE_GET_AUTHENTICATION_DOMAIN
-
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
-
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(
- r'.*(.*).*\s*'
- r'(.*).*', xml_str)
-
- if re_find:
- return re_find
- else:
- return result
-
- def merge_authentication_scheme(self, **kwargs):
- """ Merge scheme of authentication """
-
- authen_scheme_name = kwargs["authen_scheme_name"]
- first_authen_mode = kwargs["first_authen_mode"]
- module = kwargs["module"]
- conf_str = CE_MERGE_AUTHENTICATION_SCHEME % (
- authen_scheme_name, first_authen_mode)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Merge authentication scheme failed.')
-
- cmds = []
- cmd = "authentication-scheme %s" % authen_scheme_name
- cmds.append(cmd)
- cmd = "authentication-mode %s" % first_authen_mode
- cmds.append(cmd)
-
- return cmds
-
- def merge_authentication_domain(self, **kwargs):
- """ Merge domain of authentication """
-
- domain_name = kwargs["domain_name"]
- authen_scheme_name = kwargs["authen_scheme_name"]
- module = kwargs["module"]
- conf_str = CE_MERGE_AUTHENTICATION_DOMAIN % (
- domain_name, authen_scheme_name)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Merge authentication domain failed.')
-
- cmds = []
- cmd = "domain %s" % domain_name
- cmds.append(cmd)
- cmd = "authentication-scheme %s" % authen_scheme_name
- cmds.append(cmd)
-
- return cmds
-
- def create_authentication_scheme(self, **kwargs):
- """ Create scheme of authentication """
-
- authen_scheme_name = kwargs["authen_scheme_name"]
- first_authen_mode = kwargs["first_authen_mode"]
- module = kwargs["module"]
- conf_str = CE_CREATE_AUTHENTICATION_SCHEME % (
- authen_scheme_name, first_authen_mode)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Create authentication scheme failed.')
-
- cmds = []
- cmd = "authentication-scheme %s" % authen_scheme_name
- cmds.append(cmd)
- cmd = "authentication-mode %s" % first_authen_mode
- cmds.append(cmd)
-
- return cmds
-
- def create_authentication_domain(self, **kwargs):
- """ Create domain of authentication """
-
- domain_name = kwargs["domain_name"]
- authen_scheme_name = kwargs["authen_scheme_name"]
- module = kwargs["module"]
- conf_str = CE_CREATE_AUTHENTICATION_DOMAIN % (
- domain_name, authen_scheme_name)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Create authentication domain failed.')
-
- cmds = []
- cmd = "domain %s" % domain_name
- cmds.append(cmd)
- cmd = "authentication-scheme %s" % authen_scheme_name
- cmds.append(cmd)
-
- return cmds
-
- def delete_authentication_scheme(self, **kwargs):
- """ Delete scheme of authentication """
-
- authen_scheme_name = kwargs["authen_scheme_name"]
- first_authen_mode = kwargs["first_authen_mode"]
- module = kwargs["module"]
-
- if authen_scheme_name == "default":
- return SUCCESS
-
- conf_str = CE_DELETE_AUTHENTICATION_SCHEME % (
- authen_scheme_name, first_authen_mode)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Delete authentication scheme failed.')
-
- cmds = []
- cmd = "undo authentication-scheme %s" % authen_scheme_name
- cmds.append(cmd)
- cmd = "authentication-mode none"
- cmds.append(cmd)
-
- return cmds
-
- def delete_authentication_domain(self, **kwargs):
- """ Delete domain of authentication """
-
- domain_name = kwargs["domain_name"]
- authen_scheme_name = kwargs["authen_scheme_name"]
- module = kwargs["module"]
-
- if domain_name == "default":
- return SUCCESS
-
- conf_str = CE_DELETE_AUTHENTICATION_DOMAIN % (
- domain_name, authen_scheme_name)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Delete authentication domain failed.')
-
- cmds = []
- cmd = "undo authentication-scheme"
- cmds.append(cmd)
- cmd = "undo domain %s" % domain_name
- cmds.append(cmd)
-
- return cmds
-
- def get_authorization_scheme(self, **kwargs):
- """ Get scheme of authorization """
-
- module = kwargs["module"]
- conf_str = CE_GET_AUTHORIZATION_SCHEME
-
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(
- r'.*(.*).*\s*'
- r'(.*).*\s*'
- r'(.*).*\s*', xml_str)
-
- if re_find:
- return re_find
- else:
- return result
-
- def get_authorization_domain(self, **kwargs):
- """ Get domain of authorization """
-
- module = kwargs["module"]
- conf_str = CE_GET_AUTHORIZATION_DOMAIN
-
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
-
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(
- r'.*(.*).*\s*'
- r'(.*).*', xml_str)
-
- if re_find:
- return re_find
- else:
- return result
-
- def merge_authorization_scheme(self, **kwargs):
- """ Merge scheme of authorization """
-
- author_scheme_name = kwargs["author_scheme_name"]
- first_author_mode = kwargs["first_author_mode"]
- module = kwargs["module"]
- conf_str = CE_MERGE_AUTHORIZATION_SCHEME % (
- author_scheme_name, first_author_mode)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Merge authorization scheme failed.')
-
- cmds = []
- cmd = "authorization-scheme %s" % author_scheme_name
- cmds.append(cmd)
- cmd = "authorization-mode %s" % first_author_mode
- cmds.append(cmd)
-
- return cmds
-
- def merge_authorization_domain(self, **kwargs):
- """ Merge domain of authorization """
-
- domain_name = kwargs["domain_name"]
- author_scheme_name = kwargs["author_scheme_name"]
- module = kwargs["module"]
- conf_str = CE_MERGE_AUTHORIZATION_DOMAIN % (
- domain_name, author_scheme_name)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Merge authorization domain failed.')
-
- cmds = []
- cmd = "domain %s" % domain_name
- cmds.append(cmd)
- cmd = "authorization-scheme %s" % author_scheme_name
- cmds.append(cmd)
-
- return cmds
-
- def create_authorization_scheme(self, **kwargs):
- """ Create scheme of authorization """
-
- author_scheme_name = kwargs["author_scheme_name"]
- first_author_mode = kwargs["first_author_mode"]
- module = kwargs["module"]
- conf_str = CE_CREATE_AUTHORIZATION_SCHEME % (
- author_scheme_name, first_author_mode)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Create authorization scheme failed.')
-
- cmds = []
- cmd = "authorization-scheme %s" % author_scheme_name
- cmds.append(cmd)
- cmd = "authorization-mode %s" % first_author_mode
- cmds.append(cmd)
-
- return cmds
-
- def create_authorization_domain(self, **kwargs):
- """ Create domain of authorization """
-
- domain_name = kwargs["domain_name"]
- author_scheme_name = kwargs["author_scheme_name"]
- module = kwargs["module"]
- conf_str = CE_CREATE_AUTHORIZATION_DOMAIN % (
- domain_name, author_scheme_name)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Create authorization domain failed.')
-
- cmds = []
- cmd = "domain %s" % domain_name
- cmds.append(cmd)
- cmd = "authorization-scheme %s" % author_scheme_name
- cmds.append(cmd)
-
- return cmds
-
- def delete_authorization_scheme(self, **kwargs):
- """ Delete scheme of authorization """
-
- author_scheme_name = kwargs["author_scheme_name"]
- first_author_mode = kwargs["first_author_mode"]
- module = kwargs["module"]
-
- if author_scheme_name == "default":
- return SUCCESS
-
- conf_str = CE_DELETE_AUTHORIZATION_SCHEME % (
- author_scheme_name, first_author_mode)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Delete authorization scheme failed.')
-
- cmds = []
- cmd = "undo authorization-scheme %s" % author_scheme_name
- cmds.append(cmd)
- cmd = "authorization-mode none"
- cmds.append(cmd)
-
- return cmds
-
- def delete_authorization_domain(self, **kwargs):
- """ Delete domain of authorization """
-
- domain_name = kwargs["domain_name"]
- author_scheme_name = kwargs["author_scheme_name"]
- module = kwargs["module"]
-
- if domain_name == "default":
- return SUCCESS
-
- conf_str = CE_DELETE_AUTHORIZATION_DOMAIN % (
- domain_name, author_scheme_name)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Delete authorization domain failed.')
-
- cmds = []
- cmd = "undo authorization-scheme"
- cmds.append(cmd)
- cmd = "undo domain %s" % domain_name
- cmds.append(cmd)
-
- return cmds
-
- def get_accounting_scheme(self, **kwargs):
- """ Get scheme of accounting """
-
- module = kwargs["module"]
- conf_str = CE_GET_ACCOUNTING_SCHEME
-
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(r'.*(.*)\s*(.*)', xml_str)
- if re_find:
- return re_find
- else:
- return result
-
- def get_accounting_domain(self, **kwargs):
- """ Get domain of accounting """
-
- module = kwargs["module"]
- conf_str = CE_GET_ACCOUNTING_DOMAIN
-
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
-
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(
- r'.*(.*).*\s*'
- r'(.*).*', xml_str)
-
- if re_find:
- return re_find
- else:
- return result
-
- def merge_accounting_scheme(self, **kwargs):
- """ Merge scheme of accounting """
-
- acct_scheme_name = kwargs["acct_scheme_name"]
- accounting_mode = kwargs["accounting_mode"]
- module = kwargs["module"]
- conf_str = CE_MERGE_ACCOUNTING_SCHEME % (
- acct_scheme_name, accounting_mode)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Merge accounting scheme failed.')
-
- cmds = []
- cmd = "accounting-scheme %s" % acct_scheme_name
- cmds.append(cmd)
- cmd = "accounting-mode %s" % accounting_mode
- cmds.append(cmd)
-
- return cmds
-
- def merge_accounting_domain(self, **kwargs):
- """ Merge domain of accounting """
-
- domain_name = kwargs["domain_name"]
- acct_scheme_name = kwargs["acct_scheme_name"]
- module = kwargs["module"]
- conf_str = CE_MERGE_ACCOUNTING_DOMAIN % (domain_name, acct_scheme_name)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Merge accounting domain failed.')
-
- cmds = []
- cmd = "domain %s" % domain_name
- cmds.append(cmd)
- cmd = "accounting-scheme %s" % acct_scheme_name
- cmds.append(cmd)
-
- return cmds
-
- def create_accounting_scheme(self, **kwargs):
- """ Create scheme of accounting """
-
- acct_scheme_name = kwargs["acct_scheme_name"]
- accounting_mode = kwargs["accounting_mode"]
- module = kwargs["module"]
- conf_str = CE_CREATE_ACCOUNTING_SCHEME % (
- acct_scheme_name, accounting_mode)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Create accounting scheme failed.')
-
- cmds = []
- cmd = "accounting-scheme %s" % acct_scheme_name
- cmds.append(cmd)
- cmd = "accounting-mode %s" % accounting_mode
- cmds.append(cmd)
-
- return cmds
-
- def create_accounting_domain(self, **kwargs):
- """ Create domain of accounting """
-
- domain_name = kwargs["domain_name"]
- acct_scheme_name = kwargs["acct_scheme_name"]
- module = kwargs["module"]
- conf_str = CE_CREATE_ACCOUNTING_DOMAIN % (
- domain_name, acct_scheme_name)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Create accounting domain failed.')
-
- cmds = []
- cmd = "domain %s" % domain_name
- cmds.append(cmd)
- cmd = "accounting-scheme %s" % acct_scheme_name
- cmds.append(cmd)
-
- return cmds
-
- def delete_accounting_scheme(self, **kwargs):
- """ Delete scheme of accounting """
-
- acct_scheme_name = kwargs["acct_scheme_name"]
- accounting_mode = kwargs["accounting_mode"]
- module = kwargs["module"]
-
- if acct_scheme_name == "default":
- return SUCCESS
-
- conf_str = CE_DELETE_ACCOUNTING_SCHEME % (
- acct_scheme_name, accounting_mode)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Delete accounting scheme failed.')
-
- cmds = []
- cmd = "undo accounting-scheme %s" % acct_scheme_name
- cmds.append(cmd)
- cmd = "accounting-mode none"
- cmds.append(cmd)
-
- return cmds
-
- def delete_accounting_domain(self, **kwargs):
- """ Delete domain of accounting """
-
- domain_name = kwargs["domain_name"]
- acct_scheme_name = kwargs["acct_scheme_name"]
- module = kwargs["module"]
-
- if domain_name == "default":
- return SUCCESS
-
- conf_str = CE_DELETE_ACCOUNTING_DOMAIN % (
- domain_name, acct_scheme_name)
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Delete accounting domain failed.')
-
- cmds = []
- cmd = "undo domain %s" % domain_name
- cmds.append(cmd)
- cmd = "undo accounting-scheme"
- cmds.append(cmd)
-
- return cmds
-
- def get_radius_template(self, **kwargs):
- """ Get radius template """
-
- module = kwargs["module"]
- conf_str = CE_GET_RADIUS_TEMPLATE
-
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
-
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(
- r'.*(.*).*', xml_str)
-
- if re_find:
- return re_find
- else:
- return result
-
- def merge_radius_template(self, **kwargs):
- """ Merge radius template """
-
- radius_server_group = kwargs["radius_server_group"]
- module = kwargs["module"]
- conf_str = CE_MERGE_RADIUS_TEMPLATE % radius_server_group
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Merge radius template failed.')
-
- cmds = []
- cmd = "radius server group %s" % radius_server_group
- cmds.append(cmd)
-
- return cmds
-
- def create_radius_template(self, **kwargs):
- """ Create radius template """
-
- radius_server_group = kwargs["radius_server_group"]
- module = kwargs["module"]
- conf_str = CE_CREATE_RADIUS_TEMPLATE % radius_server_group
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Create radius template failed.')
-
- cmds = []
- cmd = "radius server group %s" % radius_server_group
- cmds.append(cmd)
-
- return cmds
-
- def delete_radius_template(self, **kwargs):
- """ Delete radius template """
-
- radius_server_group = kwargs["radius_server_group"]
- module = kwargs["module"]
- conf_str = CE_DELETE_RADIUS_TEMPLATE % radius_server_group
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Delete radius template failed.')
-
- cmds = []
- cmd = "undo radius server group %s" % radius_server_group
- cmds.append(cmd)
-
- return cmds
-
- def get_radius_client(self, **kwargs):
- """ Get radius client """
-
- module = kwargs["module"]
- conf_str = CE_GET_RADIUS_CLIENT
-
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
-
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(
- r'.*(.*).*', xml_str)
-
- if re_find:
- return re_find
- else:
- return result
-
- def merge_radius_client(self, **kwargs):
- """ Merge radius client """
-
- enable = kwargs["isEnable"]
- module = kwargs["module"]
- conf_str = CE_MERGE_RADIUS_CLIENT % enable
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Merge radius client failed.')
-
- cmds = []
- if enable == "true":
- cmd = "radius enable"
- else:
- cmd = "undo radius enable"
- cmds.append(cmd)
-
- return cmds
-
- def get_hwtacacs_template(self, **kwargs):
- """ Get hwtacacs template """
-
- module = kwargs["module"]
- conf_str = CE_GET_HWTACACS_TEMPLATE
-
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
-
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(
- r'.*(.*).*', xml_str)
-
- if re_find:
- return re_find
- else:
- return result
-
- def merge_hwtacacs_template(self, **kwargs):
- """ Merge hwtacacs template """
-
- hwtacas_template = kwargs["hwtacas_template"]
- module = kwargs["module"]
- conf_str = CE_MERGE_HWTACACS_TEMPLATE % hwtacas_template
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Merge hwtacacs template failed.')
-
- cmds = []
- cmd = "hwtacacs server template %s" % hwtacas_template
- cmds.append(cmd)
-
- return cmds
-
- def create_hwtacacs_template(self, **kwargs):
- """ Create hwtacacs template """
-
- hwtacas_template = kwargs["hwtacas_template"]
- module = kwargs["module"]
- conf_str = CE_CREATE_HWTACACS_TEMPLATE % hwtacas_template
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Create hwtacacs template failed.')
-
- cmds = []
- cmd = "hwtacacs server template %s" % hwtacas_template
- cmds.append(cmd)
-
- return cmds
-
- def delete_hwtacacs_template(self, **kwargs):
- """ Delete hwtacacs template """
-
- hwtacas_template = kwargs["hwtacas_template"]
- module = kwargs["module"]
- conf_str = CE_DELETE_HWTACACS_TEMPLATE % hwtacas_template
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Delete hwtacacs template failed.')
-
- cmds = []
- cmd = "undo hwtacacs server template %s" % hwtacas_template
- cmds.append(cmd)
-
- return cmds
-
- def get_hwtacacs_global_cfg(self, **kwargs):
- """ Get hwtacacs global configure """
-
- module = kwargs["module"]
- conf_str = CE_GET_HWTACACS_GLOBAL_CFG
-
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
-
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(
- r'.*(.*).*', xml_str)
-
- if re_find:
- return re_find
- else:
- return result
-
- def merge_hwtacacs_global_cfg(self, **kwargs):
- """ Merge hwtacacs global configure """
-
- enable = kwargs["isEnable"]
- module = kwargs["module"]
- conf_str = CE_MERGE_HWTACACS_GLOBAL_CFG % enable
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Merge hwtacacs global config failed.')
-
- cmds = []
-
- if enable == "true":
- cmd = "hwtacacs enable"
- else:
- cmd = "undo hwtacacs enable"
- cmds.append(cmd)
-
- return cmds
-
- def get_local_user_group(self, **kwargs):
- """ Get local user group """
-
- module = kwargs["module"]
- conf_str = CE_GET_LOCAL_USER_GROUP
-
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
-
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(
- r'.*(.*).*', xml_str)
-
- if re_find:
- return re_find
- else:
- return result
-
- def merge_local_user_group(self, **kwargs):
- """ Merge local user group """
-
- local_user_group = kwargs["local_user_group"]
- module = kwargs["module"]
- conf_str = CE_MERGE_LOCAL_USER_GROUP % local_user_group
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Merge local user group failed.')
-
- cmds = []
- cmd = "user-group %s" % local_user_group
- cmds.append(cmd)
-
- return cmds
-
- def delete_local_user_group(self, **kwargs):
- """ Delete local user group """
-
- local_user_group = kwargs["local_user_group"]
- module = kwargs["module"]
- conf_str = CE_DELETE_LOCAL_USER_GROUP % local_user_group
-
- xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in xml:
- module.fail_json(msg='Error: Delete local user group failed.')
-
- cmds = []
- cmd = "undo user-group %s" % local_user_group
- cmds.append(cmd)
-
- return cmds
-
-
-def check_name(**kwargs):
- """ Check invalid name """
-
- module = kwargs["module"]
- name = kwargs["name"]
- invalid_char = kwargs["invalid_char"]
-
- for item in invalid_char:
- if item in name:
- module.fail_json(
- msg='Error: invalid char %s is in the name %s.' % (item, name))
-
-
-def check_module_argument(**kwargs):
- """ Check module argument """
-
- module = kwargs["module"]
-
- authen_scheme_name = module.params['authen_scheme_name']
- author_scheme_name = module.params['author_scheme_name']
- acct_scheme_name = module.params['acct_scheme_name']
- domain_name = module.params['domain_name']
- radius_server_group = module.params['radius_server_group']
- hwtacas_template = module.params['hwtacas_template']
- local_user_group = module.params['local_user_group']
-
- if authen_scheme_name:
- if len(authen_scheme_name) > 32:
- module.fail_json(
- msg='Error: authen_scheme_name %s '
- 'is large than 32.' % authen_scheme_name)
- check_name(module=module, name=authen_scheme_name,
- invalid_char=INVALID_SCHEME_CHAR)
-
- if author_scheme_name:
- if len(author_scheme_name) > 32:
- module.fail_json(
- msg='Error: author_scheme_name %s '
- 'is large than 32.' % author_scheme_name)
- check_name(module=module, name=author_scheme_name,
- invalid_char=INVALID_SCHEME_CHAR)
-
- if acct_scheme_name:
- if len(acct_scheme_name) > 32:
- module.fail_json(
- msg='Error: acct_scheme_name %s '
- 'is large than 32.' % acct_scheme_name)
- check_name(module=module, name=acct_scheme_name,
- invalid_char=INVALID_SCHEME_CHAR)
-
- if domain_name:
- if len(domain_name) > 64:
- module.fail_json(
- msg='Error: domain_name %s '
- 'is large than 64.' % domain_name)
- check_name(module=module, name=domain_name,
- invalid_char=INVALID_DOMAIN_CHAR)
- if domain_name == "-" or domain_name == "--":
- module.fail_json(msg='domain_name %s '
- 'is invalid.' % domain_name)
-
- if radius_server_group and len(radius_server_group) > 32:
- module.fail_json(msg='Error: radius_server_group %s '
- 'is large than 32.' % radius_server_group)
-
- if hwtacas_template and len(hwtacas_template) > 32:
- module.fail_json(
- msg='Error: hwtacas_template %s '
- 'is large than 32.' % hwtacas_template)
-
- if local_user_group:
- if len(local_user_group) > 32:
- module.fail_json(
- msg='Error: local_user_group %s '
- 'is large than 32.' % local_user_group)
- check_name(module=module, name=local_user_group, invalid_char=INVALID_GROUP_CHAR)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- authen_scheme_name=dict(type='str'),
- first_authen_mode=dict(default='local', choices=['invalid', 'local', 'hwtacacs', 'radius', 'none']),
- author_scheme_name=dict(type='str'),
- first_author_mode=dict(default='local', choices=['invalid', 'local', 'hwtacacs', 'if-authenticated', 'none']),
- acct_scheme_name=dict(type='str'),
- accounting_mode=dict(default='none', choices=['invalid', 'hwtacacs', 'radius', 'none']),
- domain_name=dict(type='str'),
- radius_server_group=dict(type='str'),
- hwtacas_template=dict(type='str'),
- local_user_group=dict(type='str')
- )
-
- argument_spec.update(ce_argument_spec)
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- check_module_argument(module=module)
-
- changed = False
- proposed = dict()
- existing = dict()
- end_state = dict()
- updates = []
-
- state = module.params['state']
- authen_scheme_name = module.params['authen_scheme_name']
- first_authen_mode = module.params['first_authen_mode']
- author_scheme_name = module.params['author_scheme_name']
- first_author_mode = module.params['first_author_mode']
- acct_scheme_name = module.params['acct_scheme_name']
- accounting_mode = module.params['accounting_mode']
- domain_name = module.params['domain_name']
- radius_server_group = module.params['radius_server_group']
- hwtacas_template = module.params['hwtacas_template']
- local_user_group = module.params['local_user_group']
-
- ce_aaa_server = AaaServer()
-
- if not ce_aaa_server:
- module.fail_json(msg='Error: init module failed.')
-
- # get proposed
- proposed["state"] = state
- if authen_scheme_name:
- proposed["authen_scheme_name"] = authen_scheme_name
- if first_authen_mode:
- proposed["first_authen_mode"] = first_authen_mode
- if author_scheme_name:
- proposed["author_scheme_name"] = author_scheme_name
- if first_author_mode:
- proposed["first_author_mode"] = first_author_mode
- if acct_scheme_name:
- proposed["acct_scheme_name"] = acct_scheme_name
- if accounting_mode:
- proposed["accounting_mode"] = accounting_mode
- if domain_name:
- proposed["domain_name"] = domain_name
- if radius_server_group:
- proposed["radius_server_group"] = radius_server_group
- if hwtacas_template:
- proposed["hwtacas_template"] = hwtacas_template
- if local_user_group:
- proposed["local_user_group"] = local_user_group
-
- # authentication
- if authen_scheme_name:
-
- scheme_exist = ce_aaa_server.get_authentication_scheme(module=module)
- scheme_new = (authen_scheme_name.lower(), first_authen_mode.lower(), "invalid")
-
- existing["authentication scheme"] = scheme_exist
-
- if state == "present":
- # present authentication scheme
- if len(scheme_exist) == 0:
- cmd = ce_aaa_server.create_authentication_scheme(
- module=module,
- authen_scheme_name=authen_scheme_name,
- first_authen_mode=first_authen_mode)
-
- updates.append(cmd)
- changed = True
-
- elif scheme_new not in scheme_exist:
- cmd = ce_aaa_server.merge_authentication_scheme(
- module=module,
- authen_scheme_name=authen_scheme_name,
- first_authen_mode=first_authen_mode)
- updates.append(cmd)
- changed = True
-
- # present authentication domain
- if domain_name:
- domain_exist = ce_aaa_server.get_authentication_domain(
- module=module)
- domain_new = (domain_name.lower(), authen_scheme_name.lower())
-
- if len(domain_exist) == 0:
- cmd = ce_aaa_server.create_authentication_domain(
- module=module,
- domain_name=domain_name,
- authen_scheme_name=authen_scheme_name)
- updates.append(cmd)
- changed = True
-
- elif domain_new not in domain_exist:
- cmd = ce_aaa_server.merge_authentication_domain(
- module=module,
- domain_name=domain_name,
- authen_scheme_name=authen_scheme_name)
- updates.append(cmd)
- changed = True
-
- else:
- # absent authentication scheme
- if not domain_name:
- if len(scheme_exist) == 0:
- pass
- elif scheme_new not in scheme_exist:
- pass
- else:
- cmd = ce_aaa_server.delete_authentication_scheme(
- module=module,
- authen_scheme_name=authen_scheme_name,
- first_authen_mode=first_authen_mode)
- updates.append(cmd)
- changed = True
-
- # absent authentication domain
- else:
- domain_exist = ce_aaa_server.get_authentication_domain(
- module=module)
- domain_new = (domain_name.lower(), authen_scheme_name.lower())
-
- if len(domain_exist) == 0:
- pass
- elif domain_new not in domain_exist:
- pass
- else:
- cmd = ce_aaa_server.delete_authentication_domain(
- module=module,
- domain_name=domain_name,
- authen_scheme_name=authen_scheme_name)
- updates.append(cmd)
- changed = True
-
- scheme_end = ce_aaa_server.get_authentication_scheme(module=module)
- end_state["authentication scheme"] = scheme_end
-
- # authorization
- if author_scheme_name:
-
- scheme_exist = ce_aaa_server.get_authorization_scheme(module=module)
- scheme_new = (author_scheme_name.lower(), first_author_mode.lower(), "invalid")
-
- existing["authorization scheme"] = scheme_exist
-
- if state == "present":
- # present authorization scheme
- if len(scheme_exist) == 0:
- cmd = ce_aaa_server.create_authorization_scheme(
- module=module,
- author_scheme_name=author_scheme_name,
- first_author_mode=first_author_mode)
- updates.append(cmd)
- changed = True
- elif scheme_new not in scheme_exist:
- cmd = ce_aaa_server.merge_authorization_scheme(
- module=module,
- author_scheme_name=author_scheme_name,
- first_author_mode=first_author_mode)
- updates.append(cmd)
- changed = True
-
- # present authorization domain
- if domain_name:
- domain_exist = ce_aaa_server.get_authorization_domain(
- module=module)
- domain_new = (domain_name.lower(), author_scheme_name.lower())
-
- if len(domain_exist) == 0:
- cmd = ce_aaa_server.create_authorization_domain(
- module=module,
- domain_name=domain_name,
- author_scheme_name=author_scheme_name)
- updates.append(cmd)
- changed = True
- elif domain_new not in domain_exist:
- cmd = ce_aaa_server.merge_authorization_domain(
- module=module,
- domain_name=domain_name,
- author_scheme_name=author_scheme_name)
- updates.append(cmd)
- changed = True
-
- else:
- # absent authorization scheme
- if not domain_name:
- if len(scheme_exist) == 0:
- pass
- elif scheme_new not in scheme_exist:
- pass
- else:
- cmd = ce_aaa_server.delete_authorization_scheme(
- module=module,
- author_scheme_name=author_scheme_name,
- first_author_mode=first_author_mode)
- updates.append(cmd)
- changed = True
-
- # absent authorization domain
- else:
- domain_exist = ce_aaa_server.get_authorization_domain(
- module=module)
- domain_new = (domain_name.lower(), author_scheme_name.lower())
-
- if len(domain_exist) == 0:
- pass
- elif domain_new not in domain_exist:
- pass
- else:
- cmd = ce_aaa_server.delete_authorization_domain(
- module=module,
- domain_name=domain_name,
- author_scheme_name=author_scheme_name)
- updates.append(cmd)
- changed = True
-
- scheme_end = ce_aaa_server.get_authorization_scheme(module=module)
- end_state["authorization scheme"] = scheme_end
-
- # accounting
- if acct_scheme_name:
-
- scheme_exist = ce_aaa_server.get_accounting_scheme(module=module)
- scheme_new = (acct_scheme_name.lower(), accounting_mode.lower())
-
- existing["accounting scheme"] = scheme_exist
-
- if state == "present":
- # present accounting scheme
- if len(scheme_exist) == 0:
- cmd = ce_aaa_server.create_accounting_scheme(
- module=module,
- acct_scheme_name=acct_scheme_name,
- accounting_mode=accounting_mode)
- updates.append(cmd)
- changed = True
- elif scheme_new not in scheme_exist:
- cmd = ce_aaa_server.merge_accounting_scheme(
- module=module,
- acct_scheme_name=acct_scheme_name,
- accounting_mode=accounting_mode)
- updates.append(cmd)
- changed = True
-
- # present accounting domain
- if domain_name:
- domain_exist = ce_aaa_server.get_accounting_domain(
- module=module)
- domain_new = (domain_name.lower(), acct_scheme_name.lower())
-
- if len(domain_exist) == 0:
- cmd = ce_aaa_server.create_accounting_domain(
- module=module,
- domain_name=domain_name,
- acct_scheme_name=acct_scheme_name)
- updates.append(cmd)
- changed = True
- elif domain_new not in domain_exist:
- cmd = ce_aaa_server.merge_accounting_domain(
- module=module,
- domain_name=domain_name,
- acct_scheme_name=acct_scheme_name)
- updates.append(cmd)
- changed = True
-
- else:
- # absent accounting scheme
- if not domain_name:
- if len(scheme_exist) == 0:
- pass
- elif scheme_new not in scheme_exist:
- pass
- else:
- cmd = ce_aaa_server.delete_accounting_scheme(
- module=module,
- acct_scheme_name=acct_scheme_name,
- accounting_mode=accounting_mode)
- updates.append(cmd)
- changed = True
-
- # absent accounting domain
- else:
- domain_exist = ce_aaa_server.get_accounting_domain(
- module=module)
- domain_new = (domain_name.lower(), acct_scheme_name.lower())
- if len(domain_exist) == 0:
- pass
- elif domain_new not in domain_exist:
- pass
- else:
- cmd = ce_aaa_server.delete_accounting_domain(
- module=module,
- domain_name=domain_name,
- acct_scheme_name=acct_scheme_name)
- updates.append(cmd)
- changed = True
-
- scheme_end = ce_aaa_server.get_accounting_scheme(module=module)
- end_state["accounting scheme"] = scheme_end
-
- # radius group name
- if (authen_scheme_name and first_authen_mode.lower() == "radius") \
- or (acct_scheme_name and accounting_mode.lower() == "radius"):
-
- if not radius_server_group:
- module.fail_json(msg='please input radius_server_group when use radius.')
-
- rds_template_exist = ce_aaa_server.get_radius_template(module=module)
- rds_template_new = (radius_server_group)
-
- rds_enable_exist = ce_aaa_server.get_radius_client(module=module)
-
- existing["radius template"] = rds_template_exist
- existing["radius enable"] = rds_enable_exist
-
- if state == "present":
- # present radius group name
- if len(rds_template_exist) == 0:
- cmd = ce_aaa_server.create_radius_template(
- module=module, radius_server_group=radius_server_group)
- updates.append(cmd)
- changed = True
- elif rds_template_new not in rds_template_exist:
- cmd = ce_aaa_server.merge_radius_template(
- module=module, radius_server_group=radius_server_group)
- updates.append(cmd)
- changed = True
-
- rds_enable_new = ("true")
- if rds_enable_new not in rds_enable_exist:
- cmd = ce_aaa_server.merge_radius_client(
- module=module, isEnable="true")
- updates.append(cmd)
- changed = True
-
- else:
- # absent radius group name
- if len(rds_template_exist) == 0:
- pass
- elif rds_template_new not in rds_template_exist:
- pass
- else:
- cmd = ce_aaa_server.delete_radius_template(
- module=module, radius_server_group=radius_server_group)
- updates.append(cmd)
- changed = True
-
- rds_enable_new = ("false")
- if rds_enable_new not in rds_enable_exist:
- cmd = ce_aaa_server.merge_radius_client(
- module=module, isEnable="false")
- updates.append(cmd)
- changed = True
- else:
- pass
-
- rds_template_end = ce_aaa_server.get_radius_template(module=module)
- end_state["radius template"] = rds_template_end
-
- rds_enable_end = ce_aaa_server.get_radius_client(module=module)
- end_state["radius enable"] = rds_enable_end
-
- tmp_scheme = author_scheme_name
-
- # hwtacas template
- if (authen_scheme_name and first_authen_mode.lower() == "hwtacacs") \
- or (tmp_scheme and first_author_mode.lower() == "hwtacacs") \
- or (acct_scheme_name and accounting_mode.lower() == "hwtacacs"):
-
- if not hwtacas_template:
- module.fail_json(
- msg='please input hwtacas_template when use hwtacas.')
-
- hwtacacs_exist = ce_aaa_server.get_hwtacacs_template(module=module)
- hwtacacs_new = (hwtacas_template)
-
- hwtacacs_enbale_exist = ce_aaa_server.get_hwtacacs_global_cfg(
- module=module)
-
- existing["hwtacacs template"] = hwtacacs_exist
- existing["hwtacacs enable"] = hwtacacs_enbale_exist
-
- if state == "present":
- # present hwtacas template
- if len(hwtacacs_exist) == 0:
- cmd = ce_aaa_server.create_hwtacacs_template(
- module=module, hwtacas_template=hwtacas_template)
- updates.append(cmd)
- changed = True
- elif hwtacacs_new not in hwtacacs_exist:
- cmd = ce_aaa_server.merge_hwtacacs_template(
- module=module, hwtacas_template=hwtacas_template)
- updates.append(cmd)
- changed = True
-
- hwtacacs_enbale_new = ("true")
- if hwtacacs_enbale_new not in hwtacacs_enbale_exist:
- cmd = ce_aaa_server.merge_hwtacacs_global_cfg(
- module=module, isEnable="true")
- updates.append(cmd)
- changed = True
-
- else:
- # absent hwtacas template
- if len(hwtacacs_exist) == 0:
- pass
- elif hwtacacs_new not in hwtacacs_exist:
- pass
- else:
- cmd = ce_aaa_server.delete_hwtacacs_template(
- module=module, hwtacas_template=hwtacas_template)
- updates.append(cmd)
- changed = True
-
- hwtacacs_enbale_new = ("false")
- if hwtacacs_enbale_new not in hwtacacs_enbale_exist:
- cmd = ce_aaa_server.merge_hwtacacs_global_cfg(
- module=module, isEnable="false")
- updates.append(cmd)
- changed = True
- else:
- pass
-
- hwtacacs_end = ce_aaa_server.get_hwtacacs_template(module=module)
- end_state["hwtacacs template"] = hwtacacs_end
-
- hwtacacs_enable_end = ce_aaa_server.get_hwtacacs_global_cfg(
- module=module)
- end_state["hwtacacs enable"] = hwtacacs_enable_end
-
- # local user group
- if local_user_group:
-
- user_group_exist = ce_aaa_server.get_local_user_group(module=module)
- user_group_new = (local_user_group)
-
- existing["local user group"] = user_group_exist
-
- if state == "present":
- # present local user group
- if len(user_group_exist) == 0:
- cmd = ce_aaa_server.merge_local_user_group(
- module=module, local_user_group=local_user_group)
- updates.append(cmd)
- changed = True
- elif user_group_new not in user_group_exist:
- cmd = ce_aaa_server.merge_local_user_group(
- module=module, local_user_group=local_user_group)
- updates.append(cmd)
- changed = True
-
- else:
- # absent local user group
- if len(user_group_exist) == 0:
- pass
- elif user_group_new not in user_group_exist:
- pass
- else:
- cmd = ce_aaa_server.delete_local_user_group(
- module=module, local_user_group=local_user_group)
- updates.append(cmd)
- changed = True
-
- user_group_end = ce_aaa_server.get_local_user_group(module=module)
- end_state["local user group"] = user_group_end
-
- results = dict()
- results['proposed'] = proposed
- results['existing'] = existing
- results['changed'] = changed
- results['end_state'] = end_state
- results['updates'] = updates
-
- module.exit_json(**results)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_aaa_server_host.py b/plugins/modules/network/cloudengine/ce_aaa_server_host.py
deleted file mode 100644
index 89777c75fd..0000000000
--- a/plugins/modules/network/cloudengine/ce_aaa_server_host.py
+++ /dev/null
@@ -1,2640 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_aaa_server_host
-short_description: Manages AAA server host configuration on HUAWEI CloudEngine switches.
-description:
- - Manages AAA server host configuration on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- state:
- description:
- - Specify desired state of the resource.
- default: present
- choices: ['present', 'absent']
- local_user_name:
- description:
- - Name of a local user.
- The value is a string of 1 to 253 characters.
- local_password:
- description:
- - Login password of a user. The password can contain letters, numbers, and special characters.
- The value is a string of 1 to 255 characters.
- local_service_type:
- description:
- - The type of local user login through, such as ftp ssh snmp telnet.
- local_ftp_dir:
- description:
- - FTP user directory.
- The value is a string of 1 to 255 characters.
- local_user_level:
- description:
- - Login level of a local user.
- The value is an integer ranging from 0 to 15.
- local_user_group:
- description:
- - Name of the user group where the user belongs. The user inherits all the rights of the user group.
- The value is a string of 1 to 32 characters.
- radius_group_name:
- description:
- - RADIUS server group's name.
- The value is a string of 1 to 32 case-insensitive characters.
- radius_server_type:
- description:
- - Type of Radius Server.
- choices: ['Authentication', 'Accounting']
- radius_server_ip:
- description:
- - IPv4 address of configured server.
- The value is a string of 0 to 255 characters, in dotted decimal notation.
- radius_server_ipv6:
- description:
- - IPv6 address of configured server.
- The total length is 128 bits.
- radius_server_port:
- description:
- - Configured server port for a particular server.
- The value is an integer ranging from 1 to 65535.
- radius_server_mode:
- description:
- - Configured primary or secondary server for a particular server.
- choices: ['Secondary-server', 'Primary-server']
- radius_vpn_name:
- description:
- - Set VPN instance.
- The value is a string of 1 to 31 case-sensitive characters.
- radius_server_name:
- description:
- - Hostname of configured server.
- The value is a string of 0 to 255 case-sensitive characters.
- hwtacacs_template:
- description:
- - Name of a HWTACACS template.
- The value is a string of 1 to 32 case-insensitive characters.
- hwtacacs_server_ip:
- description:
- - Server IPv4 address. Must be a valid unicast IP address.
- The value is a string of 0 to 255 characters, in dotted decimal notation.
- hwtacacs_server_ipv6:
- description:
- - Server IPv6 address. Must be a valid unicast IP address.
- The total length is 128 bits.
- hwtacacs_server_type:
- description:
- - Hwtacacs server type.
- choices: ['Authentication', 'Authorization', 'Accounting', 'Common']
- hwtacacs_is_secondary_server:
- description:
- - Whether the server is secondary.
- type: bool
- default: 'no'
- hwtacacs_vpn_name:
- description:
- - VPN instance name.
- hwtacacs_is_public_net:
- description:
- - Set the public-net.
- type: bool
- default: 'no'
- hwtacacs_server_host_name:
- description:
- - Hwtacacs server host name.
-'''
-
-EXAMPLES = '''
-
-- name: AAA server host test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Config local user when use local scheme"
- ce_aaa_server_host:
- state: present
- local_user_name: user1
- local_password: 123456
- provider: "{{ cli }}"
-
- - name: "Undo local user when use local scheme"
- ce_aaa_server_host:
- state: absent
- local_user_name: user1
- local_password: 123456
- provider: "{{ cli }}"
-
- - name: "Config radius server ip"
- ce_aaa_server_host:
- state: present
- radius_group_name: group1
- radius_server_type: Authentication
- radius_server_ip: 10.1.10.1
- radius_server_port: 2000
- radius_server_mode: Primary-server
- radius_vpn_name: _public_
- provider: "{{ cli }}"
-
- - name: "Undo radius server ip"
- ce_aaa_server_host:
- state: absent
- radius_group_name: group1
- radius_server_type: Authentication
- radius_server_ip: 10.1.10.1
- radius_server_port: 2000
- radius_server_mode: Primary-server
- radius_vpn_name: _public_
- provider: "{{ cli }}"
-
- - name: "Config hwtacacs server ip"
- ce_aaa_server_host:
- state: present
- hwtacacs_template: template
- hwtacacs_server_ip: 10.10.10.10
- hwtacacs_server_type: Authorization
- hwtacacs_vpn_name: _public_
- provider: "{{ cli }}"
-
- - name: "Undo hwtacacs server ip"
- ce_aaa_server_host:
- state: absent
- hwtacacs_template: template
- hwtacacs_server_ip: 10.10.10.10
- hwtacacs_server_type: Authorization
- hwtacacs_vpn_name: _public_
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"hwtacacs_is_public_net": "false",
- "hwtacacs_is_secondary_server": "false",
- "hwtacacs_server_ip": "10.135.182.157",
- "hwtacacs_server_type": "Authorization",
- "hwtacacs_template": "wdz",
- "hwtacacs_vpn_name": "_public_",
- "local_password": "******",
- "state": "present"}
-existing:
- description: k/v pairs of existing aaa server host
- returned: always
- type: dict
- sample: {"radius server ipv4": []}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"radius server ipv4": [
- [
- "10.1.10.1",
- "Authentication",
- "2000",
- "Primary-server",
- "_public_"
- ]
- ]}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["hwtacacs server template test",
- "hwtacacs server authorization 10.135.182.157 vpn-instance test_vpn public-net"]
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec, check_ip_addr
-
-SUCCESS = """success"""
-FAILED = """failed"""
-
-INVALID_USER_NAME_CHAR = [' ', '/', '\\',
- ':', '*', '?', '"', '\'', '<', '>', '%']
-
-# get local user name
-CE_GET_LOCAL_USER_INFO_HEADER = """
-
-
-
-
-
-
-
-"""
-CE_GET_LOCAL_USER_INFO_TAIL = """
-
-
-
-
-
-"""
-
-# merge local user name
-CE_MERGE_LOCAL_USER_INFO_HEADER = """
-
-
-
-
-
- %s
-"""
-CE_MERGE_LOCAL_USER_INFO_TAIL = """
-
-
-
-
-
-"""
-
-# delete local user name
-CE_DELETE_LOCAL_USER_INFO_HEADER = """
-
-
-
-
-
- %s
-"""
-CE_DELETE_LOCAL_USER_INFO_TAIL = """
-
-
-
-
-
-"""
-
-# get radius server config ipv4
-CE_GET_RADIUS_SERVER_CFG_IPV4 = """
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge radius server config ipv4
-CE_MERGE_RADIUS_SERVER_CFG_IPV4 = """
-
-
-
-
- %s
-
-
- %s
- %s
- %s
- %s
- %s
-
-
-
-
-
-
-"""
-
-# delete radius server config ipv4
-CE_DELETE_RADIUS_SERVER_CFG_IPV4 = """
-
-
-
-
- %s
-
-
- %s
- %s
- %s
- %s
- %s
-
-
-
-
-
-
-"""
-
-# get radius server config ipv6
-CE_GET_RADIUS_SERVER_CFG_IPV6 = """
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge radius server config ipv6
-CE_MERGE_RADIUS_SERVER_CFG_IPV6 = """
-
-
-
-
- %s
-
-
- %s
- %s
- %s
- %s
-
-
-
-
-
-
-"""
-
-# delete radius server config ipv6
-CE_DELETE_RADIUS_SERVER_CFG_IPV6 = """
-
-
-
-
- %s
-
-
- %s
- %s
- %s
- %s
-
-
-
-
-
-
-"""
-
-# get radius server name
-CE_GET_RADIUS_SERVER_NAME = """
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge radius server name
-CE_MERGE_RADIUS_SERVER_NAME = """
-
-
-
-
- %s
-
-
- %s
- %s
- %s
- %s
- %s
-
-
-
-
-
-
-"""
-
-# delete radius server name
-CE_DELETE_RADIUS_SERVER_NAME = """
-
-
-
-
- %s
-
-
- %s
- %s
- %s
- %s
- %s
-
-
-
-
-
-
-"""
-
-# get hwtacacs server config ipv4
-CE_GET_HWTACACS_SERVER_CFG_IPV4 = """
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge hwtacacs server config ipv4
-CE_MERGE_HWTACACS_SERVER_CFG_IPV4 = """
-
-
-
-
- %s
-
-
- %s
- %s
- %s
- %s
- %s
-
-
-
-
-
-
-"""
-
-# delete hwtacacs server config ipv4
-CE_DELETE_HWTACACS_SERVER_CFG_IPV4 = """
-
-
-
-
- %s
-
-
- %s
- %s
- %s
- %s
- %s
-
-
-
-
-
-
-"""
-
-# get hwtacacs server config ipv6
-CE_GET_HWTACACS_SERVER_CFG_IPV6 = """
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge hwtacacs server config ipv6
-CE_MERGE_HWTACACS_SERVER_CFG_IPV6 = """
-
-
-
-
- %s
-
-
- %s
- %s
- %s
- %s
-
-
-
-
-
-
-"""
-
-# delete hwtacacs server config ipv6
-CE_DELETE_HWTACACS_SERVER_CFG_IPV6 = """
-
-
-
-
- %s
-
-
- %s
- %s
- %s
- %s
-
-
-
-
-
-
-"""
-
-# get hwtacacs host server config
-CE_GET_HWTACACS_HOST_SERVER_CFG = """
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge hwtacacs host server config
-CE_MERGE_HWTACACS_HOST_SERVER_CFG = """
-
-
-
-
- %s
-
-
- %s
- %s
- %s
- %s
- %s
-
-
-
-
-
-
-"""
-
-# delete hwtacacs host server config
-CE_DELETE_HWTACACS_HOST_SERVER_CFG = """
-
-
-
-
- %s
-
-
- %s
- %s
- %s
- %s
- %s
-
-
-
-
-
-
-"""
-
-
-class AaaServerHost(object):
- """ Manages aaa server host configuration """
-
- def netconf_get_config(self, **kwargs):
- """ Get configure by netconf """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- xml_str = get_nc_config(module, conf_str)
-
- return xml_str
-
- def netconf_set_config(self, **kwargs):
- """ Set configure by netconf """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- recv_xml = set_nc_config(module, conf_str)
-
- return recv_xml
-
- def get_local_user_info(self, **kwargs):
- """ Get local user information """
-
- module = kwargs["module"]
- local_user_name = module.params['local_user_name']
- local_service_type = module.params['local_service_type']
- local_ftp_dir = module.params['local_ftp_dir']
- local_user_level = module.params['local_user_level']
- local_user_group = module.params['local_user_group']
- state = module.params['state']
-
- result = dict()
- result["local_user_info"] = []
- need_cfg = False
-
- conf_str = CE_GET_LOCAL_USER_INFO_HEADER
-
- if local_service_type:
- if local_service_type == "none":
- conf_str += ""
- conf_str += ""
- conf_str += ""
- conf_str += ""
- conf_str += ""
- conf_str += ""
- elif local_service_type == "dot1x":
- conf_str += ""
- else:
- option = local_service_type.split(" ")
- for tmp in option:
- if tmp == "dot1x":
- module.fail_json(
- msg='Error: Do not input dot1x with other service type.')
- elif tmp == "none":
- module.fail_json(
- msg='Error: Do not input none with other service type.')
- elif tmp == "ftp":
- conf_str += ""
- elif tmp == "snmp":
- conf_str += ""
- elif tmp == "ssh":
- conf_str += ""
- elif tmp == "telnet":
- conf_str += ""
- elif tmp == "terminal":
- conf_str += ""
- else:
- module.fail_json(
- msg='Error: Do not support the type [%s].' % tmp)
-
- if local_ftp_dir:
- conf_str += ""
-
- if local_user_level:
- conf_str += ""
-
- if local_user_group:
- conf_str += ""
-
- conf_str += CE_GET_LOCAL_USER_INFO_TAIL
-
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- if state == "present":
- need_cfg = True
-
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- local_user_info = root.findall("aaa/lam/users/user")
- if local_user_info:
- for tmp in local_user_info:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["userName", "password", "userLevel", "ftpDir", "userGroupName",
- "serviceTerminal", "serviceTelnet", "serviceFtp", "serviceSsh",
- "serviceSnmp", "serviceDot1x"]:
- tmp_dict[site.tag] = site.text
-
- result["local_user_info"].append(tmp_dict)
-
- if state == "present":
- need_cfg = True
- else:
- if result["local_user_info"]:
- for tmp in result["local_user_info"]:
- if "userName" in tmp.keys():
- if tmp["userName"] == local_user_name:
-
- if not local_service_type and not local_user_level \
- and not local_ftp_dir and not local_user_group:
-
- need_cfg = True
-
- if local_service_type:
- if local_service_type == "none":
- if tmp.get("serviceTerminal") == "true" or \
- tmp.get("serviceTelnet") == "true" or \
- tmp.get("serviceFtp") == "true" or \
- tmp.get("serviceSsh") == "true" or \
- tmp.get("serviceSnmp") == "true" or \
- tmp.get("serviceDot1x") == "true":
- need_cfg = True
- elif local_service_type == "dot1x":
- if tmp.get("serviceDot1x") == "true":
- need_cfg = True
- elif tmp == "ftp":
- if tmp.get("serviceFtp") == "true":
- need_cfg = True
- elif tmp == "snmp":
- if tmp.get("serviceSnmp") == "true":
- need_cfg = True
- elif tmp == "ssh":
- if tmp.get("serviceSsh") == "true":
- need_cfg = True
- elif tmp == "telnet":
- if tmp.get("serviceTelnet") == "true":
- need_cfg = True
- elif tmp == "terminal":
- if tmp.get("serviceTerminal") == "true":
- need_cfg = True
-
- if local_user_level:
- if tmp.get("userLevel") == local_user_level:
- need_cfg = True
-
- if local_ftp_dir:
- if tmp.get("ftpDir") == local_ftp_dir:
- need_cfg = True
-
- if local_user_group:
- if tmp.get("userGroupName") == local_user_group:
- need_cfg = True
-
- break
-
- result["need_cfg"] = need_cfg
- return result
-
- def merge_local_user_info(self, **kwargs):
- """ Merge local user information by netconf """
-
- module = kwargs["module"]
- local_user_name = module.params['local_user_name']
- local_password = module.params['local_password']
- local_service_type = module.params['local_service_type']
- local_ftp_dir = module.params['local_ftp_dir']
- local_user_level = module.params['local_user_level']
- local_user_group = module.params['local_user_group']
- state = module.params['state']
-
- cmds = []
-
- conf_str = CE_MERGE_LOCAL_USER_INFO_HEADER % local_user_name
-
- if local_password:
- conf_str += "%s" % local_password
-
- if state == "present":
- cmd = "local-user %s password cipher %s" % (
- local_user_name, local_password)
- cmds.append(cmd)
-
- if local_service_type:
- if local_service_type == "none":
- conf_str += "false"
- conf_str += "false"
- conf_str += "false"
- conf_str += "false"
- conf_str += "false"
- conf_str += "false"
-
- cmd = "local-user %s service-type none" % local_user_name
- cmds.append(cmd)
-
- elif local_service_type == "dot1x":
- if state == "present":
- conf_str += "true"
- cmd = "local-user %s service-type dot1x" % local_user_name
- else:
- conf_str += "false"
- cmd = "undo local-user %s service-type" % local_user_name
-
- cmds.append(cmd)
-
- else:
- option = local_service_type.split(" ")
- for tmp in option:
- if tmp == "dot1x":
- module.fail_json(
- msg='Error: Do not input dot1x with other service type.')
- if tmp == "none":
- module.fail_json(
- msg='Error: Do not input none with other service type.')
-
- if state == "present":
- if tmp == "ftp":
- conf_str += "true"
- cmd = "local-user %s service-type ftp" % local_user_name
- elif tmp == "snmp":
- conf_str += "true"
- cmd = "local-user %s service-type snmp" % local_user_name
- elif tmp == "ssh":
- conf_str += "true"
- cmd = "local-user %s service-type ssh" % local_user_name
- elif tmp == "telnet":
- conf_str += "true"
- cmd = "local-user %s service-type telnet" % local_user_name
- elif tmp == "terminal":
- conf_str += "true"
- cmd = "local-user %s service-type terminal" % local_user_name
-
- cmds.append(cmd)
-
- else:
- if tmp == "ftp":
- conf_str += "false"
- elif tmp == "snmp":
- conf_str += "false"
- elif tmp == "ssh":
- conf_str += "false"
- elif tmp == "telnet":
- conf_str += "false"
- elif tmp == "terminal":
- conf_str += "false"
-
- if state == "absent":
- cmd = "undo local-user %s service-type" % local_user_name
- cmds.append(cmd)
-
- if local_ftp_dir:
- if state == "present":
- conf_str += "%s" % local_ftp_dir
- cmd = "local-user %s ftp-directory %s" % (
- local_user_name, local_ftp_dir)
- cmds.append(cmd)
- else:
- conf_str += ""
- cmd = "undo local-user %s ftp-directory" % local_user_name
- cmds.append(cmd)
-
- if local_user_level:
- if state == "present":
- conf_str += "%s" % local_user_level
- cmd = "local-user %s level %s" % (
- local_user_name, local_user_level)
- cmds.append(cmd)
- else:
- conf_str += ""
- cmd = "undo local-user %s level" % local_user_name
- cmds.append(cmd)
-
- if local_user_group:
- if state == "present":
- conf_str += "%s" % local_user_group
- cmd = "local-user %s user-group %s" % (
- local_user_name, local_user_group)
- cmds.append(cmd)
- else:
- conf_str += ""
- cmd = "undo local-user %s user-group" % local_user_name
- cmds.append(cmd)
-
- conf_str += CE_MERGE_LOCAL_USER_INFO_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge local user info failed.')
-
- return cmds
-
- def delete_local_user_info(self, **kwargs):
- """ Delete local user information by netconf """
-
- module = kwargs["module"]
- local_user_name = module.params['local_user_name']
- conf_str = CE_DELETE_LOCAL_USER_INFO_HEADER % local_user_name
- conf_str += CE_DELETE_LOCAL_USER_INFO_TAIL
-
- cmds = []
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Delete local user info failed.')
-
- cmd = "undo local-user %s" % local_user_name
- cmds.append(cmd)
-
- return cmds
-
- def get_radius_server_cfg_ipv4(self, **kwargs):
- """ Get radius server configure ipv4 """
-
- module = kwargs["module"]
- radius_group_name = module.params['radius_group_name']
- radius_server_type = module.params['radius_server_type']
- radius_server_ip = module.params['radius_server_ip']
- radius_server_port = module.params['radius_server_port']
- radius_server_mode = module.params['radius_server_mode']
- radius_vpn_name = module.params['radius_vpn_name']
- state = module.params['state']
-
- result = dict()
- result["radius_server_ip_v4"] = []
- need_cfg = False
-
- conf_str = CE_GET_RADIUS_SERVER_CFG_IPV4 % radius_group_name
-
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- if state == "present":
- need_cfg = True
-
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- radius_server_ip_v4 = root.findall(
- "radius/rdsTemplates/rdsTemplate/rdsServerIPV4s/rdsServerIPV4")
- if radius_server_ip_v4:
- for tmp in radius_server_ip_v4:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["serverType", "serverIPAddress", "serverPort", "serverMode", "vpnName"]:
- tmp_dict[site.tag] = site.text
-
- result["radius_server_ip_v4"].append(tmp_dict)
-
- if result["radius_server_ip_v4"]:
- cfg = dict()
- config_list = list()
- if radius_server_type:
- cfg["serverType"] = radius_server_type.lower()
- if radius_server_ip:
- cfg["serverIPAddress"] = radius_server_ip.lower()
- if radius_server_port:
- cfg["serverPort"] = radius_server_port.lower()
- if radius_server_mode:
- cfg["serverMode"] = radius_server_mode.lower()
- if radius_vpn_name:
- cfg["vpnName"] = radius_vpn_name.lower()
-
- for tmp in result["radius_server_ip_v4"]:
- exist_cfg = dict()
- if radius_server_type:
- exist_cfg["serverType"] = tmp.get("serverType").lower()
- if radius_server_ip:
- exist_cfg["serverIPAddress"] = tmp.get("serverIPAddress").lower()
- if radius_server_port:
- exist_cfg["serverPort"] = tmp.get("serverPort").lower()
- if radius_server_mode:
- exist_cfg["serverMode"] = tmp.get("serverMode").lower()
- if radius_vpn_name:
- exist_cfg["vpnName"] = tmp.get("vpnName").lower()
- config_list.append(exist_cfg)
- if cfg in config_list:
- if state == "present":
- need_cfg = False
- else:
- need_cfg = True
- else:
- if state == "present":
- need_cfg = True
- else:
- need_cfg = False
- result["need_cfg"] = need_cfg
- return result
-
- def merge_radius_server_cfg_ipv4(self, **kwargs):
- """ Merge radius server configure ipv4 """
-
- module = kwargs["module"]
- radius_group_name = module.params['radius_group_name']
- radius_server_type = module.params['radius_server_type']
- radius_server_ip = module.params['radius_server_ip']
- radius_server_port = module.params['radius_server_port']
- radius_server_mode = module.params['radius_server_mode']
- radius_vpn_name = module.params['radius_vpn_name']
-
- conf_str = CE_MERGE_RADIUS_SERVER_CFG_IPV4 % (
- radius_group_name, radius_server_type,
- radius_server_ip, radius_server_port,
- radius_server_mode, radius_vpn_name)
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Merge radius server config ipv4 failed.')
-
- cmds = []
-
- cmd = "radius server group %s" % radius_group_name
- cmds.append(cmd)
-
- if radius_server_type == "Authentication":
- cmd = "radius server authentication %s %s" % (
- radius_server_ip, radius_server_port)
-
- if radius_vpn_name and radius_vpn_name != "_public_":
- cmd += " vpn-instance %s" % radius_vpn_name
-
- if radius_server_mode == "Secondary-server":
- cmd += " secondary"
- else:
- cmd = "radius server accounting %s %s" % (
- radius_server_ip, radius_server_port)
-
- if radius_vpn_name and radius_vpn_name != "_public_":
- cmd += " vpn-instance %s" % radius_vpn_name
-
- if radius_server_mode == "Secondary-server":
- cmd += " secondary"
-
- cmds.append(cmd)
- return cmds
-
- def delete_radius_server_cfg_ipv4(self, **kwargs):
- """ Delete radius server configure ipv4 """
-
- module = kwargs["module"]
- radius_group_name = module.params['radius_group_name']
- radius_server_type = module.params['radius_server_type']
- radius_server_ip = module.params['radius_server_ip']
- radius_server_port = module.params['radius_server_port']
- radius_server_mode = module.params['radius_server_mode']
- radius_vpn_name = module.params['radius_vpn_name']
-
- conf_str = CE_DELETE_RADIUS_SERVER_CFG_IPV4 % (
- radius_group_name, radius_server_type,
- radius_server_ip, radius_server_port,
- radius_server_mode, radius_vpn_name)
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Create radius server config ipv4 failed.')
-
- cmds = []
-
- cmd = "radius server group %s" % radius_group_name
- cmds.append(cmd)
-
- if radius_server_type == "Authentication":
- cmd = "undo radius server authentication %s %s" % (
- radius_server_ip, radius_server_port)
-
- if radius_vpn_name and radius_vpn_name != "_public_":
- cmd += " vpn-instance %s" % radius_vpn_name
-
- if radius_server_mode == "Secondary-server":
- cmd += " secondary"
- else:
- cmd = "undo radius server accounting %s %s" % (
- radius_server_ip, radius_server_port)
-
- if radius_vpn_name and radius_vpn_name != "_public_":
- cmd += " vpn-instance %s" % radius_vpn_name
-
- if radius_server_mode == "Secondary-server":
- cmd += " secondary"
-
- cmds.append(cmd)
- return cmds
-
- def get_radius_server_cfg_ipv6(self, **kwargs):
- """ Get radius server configure ipv6 """
-
- module = kwargs["module"]
- radius_group_name = module.params['radius_group_name']
- radius_server_type = module.params['radius_server_type']
- radius_server_ipv6 = module.params['radius_server_ipv6']
- radius_server_port = module.params['radius_server_port']
- radius_server_mode = module.params['radius_server_mode']
- state = module.params['state']
-
- result = dict()
- result["radius_server_ip_v6"] = []
- need_cfg = False
-
- conf_str = CE_GET_RADIUS_SERVER_CFG_IPV6 % radius_group_name
-
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- if state == "present":
- need_cfg = True
-
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- radius_server_ip_v6 = root.findall(
- "radius/rdsTemplates/rdsTemplate/rdsServerIPV6s/rdsServerIPV6")
- if radius_server_ip_v6:
- for tmp in radius_server_ip_v6:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["serverType", "serverIPAddress", "serverPort", "serverMode"]:
- tmp_dict[site.tag] = site.text
-
- result["radius_server_ip_v6"].append(tmp_dict)
-
- if result["radius_server_ip_v6"]:
- cfg = dict()
- config_list = list()
- if radius_server_type:
- cfg["serverType"] = radius_server_type.lower()
- if radius_server_ipv6:
- cfg["serverIPAddress"] = radius_server_ipv6.lower()
- if radius_server_port:
- cfg["serverPort"] = radius_server_port.lower()
- if radius_server_mode:
- cfg["serverMode"] = radius_server_mode.lower()
-
- for tmp in result["radius_server_ip_v6"]:
- exist_cfg = dict()
- if radius_server_type:
- exist_cfg["serverType"] = tmp.get("serverType").lower()
- if radius_server_ipv6:
- exist_cfg["serverIPAddress"] = tmp.get("serverIPAddress").lower()
- if radius_server_port:
- exist_cfg["serverPort"] = tmp.get("serverPort").lower()
- if radius_server_mode:
- exist_cfg["serverMode"] = tmp.get("serverMode").lower()
- config_list.append(exist_cfg)
- if cfg in config_list:
- if state == "present":
- need_cfg = False
- else:
- need_cfg = True
- else:
- if state == "present":
- need_cfg = True
- else:
- need_cfg = False
-
- result["need_cfg"] = need_cfg
- return result
-
- def merge_radius_server_cfg_ipv6(self, **kwargs):
- """ Merge radius server configure ipv6 """
-
- module = kwargs["module"]
- radius_group_name = module.params['radius_group_name']
- radius_server_type = module.params['radius_server_type']
- radius_server_ipv6 = module.params['radius_server_ipv6']
- radius_server_port = module.params['radius_server_port']
- radius_server_mode = module.params['radius_server_mode']
-
- conf_str = CE_MERGE_RADIUS_SERVER_CFG_IPV6 % (
- radius_group_name, radius_server_type,
- radius_server_ipv6, radius_server_port,
- radius_server_mode)
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Merge radius server config ipv6 failed.')
-
- cmds = []
-
- cmd = "radius server group %s" % radius_group_name
- cmds.append(cmd)
-
- if radius_server_type == "Authentication":
- cmd = "radius server authentication %s %s" % (
- radius_server_ipv6, radius_server_port)
-
- if radius_server_mode == "Secondary-server":
- cmd += " secondary"
- else:
- cmd = "radius server accounting %s %s" % (
- radius_server_ipv6, radius_server_port)
-
- if radius_server_mode == "Secondary-server":
- cmd += " secondary"
-
- cmds.append(cmd)
- return cmds
-
- def delete_radius_server_cfg_ipv6(self, **kwargs):
- """ Delete radius server configure ipv6 """
-
- module = kwargs["module"]
- radius_group_name = module.params['radius_group_name']
- radius_server_type = module.params['radius_server_type']
- radius_server_ipv6 = module.params['radius_server_ipv6']
- radius_server_port = module.params['radius_server_port']
- radius_server_mode = module.params['radius_server_mode']
-
- conf_str = CE_DELETE_RADIUS_SERVER_CFG_IPV6 % (
- radius_group_name, radius_server_type,
- radius_server_ipv6, radius_server_port,
- radius_server_mode)
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Create radius server config ipv6 failed.')
-
- cmds = []
-
- cmd = "radius server group %s" % radius_group_name
- cmds.append(cmd)
-
- if radius_server_type == "Authentication":
- cmd = "undo radius server authentication %s %s" % (
- radius_server_ipv6, radius_server_port)
-
- if radius_server_mode == "Secondary-server":
- cmd += " secondary"
- else:
- cmd = "undo radius server accounting %s %s" % (
- radius_server_ipv6, radius_server_port)
-
- if radius_server_mode == "Secondary-server":
- cmd += " secondary"
-
- cmds.append(cmd)
- return cmds
-
- def get_radius_server_name(self, **kwargs):
- """ Get radius server name """
-
- module = kwargs["module"]
- radius_group_name = module.params['radius_group_name']
- radius_server_type = module.params['radius_server_type']
- radius_server_name = module.params['radius_server_name']
- radius_server_port = module.params['radius_server_port']
- radius_server_mode = module.params['radius_server_mode']
- radius_vpn_name = module.params['radius_vpn_name']
- state = module.params['state']
-
- result = dict()
- result["radius_server_name_cfg"] = []
- need_cfg = False
-
- conf_str = CE_GET_RADIUS_SERVER_NAME % radius_group_name
-
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- if state == "present":
- need_cfg = True
-
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- radius_server_name_cfg = root.findall(
- "radius/rdsTemplates/rdsTemplate/rdsServerNames/rdsServerName")
- if radius_server_name_cfg:
- for tmp in radius_server_name_cfg:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["serverType", "serverName", "serverPort", "serverMode", "vpnName"]:
- tmp_dict[site.tag] = site.text
-
- result["radius_server_name_cfg"].append(tmp_dict)
-
- if result["radius_server_name_cfg"]:
- cfg = dict()
- config_list = list()
- if radius_server_type:
- cfg["serverType"] = radius_server_type.lower()
- if radius_server_name:
- cfg["serverName"] = radius_server_name.lower()
- if radius_server_port:
- cfg["serverPort"] = radius_server_port.lower()
- if radius_server_mode:
- cfg["serverMode"] = radius_server_mode.lower()
- if radius_vpn_name:
- cfg["vpnName"] = radius_vpn_name.lower()
-
- for tmp in result["radius_server_name_cfg"]:
- exist_cfg = dict()
- if radius_server_type:
- exist_cfg["serverType"] = tmp.get("serverType").lower()
- if radius_server_name:
- exist_cfg["serverName"] = tmp.get("serverName").lower()
- if radius_server_port:
- exist_cfg["serverPort"] = tmp.get("serverPort").lower()
- if radius_server_mode:
- exist_cfg["serverMode"] = tmp.get("serverMode").lower()
- if radius_vpn_name:
- exist_cfg["vpnName"] = tmp.get("vpnName").lower()
- config_list.append(exist_cfg)
- if cfg in config_list:
- if state == "present":
- need_cfg = False
- else:
- need_cfg = True
- else:
- if state == "present":
- need_cfg = True
- else:
- need_cfg = False
- result["need_cfg"] = need_cfg
- return result
-
- def merge_radius_server_name(self, **kwargs):
- """ Merge radius server name """
-
- module = kwargs["module"]
- radius_group_name = module.params['radius_group_name']
- radius_server_type = module.params['radius_server_type']
- radius_server_name = module.params['radius_server_name']
- radius_server_port = module.params['radius_server_port']
- radius_server_mode = module.params['radius_server_mode']
- radius_vpn_name = module.params['radius_vpn_name']
-
- conf_str = CE_MERGE_RADIUS_SERVER_NAME % (
- radius_group_name, radius_server_type,
- radius_server_name, radius_server_port,
- radius_server_mode, radius_vpn_name)
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge radius server name failed.')
-
- cmds = []
-
- cmd = "radius server group %s" % radius_group_name
- cmds.append(cmd)
-
- if radius_server_type == "Authentication":
- cmd = "radius server authentication hostname %s %s" % (
- radius_server_name, radius_server_port)
-
- if radius_vpn_name and radius_vpn_name != "_public_":
- cmd += " vpn-instance %s" % radius_vpn_name
-
- if radius_server_mode == "Secondary-server":
- cmd += " secondary"
- else:
- cmd = "radius server accounting hostname %s %s" % (
- radius_server_name, radius_server_port)
-
- if radius_vpn_name and radius_vpn_name != "_public_":
- cmd += " vpn-instance %s" % radius_vpn_name
-
- if radius_server_mode == "Secondary-server":
- cmd += " secondary"
-
- cmds.append(cmd)
- return cmds
-
- def delete_radius_server_name(self, **kwargs):
- """ Delete radius server name """
-
- module = kwargs["module"]
- radius_group_name = module.params['radius_group_name']
- radius_server_type = module.params['radius_server_type']
- radius_server_name = module.params['radius_server_name']
- radius_server_port = module.params['radius_server_port']
- radius_server_mode = module.params['radius_server_mode']
- radius_vpn_name = module.params['radius_vpn_name']
-
- conf_str = CE_DELETE_RADIUS_SERVER_NAME % (
- radius_group_name, radius_server_type,
- radius_server_name, radius_server_port,
- radius_server_mode, radius_vpn_name)
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: delete radius server name failed.')
-
- cmds = []
-
- cmd = "radius server group %s" % radius_group_name
- cmds.append(cmd)
-
- if radius_server_type == "Authentication":
- cmd = "undo radius server authentication hostname %s %s" % (
- radius_server_name, radius_server_port)
-
- if radius_vpn_name and radius_vpn_name != "_public_":
- cmd += " vpn-instance %s" % radius_vpn_name
-
- if radius_server_mode == "Secondary-server":
- cmd += " secondary"
- else:
- cmd = "undo radius server accounting hostname %s %s" % (
- radius_server_name, radius_server_port)
-
- if radius_vpn_name and radius_vpn_name != "_public_":
- cmd += " vpn-instance %s" % radius_vpn_name
-
- if radius_server_mode == "Secondary-server":
- cmd += " secondary"
-
- cmds.append(cmd)
- return cmds
-
- def get_hwtacacs_server_cfg_ipv4(self, **kwargs):
- """ Get hwtacacs server configure ipv4 """
-
- module = kwargs["module"]
- hwtacacs_template = module.params["hwtacacs_template"]
- hwtacacs_server_ip = module.params["hwtacacs_server_ip"]
- hwtacacs_server_type = module.params["hwtacacs_server_type"]
- hwtacacs_is_secondary_server = module.params[
- "hwtacacs_is_secondary_server"]
- hwtacacs_vpn_name = module.params["hwtacacs_vpn_name"]
- hwtacacs_is_public_net = module.params["hwtacacs_is_public_net"]
- state = module.params["state"]
-
- result = dict()
- result["hwtacacs_server_cfg_ipv4"] = []
- need_cfg = False
-
- conf_str = CE_GET_HWTACACS_SERVER_CFG_IPV4 % hwtacacs_template
-
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- if state == "present":
- need_cfg = True
-
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- hwtacacs_server_cfg_ipv4 = root.findall(
- "hwtacacs/hwTacTempCfgs/hwTacTempCfg/hwTacSrvCfgs/hwTacSrvCfg")
- if hwtacacs_server_cfg_ipv4:
- for tmp in hwtacacs_server_cfg_ipv4:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["serverIpAddress", "serverType", "isSecondaryServer", "isPublicNet", "vpnName"]:
- tmp_dict[site.tag] = site.text
-
- result["hwtacacs_server_cfg_ipv4"].append(tmp_dict)
-
- if result["hwtacacs_server_cfg_ipv4"]:
- cfg = dict()
- config_list = list()
-
- if hwtacacs_server_ip:
- cfg["serverIpAddress"] = hwtacacs_server_ip.lower()
- if hwtacacs_server_type:
- cfg["serverType"] = hwtacacs_server_type.lower()
- if hwtacacs_is_secondary_server:
- cfg["isSecondaryServer"] = str(hwtacacs_is_secondary_server).lower()
- if hwtacacs_is_public_net:
- cfg["isPublicNet"] = str(hwtacacs_is_public_net).lower()
- if hwtacacs_vpn_name:
- cfg["vpnName"] = hwtacacs_vpn_name.lower()
-
- for tmp in result["hwtacacs_server_cfg_ipv4"]:
- exist_cfg = dict()
- if hwtacacs_server_ip:
- exist_cfg["serverIpAddress"] = tmp.get("serverIpAddress").lower()
- if hwtacacs_server_type:
- exist_cfg["serverType"] = tmp.get("serverType").lower()
- if hwtacacs_is_secondary_server:
- exist_cfg["isSecondaryServer"] = tmp.get("isSecondaryServer").lower()
- if hwtacacs_is_public_net:
- exist_cfg["isPublicNet"] = tmp.get("isPublicNet").lower()
- if hwtacacs_vpn_name:
- exist_cfg["vpnName"] = tmp.get("vpnName").lower()
- config_list.append(exist_cfg)
- if cfg in config_list:
- if state == "present":
- need_cfg = False
- else:
- need_cfg = True
- else:
- if state == "present":
- need_cfg = True
- else:
- need_cfg = False
- result["need_cfg"] = need_cfg
- return result
-
- def merge_hwtacacs_server_cfg_ipv4(self, **kwargs):
- """ Merge hwtacacs server configure ipv4 """
-
- module = kwargs["module"]
- hwtacacs_template = module.params["hwtacacs_template"]
- hwtacacs_server_ip = module.params["hwtacacs_server_ip"]
- hwtacacs_server_type = module.params["hwtacacs_server_type"]
- hwtacacs_is_secondary_server = module.params[
- "hwtacacs_is_secondary_server"]
- hwtacacs_vpn_name = module.params["hwtacacs_vpn_name"]
- hwtacacs_is_public_net = module.params["hwtacacs_is_public_net"]
-
- conf_str = CE_MERGE_HWTACACS_SERVER_CFG_IPV4 % (
- hwtacacs_template, hwtacacs_server_ip,
- hwtacacs_server_type, str(hwtacacs_is_secondary_server).lower(),
- hwtacacs_vpn_name, str(hwtacacs_is_public_net).lower())
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Merge hwtacacs server config ipv4 failed.')
-
- cmds = []
-
- cmd = "hwtacacs server template %s" % hwtacacs_template
- cmds.append(cmd)
-
- if hwtacacs_server_type == "Authentication":
- cmd = "hwtacacs server authentication %s" % hwtacacs_server_ip
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Authorization":
- cmd = "hwtacacs server authorization %s" % hwtacacs_server_ip
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Accounting":
- cmd = "hwtacacs server accounting %s" % hwtacacs_server_ip
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Common":
- cmd = "hwtacacs server %s" % hwtacacs_server_ip
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- cmds.append(cmd)
- return cmds
-
- def delete_hwtacacs_server_cfg_ipv4(self, **kwargs):
- """ Delete hwtacacs server configure ipv4 """
-
- module = kwargs["module"]
- hwtacacs_template = module.params["hwtacacs_template"]
- hwtacacs_server_ip = module.params["hwtacacs_server_ip"]
- hwtacacs_server_type = module.params["hwtacacs_server_type"]
- hwtacacs_is_secondary_server = module.params[
- "hwtacacs_is_secondary_server"]
- hwtacacs_vpn_name = module.params["hwtacacs_vpn_name"]
- hwtacacs_is_public_net = module.params["hwtacacs_is_public_net"]
-
- conf_str = CE_DELETE_HWTACACS_SERVER_CFG_IPV4 % (
- hwtacacs_template, hwtacacs_server_ip,
- hwtacacs_server_type, str(hwtacacs_is_secondary_server).lower(),
- hwtacacs_vpn_name, str(hwtacacs_is_public_net).lower())
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Delete hwtacacs server config ipv4 failed.')
-
- cmds = []
-
- cmd = "hwtacacs server template %s" % hwtacacs_template
- cmds.append(cmd)
-
- if hwtacacs_server_type == "Authentication":
- cmd = "undo hwtacacs server authentication %s" % hwtacacs_server_ip
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Authorization":
- cmd = "undo hwtacacs server authorization %s" % hwtacacs_server_ip
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Accounting":
- cmd = "undo hwtacacs server accounting %s" % hwtacacs_server_ip
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Common":
- cmd = "undo hwtacacs server %s" % hwtacacs_server_ip
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- cmds.append(cmd)
- return cmds
-
- def get_hwtacacs_server_cfg_ipv6(self, **kwargs):
- """ Get hwtacacs server configure ipv6 """
-
- module = kwargs["module"]
- hwtacacs_template = module.params["hwtacacs_template"]
- hwtacacs_server_ipv6 = module.params["hwtacacs_server_ipv6"]
- hwtacacs_server_type = module.params["hwtacacs_server_type"]
- hwtacacs_is_secondary_server = module.params[
- "hwtacacs_is_secondary_server"]
- hwtacacs_vpn_name = module.params["hwtacacs_vpn_name"]
- state = module.params["state"]
-
- result = dict()
- result["hwtacacs_server_cfg_ipv6"] = []
- need_cfg = False
-
- conf_str = CE_GET_HWTACACS_SERVER_CFG_IPV6 % hwtacacs_template
-
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- if state == "present":
- need_cfg = True
-
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- hwtacacs_server_cfg_ipv6 = root.findall(
- "hwtacacs/hwTacTempCfgs/hwTacTempCfg/hwTacIpv6SrvCfgs/hwTacIpv6SrvCfg")
- if hwtacacs_server_cfg_ipv6:
- for tmp in hwtacacs_server_cfg_ipv6:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["serverIpAddress", "serverType", "isSecondaryServer", "vpnName"]:
- tmp_dict[site.tag] = site.text
-
- result["hwtacacs_server_cfg_ipv6"].append(tmp_dict)
-
- if result["hwtacacs_server_cfg_ipv6"]:
- cfg = dict()
- config_list = list()
-
- if hwtacacs_server_ipv6:
- cfg["serverIpAddress"] = hwtacacs_server_ipv6.lower()
- if hwtacacs_server_type:
- cfg["serverType"] = hwtacacs_server_type.lower()
- if hwtacacs_is_secondary_server:
- cfg["isSecondaryServer"] = str(hwtacacs_is_secondary_server).lower()
- if hwtacacs_vpn_name:
- cfg["vpnName"] = hwtacacs_vpn_name.lower()
-
- for tmp in result["hwtacacs_server_cfg_ipv6"]:
- exist_cfg = dict()
- if hwtacacs_server_ipv6:
- exist_cfg["serverIpAddress"] = tmp.get("serverIpAddress").lower()
- if hwtacacs_server_type:
- exist_cfg["serverType"] = tmp.get("serverType").lower()
- if hwtacacs_is_secondary_server:
- exist_cfg["isSecondaryServer"] = tmp.get("isSecondaryServer").lower()
- if hwtacacs_vpn_name:
- exist_cfg["vpnName"] = tmp.get("vpnName").lower()
- config_list.append(exist_cfg)
- if cfg in config_list:
- if state == "present":
- need_cfg = False
- else:
- need_cfg = True
- else:
- if state == "present":
- need_cfg = True
- else:
- need_cfg = False
- result["need_cfg"] = need_cfg
- return result
-
- def merge_hwtacacs_server_cfg_ipv6(self, **kwargs):
- """ Merge hwtacacs server configure ipv6 """
-
- module = kwargs["module"]
- hwtacacs_template = module.params["hwtacacs_template"]
- hwtacacs_server_ipv6 = module.params["hwtacacs_server_ipv6"]
- hwtacacs_server_type = module.params["hwtacacs_server_type"]
- hwtacacs_is_secondary_server = module.params[
- "hwtacacs_is_secondary_server"]
- hwtacacs_vpn_name = module.params["hwtacacs_vpn_name"]
-
- conf_str = CE_MERGE_HWTACACS_SERVER_CFG_IPV6 % (
- hwtacacs_template, hwtacacs_server_ipv6,
- hwtacacs_server_type, str(hwtacacs_is_secondary_server).lower(),
- hwtacacs_vpn_name)
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Merge hwtacacs server config ipv6 failed.')
-
- cmds = []
-
- cmd = "hwtacacs server template %s" % hwtacacs_template
- cmds.append(cmd)
-
- if hwtacacs_server_type == "Authentication":
- cmd = "hwtacacs server authentication %s" % hwtacacs_server_ipv6
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Authorization":
- cmd = "hwtacacs server authorization %s" % hwtacacs_server_ipv6
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Accounting":
- cmd = "hwtacacs server accounting %s" % hwtacacs_server_ipv6
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Common":
- cmd = "hwtacacs server %s" % hwtacacs_server_ipv6
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- cmds.append(cmd)
- return cmds
-
- def delete_hwtacacs_server_cfg_ipv6(self, **kwargs):
- """ Delete hwtacacs server configure ipv6 """
-
- module = kwargs["module"]
- hwtacacs_template = module.params["hwtacacs_template"]
- hwtacacs_server_ipv6 = module.params["hwtacacs_server_ipv6"]
- hwtacacs_server_type = module.params["hwtacacs_server_type"]
- hwtacacs_is_secondary_server = module.params[
- "hwtacacs_is_secondary_server"]
- hwtacacs_vpn_name = module.params["hwtacacs_vpn_name"]
-
- conf_str = CE_DELETE_HWTACACS_SERVER_CFG_IPV6 % (
- hwtacacs_template, hwtacacs_server_ipv6,
- hwtacacs_server_type, str(hwtacacs_is_secondary_server).lower(),
- hwtacacs_vpn_name)
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Delete hwtacacs server config ipv6 failed.')
-
- cmds = []
-
- cmd = "hwtacacs server template %s" % hwtacacs_template
- cmds.append(cmd)
-
- if hwtacacs_server_type == "Authentication":
- cmd = "undo hwtacacs server authentication %s" % hwtacacs_server_ipv6
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Authorization":
- cmd = "undo hwtacacs server authorization %s" % hwtacacs_server_ipv6
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Accounting":
- cmd = "undo hwtacacs server accounting %s" % hwtacacs_server_ipv6
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Common":
- cmd = "undo hwtacacs server %s" % hwtacacs_server_ipv6
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- cmds.append(cmd)
- return cmds
-
- def get_hwtacacs_host_server_cfg(self, **kwargs):
- """ Get hwtacacs host server configure """
-
- module = kwargs["module"]
- hwtacacs_template = module.params["hwtacacs_template"]
- hwtacacs_server_host_name = module.params["hwtacacs_server_host_name"]
- hwtacacs_server_type = module.params["hwtacacs_server_type"]
- hwtacacs_is_secondary_server = "true" if module.params[
- "hwtacacs_is_secondary_server"] is True else "false"
- hwtacacs_vpn_name = module.params["hwtacacs_vpn_name"]
- hwtacacs_is_public_net = "true" if module.params[
- "hwtacacs_is_public_net"] is True else "false"
- state = module.params["state"]
-
- result = dict()
- result["hwtacacs_server_name_cfg"] = []
- need_cfg = False
-
- conf_str = CE_GET_HWTACACS_HOST_SERVER_CFG % hwtacacs_template
-
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- if state == "present":
- need_cfg = True
-
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- hwtacacs_server_name_cfg = root.findall(
- "hwtacacs/hwTacTempCfgs/hwTacTempCfg/hwTacHostSrvCfgs/hwTacHostSrvCfg")
- if hwtacacs_server_name_cfg:
- for tmp in hwtacacs_server_name_cfg:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["serverHostName", "serverType", "isSecondaryServer", "isPublicNet", "vpnName"]:
- tmp_dict[site.tag] = site.text
-
- result["hwtacacs_server_name_cfg"].append(tmp_dict)
-
- if result["hwtacacs_server_name_cfg"]:
- cfg = dict()
- config_list = list()
-
- if hwtacacs_server_host_name:
- cfg["serverHostName"] = hwtacacs_server_host_name.lower()
- if hwtacacs_server_type:
- cfg["serverType"] = hwtacacs_server_type.lower()
- if hwtacacs_is_secondary_server:
- cfg["isSecondaryServer"] = str(hwtacacs_is_secondary_server).lower()
- if hwtacacs_is_public_net:
- cfg["isPublicNet"] = str(hwtacacs_is_public_net).lower()
- if hwtacacs_vpn_name:
- cfg["vpnName"] = hwtacacs_vpn_name.lower()
-
- for tmp in result["hwtacacs_server_name_cfg"]:
- exist_cfg = dict()
- if hwtacacs_server_host_name:
- exist_cfg["serverHostName"] = tmp.get("serverHostName").lower()
- if hwtacacs_server_type:
- exist_cfg["serverType"] = tmp.get("serverType").lower()
- if hwtacacs_is_secondary_server:
- exist_cfg["isSecondaryServer"] = tmp.get("isSecondaryServer").lower()
- if hwtacacs_is_public_net:
- exist_cfg["isPublicNet"] = tmp.get("isPublicNet").lower()
- if hwtacacs_vpn_name:
- exist_cfg["vpnName"] = tmp.get("vpnName").lower()
- config_list.append(exist_cfg)
- if cfg in config_list:
- if state == "present":
- need_cfg = False
- else:
- need_cfg = True
- else:
- if state == "present":
- need_cfg = True
- else:
- need_cfg = False
- result["need_cfg"] = need_cfg
- return result
-
- def merge_hwtacacs_host_server_cfg(self, **kwargs):
- """ Merge hwtacacs host server configure """
-
- module = kwargs["module"]
- hwtacacs_template = module.params["hwtacacs_template"]
- hwtacacs_server_host_name = module.params["hwtacacs_server_host_name"]
- hwtacacs_server_type = module.params["hwtacacs_server_type"]
- hwtacacs_is_secondary_server = module.params[
- "hwtacacs_is_secondary_server"]
- hwtacacs_vpn_name = module.params["hwtacacs_vpn_name"]
- hwtacacs_is_public_net = module.params["hwtacacs_is_public_net"]
-
- conf_str = CE_MERGE_HWTACACS_HOST_SERVER_CFG % (
- hwtacacs_template, hwtacacs_server_host_name,
- hwtacacs_server_type, str(hwtacacs_is_secondary_server).lower(),
- hwtacacs_vpn_name, str(hwtacacs_is_public_net).lower())
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Merge hwtacacs host server config failed.')
-
- cmds = []
-
- if hwtacacs_server_type == "Authentication":
- cmd = "hwtacacs server authentication host %s" % hwtacacs_server_host_name
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Authorization":
- cmd = "hwtacacs server authorization host %s" % hwtacacs_server_host_name
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Accounting":
- cmd = "hwtacacs server accounting host %s" % hwtacacs_server_host_name
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Common":
- cmd = "hwtacacs server host host-name %s" % hwtacacs_server_host_name
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- cmds.append(cmd)
- return cmds
-
- def delete_hwtacacs_host_server_cfg(self, **kwargs):
- """ Delete hwtacacs host server configure """
-
- module = kwargs["module"]
- hwtacacs_template = module.params["hwtacacs_template"]
- hwtacacs_server_host_name = module.params["hwtacacs_server_host_name"]
- hwtacacs_server_type = module.params["hwtacacs_server_type"]
- hwtacacs_is_secondary_server = module.params[
- "hwtacacs_is_secondary_server"]
- hwtacacs_vpn_name = module.params["hwtacacs_vpn_name"]
- hwtacacs_is_public_net = module.params["hwtacacs_is_public_net"]
-
- conf_str = CE_DELETE_HWTACACS_HOST_SERVER_CFG % (
- hwtacacs_template, hwtacacs_server_host_name,
- hwtacacs_server_type, str(hwtacacs_is_secondary_server).lower(),
- hwtacacs_vpn_name, str(hwtacacs_is_public_net).lower())
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Delete hwtacacs host server config failed.')
-
- cmds = []
-
- if hwtacacs_server_type == "Authentication":
- cmd = "undo hwtacacs server authentication host %s" % hwtacacs_server_host_name
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Authorization":
- cmd = "undo hwtacacs server authorization host %s" % hwtacacs_server_host_name
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Accounting":
- cmd = "undo hwtacacs server accounting host %s" % hwtacacs_server_host_name
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- elif hwtacacs_server_type == "Common":
- cmd = "undo hwtacacs server host %s" % hwtacacs_server_host_name
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- cmd += " vpn-instance %s" % hwtacacs_vpn_name
- if hwtacacs_is_public_net:
- cmd += " public-net"
- if hwtacacs_is_secondary_server:
- cmd += " secondary"
-
- cmds.append(cmd)
- return cmds
-
-
-def check_name(**kwargs):
- """ Check invalid name """
-
- module = kwargs["module"]
- name = kwargs["name"]
- invalid_char = kwargs["invalid_char"]
-
- for item in invalid_char:
- if item in name:
- module.fail_json(
- msg='Error: Invalid char %s is in the name %s ' % (item, name))
-
-
-def check_module_argument(**kwargs):
- """ Check module argument """
-
- module = kwargs["module"]
-
- # local para
- local_user_name = module.params['local_user_name']
- local_password = module.params['local_password']
- local_ftp_dir = module.params['local_ftp_dir']
- local_user_level = module.params['local_user_level']
- local_user_group = module.params['local_user_group']
-
- # radius para
- radius_group_name = module.params['radius_group_name']
- radius_server_ip = module.params['radius_server_ip']
- radius_server_port = module.params['radius_server_port']
- radius_vpn_name = module.params['radius_vpn_name']
- radius_server_name = module.params['radius_server_name']
-
- # hwtacacs para
- hwtacacs_template = module.params['hwtacacs_template']
- hwtacacs_server_ip = module.params['hwtacacs_server_ip']
- hwtacacs_vpn_name = module.params['hwtacacs_vpn_name']
- hwtacacs_server_host_name = module.params['hwtacacs_server_host_name']
-
- if local_user_name:
- if len(local_user_name) > 253:
- module.fail_json(
- msg='Error: The local_user_name %s is large than 253.' % local_user_name)
- check_name(module=module, name=local_user_name,
- invalid_char=INVALID_USER_NAME_CHAR)
-
- if local_password and len(local_password) > 255:
- module.fail_json(
- msg='Error: The local_password %s is large than 255.' % local_password)
-
- if local_user_level:
- if int(local_user_level) > 15 or int(local_user_level) < 0:
- module.fail_json(
- msg='Error: The local_user_level %s is out of [0 - 15].' % local_user_level)
-
- if local_ftp_dir:
- if len(local_ftp_dir) > 255:
- module.fail_json(
- msg='Error: The local_ftp_dir %s is large than 255.' % local_ftp_dir)
-
- if local_user_group:
- if len(local_user_group) > 32 or len(local_user_group) < 1:
- module.fail_json(
- msg='Error: The local_user_group %s is out of [1 - 32].' % local_user_group)
-
- if radius_group_name and len(radius_group_name) > 32:
- module.fail_json(
- msg='Error: The radius_group_name %s is large than 32.' % radius_group_name)
-
- if radius_server_ip and not check_ip_addr(radius_server_ip):
- module.fail_json(
- msg='Error: The radius_server_ip %s is invalid.' % radius_server_ip)
-
- if radius_server_port and not radius_server_port.isdigit():
- module.fail_json(
- msg='Error: The radius_server_port %s is invalid.' % radius_server_port)
-
- if radius_vpn_name:
- if len(radius_vpn_name) > 31:
- module.fail_json(
- msg='Error: The radius_vpn_name %s is large than 31.' % radius_vpn_name)
- if ' ' in radius_vpn_name:
- module.fail_json(
- msg='Error: The radius_vpn_name %s include space.' % radius_vpn_name)
-
- if radius_server_name:
- if len(radius_server_name) > 255:
- module.fail_json(
- msg='Error: The radius_server_name %s is large than 255.' % radius_server_name)
- if ' ' in radius_server_name:
- module.fail_json(
- msg='Error: The radius_server_name %s include space.' % radius_server_name)
-
- if hwtacacs_template and len(hwtacacs_template) > 32:
- module.fail_json(
- msg='Error: The hwtacacs_template %s is large than 32.' % hwtacacs_template)
-
- if hwtacacs_server_ip and not check_ip_addr(hwtacacs_server_ip):
- module.fail_json(
- msg='Error: The hwtacacs_server_ip %s is invalid.' % hwtacacs_server_ip)
-
- if hwtacacs_vpn_name:
- if len(hwtacacs_vpn_name) > 31:
- module.fail_json(
- msg='Error: The hwtacacs_vpn_name %s is large than 31.' % hwtacacs_vpn_name)
- if ' ' in hwtacacs_vpn_name:
- module.fail_json(
- msg='Error: The hwtacacs_vpn_name %s include space.' % hwtacacs_vpn_name)
-
- if hwtacacs_server_host_name:
- if len(hwtacacs_server_host_name) > 255:
- module.fail_json(
- msg='Error: The hwtacacs_server_host_name %s is large than 255.' % hwtacacs_server_host_name)
- if ' ' in hwtacacs_server_host_name:
- module.fail_json(
- msg='Error: The hwtacacs_server_host_name %s include space.' % hwtacacs_server_host_name)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- local_user_name=dict(type='str'),
- local_password=dict(type='str', no_log=True),
- local_service_type=dict(type='str'),
- local_ftp_dir=dict(type='str'),
- local_user_level=dict(type='str'),
- local_user_group=dict(type='str'),
- radius_group_name=dict(type='str'),
- radius_server_type=dict(choices=['Authentication', 'Accounting']),
- radius_server_ip=dict(type='str'),
- radius_server_ipv6=dict(type='str'),
- radius_server_port=dict(type='str'),
- radius_server_mode=dict(
- choices=['Secondary-server', 'Primary-server']),
- radius_vpn_name=dict(type='str'),
- radius_server_name=dict(type='str'),
- hwtacacs_template=dict(type='str'),
- hwtacacs_server_ip=dict(type='str'),
- hwtacacs_server_ipv6=dict(type='str'),
- hwtacacs_server_type=dict(
- choices=['Authentication', 'Authorization', 'Accounting', 'Common']),
- hwtacacs_is_secondary_server=dict(
- required=False, default=False, type='bool'),
- hwtacacs_vpn_name=dict(type='str'),
- hwtacacs_is_public_net=dict(
- required=False, default=False, type='bool'),
- hwtacacs_server_host_name=dict(type='str')
- )
-
- argument_spec.update(ce_argument_spec)
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- check_module_argument(module=module)
-
- changed = False
- proposed = dict()
- existing = dict()
- end_state = dict()
- updates = []
-
- # common para
- state = module.params['state']
-
- # local para
- local_user_name = module.params['local_user_name']
- local_password = module.params['local_password']
- local_service_type = module.params['local_service_type']
- local_ftp_dir = module.params['local_ftp_dir']
- local_user_level = module.params['local_user_level']
- local_user_group = module.params['local_user_group']
-
- # radius para
- radius_group_name = module.params['radius_group_name']
- radius_server_type = module.params['radius_server_type']
- radius_server_ip = module.params['radius_server_ip']
- radius_server_ipv6 = module.params['radius_server_ipv6']
- radius_server_port = module.params['radius_server_port']
- radius_server_mode = module.params['radius_server_mode']
- radius_vpn_name = module.params['radius_vpn_name']
- radius_server_name = module.params['radius_server_name']
-
- # hwtacacs para
- hwtacacs_template = module.params['hwtacacs_template']
- hwtacacs_server_ip = module.params['hwtacacs_server_ip']
- hwtacacs_server_ipv6 = module.params['hwtacacs_server_ipv6']
- hwtacacs_server_type = module.params['hwtacacs_server_type']
- hwtacacs_is_secondary_server = module.params[
- 'hwtacacs_is_secondary_server']
- hwtacacs_vpn_name = module.params['hwtacacs_vpn_name']
- hwtacacs_is_public_net = module.params['hwtacacs_is_public_net']
- hwtacacs_server_host_name = module.params['hwtacacs_server_host_name']
-
- ce_aaa_server_host = AaaServerHost()
-
- if not ce_aaa_server_host:
- module.fail_json(msg='Error: Construct ce_aaa_server failed.')
-
- # get proposed
- proposed["state"] = state
- if local_user_name:
- proposed["local_user_name"] = local_user_name
- if local_password:
- proposed["local_password"] = "******"
- if local_service_type:
- proposed["local_service_type"] = local_service_type
- if local_ftp_dir:
- proposed["local_ftp_dir"] = local_ftp_dir
- if local_user_level:
- proposed["local_user_level"] = local_user_level
- if local_user_group:
- proposed["local_user_group"] = local_user_group
- if radius_group_name:
- proposed["radius_group_name"] = radius_group_name
- if radius_server_type:
- proposed["radius_server_type"] = radius_server_type
- if radius_server_ip:
- proposed["radius_server_ip"] = radius_server_ip
- if radius_server_ipv6:
- proposed["radius_server_ipv6"] = radius_server_ipv6
- if radius_server_port:
- proposed["radius_server_port"] = radius_server_port
- if radius_server_mode:
- proposed["radius_server_mode"] = radius_server_mode
- if radius_vpn_name:
- proposed["radius_vpn_name"] = radius_vpn_name
- if radius_server_name:
- proposed["radius_server_name"] = radius_server_name
- if hwtacacs_template:
- proposed["hwtacacs_template"] = hwtacacs_template
- if hwtacacs_server_ip:
- proposed["hwtacacs_server_ip"] = hwtacacs_server_ip
- if hwtacacs_server_ipv6:
- proposed["hwtacacs_server_ipv6"] = hwtacacs_server_ipv6
- if hwtacacs_server_type:
- proposed["hwtacacs_server_type"] = hwtacacs_server_type
- proposed["hwtacacs_is_secondary_server"] = hwtacacs_is_secondary_server
- if hwtacacs_vpn_name:
- proposed["hwtacacs_vpn_name"] = hwtacacs_vpn_name
- proposed["hwtacacs_is_public_net"] = hwtacacs_is_public_net
- if hwtacacs_server_host_name:
- proposed["hwtacacs_server_host_name"] = hwtacacs_server_host_name
-
- if local_user_name:
-
- if state == "present" and not local_password:
- module.fail_json(
- msg='Error: Please input local_password when config local user.')
-
- local_user_result = ce_aaa_server_host.get_local_user_info(
- module=module)
- existing["local user name"] = local_user_result["local_user_info"]
-
- if state == "present":
- # present local user
- if local_user_result["need_cfg"]:
- cmd = ce_aaa_server_host.merge_local_user_info(module=module)
-
- changed = True
- updates.append(cmd)
-
- else:
- # absent local user
- if local_user_result["need_cfg"]:
- if not local_service_type and not local_ftp_dir and not local_user_level and not local_user_group:
- cmd = ce_aaa_server_host.delete_local_user_info(
- module=module)
- else:
- cmd = ce_aaa_server_host.merge_local_user_info(
- module=module)
-
- changed = True
- updates.append(cmd)
-
- local_user_result = ce_aaa_server_host.get_local_user_info(
- module=module)
- end_state["local user name"] = local_user_result["local_user_info"]
-
- if radius_group_name:
-
- if not radius_server_ip and not radius_server_ipv6 and not radius_server_name:
- module.fail_json(
- msg='Error: Please input radius_server_ip or radius_server_ipv6 or radius_server_name.')
-
- if radius_server_ip and radius_server_ipv6:
- module.fail_json(
- msg='Error: Please do not input radius_server_ip and radius_server_ipv6 at the same time.')
-
- if not radius_server_type or not radius_server_port or not radius_server_mode or not radius_vpn_name:
- module.fail_json(
- msg='Error: Please input radius_server_type radius_server_port radius_server_mode radius_vpn_name.')
-
- if radius_server_ip:
- rds_server_ipv4_result = ce_aaa_server_host.get_radius_server_cfg_ipv4(
- module=module)
- if radius_server_ipv6:
- rds_server_ipv6_result = ce_aaa_server_host.get_radius_server_cfg_ipv6(
- module=module)
- if radius_server_name:
- rds_server_name_result = ce_aaa_server_host.get_radius_server_name(
- module=module)
-
- if radius_server_ip and rds_server_ipv4_result["radius_server_ip_v4"]:
- existing["radius server ipv4"] = rds_server_ipv4_result[
- "radius_server_ip_v4"]
- if radius_server_ipv6 and rds_server_ipv6_result["radius_server_ip_v6"]:
- existing["radius server ipv6"] = rds_server_ipv6_result[
- "radius_server_ip_v6"]
- if radius_server_name and rds_server_name_result["radius_server_name_cfg"]:
- existing["radius server name cfg"] = rds_server_name_result[
- "radius_server_name_cfg"]
-
- if state == "present":
- if radius_server_ip and rds_server_ipv4_result["need_cfg"]:
- cmd = ce_aaa_server_host.merge_radius_server_cfg_ipv4(
- module=module)
- changed = True
- updates.append(cmd)
-
- if radius_server_ipv6 and rds_server_ipv6_result["need_cfg"]:
- cmd = ce_aaa_server_host.merge_radius_server_cfg_ipv6(
- module=module)
- changed = True
- updates.append(cmd)
-
- if radius_server_name and rds_server_name_result["need_cfg"]:
- cmd = ce_aaa_server_host.merge_radius_server_name(
- module=module)
- changed = True
- updates.append(cmd)
- else:
- if radius_server_ip and rds_server_ipv4_result["need_cfg"]:
- cmd = ce_aaa_server_host.delete_radius_server_cfg_ipv4(
- module=module)
- changed = True
- updates.append(cmd)
-
- if radius_server_ipv6 and rds_server_ipv6_result["need_cfg"]:
- cmd = ce_aaa_server_host.delete_radius_server_cfg_ipv6(
- module=module)
- changed = True
- updates.append(cmd)
-
- if radius_server_name and rds_server_name_result["need_cfg"]:
- cmd = ce_aaa_server_host.delete_radius_server_name(
- module=module)
- changed = True
- updates.append(cmd)
-
- if radius_server_ip:
- rds_server_ipv4_result = ce_aaa_server_host.get_radius_server_cfg_ipv4(
- module=module)
- if radius_server_ipv6:
- rds_server_ipv6_result = ce_aaa_server_host.get_radius_server_cfg_ipv6(
- module=module)
- if radius_server_name:
- rds_server_name_result = ce_aaa_server_host.get_radius_server_name(
- module=module)
-
- if radius_server_ip and rds_server_ipv4_result["radius_server_ip_v4"]:
- end_state["radius server ipv4"] = rds_server_ipv4_result[
- "radius_server_ip_v4"]
- if radius_server_ipv6 and rds_server_ipv6_result["radius_server_ip_v6"]:
- end_state["radius server ipv6"] = rds_server_ipv6_result[
- "radius_server_ip_v6"]
- if radius_server_name and rds_server_name_result["radius_server_name_cfg"]:
- end_state["radius server name cfg"] = rds_server_name_result[
- "radius_server_name_cfg"]
-
- if hwtacacs_template:
-
- if not hwtacacs_server_ip and not hwtacacs_server_ipv6 and not hwtacacs_server_host_name:
- module.fail_json(
- msg='Error: Please input hwtacacs_server_ip or hwtacacs_server_ipv6 or hwtacacs_server_host_name.')
-
- if not hwtacacs_server_type or not hwtacacs_vpn_name:
- module.fail_json(
- msg='Error: Please input hwtacacs_server_type hwtacacs_vpn_name.')
-
- if hwtacacs_server_ip and hwtacacs_server_ipv6:
- module.fail_json(
- msg='Error: Please do not set hwtacacs_server_ip and hwtacacs_server_ipv6 at the same time.')
-
- if hwtacacs_vpn_name and hwtacacs_vpn_name != "_public_":
- if hwtacacs_is_public_net:
- module.fail_json(
- msg='Error: Please do not set vpn and public net at the same time.')
-
- if hwtacacs_server_ip:
- hwtacacs_server_ipv4_result = ce_aaa_server_host.get_hwtacacs_server_cfg_ipv4(
- module=module)
- if hwtacacs_server_ipv6:
- hwtacacs_server_ipv6_result = ce_aaa_server_host.get_hwtacacs_server_cfg_ipv6(
- module=module)
- if hwtacacs_server_host_name:
- hwtacacs_host_name_result = ce_aaa_server_host.get_hwtacacs_host_server_cfg(
- module=module)
-
- if hwtacacs_server_ip and hwtacacs_server_ipv4_result["hwtacacs_server_cfg_ipv4"]:
- existing["hwtacacs server cfg ipv4"] = hwtacacs_server_ipv4_result[
- "hwtacacs_server_cfg_ipv4"]
- if hwtacacs_server_ipv6 and hwtacacs_server_ipv6_result["hwtacacs_server_cfg_ipv6"]:
- existing["hwtacacs server cfg ipv6"] = hwtacacs_server_ipv6_result[
- "hwtacacs_server_cfg_ipv6"]
- if hwtacacs_server_host_name and hwtacacs_host_name_result["hwtacacs_server_name_cfg"]:
- existing["hwtacacs server name cfg"] = hwtacacs_host_name_result[
- "hwtacacs_server_name_cfg"]
-
- if state == "present":
- if hwtacacs_server_ip and hwtacacs_server_ipv4_result["need_cfg"]:
- cmd = ce_aaa_server_host.merge_hwtacacs_server_cfg_ipv4(
- module=module)
- changed = True
- updates.append(cmd)
-
- if hwtacacs_server_ipv6 and hwtacacs_server_ipv6_result["need_cfg"]:
- cmd = ce_aaa_server_host.merge_hwtacacs_server_cfg_ipv6(
- module=module)
- changed = True
- updates.append(cmd)
-
- if hwtacacs_server_host_name and hwtacacs_host_name_result["need_cfg"]:
- cmd = ce_aaa_server_host.merge_hwtacacs_host_server_cfg(
- module=module)
- changed = True
- updates.append(cmd)
-
- else:
- if hwtacacs_server_ip and hwtacacs_server_ipv4_result["need_cfg"]:
- cmd = ce_aaa_server_host.delete_hwtacacs_server_cfg_ipv4(
- module=module)
- changed = True
- updates.append(cmd)
-
- if hwtacacs_server_ipv6 and hwtacacs_server_ipv6_result["need_cfg"]:
- cmd = ce_aaa_server_host.delete_hwtacacs_server_cfg_ipv6(
- module=module)
- changed = True
- updates.append(cmd)
-
- if hwtacacs_server_host_name and hwtacacs_host_name_result["need_cfg"]:
- cmd = ce_aaa_server_host.delete_hwtacacs_host_server_cfg(
- module=module)
- changed = True
- updates.append(cmd)
-
- if hwtacacs_server_ip:
- hwtacacs_server_ipv4_result = ce_aaa_server_host.get_hwtacacs_server_cfg_ipv4(
- module=module)
- if hwtacacs_server_ipv6:
- hwtacacs_server_ipv6_result = ce_aaa_server_host.get_hwtacacs_server_cfg_ipv6(
- module=module)
- if hwtacacs_server_host_name:
- hwtacacs_host_name_result = ce_aaa_server_host.get_hwtacacs_host_server_cfg(
- module=module)
-
- if hwtacacs_server_ip and hwtacacs_server_ipv4_result["hwtacacs_server_cfg_ipv4"]:
- end_state["hwtacacs server cfg ipv4"] = hwtacacs_server_ipv4_result[
- "hwtacacs_server_cfg_ipv4"]
- if hwtacacs_server_ipv6 and hwtacacs_server_ipv6_result["hwtacacs_server_cfg_ipv6"]:
- end_state["hwtacacs server cfg ipv6"] = hwtacacs_server_ipv6_result[
- "hwtacacs_server_cfg_ipv6"]
- if hwtacacs_server_host_name and hwtacacs_host_name_result["hwtacacs_server_name_cfg"]:
- end_state["hwtacacs server name cfg"] = hwtacacs_host_name_result[
- "hwtacacs_server_name_cfg"]
-
- results = dict()
- results['proposed'] = proposed
- results['existing'] = existing
- results['changed'] = changed
- results['end_state'] = end_state
- results['updates'] = updates
-
- module.exit_json(**results)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_acl.py b/plugins/modules/network/cloudengine/ce_acl.py
deleted file mode 100644
index 4b82418bb2..0000000000
--- a/plugins/modules/network/cloudengine/ce_acl.py
+++ /dev/null
@@ -1,1004 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_acl
-short_description: Manages base ACL configuration on HUAWEI CloudEngine switches.
-description:
- - Manages base ACL configurations on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- state:
- description:
- - Specify desired state of the resource.
- default: present
- choices: ['present','absent','delete_acl']
- acl_name:
- description:
- - ACL number or name.
- For a numbered rule group, the value ranging from 2000 to 2999 indicates a basic ACL.
- For a named rule group, the value is a string of 1 to 32 case-sensitive characters starting
- with a letter, spaces not supported.
- required: true
- acl_num:
- description:
- - ACL number.
- The value is an integer ranging from 2000 to 2999.
- acl_step:
- description:
- - ACL step.
- The value is an integer ranging from 1 to 20. The default value is 5.
- acl_description:
- description:
- - ACL description.
- The value is a string of 1 to 127 characters.
- rule_name:
- description:
- - Name of a basic ACL rule.
- The value is a string of 1 to 32 characters.
- The value is case-insensitive, and cannot contain spaces or begin with an underscore (_).
- rule_id:
- description:
- - ID of a basic ACL rule in configuration mode.
- The value is an integer ranging from 0 to 4294967294.
- rule_action:
- description:
- - Matching mode of basic ACL rules.
- choices: ['permit','deny']
- source_ip:
- description:
- - Source IP address.
- The value is a string of 0 to 255 characters.The default value is 0.0.0.0.
- The value is in dotted decimal notation.
- src_mask:
- description:
- - Mask of a source IP address.
- The value is an integer ranging from 1 to 32.
- frag_type:
- description:
- - Type of packet fragmentation.
- choices: ['fragment', 'clear_fragment']
- vrf_name:
- description:
- - VPN instance name.
- The value is a string of 1 to 31 characters.The default value is _public_.
- time_range:
- description:
- - Name of a time range in which an ACL rule takes effect.
- The value is a string of 1 to 32 characters.
- The value is case-insensitive, and cannot contain spaces. The name must start with an uppercase
- or lowercase letter. In addition, the word "all" cannot be specified as a time range name.
- rule_description:
- description:
- - Description about an ACL rule.
- The value is a string of 1 to 127 characters.
- log_flag:
- description:
- - Flag of logging matched data packets.
- type: bool
- default: 'no'
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine acl test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Config ACL"
- ce_acl:
- state: present
- acl_name: 2200
- provider: "{{ cli }}"
-
- - name: "Undo ACL"
- ce_acl:
- state: delete_acl
- acl_name: 2200
- provider: "{{ cli }}"
-
- - name: "Config ACL base rule"
- ce_acl:
- state: present
- acl_name: 2200
- rule_name: test_rule
- rule_id: 111
- rule_action: permit
- source_ip: 10.10.10.10
- src_mask: 24
- frag_type: fragment
- time_range: wdz_acl_time
- provider: "{{ cli }}"
-
- - name: "undo ACL base rule"
- ce_acl:
- state: absent
- acl_name: 2200
- rule_name: test_rule
- rule_id: 111
- rule_action: permit
- source_ip: 10.10.10.10
- src_mask: 24
- frag_type: fragment
- time_range: wdz_acl_time
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"acl_name": "test", "state": "delete_acl"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {"aclNumOrName": "test", "aclType": "Basic"}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["undo acl name test"]
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec, check_ip_addr
-
-# get acl
-CE_GET_ACL_HEADER = """
-
-
-
-
-
-"""
-CE_GET_ACL_TAIL = """
-
-
-
-
-"""
-# merge acl
-CE_MERGE_ACL_HEADER = """
-
-
-
-
- %s
-"""
-CE_MERGE_ACL_TAIL = """
-
-
-
-
-"""
-# delete acl
-CE_DELETE_ACL_HEADER = """
-
-
-
-
- %s
-"""
-CE_DELETE_ACL_TAIL = """
-
-
-
-
-"""
-
-# get acl base rule
-CE_GET_ACL_BASE_RULE_HEADER = """
-
-
-
-
- %s
-
-
-
-"""
-CE_GET_ACL_BASE_RULE_TAIL = """
-
-
-
-
-
-
-"""
-# merge acl base rule
-CE_MERGE_ACL_BASE_RULE_HEADER = """
-
-
-
-
- %s
-
-
- %s
-"""
-CE_MERGE_ACL_BASE_RULE_TAIL = """
-
-
-
-
-
-
-"""
-# delete acl base rule
-CE_DELETE_ACL_BASE_RULE_HEADER = """
-
-
-
-
- %s
-
-
- %s
-"""
-CE_DELETE_ACL_BASE_RULE_TAIL = """
-
-
-
-
-
-
-"""
-
-
-class BaseAcl(object):
- """ Manages base acl configuration """
-
- def __init__(self, **kwargs):
- """ Class init """
-
- # argument spec
- argument_spec = kwargs["argument_spec"]
- self.spec = argument_spec
- self.module = AnsibleModule(argument_spec=self.spec, supports_check_mode=True)
-
- # module args
- self.state = self.module.params['state']
- self.acl_name = self.module.params['acl_name'] or None
- self.acl_num = self.module.params['acl_num'] or None
- self.acl_type = None
- self.acl_step = self.module.params['acl_step'] or None
- self.acl_description = self.module.params['acl_description'] or None
- self.rule_name = self.module.params['rule_name'] or None
- self.rule_id = self.module.params['rule_id'] or None
- self.rule_action = self.module.params['rule_action'] or None
- self.source_ip = self.module.params['source_ip'] or None
- self.src_mask = self.module.params['src_mask'] or None
- self.src_wild = None
- self.frag_type = self.module.params['frag_type'] or None
- self.vrf_name = self.module.params['vrf_name'] or None
- self.time_range = self.module.params['time_range'] or None
- self.rule_description = self.module.params['rule_description'] or None
- self.log_flag = self.module.params['log_flag']
-
- # cur config
- self.cur_acl_cfg = dict()
- self.cur_base_rule_cfg = dict()
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def netconf_get_config(self, conf_str):
- """ Get configure by netconf """
-
- xml_str = get_nc_config(self.module, conf_str)
-
- return xml_str
-
- def netconf_set_config(self, conf_str):
- """ Set configure by netconf """
-
- xml_str = set_nc_config(self.module, conf_str)
-
- return xml_str
-
- def get_wildcard_mask(self):
- """ convert mask length to ip address wildcard mask, i.e. 24 to 0.0.0.255 """
-
- mask_int = ["255"] * 4
- value = int(self.src_mask)
-
- if value > 32:
- self.module.fail_json(msg='Error: IPv4 ipaddress mask length is invalid.')
- if value < 8:
- mask_int[0] = str(int(~(0xFF << (8 - value % 8)) & 0xFF))
- if value >= 8:
- mask_int[0] = '0'
- mask_int[1] = str(int(~(0xFF << (16 - (value % 16))) & 0xFF))
- if value >= 16:
- mask_int[1] = '0'
- mask_int[2] = str(int(~(0xFF << (24 - (value % 24))) & 0xFF))
- if value >= 24:
- mask_int[2] = '0'
- mask_int[3] = str(int(~(0xFF << (32 - (value % 32))) & 0xFF))
- if value == 32:
- mask_int[3] = '0'
-
- return '.'.join(mask_int)
-
- def check_acl_args(self):
- """ Check acl invalid args """
-
- need_cfg = False
- find_flag = False
- self.cur_acl_cfg["acl_info"] = []
-
- if self.acl_name:
-
- if self.acl_name.isdigit():
- if int(self.acl_name) < 2000 or int(self.acl_name) > 2999:
- self.module.fail_json(
- msg='Error: The value of acl_name is out of [2000-2999] for base ACL.')
-
- if self.acl_num:
- self.module.fail_json(
- msg='Error: The acl_name is digit, so should not input acl_num at the same time.')
- else:
-
- self.acl_type = "Basic"
-
- if len(self.acl_name) < 1 or len(self.acl_name) > 32:
- self.module.fail_json(
- msg='Error: The len of acl_name is out of [1 - 32].')
-
- if self.state == "present":
- if not self.acl_num and not self.acl_type and not self.rule_name:
- self.module.fail_json(
- msg='Error: Please input acl_num or acl_type when config ACL.')
-
- if self.acl_num:
- if self.acl_num.isdigit():
- if int(self.acl_num) < 2000 or int(self.acl_num) > 2999:
- self.module.fail_json(
- msg='Error: The value of acl_name is out of [2000-2999] for base ACL.')
- else:
- self.module.fail_json(
- msg='Error: The acl_num is not digit.')
-
- if self.acl_step:
- if self.acl_step.isdigit():
- if int(self.acl_step) < 1 or int(self.acl_step) > 20:
- self.module.fail_json(
- msg='Error: The value of acl_step is out of [1 - 20].')
- else:
- self.module.fail_json(
- msg='Error: The acl_step is not digit.')
-
- if self.acl_description:
- if len(self.acl_description) < 1 or len(self.acl_description) > 127:
- self.module.fail_json(
- msg='Error: The len of acl_description is out of [1 - 127].')
-
- conf_str = CE_GET_ACL_HEADER
-
- if self.acl_type:
- conf_str += ""
- if self.acl_num or self.acl_name.isdigit():
- conf_str += ""
- if self.acl_step:
- conf_str += ""
- if self.acl_description:
- conf_str += ""
-
- conf_str += CE_GET_ACL_TAIL
- recv_xml = self.netconf_get_config(conf_str=conf_str)
-
- if "" in recv_xml:
- find_flag = False
-
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
-
- # parse acl
- acl_info = root.findall(
- "acl/aclGroups/aclGroup")
- if acl_info:
- for tmp in acl_info:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["aclNumOrName", "aclType", "aclNumber", "aclStep", "aclDescription"]:
- tmp_dict[site.tag] = site.text
-
- self.cur_acl_cfg["acl_info"].append(tmp_dict)
-
- if self.cur_acl_cfg["acl_info"]:
- find_list = list()
- for tmp in self.cur_acl_cfg["acl_info"]:
- cur_cfg_dict = dict()
- exist_cfg_dict = dict()
- if self.acl_name:
- if self.acl_name.isdigit() and tmp.get("aclNumber"):
- cur_cfg_dict["aclNumber"] = self.acl_name
- exist_cfg_dict["aclNumber"] = tmp.get("aclNumber")
- else:
- cur_cfg_dict["aclNumOrName"] = self.acl_name
- exist_cfg_dict["aclNumOrName"] = tmp.get("aclNumOrName")
- if self.acl_type:
- cur_cfg_dict["aclType"] = self.acl_type
- exist_cfg_dict["aclType"] = tmp.get("aclType")
- if self.acl_num:
- cur_cfg_dict["aclNumber"] = self.acl_num
- exist_cfg_dict["aclNumber"] = tmp.get("aclNumber")
- if self.acl_step:
- cur_cfg_dict["aclStep"] = self.acl_step
- exist_cfg_dict["aclStep"] = tmp.get("aclStep")
- if self.acl_description:
- cur_cfg_dict["aclDescription"] = self.acl_description
- exist_cfg_dict["aclDescription"] = tmp.get("aclDescription")
-
- if cur_cfg_dict == exist_cfg_dict:
- find_bool = True
- else:
- find_bool = False
- find_list.append(find_bool)
-
- for mem in find_list:
- if mem:
- find_flag = True
- break
- else:
- find_flag = False
-
- else:
- find_flag = False
-
- if self.state == "present":
- need_cfg = bool(not find_flag)
- elif self.state == "delete_acl":
- need_cfg = bool(find_flag)
- else:
- need_cfg = False
-
- self.cur_acl_cfg["need_cfg"] = need_cfg
-
- def check_base_rule_args(self):
- """ Check base rule invalid args """
-
- need_cfg = False
- find_flag = False
- self.cur_base_rule_cfg["base_rule_info"] = []
-
- if self.acl_name:
-
- if self.state == "absent":
- if not self.rule_name:
- self.module.fail_json(
- msg='Error: Please input rule_name when state is absent.')
-
- # config rule
- if self.rule_name:
- if len(self.rule_name) < 1 or len(self.rule_name) > 32:
- self.module.fail_json(
- msg='Error: The len of rule_name is out of [1 - 32].')
-
- if self.state != "delete_acl" and not self.rule_id:
- self.module.fail_json(
- msg='Error: Please input rule_id.')
-
- if self.rule_id:
- if self.rule_id.isdigit():
- if int(self.rule_id) < 0 or int(self.rule_id) > 4294967294:
- self.module.fail_json(
- msg='Error: The value of rule_id is out of [0 - 4294967294].')
- else:
- self.module.fail_json(
- msg='Error: The rule_id is not digit.')
-
- if self.source_ip:
- if not check_ip_addr(self.source_ip):
- self.module.fail_json(
- msg='Error: The source_ip %s is invalid.' % self.source_ip)
- if not self.src_mask:
- self.module.fail_json(
- msg='Error: Please input src_mask.')
-
- if self.src_mask:
- if self.src_mask.isdigit():
- if int(self.src_mask) < 1 or int(self.src_mask) > 32:
- self.module.fail_json(
- msg='Error: The src_mask is out of [1 - 32].')
- self.src_wild = self.get_wildcard_mask()
- else:
- self.module.fail_json(
- msg='Error: The src_mask is not digit.')
-
- if self.vrf_name:
- if len(self.vrf_name) < 1 or len(self.vrf_name) > 31:
- self.module.fail_json(
- msg='Error: The len of vrf_name is out of [1 - 31].')
-
- if self.time_range:
- if len(self.time_range) < 1 or len(self.time_range) > 32:
- self.module.fail_json(
- msg='Error: The len of time_range is out of [1 - 32].')
-
- if self.rule_description:
- if len(self.rule_description) < 1 or len(self.rule_description) > 127:
- self.module.fail_json(
- msg='Error: The len of rule_description is out of [1 - 127].')
-
- if self.state != "delete_acl" and not self.rule_id:
- self.module.fail_json(
- msg='Error: Please input rule_id.')
-
- conf_str = CE_GET_ACL_BASE_RULE_HEADER % self.acl_name
-
- if self.rule_id:
- conf_str += ""
- if self.rule_action:
- conf_str += ""
- if self.source_ip:
- conf_str += ""
- if self.src_wild:
- conf_str += ""
- if self.frag_type:
- conf_str += ""
- if self.vrf_name:
- conf_str += ""
- if self.time_range:
- conf_str += ""
- if self.rule_description:
- conf_str += ""
- conf_str += ""
-
- conf_str += CE_GET_ACL_BASE_RULE_TAIL
- recv_xml = self.netconf_get_config(conf_str=conf_str)
-
- if "" in recv_xml:
- find_flag = False
-
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
-
- # parse base rule
- base_rule_info = root.findall(
- "acl/aclGroups/aclGroup/aclRuleBas4s/aclRuleBas4")
- if base_rule_info:
- for tmp in base_rule_info:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["aclRuleName", "aclRuleID", "aclAction", "aclSourceIp", "aclSrcWild",
- "aclFragType", "vrfName", "aclTimeName", "aclRuleDescription",
- "aclLogFlag"]:
- tmp_dict[site.tag] = site.text
-
- self.cur_base_rule_cfg[
- "base_rule_info"].append(tmp_dict)
-
- if self.cur_base_rule_cfg["base_rule_info"]:
- for tmp in self.cur_base_rule_cfg["base_rule_info"]:
- find_flag = True
-
- if self.rule_name and tmp.get("aclRuleName") != self.rule_name:
- find_flag = False
- if self.rule_id and tmp.get("aclRuleID") != self.rule_id:
- find_flag = False
- if self.rule_action and tmp.get("aclAction") != self.rule_action:
- find_flag = False
- if self.source_ip:
- tmp_src_ip = self.source_ip.split(".")
- tmp_src_wild = self.src_wild.split(".")
- tmp_addr_item = []
- for idx in range(4):
- item1 = 255 - int(tmp_src_wild[idx])
- item2 = item1 & int(tmp_src_ip[idx])
- tmp_addr_item.append(item2)
- tmp_addr = "%s.%s.%s.%s" % (tmp_addr_item[0], tmp_addr_item[1],
- tmp_addr_item[2], tmp_addr_item[3])
- if tmp_addr != tmp.get("aclSourceIp"):
- find_flag = False
- if self.src_wild and tmp.get("aclSrcWild") != self.src_wild:
- find_flag = False
- frag_type = "clear_fragment" if tmp.get("aclFragType") is None else tmp.get("aclFragType")
- if self.frag_type and frag_type != self.frag_type:
- find_flag = False
- if self.vrf_name and tmp.get("vrfName") != self.vrf_name:
- find_flag = False
- if self.time_range and tmp.get("aclTimeName") != self.time_range:
- find_flag = False
- if self.rule_description and tmp.get("aclRuleDescription") != self.rule_description:
- find_flag = False
- if tmp.get("aclLogFlag") != str(self.log_flag).lower():
- find_flag = False
-
- if find_flag:
- break
- else:
- find_flag = False
-
- if self.state == "present":
- need_cfg = bool(not find_flag)
- elif self.state == "absent":
- need_cfg = bool(find_flag)
- else:
- need_cfg = False
-
- self.cur_base_rule_cfg["need_cfg"] = need_cfg
-
- def get_proposed(self):
- """ Get proposed state """
-
- self.proposed["state"] = self.state
-
- if self.acl_name:
- self.proposed["acl_name"] = self.acl_name
- if self.acl_num:
- self.proposed["acl_num"] = self.acl_num
- if self.acl_step:
- self.proposed["acl_step"] = self.acl_step
- if self.acl_description:
- self.proposed["acl_description"] = self.acl_description
- if self.rule_name:
- self.proposed["rule_name"] = self.rule_name
- if self.rule_id:
- self.proposed["rule_id"] = self.rule_id
- if self.rule_action:
- self.proposed["rule_action"] = self.rule_action
- if self.source_ip:
- self.proposed["source_ip"] = self.source_ip
- if self.src_mask:
- self.proposed["src_mask"] = self.src_mask
- if self.frag_type:
- self.proposed["frag_type"] = self.frag_type
- if self.vrf_name:
- self.proposed["vrf_name"] = self.vrf_name
- if self.time_range:
- self.proposed["time_range"] = self.time_range
- if self.rule_description:
- self.proposed["rule_description"] = self.rule_description
- if self.log_flag:
- self.proposed["log_flag"] = self.log_flag
-
- def get_existing(self):
- """ Get existing state """
-
- self.existing["acl_info"] = self.cur_acl_cfg["acl_info"]
- self.existing["base_rule_info"] = self.cur_base_rule_cfg[
- "base_rule_info"]
-
- def get_end_state(self):
- """ Get end state """
-
- self.check_acl_args()
- self.end_state["acl_info"] = self.cur_acl_cfg["acl_info"]
-
- self.check_base_rule_args()
- self.end_state["base_rule_info"] = self.cur_base_rule_cfg[
- "base_rule_info"]
-
- def merge_acl(self):
- """ Merge acl operation """
-
- conf_str = CE_MERGE_ACL_HEADER % self.acl_name
-
- if self.acl_type:
- conf_str += "%s" % self.acl_type
- if self.acl_num:
- conf_str += "%s" % self.acl_num
- if self.acl_step:
- conf_str += "%s" % self.acl_step
- if self.acl_description:
- conf_str += "%s" % self.acl_description
-
- conf_str += CE_MERGE_ACL_TAIL
-
- recv_xml = self.netconf_set_config(conf_str=conf_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Merge acl failed.')
-
- if self.acl_name.isdigit():
- cmd = "acl number %s" % self.acl_name
- else:
- if self.acl_type and not self.acl_num:
- cmd = "acl name %s %s" % (self.acl_name, self.acl_type.lower())
- elif self.acl_type and self.acl_num:
- cmd = "acl name %s number %s" % (self.acl_name, self.acl_num)
- elif not self.acl_type and self.acl_num:
- cmd = "acl name %s number %s" % (self.acl_name, self.acl_num)
- self.updates_cmd.append(cmd)
-
- if self.acl_description:
- cmd = "description %s" % self.acl_description
- self.updates_cmd.append(cmd)
-
- if self.acl_step:
- cmd = "step %s" % self.acl_step
- self.updates_cmd.append(cmd)
-
- self.changed = True
-
- def delete_acl(self):
- """ Delete acl operation """
-
- conf_str = CE_DELETE_ACL_HEADER % self.acl_name
-
- if self.acl_type:
- conf_str += "%s" % self.acl_type
- if self.acl_num:
- conf_str += "%s" % self.acl_num
- if self.acl_step:
- conf_str += "%s" % self.acl_step
- if self.acl_description:
- conf_str += "%s" % self.acl_description
-
- conf_str += CE_DELETE_ACL_TAIL
-
- recv_xml = self.netconf_set_config(conf_str=conf_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Delete acl failed.')
-
- if self.acl_description:
- cmd = "undo description"
- self.updates_cmd.append(cmd)
-
- if self.acl_step:
- cmd = "undo step"
- self.updates_cmd.append(cmd)
-
- if self.acl_name.isdigit():
- cmd = "undo acl number %s" % self.acl_name
- else:
- cmd = "undo acl name %s" % self.acl_name
- self.updates_cmd.append(cmd)
-
- self.changed = True
-
- def merge_base_rule(self):
- """ Merge base rule operation """
-
- conf_str = CE_MERGE_ACL_BASE_RULE_HEADER % (
- self.acl_name, self.rule_name)
-
- if self.rule_id:
- conf_str += "%s" % self.rule_id
- if self.rule_action:
- conf_str += "%s" % self.rule_action
- if self.source_ip:
- conf_str += "%s" % self.source_ip
- if self.src_wild:
- conf_str += "%s" % self.src_wild
- if self.frag_type:
- conf_str += "%s" % self.frag_type
- if self.vrf_name:
- conf_str += "%s" % self.vrf_name
- if self.time_range:
- conf_str += "%s" % self.time_range
- if self.rule_description:
- conf_str += "%s" % self.rule_description
- conf_str += "%s" % str(self.log_flag).lower()
-
- conf_str += CE_MERGE_ACL_BASE_RULE_TAIL
-
- recv_xml = self.netconf_set_config(conf_str=conf_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Merge acl base rule failed.')
-
- if self.rule_action:
- cmd = "rule"
- if self.rule_id:
- cmd += " %s" % self.rule_id
- cmd += " %s" % self.rule_action
- if self.frag_type == "fragment":
- cmd += " fragment-type fragment"
- if self.source_ip and self.src_wild:
- cmd += " source %s %s" % (self.source_ip, self.src_wild)
- if self.time_range:
- cmd += " time-range %s" % self.time_range
- if self.vrf_name:
- cmd += " vpn-instance %s" % self.vrf_name
- if self.log_flag:
- cmd += " logging"
- self.updates_cmd.append(cmd)
-
- if self.rule_description:
- cmd = "rule %s description %s" % (
- self.rule_id, self.rule_description)
- self.updates_cmd.append(cmd)
-
- self.changed = True
-
- def delete_base_rule(self):
- """ Delete base rule operation """
-
- conf_str = CE_DELETE_ACL_BASE_RULE_HEADER % (
- self.acl_name, self.rule_name)
-
- if self.rule_id:
- conf_str += "%s" % self.rule_id
- if self.rule_action:
- conf_str += "%s" % self.rule_action
- if self.source_ip:
- conf_str += "%s" % self.source_ip
- if self.src_wild:
- conf_str += "%s" % self.src_wild
- if self.frag_type:
- conf_str += "%s" % self.frag_type
- if self.vrf_name:
- conf_str += "%s" % self.vrf_name
- if self.time_range:
- conf_str += "%s" % self.time_range
- if self.rule_description:
- conf_str += "%s" % self.rule_description
- conf_str += "%s" % str(self.log_flag).lower()
-
- conf_str += CE_DELETE_ACL_BASE_RULE_TAIL
-
- recv_xml = self.netconf_set_config(conf_str=conf_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Delete acl base rule failed.')
-
- if self.rule_description:
- if self.acl_name.isdigit():
- cmd = "acl number %s" % self.acl_name
- else:
- cmd = "acl name %s" % self.acl_name
- self.updates_cmd.append(cmd)
-
- cmd = "undo rule %s description" % self.rule_id
- self.updates_cmd.append(cmd)
-
- if self.rule_id:
- if self.acl_name.isdigit():
- cmd = "acl number %s" % self.acl_name
- else:
- cmd = "acl name %s" % self.acl_name
- self.updates_cmd.append(cmd)
-
- cmd = "undo rule %s" % self.rule_id
- self.updates_cmd.append(cmd)
- elif self.rule_action:
- if self.acl_name.isdigit():
- cmd = "acl number %s" % self.acl_name
- else:
- cmd = "acl name %s" % self.acl_name
- self.updates_cmd.append(cmd)
-
- cmd = "undo rule"
- cmd += " %s" % self.rule_action
- if self.frag_type == "fragment":
- cmd += " fragment-type fragment"
- if self.source_ip and self.src_wild:
- cmd += " source %s %s" % (self.source_ip, self.src_wild)
- if self.time_range:
- cmd += " time-range %s" % self.time_range
- if self.vrf_name:
- cmd += " vpn-instance %s" % self.vrf_name
- if self.log_flag:
- cmd += " logging"
- self.updates_cmd.append(cmd)
-
- self.changed = True
-
- def work(self):
- """ Main work function """
-
- self.check_acl_args()
- self.check_base_rule_args()
- self.get_proposed()
- self.get_existing()
-
- if self.state == "present":
- if self.cur_acl_cfg["need_cfg"]:
- self.merge_acl()
- if self.cur_base_rule_cfg["need_cfg"]:
- self.merge_base_rule()
-
- elif self.state == "absent":
- if self.cur_base_rule_cfg["need_cfg"]:
- self.delete_base_rule()
-
- elif self.state == "delete_acl":
- if self.cur_acl_cfg["need_cfg"]:
- self.delete_acl()
-
- self.get_end_state()
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- self.results['updates'] = self.updates_cmd
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent',
- 'delete_acl'], default='present'),
- acl_name=dict(type='str', required=True),
- acl_num=dict(type='str'),
- acl_step=dict(type='str'),
- acl_description=dict(type='str'),
- rule_name=dict(type='str'),
- rule_id=dict(type='str'),
- rule_action=dict(choices=['permit', 'deny']),
- source_ip=dict(type='str'),
- src_mask=dict(type='str'),
- frag_type=dict(choices=['fragment', 'clear_fragment']),
- vrf_name=dict(type='str'),
- time_range=dict(type='str'),
- rule_description=dict(type='str'),
- log_flag=dict(required=False, default=False, type='bool')
- )
-
- argument_spec.update(ce_argument_spec)
- module = BaseAcl(argument_spec=argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_acl_advance.py b/plugins/modules/network/cloudengine/ce_acl_advance.py
deleted file mode 100644
index 869963bda0..0000000000
--- a/plugins/modules/network/cloudengine/ce_acl_advance.py
+++ /dev/null
@@ -1,1750 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_acl_advance
-short_description: Manages advanced ACL configuration on HUAWEI CloudEngine switches.
-description:
- - Manages advanced ACL configurations on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- state:
- description:
- - Specify desired state of the resource.
- required: false
- default: present
- choices: ['present','absent','delete_acl']
- acl_name:
- description:
- - ACL number or name.
- For a numbered rule group, the value ranging from 3000 to 3999 indicates a advance ACL.
- For a named rule group, the value is a string of 1 to 32 case-sensitive characters starting
- with a letter, spaces not supported.
- required: true
- acl_num:
- description:
- - ACL number.
- The value is an integer ranging from 3000 to 3999.
- acl_step:
- description:
- - ACL step.
- The value is an integer ranging from 1 to 20. The default value is 5.
- acl_description:
- description:
- - ACL description.
- The value is a string of 1 to 127 characters.
- rule_name:
- description:
- - Name of a basic ACL rule.
- The value is a string of 1 to 32 characters.
- rule_id:
- description:
- - ID of a basic ACL rule in configuration mode.
- The value is an integer ranging from 0 to 4294967294.
- rule_action:
- description:
- - Matching mode of basic ACL rules.
- choices: ['permit','deny']
- protocol:
- description:
- - Protocol type.
- choices: ['ip', 'icmp', 'igmp', 'ipinip', 'tcp', 'udp', 'gre', 'ospf']
- source_ip:
- description:
- - Source IP address.
- The value is a string of 0 to 255 characters.The default value is 0.0.0.0.
- The value is in dotted decimal notation.
- src_mask:
- description:
- - Source IP address mask.
- The value is an integer ranging from 1 to 32.
- src_pool_name:
- description:
- - Name of a source pool.
- The value is a string of 1 to 32 characters.
- dest_ip:
- description:
- - Destination IP address.
- The value is a string of 0 to 255 characters.The default value is 0.0.0.0.
- The value is in dotted decimal notation.
- dest_mask:
- description:
- - Destination IP address mask.
- The value is an integer ranging from 1 to 32.
- dest_pool_name:
- description:
- - Name of a destination pool.
- The value is a string of 1 to 32 characters.
- src_port_op:
- description:
- - Range type of the source port.
- choices: ['lt','eq', 'gt', 'range']
- src_port_begin:
- description:
- - Start port number of the source port.
- The value is an integer ranging from 0 to 65535.
- src_port_end:
- description:
- - End port number of the source port.
- The value is an integer ranging from 0 to 65535.
- src_port_pool_name:
- description:
- - Name of a source port pool.
- The value is a string of 1 to 32 characters.
- dest_port_op:
- description:
- - Range type of the destination port.
- choices: ['lt','eq', 'gt', 'range']
- dest_port_begin:
- description:
- - Start port number of the destination port.
- The value is an integer ranging from 0 to 65535.
- dest_port_end:
- description:
- - End port number of the destination port.
- The value is an integer ranging from 0 to 65535.
- dest_port_pool_name:
- description:
- - Name of a destination port pool.
- The value is a string of 1 to 32 characters.
- frag_type:
- description:
- - Type of packet fragmentation.
- choices: ['fragment', 'clear_fragment']
- precedence:
- description:
- - Data packets can be filtered based on the priority field.
- The value is an integer ranging from 0 to 7.
- tos:
- description:
- - ToS value on which data packet filtering is based.
- The value is an integer ranging from 0 to 15.
- dscp:
- description:
- - Differentiated Services Code Point.
- The value is an integer ranging from 0 to 63.
- icmp_name:
- description:
- - ICMP name.
- choices: ['unconfiged', 'echo', 'echo-reply', 'fragmentneed-DFset', 'host-redirect',
- 'host-tos-redirect', 'host-unreachable', 'information-reply', 'information-request',
- 'net-redirect', 'net-tos-redirect', 'net-unreachable', 'parameter-problem',
- 'port-unreachable', 'protocol-unreachable', 'reassembly-timeout', 'source-quench',
- 'source-route-failed', 'timestamp-reply', 'timestamp-request', 'ttl-exceeded',
- 'address-mask-reply', 'address-mask-request', 'custom']
- icmp_type:
- description:
- - ICMP type. This parameter is available only when the packet protocol is ICMP.
- The value is an integer ranging from 0 to 255.
- icmp_code:
- description:
- - ICMP message code. Data packets can be filtered based on the ICMP message code.
- The value is an integer ranging from 0 to 255.
- ttl_expired:
- description:
- - Whether TTL Expired is matched, with the TTL value of 1.
- type: bool
- default: 'no'
- vrf_name:
- description:
- - VPN instance name.
- The value is a string of 1 to 31 characters.The default value is _public_.
- syn_flag:
- description:
- - TCP flag value.
- The value is an integer ranging from 0 to 63.
- tcp_flag_mask:
- description:
- - TCP flag mask value.
- The value is an integer ranging from 0 to 63.
- established:
- description:
- - Match established connections.
- type: bool
- default: 'no'
- time_range:
- description:
- - Name of a time range in which an ACL rule takes effect.
- rule_description:
- description:
- - Description about an ACL rule.
- igmp_type:
- description:
- - Internet Group Management Protocol.
- choices: ['host-query', 'mrouter-adver', 'mrouter-solic', 'mrouter-termi', 'mtrace-resp', 'mtrace-route',
- 'v1host-report', 'v2host-report', 'v2leave-group', 'v3host-report']
- log_flag:
- description:
- - Flag of logging matched data packets.
- type: bool
- default: 'no'
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine advance acl test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Config ACL"
- ce_acl_advance:
- state: present
- acl_name: 3200
- provider: "{{ cli }}"
-
- - name: "Undo ACL"
- ce_acl_advance:
- state: delete_acl
- acl_name: 3200
- provider: "{{ cli }}"
-
- - name: "Config ACL advance rule"
- ce_acl_advance:
- state: present
- acl_name: test
- rule_name: test_rule
- rule_id: 111
- rule_action: permit
- protocol: tcp
- source_ip: 10.10.10.10
- src_mask: 24
- frag_type: fragment
- provider: "{{ cli }}"
-
- - name: "Undo ACL advance rule"
- ce_acl_advance:
- state: absent
- acl_name: test
- rule_name: test_rule
- rule_id: 111
- rule_action: permit
- protocol: tcp
- source_ip: 10.10.10.10
- src_mask: 24
- frag_type: fragment
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"acl_name": "test", "state": "delete_acl"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {"aclNumOrName": "test", "aclType": "Advance"}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["undo acl name test"]
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec, check_ip_addr
-
-
-# get acl
-CE_GET_ACL_HEADER = """
-
-
-
-
-
-"""
-CE_GET_ACL_TAIL = """
-
-
-
-
-"""
-# merge acl
-CE_MERGE_ACL_HEADER = """
-
-
-
-
- %s
-"""
-CE_MERGE_ACL_TAIL = """
-
-
-
-
-"""
-# delete acl
-CE_DELETE_ACL_HEADER = """
-
-
-
-
- %s
-"""
-CE_DELETE_ACL_TAIL = """
-
-
-
-
-"""
-
-# get acl advance rule
-CE_GET_ACL_ADVANCE_RULE_HEADER = """
-
-
-
-
- %s
-
-
-
-"""
-CE_GET_ACL_ADVANCE_RULE_TAIL = """
-
-
-
-
-
-
-"""
-# merge acl advance rule
-CE_MERGE_ACL_ADVANCE_RULE_HEADER = """
-
-
-
-
- %s
-
-
- %s
-"""
-CE_MERGE_ACL_ADVANCE_RULE_TAIL = """
-
-
-
-
-
-
-"""
-# delete acl advance rule
-CE_DELETE_ACL_ADVANCE_RULE_HEADER = """
-
-
-
-
- %s
-
-
- %s
-"""
-CE_DELETE_ACL_ADVANCE_RULE_TAIL = """
-
-
-
-
-
-
-"""
-
-
-PROTOCOL_NUM = {"ip": "0",
- "icmp": "1",
- "igmp": "2",
- "ipinip": "4",
- "tcp": "6",
- "udp": "17",
- "gre": "47",
- "ospf": "89"}
-
-IGMP_TYPE_NUM = {"host-query": "17",
- "mrouter-adver": "48",
- "mrouter-solic": "49",
- "mrouter-termi": "50",
- "mtrace-resp": "30",
- "mtrace-route": "31",
- "v1host-report": "18",
- "v2host-report": "22",
- "v2leave-group": "23",
- "v3host-report": "34"}
-
-
-def get_wildcard_mask(mask):
- """ convert mask length to ip address wildcard mask, i.e. 24 to 0.0.0.255 """
-
- mask_int = ["255"] * 4
- value = int(mask)
-
- if value > 32:
- return None
- if value < 8:
- mask_int[0] = str(int(~(0xFF << (8 - value % 8)) & 0xFF))
- if value >= 8:
- mask_int[0] = '0'
- mask_int[1] = str(int(~(0xFF << (16 - (value % 16))) & 0xFF))
- if value >= 16:
- mask_int[1] = '0'
- mask_int[2] = str(int(~(0xFF << (24 - (value % 24))) & 0xFF))
- if value >= 24:
- mask_int[2] = '0'
- mask_int[3] = str(int(~(0xFF << (32 - (value % 32))) & 0xFF))
- if value == 32:
- mask_int[3] = '0'
-
- return '.'.join(mask_int)
-
-
-class AdvanceAcl(object):
- """ Manages advance acl configuration """
-
- def __init__(self, **kwargs):
- """ Class init """
-
- # argument spec
- argument_spec = kwargs["argument_spec"]
- self.spec = argument_spec
- self.module = AnsibleModule(argument_spec=self.spec, supports_check_mode=True)
-
- # module args
- self.state = self.module.params['state']
- self.acl_name = self.module.params['acl_name'] or None
- self.acl_num = self.module.params['acl_num'] or None
- self.acl_type = None
- self.acl_step = self.module.params['acl_step'] or None
- self.acl_description = self.module.params['acl_description'] or None
- self.rule_name = self.module.params['rule_name'] or None
- self.rule_id = self.module.params['rule_id'] or None
- self.rule_action = self.module.params['rule_action'] or None
- self.protocol = self.module.params['protocol'] or None
- self.protocol_num = None
- self.source_ip = self.module.params['source_ip'] or None
- self.src_mask = self.module.params['src_mask'] or None
- self.src_wild = None
- self.src_pool_name = self.module.params['src_pool_name'] or None
- self.dest_ip = self.module.params['dest_ip'] or None
- self.dest_mask = self.module.params['dest_mask'] or None
- self.dest_wild = None
- self.dest_pool_name = self.module.params['dest_pool_name'] or None
- self.src_port_op = self.module.params['src_port_op'] or None
- self.src_port_begin = self.module.params['src_port_begin'] or None
- self.src_port_end = self.module.params['src_port_end'] or None
- self.src_port_pool_name = self.module.params[
- 'src_port_pool_name'] or None
- self.dest_port_op = self.module.params['dest_port_op'] or None
- self.dest_port_begin = self.module.params['dest_port_begin'] or None
- self.dest_port_end = self.module.params['dest_port_end'] or None
- self.dest_port_pool_name = self.module.params[
- 'dest_port_pool_name'] or None
- self.frag_type = self.module.params['frag_type'] or None
- self.precedence = self.module.params['precedence'] or None
- self.tos = self.module.params['tos'] or None
- self.dscp = self.module.params['dscp'] or None
- self.icmp_name = self.module.params['icmp_name'] or None
- self.icmp_type = self.module.params['icmp_type'] or None
- self.icmp_code = self.module.params['icmp_code'] or None
- self.ttl_expired = self.module.params['ttl_expired']
- self.vrf_name = self.module.params['vrf_name'] or None
- self.syn_flag = self.module.params['syn_flag'] or None
- self.tcp_flag_mask = self.module.params['tcp_flag_mask'] or None
- self.established = self.module.params['established']
- self.time_range = self.module.params['time_range'] or None
- self.rule_description = self.module.params['rule_description'] or None
- self.igmp_type = self.module.params['igmp_type'] or None
- self.igmp_type_num = None
- self.log_flag = self.module.params['log_flag']
-
- self.precedence_name = dict()
- self.precedence_name["0"] = "routine"
- self.precedence_name["1"] = "priority"
- self.precedence_name["2"] = "immediate"
- self.precedence_name["3"] = "flash"
- self.precedence_name["4"] = "flash-override"
- self.precedence_name["5"] = "critical"
- self.precedence_name["6"] = "internet"
- self.precedence_name["7"] = "network"
-
- # cur config
- self.cur_acl_cfg = dict()
- self.cur_advance_rule_cfg = dict()
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def netconf_get_config(self, conf_str):
- """ Get configure by netconf """
-
- xml_str = get_nc_config(self.module, conf_str)
-
- return xml_str
-
- def netconf_set_config(self, conf_str):
- """ Set configure by netconf """
-
- xml_str = set_nc_config(self.module, conf_str)
-
- return xml_str
-
- def get_protocol_num(self):
- """ Get protocol num by name """
-
- if self.protocol:
- self.protocol_num = PROTOCOL_NUM.get(self.protocol)
-
- def get_igmp_type_num(self):
- """ Get igmp type num by type """
-
- if self.igmp_type:
- self.igmp_type_num = IGMP_TYPE_NUM.get(self.igmp_type)
-
- def check_acl_args(self):
- """ Check acl invalid args """
-
- need_cfg = False
- find_flag = False
- self.cur_acl_cfg["acl_info"] = []
-
- if self.acl_name:
-
- if self.acl_name.isdigit():
- if int(self.acl_name) < 3000 or int(self.acl_name) > 3999:
- self.module.fail_json(
- msg='Error: The value of acl_name is out of [3000-3999] for advance ACL.')
-
- if self.acl_num:
- self.module.fail_json(
- msg='Error: The acl_name is digit, so should not input acl_num at the same time.')
- else:
-
- self.acl_type = "Advance"
-
- if len(self.acl_name) < 1 or len(self.acl_name) > 32:
- self.module.fail_json(
- msg='Error: The len of acl_name is out of [1 - 32].')
-
- if self.state == "present":
- if not self.acl_num and not self.acl_type and not self.rule_name:
- self.module.fail_json(
- msg='Error: Please input acl_num or acl_type when config ACL.')
-
- if self.acl_num:
- if self.acl_num.isdigit():
- if int(self.acl_num) < 3000 or int(self.acl_num) > 3999:
- self.module.fail_json(
- msg='Error: The value of acl_name is out of [3000-3999] for advance ACL.')
- else:
- self.module.fail_json(
- msg='Error: The acl_num is not digit.')
-
- if self.acl_step:
- if self.acl_step.isdigit():
- if int(self.acl_step) < 1 or int(self.acl_step) > 20:
- self.module.fail_json(
- msg='Error: The value of acl_step is out of [1 - 20].')
- else:
- self.module.fail_json(
- msg='Error: The acl_step is not digit.')
-
- if self.acl_description:
- if len(self.acl_description) < 1 or len(self.acl_description) > 127:
- self.module.fail_json(
- msg='Error: The len of acl_description is out of [1 - 127].')
-
- conf_str = CE_GET_ACL_HEADER
-
- if self.acl_type:
- conf_str += ""
- if self.acl_num or self.acl_name.isdigit():
- conf_str += ""
- if self.acl_step:
- conf_str += ""
- if self.acl_description:
- conf_str += ""
-
- conf_str += CE_GET_ACL_TAIL
- recv_xml = self.netconf_get_config(conf_str=conf_str)
-
- if "" in recv_xml:
- find_flag = False
-
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
-
- # parse acl
- acl_info = root.findall(
- "acl/aclGroups/aclGroup")
- if acl_info:
- for tmp in acl_info:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["aclNumOrName", "aclType", "aclNumber", "aclStep", "aclDescription"]:
- tmp_dict[site.tag] = site.text
-
- self.cur_acl_cfg["acl_info"].append(tmp_dict)
-
- if self.cur_acl_cfg["acl_info"]:
- find_list = list()
- for tmp in self.cur_acl_cfg["acl_info"]:
- cur_cfg_dict = dict()
- exist_cfg_dict = dict()
-
- if self.acl_name:
- if self.acl_name.isdigit() and tmp.get("aclNumber"):
- cur_cfg_dict["aclNumber"] = self.acl_name
- exist_cfg_dict["aclNumber"] = tmp.get("aclNumber")
- else:
- cur_cfg_dict["aclNumOrName"] = self.acl_name
- exist_cfg_dict["aclNumOrName"] = tmp.get("aclNumOrName")
- if self.acl_type:
- cur_cfg_dict["aclType"] = self.acl_type
- exist_cfg_dict["aclType"] = tmp.get("aclType")
- if self.acl_num:
- cur_cfg_dict["aclNumber"] = self.acl_num
- exist_cfg_dict["aclNumber"] = tmp.get("aclNumber")
- if self.acl_step:
- cur_cfg_dict["aclStep"] = self.acl_step
- exist_cfg_dict["aclStep"] = tmp.get("aclStep")
- if self.acl_description:
- cur_cfg_dict["aclDescription"] = self.acl_description
- exist_cfg_dict["aclDescription"] = tmp.get("aclDescription")
-
- if cur_cfg_dict == exist_cfg_dict:
- find_bool = True
- else:
- find_bool = False
- find_list.append(find_bool)
- for mem in find_list:
- if mem:
- find_flag = True
- break
- else:
- find_flag = False
- else:
- find_flag = False
-
- if self.state == "present":
- need_cfg = bool(not find_flag)
- elif self.state == "delete_acl":
- need_cfg = bool(find_flag)
- else:
- need_cfg = False
-
- self.cur_acl_cfg["need_cfg"] = need_cfg
-
- def check_advance_rule_args(self):
- """ Check advance rule invalid args """
-
- need_cfg = False
- find_flag = False
- self.cur_advance_rule_cfg["adv_rule_info"] = []
-
- if self.acl_name:
-
- if self.state == "absent":
- if not self.rule_name:
- self.module.fail_json(
- msg='Error: Please input rule_name when state is absent.')
-
- # config rule
- if self.rule_name:
- if len(self.rule_name) < 1 or len(self.rule_name) > 32:
- self.module.fail_json(
- msg='Error: The len of rule_name is out of [1 - 32].')
-
- if self.state != "delete_acl" and not self.rule_id:
- self.module.fail_json(
- msg='Error: Please input rule_id.')
-
- if self.rule_id:
- if self.rule_id.isdigit():
- if int(self.rule_id) < 0 or int(self.rule_id) > 4294967294:
- self.module.fail_json(
- msg='Error: The value of rule_id is out of [0 - 4294967294].')
- else:
- self.module.fail_json(
- msg='Error: The rule_id is not digit.')
-
- if self.rule_action and not self.protocol:
- self.module.fail_json(
- msg='Error: The rule_action and the protocol must input at the same time.')
-
- if not self.rule_action and self.protocol:
- self.module.fail_json(
- msg='Error: The rule_action and the protocol must input at the same time.')
-
- if self.protocol:
- self.get_protocol_num()
-
- if self.source_ip:
- if not check_ip_addr(self.source_ip):
- self.module.fail_json(
- msg='Error: The source_ip %s is invalid.' % self.source_ip)
- if not self.src_mask:
- self.module.fail_json(
- msg='Error: Please input src_mask.')
-
- if self.src_mask:
- if self.src_mask.isdigit():
- if int(self.src_mask) < 1 or int(self.src_mask) > 32:
- self.module.fail_json(
- msg='Error: The value of src_mask is out of [1 - 32].')
- self.src_wild = get_wildcard_mask(self.src_mask)
- else:
- self.module.fail_json(
- msg='Error: The src_mask is not digit.')
-
- if self.src_pool_name:
- if len(self.src_pool_name) < 1 or len(self.src_pool_name) > 32:
- self.module.fail_json(
- msg='Error: The len of src_pool_name is out of [1 - 32].')
-
- if self.dest_ip:
- if not check_ip_addr(self.dest_ip):
- self.module.fail_json(
- msg='Error: The dest_ip %s is invalid.' % self.dest_ip)
- if not self.dest_mask:
- self.module.fail_json(
- msg='Error: Please input dest_mask.')
-
- if self.dest_mask:
- if self.dest_mask.isdigit():
- if int(self.dest_mask) < 1 or int(self.dest_mask) > 32:
- self.module.fail_json(
- msg='Error: The value of dest_mask is out of [1 - 32].')
- self.dest_wild = get_wildcard_mask(self.dest_mask)
- else:
- self.module.fail_json(
- msg='Error: The dest_mask is not digit.')
-
- if self.dest_pool_name:
- if len(self.dest_pool_name) < 1 or len(self.dest_pool_name) > 32:
- self.module.fail_json(
- msg='Error: The len of dest_pool_name is out of [1 - 32].')
-
- if self.src_port_op:
- if self.src_port_op == "lt":
- if not self.src_port_end:
- self.module.fail_json(
- msg='Error: The src_port_end must input.')
- if self.src_port_begin:
- self.module.fail_json(
- msg='Error: The src_port_begin should not input.')
- if self.src_port_op == "eq" or self.src_port_op == "gt":
- if not self.src_port_begin:
- self.module.fail_json(
- msg='Error: The src_port_begin must input.')
- if self.src_port_end:
- self.module.fail_json(
- msg='Error: The src_port_end should not input.')
- if self.src_port_op == "range":
- if not self.src_port_begin or not self.src_port_end:
- self.module.fail_json(
- msg='Error: The src_port_begin and src_port_end must input.')
-
- if self.src_port_begin:
- if self.src_port_begin.isdigit():
- if int(self.src_port_begin) < 0 or int(self.src_port_begin) > 65535:
- self.module.fail_json(
- msg='Error: The value of src_port_begin is out of [0 - 65535].')
- else:
- self.module.fail_json(
- msg='Error: The src_port_begin is not digit.')
-
- if self.src_port_end:
- if self.src_port_end.isdigit():
- if int(self.src_port_end) < 0 or int(self.src_port_end) > 65535:
- self.module.fail_json(
- msg='Error: The value of src_port_end is out of [0 - 65535].')
- else:
- self.module.fail_json(
- msg='Error: The src_port_end is not digit.')
-
- if self.src_port_pool_name:
- if len(self.src_port_pool_name) < 1 or len(self.src_port_pool_name) > 32:
- self.module.fail_json(
- msg='Error: The len of src_port_pool_name is out of [1 - 32].')
-
- if self.dest_port_op:
- if self.dest_port_op == "lt":
- if not self.dest_port_end:
- self.module.fail_json(
- msg='Error: The dest_port_end must input.')
- if self.dest_port_begin:
- self.module.fail_json(
- msg='Error: The dest_port_begin should not input.')
- if self.dest_port_op == "eq" or self.dest_port_op == "gt":
- if not self.dest_port_begin:
- self.module.fail_json(
- msg='Error: The dest_port_begin must input.')
- if self.dest_port_end:
- self.module.fail_json(
- msg='Error: The dest_port_end should not input.')
- if self.dest_port_op == "range":
- if not self.dest_port_begin or not self.dest_port_end:
- self.module.fail_json(
- msg='Error: The dest_port_begin and dest_port_end must input.')
-
- if self.dest_port_begin:
- if self.dest_port_begin.isdigit():
- if int(self.dest_port_begin) < 0 or int(self.dest_port_begin) > 65535:
- self.module.fail_json(
- msg='Error: The value of dest_port_begin is out of [0 - 65535].')
- else:
- self.module.fail_json(
- msg='Error: The dest_port_begin is not digit.')
-
- if self.dest_port_end:
- if self.dest_port_end.isdigit():
- if int(self.dest_port_end) < 0 or int(self.dest_port_end) > 65535:
- self.module.fail_json(
- msg='Error: The value of dest_port_end is out of [0 - 65535].')
- else:
- self.module.fail_json(
- msg='Error: The dest_port_end is not digit.')
-
- if self.dest_port_pool_name:
- if len(self.dest_port_pool_name) < 1 or len(self.dest_port_pool_name) > 32:
- self.module.fail_json(
- msg='Error: The len of dest_port_pool_name is out of [1 - 32].')
-
- if self.precedence:
- if self.precedence.isdigit():
- if int(self.precedence) < 0 or int(self.precedence) > 7:
- self.module.fail_json(
- msg='Error: The value of precedence is out of [0 - 7].')
- else:
- self.module.fail_json(
- msg='Error: The precedence is not digit.')
-
- if self.tos:
- if self.tos.isdigit():
- if int(self.tos) < 0 or int(self.tos) > 15:
- self.module.fail_json(
- msg='Error: The value of tos is out of [0 - 15].')
- else:
- self.module.fail_json(
- msg='Error: The tos is not digit.')
-
- if self.dscp:
- if self.dscp.isdigit():
- if int(self.dscp) < 0 or int(self.dscp) > 63:
- self.module.fail_json(
- msg='Error: The value of dscp is out of [0 - 63].')
- else:
- self.module.fail_json(
- msg='Error: The dscp is not digit.')
-
- if self.icmp_type:
- if self.icmp_type.isdigit():
- if int(self.icmp_type) < 0 or int(self.icmp_type) > 255:
- self.module.fail_json(
- msg='Error: The value of icmp_type is out of [0 - 255].')
- else:
- self.module.fail_json(
- msg='Error: The icmp_type is not digit.')
-
- if self.icmp_code:
- if self.icmp_code.isdigit():
- if int(self.icmp_code) < 0 or int(self.icmp_code) > 255:
- self.module.fail_json(
- msg='Error: The value of icmp_code is out of [0 - 255].')
- else:
- self.module.fail_json(
- msg='Error: The icmp_code is not digit.')
-
- if self.vrf_name:
- if len(self.vrf_name) < 1 or len(self.vrf_name) > 31:
- self.module.fail_json(
- msg='Error: The len of vrf_name is out of [1 - 31].')
-
- if self.syn_flag:
- if self.syn_flag.isdigit():
- if int(self.syn_flag) < 0 or int(self.syn_flag) > 63:
- self.module.fail_json(
- msg='Error: The value of syn_flag is out of [0 - 63].')
- else:
- self.module.fail_json(
- msg='Error: The syn_flag is not digit.')
-
- if self.tcp_flag_mask:
- if self.tcp_flag_mask.isdigit():
- if int(self.tcp_flag_mask) < 0 or int(self.tcp_flag_mask) > 63:
- self.module.fail_json(
- msg='Error: The value of tcp_flag_mask is out of [0 - 63].')
- else:
- self.module.fail_json(
- msg='Error: The tcp_flag_mask is not digit.')
-
- if self.time_range:
- if len(self.time_range) < 1 or len(self.time_range) > 32:
- self.module.fail_json(
- msg='Error: The len of time_range is out of [1 - 32].')
-
- if self.rule_description:
- if len(self.rule_description) < 1 or len(self.rule_description) > 127:
- self.module.fail_json(
- msg='Error: The len of rule_description is out of [1 - 127].')
-
- if self.igmp_type:
- self.get_igmp_type_num()
-
- conf_str = CE_GET_ACL_ADVANCE_RULE_HEADER % self.acl_name
-
- if self.rule_id:
- conf_str += ""
- if self.rule_action:
- conf_str += ""
- if self.protocol:
- conf_str += ""
- if self.source_ip:
- conf_str += ""
- if self.src_wild:
- conf_str += ""
- if self.src_pool_name:
- conf_str += ""
- if self.dest_ip:
- conf_str += ""
- if self.dest_wild:
- conf_str += ""
- if self.dest_pool_name:
- conf_str += ""
- if self.src_port_op:
- conf_str += ""
- if self.src_port_begin:
- conf_str += ""
- if self.src_port_end:
- conf_str += ""
- if self.src_port_pool_name:
- conf_str += ""
- if self.dest_port_op:
- conf_str += ""
- if self.dest_port_begin:
- conf_str += ""
- if self.dest_port_end:
- conf_str += ""
- if self.dest_port_pool_name:
- conf_str += ""
- if self.frag_type:
- conf_str += ""
- if self.precedence:
- conf_str += ""
- if self.tos:
- conf_str += ""
- if self.dscp:
- conf_str += ""
- if self.icmp_name:
- conf_str += ""
- if self.icmp_type:
- conf_str += ""
- if self.icmp_code:
- conf_str += ""
- conf_str += ""
- if self.vrf_name:
- conf_str += ""
- if self.syn_flag:
- conf_str += ""
- if self.tcp_flag_mask:
- conf_str += ""
- conf_str += ""
- if self.time_range:
- conf_str += ""
- if self.rule_description:
- conf_str += ""
- if self.igmp_type:
- conf_str += ""
- conf_str += ""
-
- conf_str += CE_GET_ACL_ADVANCE_RULE_TAIL
- recv_xml = self.netconf_get_config(conf_str=conf_str)
-
- if "" in recv_xml:
- find_flag = False
-
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
-
- # parse advance rule
- adv_rule_info = root.findall(
- "acl/aclGroups/aclGroup/aclRuleAdv4s/aclRuleAdv4")
- if adv_rule_info:
- for tmp in adv_rule_info:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["aclRuleName", "aclRuleID", "aclAction", "aclProtocol", "aclSourceIp",
- "aclSrcWild", "aclSPoolName", "aclDestIp", "aclDestWild",
- "aclDPoolName", "aclSrcPortOp", "aclSrcPortBegin", "aclSrcPortEnd",
- "aclSPortPoolName", "aclDestPortOp", "aclDestPortB", "aclDestPortE",
- "aclDPortPoolName", "aclFragType", "aclPrecedence", "aclTos",
- "aclDscp", "aclIcmpName", "aclIcmpType", "aclIcmpCode", "aclTtlExpired",
- "vrfName", "aclSynFlag", "aclTcpFlagMask", "aclEstablished",
- "aclTimeName", "aclRuleDescription", "aclIgmpType", "aclLogFlag"]:
- tmp_dict[site.tag] = site.text
-
- self.cur_advance_rule_cfg[
- "adv_rule_info"].append(tmp_dict)
-
- if self.cur_advance_rule_cfg["adv_rule_info"]:
- for tmp in self.cur_advance_rule_cfg["adv_rule_info"]:
- find_flag = True
-
- if self.rule_name and tmp.get("aclRuleName") != self.rule_name:
- find_flag = False
- if self.rule_id and tmp.get("aclRuleID") != self.rule_id:
- find_flag = False
- if self.rule_action and tmp.get("aclAction") != self.rule_action:
- find_flag = False
- if self.protocol and tmp.get("aclProtocol") != self.protocol_num:
- find_flag = False
- if self.source_ip:
- tmp_src_ip = self.source_ip.split(".")
- tmp_src_wild = self.src_wild.split(".")
- tmp_addr_item = []
- for idx in range(4):
- item1 = 255 - int(tmp_src_wild[idx])
- item2 = item1 & int(tmp_src_ip[idx])
- tmp_addr_item.append(item2)
- tmp_addr = "%s.%s.%s.%s" % (tmp_addr_item[0], tmp_addr_item[1],
- tmp_addr_item[2], tmp_addr_item[3])
- if tmp_addr != tmp.get("aclSourceIp"):
- find_flag = False
- if self.src_wild and tmp.get("aclSrcWild") != self.src_wild:
- find_flag = False
- if self.src_pool_name and tmp.get("aclSPoolName") != self.src_pool_name:
- find_flag = False
- if self.dest_ip:
- tmp_src_ip = self.dest_ip.split(".")
- tmp_src_wild = self.dest_wild.split(".")
- tmp_addr_item = []
- for idx in range(4):
- item1 = 255 - int(tmp_src_wild[idx])
- item2 = item1 & int(tmp_src_ip[idx])
- tmp_addr_item.append(item2)
- tmp_addr = "%s.%s.%s.%s" % (tmp_addr_item[0], tmp_addr_item[1],
- tmp_addr_item[2], tmp_addr_item[3])
- if tmp_addr != tmp.get("aclDestIp"):
- find_flag = False
- if self.dest_wild and tmp.get("aclDestWild") != self.dest_wild:
- find_flag = False
- if self.dest_pool_name and tmp.get("aclDPoolName") != self.dest_pool_name:
- find_flag = False
- if self.src_port_op and tmp.get("aclSrcPortOp") != self.src_port_op:
- find_flag = False
- if self.src_port_begin and tmp.get("aclSrcPortBegin") != self.src_port_begin:
- find_flag = False
- if self.src_port_end and tmp.get("aclSrcPortEnd") != self.src_port_end:
- find_flag = False
- if self.src_port_pool_name and tmp.get("aclSPortPoolName") != self.src_port_pool_name:
- find_flag = False
- if self.dest_port_op and tmp.get("aclDestPortOp") != self.dest_port_op:
- find_flag = False
- if self.dest_port_begin and tmp.get("aclDestPortB") != self.dest_port_begin:
- find_flag = False
- if self.dest_port_end and tmp.get("aclDestPortE") != self.dest_port_end:
- find_flag = False
- if self.dest_port_pool_name and tmp.get("aclDPortPoolName") != self.dest_port_pool_name:
- find_flag = False
- frag_type = "clear_fragment" if tmp.get("aclFragType") is None else tmp.get("aclFragType")
- if self.frag_type and frag_type != self.frag_type:
- find_flag = False
- if self.precedence and tmp.get("aclPrecedence") != self.precedence:
- find_flag = False
- if self.tos and tmp.get("aclTos") != self.tos:
- find_flag = False
- if self.dscp and tmp.get("aclDscp") != self.dscp:
- find_flag = False
- if self.icmp_name and tmp.get("aclIcmpName") != self.icmp_name:
- find_flag = False
- if self.icmp_type and tmp.get("aclIcmpType") != self.icmp_type:
- find_flag = False
- if self.icmp_code and tmp.get("aclIcmpCode") != self.icmp_code:
- find_flag = False
- if tmp.get("aclTtlExpired").lower() != str(self.ttl_expired).lower():
- find_flag = False
- if self.vrf_name and tmp.get("vrfName") != self.vrf_name:
- find_flag = False
- if self.syn_flag and tmp.get("aclSynFlag") != self.syn_flag:
- find_flag = False
- if self.tcp_flag_mask and tmp.get("aclTcpFlagMask") != self.tcp_flag_mask:
- find_flag = False
- if self.protocol == "tcp" and \
- tmp.get("aclEstablished").lower() != str(self.established).lower():
- find_flag = False
- if self.time_range and tmp.get("aclTimeName") != self.time_range:
- find_flag = False
- if self.rule_description and tmp.get("aclRuleDescription") != self.rule_description:
- find_flag = False
- if self.igmp_type and tmp.get("aclIgmpType") != self.igmp_type_num:
- find_flag = False
- if tmp.get("aclLogFlag").lower() != str(self.log_flag).lower():
- find_flag = False
-
- if find_flag:
- break
- else:
- find_flag = False
-
- if self.state == "present":
- need_cfg = bool(not find_flag)
- elif self.state == "absent":
- need_cfg = bool(find_flag)
- else:
- need_cfg = False
-
- self.cur_advance_rule_cfg["need_cfg"] = need_cfg
-
- def get_proposed(self):
- """ Get proposed state """
-
- self.proposed["state"] = self.state
-
- if self.acl_name:
- self.proposed["acl_name"] = self.acl_name
- if self.acl_num:
- self.proposed["acl_num"] = self.acl_num
- if self.acl_step:
- self.proposed["acl_step"] = self.acl_step
- if self.acl_description:
- self.proposed["acl_description"] = self.acl_description
- if self.rule_name:
- self.proposed["rule_name"] = self.rule_name
- if self.rule_id:
- self.proposed["rule_id"] = self.rule_id
- if self.rule_action:
- self.proposed["rule_action"] = self.rule_action
- if self.protocol:
- self.proposed["protocol"] = self.protocol
- if self.source_ip:
- self.proposed["source_ip"] = self.source_ip
- if self.src_mask:
- self.proposed["src_mask"] = self.src_mask
- if self.src_pool_name:
- self.proposed["src_pool_name"] = self.src_pool_name
- if self.dest_ip:
- self.proposed["dest_ip"] = self.dest_ip
- if self.dest_mask:
- self.proposed["dest_mask"] = self.dest_mask
- if self.dest_pool_name:
- self.proposed["dest_pool_name"] = self.dest_pool_name
- if self.src_port_op:
- self.proposed["src_port_op"] = self.src_port_op
- if self.src_port_begin:
- self.proposed["src_port_begin"] = self.src_port_begin
- if self.src_port_end:
- self.proposed["src_port_end"] = self.src_port_end
- if self.src_port_pool_name:
- self.proposed["src_port_pool_name"] = self.src_port_pool_name
- if self.dest_port_op:
- self.proposed["dest_port_op"] = self.dest_port_op
- if self.dest_port_begin:
- self.proposed["dest_port_begin"] = self.dest_port_begin
- if self.dest_port_end:
- self.proposed["dest_port_end"] = self.dest_port_end
- if self.dest_port_pool_name:
- self.proposed["dest_port_pool_name"] = self.dest_port_pool_name
- if self.frag_type:
- self.proposed["frag_type"] = self.frag_type
- if self.precedence:
- self.proposed["precedence"] = self.precedence
- if self.tos:
- self.proposed["tos"] = self.tos
- if self.dscp:
- self.proposed["dscp"] = self.dscp
- if self.icmp_name:
- self.proposed["icmp_name"] = self.icmp_name
- if self.icmp_type:
- self.proposed["icmp_type"] = self.icmp_type
- if self.icmp_code:
- self.proposed["icmp_code"] = self.icmp_code
- if self.ttl_expired:
- self.proposed["ttl_expired"] = self.ttl_expired
- if self.vrf_name:
- self.proposed["vrf_name"] = self.vrf_name
- if self.syn_flag:
- self.proposed["syn_flag"] = self.syn_flag
- if self.tcp_flag_mask:
- self.proposed["tcp_flag_mask"] = self.tcp_flag_mask
- self.proposed["established"] = self.established
- if self.time_range:
- self.proposed["time_range"] = self.time_range
- if self.rule_description:
- self.proposed["rule_description"] = self.rule_description
- if self.igmp_type:
- self.proposed["igmp_type"] = self.igmp_type
- self.proposed["log_flag"] = self.log_flag
-
- def get_existing(self):
- """ Get existing state """
-
- self.existing["acl_info"] = self.cur_acl_cfg["acl_info"]
- self.existing["adv_rule_info"] = self.cur_advance_rule_cfg[
- "adv_rule_info"]
-
- def get_end_state(self):
- """ Get end state """
-
- self.check_acl_args()
- self.end_state["acl_info"] = self.cur_acl_cfg["acl_info"]
-
- self.check_advance_rule_args()
- self.end_state["adv_rule_info"] = self.cur_advance_rule_cfg[
- "adv_rule_info"]
- if self.end_state == self.existing:
- self.changed = False
- self.updates_cmd = list()
-
- def merge_acl(self):
- """ Merge acl operation """
-
- conf_str = CE_MERGE_ACL_HEADER % self.acl_name
-
- if self.acl_type:
- conf_str += "%s" % self.acl_type
- if self.acl_num:
- conf_str += "%s" % self.acl_num
- if self.acl_step:
- conf_str += "%s" % self.acl_step
- if self.acl_description:
- conf_str += "%s" % self.acl_description
-
- conf_str += CE_MERGE_ACL_TAIL
-
- recv_xml = self.netconf_set_config(conf_str=conf_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Merge acl failed.')
-
- if self.acl_name.isdigit():
- cmd = "acl number %s" % self.acl_name
- else:
- if self.acl_type and not self.acl_num:
- cmd = "acl name %s %s" % (self.acl_name, self.acl_type.lower())
- elif self.acl_type and self.acl_num:
- cmd = "acl name %s number %s" % (self.acl_name, self.acl_num)
- elif not self.acl_type and self.acl_num:
- cmd = "acl name %s number %s" % (self.acl_name, self.acl_num)
- self.updates_cmd.append(cmd)
-
- if self.acl_description:
- cmd = "description %s" % self.acl_description
- self.updates_cmd.append(cmd)
-
- if self.acl_step:
- cmd = "step %s" % self.acl_step
- self.updates_cmd.append(cmd)
-
- self.changed = True
-
- def delete_acl(self):
- """ Delete acl operation """
-
- conf_str = CE_DELETE_ACL_HEADER % self.acl_name
-
- if self.acl_type:
- conf_str += "%s" % self.acl_type
- if self.acl_num:
- conf_str += "%s" % self.acl_num
- if self.acl_step:
- conf_str += "%s" % self.acl_step
- if self.acl_description:
- conf_str += "%s" % self.acl_description
-
- conf_str += CE_DELETE_ACL_TAIL
-
- recv_xml = self.netconf_set_config(conf_str=conf_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Delete acl failed.')
-
- if self.acl_description:
- cmd = "undo description"
- self.updates_cmd.append(cmd)
-
- if self.acl_step:
- cmd = "undo step"
- self.updates_cmd.append(cmd)
-
- if self.acl_name.isdigit():
- cmd = "undo acl number %s" % self.acl_name
- else:
- cmd = "undo acl name %s" % self.acl_name
- self.updates_cmd.append(cmd)
-
- self.changed = True
-
- def merge_adv_rule(self):
- """ Merge advance rule operation """
-
- conf_str = CE_MERGE_ACL_ADVANCE_RULE_HEADER % (
- self.acl_name, self.rule_name)
-
- if self.rule_id:
- conf_str += "%s" % self.rule_id
- if self.rule_action:
- conf_str += "%s" % self.rule_action
- if self.protocol:
- conf_str += "%s" % self.protocol_num
- if self.source_ip:
- conf_str += "%s" % self.source_ip
- if self.src_wild:
- conf_str += "%s" % self.src_wild
- if self.src_pool_name:
- conf_str += "%s" % self.src_pool_name
- if self.dest_ip:
- conf_str += "%s" % self.dest_ip
- if self.dest_wild:
- conf_str += "%s" % self.dest_wild
- if self.dest_pool_name:
- conf_str += "%s" % self.dest_pool_name
- if self.src_port_op:
- conf_str += "%s" % self.src_port_op
- if self.src_port_begin:
- conf_str += "%s" % self.src_port_begin
- if self.src_port_end:
- conf_str += "%s" % self.src_port_end
- if self.src_port_pool_name:
- conf_str += "%s" % self.src_port_pool_name
- if self.dest_port_op:
- conf_str += "%s" % self.dest_port_op
- if self.dest_port_begin:
- conf_str += "%s" % self.dest_port_begin
- if self.dest_port_end:
- conf_str += "%s" % self.dest_port_end
- if self.dest_port_pool_name:
- conf_str += "%s" % self.dest_port_pool_name
- if self.frag_type:
- conf_str += "%s" % self.frag_type
- if self.precedence:
- conf_str += "%s" % self.precedence
- if self.tos:
- conf_str += "%s" % self.tos
- if self.dscp:
- conf_str += "%s" % self.dscp
- if self.icmp_name:
- conf_str += "%s" % self.icmp_name
- if self.icmp_type:
- conf_str += "%s" % self.icmp_type
- if self.icmp_code:
- conf_str += "%s" % self.icmp_code
- conf_str += "%s" % str(self.ttl_expired).lower()
- if self.vrf_name:
- conf_str += "%s" % self.vrf_name
- if self.syn_flag:
- conf_str += "%s" % self.syn_flag
- if self.tcp_flag_mask:
- conf_str += "%s" % self.tcp_flag_mask
- if self.protocol == "tcp":
- conf_str += "%s" % str(self.established).lower()
- if self.time_range:
- conf_str += "%s" % self.time_range
- if self.rule_description:
- conf_str += "%s" % self.rule_description
- if self.igmp_type:
- conf_str += "%s" % self.igmp_type_num
- conf_str += "%s" % str(self.log_flag).lower()
-
- conf_str += CE_MERGE_ACL_ADVANCE_RULE_TAIL
-
- recv_xml = self.netconf_set_config(conf_str=conf_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Merge acl base rule failed.')
-
- if self.rule_action and self.protocol:
- cmd = "rule"
- if self.rule_id:
- cmd += " %s" % self.rule_id
- cmd += " %s" % self.rule_action
- cmd += " %s" % self.protocol
- if self.dscp:
- cmd += " dscp %s" % self.dscp
- if self.tos:
- cmd += " tos %s" % self.tos
- if self.source_ip and self.src_wild:
- cmd += " source %s %s" % (self.source_ip, self.src_wild)
- if self.src_pool_name:
- cmd += " source-pool %s" % self.src_pool_name
- if self.src_port_op:
- cmd += " source-port"
- if self.src_port_op == "lt":
- cmd += " lt %s" % self.src_port_end
- elif self.src_port_op == "eq":
- cmd += " eq %s" % self.src_port_begin
- elif self.src_port_op == "gt":
- cmd += " gt %s" % self.src_port_begin
- elif self.src_port_op == "range":
- cmd += " range %s %s" % (self.src_port_begin,
- self.src_port_end)
- if self.src_port_pool_name:
- cmd += " source-port-pool %s" % self.src_port_pool_name
- if self.dest_ip and self.dest_wild:
- cmd += " destination %s %s" % (self.dest_ip, self.dest_wild)
- if self.dest_pool_name:
- cmd += " destination-pool %s" % self.dest_pool_name
- if self.dest_port_op:
- cmd += " destination-port"
- if self.dest_port_op == "lt":
- cmd += " lt %s" % self.dest_port_end
- elif self.dest_port_op == "eq":
- cmd += " eq %s" % self.dest_port_begin
- elif self.dest_port_op == "gt":
- cmd += " gt %s" % self.dest_port_begin
- elif self.dest_port_op == "range":
- cmd += " range %s %s" % (self.dest_port_begin,
- self.dest_port_end)
- if self.dest_port_pool_name:
- cmd += " destination-port-pool %s" % self.dest_port_pool_name
- if self.frag_type == "fragment":
- cmd += " fragment-type fragment"
- if self.precedence:
- cmd += " precedence %s" % self.precedence_name[self.precedence]
-
- if self.protocol == "icmp":
- if self.icmp_name:
- cmd += " icmp-type %s" % self.icmp_name
- elif self.icmp_type and self.icmp_code:
- cmd += " icmp-type %s %s" % (self.icmp_type, self.icmp_code)
- elif self.icmp_type:
- cmd += " icmp-type %s" % self.icmp_type
- if self.protocol == "tcp":
- if self.syn_flag:
- cmd += " tcp-flag %s" % self.syn_flag
- if self.tcp_flag_mask:
- cmd += " mask %s" % self.tcp_flag_mask
- if self.established:
- cmd += " established"
- if self.protocol == "igmp":
- if self.igmp_type:
- cmd += " igmp-type %s" % self.igmp_type
- if self.time_range:
- cmd += " time-range %s" % self.time_range
- if self.vrf_name:
- cmd += " vpn-instance %s" % self.vrf_name
- if self.ttl_expired:
- cmd += " ttl-expired"
- if self.log_flag:
- cmd += " logging"
- self.updates_cmd.append(cmd)
-
- if self.rule_description:
- cmd = "rule %s description %s" % (
- self.rule_id, self.rule_description)
- self.updates_cmd.append(cmd)
-
- self.changed = True
-
- def delete_adv_rule(self):
- """ Delete advance rule operation """
-
- conf_str = CE_DELETE_ACL_ADVANCE_RULE_HEADER % (
- self.acl_name, self.rule_name)
-
- if self.rule_id:
- conf_str += "%s" % self.rule_id
- if self.rule_action:
- conf_str += "%s" % self.rule_action
- if self.protocol:
- conf_str += "%s" % self.protocol_num
- if self.source_ip:
- conf_str += "%s" % self.source_ip
- if self.src_wild:
- conf_str += "%s" % self.src_wild
- if self.src_pool_name:
- conf_str += "%s" % self.src_pool_name
- if self.dest_ip:
- conf_str += "%s" % self.dest_ip
- if self.dest_wild:
- conf_str += "%s" % self.dest_wild
- if self.dest_pool_name:
- conf_str += "%s" % self.dest_pool_name
- if self.src_port_op:
- conf_str += "%s" % self.src_port_op
- if self.src_port_begin:
- conf_str += "%s" % self.src_port_begin
- if self.src_port_end:
- conf_str += "%s" % self.src_port_end
- if self.src_port_pool_name:
- conf_str += "%s" % self.src_port_pool_name
- if self.dest_port_op:
- conf_str += "%s" % self.dest_port_op
- if self.dest_port_begin:
- conf_str += "%s" % self.dest_port_begin
- if self.dest_port_end:
- conf_str += "%s" % self.dest_port_end
- if self.dest_port_pool_name:
- conf_str += "%s" % self.dest_port_pool_name
- if self.frag_type:
- conf_str += "%s" % self.frag_type
- if self.precedence:
- conf_str += "%s" % self.precedence
- if self.tos:
- conf_str += "%s" % self.tos
- if self.dscp:
- conf_str += "%s" % self.dscp
- if self.icmp_name:
- conf_str += "%s" % self.icmp_name
- if self.icmp_type:
- conf_str += "%s" % self.icmp_type
- if self.icmp_code:
- conf_str += "%s" % self.icmp_code
- conf_str += "%s" % str(self.ttl_expired).lower()
- if self.vrf_name:
- conf_str += "%s" % self.vrf_name
- if self.syn_flag:
- conf_str += "%s" % self.syn_flag
- if self.tcp_flag_mask:
- conf_str += "%s" % self.tcp_flag_mask
- if self.protocol == "tcp":
- conf_str += "%s" % str(self.established).lower()
- if self.time_range:
- conf_str += "%s" % self.time_range
- if self.rule_description:
- conf_str += "%s" % self.rule_description
- if self.igmp_type:
- conf_str += "%s" % self.igmp_type
- conf_str += "%s" % str(self.log_flag).lower()
-
- conf_str += CE_DELETE_ACL_ADVANCE_RULE_TAIL
-
- recv_xml = self.netconf_set_config(conf_str=conf_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Delete acl base rule failed.')
-
- if self.rule_description:
- if self.acl_name.isdigit():
- cmd = "acl number %s" % self.acl_name
- else:
- cmd = "acl name %s" % self.acl_name
- self.updates_cmd.append(cmd)
-
- cmd = "undo rule %s description" % self.rule_id
- self.updates_cmd.append(cmd)
-
- if self.rule_id:
- if self.acl_name.isdigit():
- cmd = "acl number %s" % self.acl_name
- else:
- cmd = "acl name %s" % self.acl_name
- self.updates_cmd.append(cmd)
-
- cmd = "undo rule %s" % self.rule_id
- self.updates_cmd.append(cmd)
- elif self.rule_action and self.protocol:
- if self.acl_name.isdigit():
- cmd = "acl number %s" % self.acl_name
- else:
- cmd = "acl name %s" % self.acl_name
- self.updates_cmd.append(cmd)
-
- cmd = "undo rule"
- cmd += " %s" % self.rule_action
- cmd += " %s" % self.protocol
- if self.dscp:
- cmd += " dscp %s" % self.dscp
- if self.tos:
- cmd += " tos %s" % self.tos
- if self.source_ip and self.src_mask:
- cmd += " source %s %s" % (self.source_ip, self.src_mask)
- if self.src_pool_name:
- cmd += " source-pool %s" % self.src_pool_name
- if self.src_port_op:
- cmd += " source-port"
- if self.src_port_op == "lt":
- cmd += " lt %s" % self.src_port_end
- elif self.src_port_op == "eq":
- cmd += " eq %s" % self.src_port_begin
- elif self.src_port_op == "gt":
- cmd += " gt %s" % self.src_port_begin
- elif self.src_port_op == "range":
- cmd += " range %s %s" % (self.src_port_begin,
- self.src_port_end)
- if self.src_port_pool_name:
- cmd += " source-port-pool %s" % self.src_port_pool_name
- if self.dest_ip and self.dest_mask:
- cmd += " destination %s %s" % (self.dest_ip, self.dest_mask)
- if self.dest_pool_name:
- cmd += " destination-pool %s" % self.dest_pool_name
- if self.dest_port_op:
- cmd += " destination-port"
- if self.dest_port_op == "lt":
- cmd += " lt %s" % self.dest_port_end
- elif self.dest_port_op == "eq":
- cmd += " eq %s" % self.dest_port_begin
- elif self.dest_port_op == "gt":
- cmd += " gt %s" % self.dest_port_begin
- elif self.dest_port_op == "range":
- cmd += " range %s %s" % (self.dest_port_begin,
- self.dest_port_end)
- if self.dest_port_pool_name:
- cmd += " destination-port-pool %s" % self.dest_port_pool_name
- if self.frag_type == "fragment":
- cmd += " fragment-type fragment"
- if self.precedence:
- cmd += " precedence %s" % self.precedence_name[self.precedence]
- if self.time_range:
- cmd += " time-range %s" % self.time_range
- if self.vrf_name:
- cmd += " vpn-instance %s" % self.vrf_name
- if self.ttl_expired:
- cmd += " ttl-expired"
- if self.log_flag:
- cmd += " logging"
- self.updates_cmd.append(cmd)
-
- self.changed = True
-
- def work(self):
- """ Main work function """
-
- self.check_acl_args()
- self.check_advance_rule_args()
- self.get_proposed()
- self.get_existing()
-
- if self.state == "present":
- if self.cur_acl_cfg["need_cfg"]:
- self.merge_acl()
- if self.cur_advance_rule_cfg["need_cfg"]:
- self.merge_adv_rule()
-
- elif self.state == "absent":
- if self.cur_advance_rule_cfg["need_cfg"]:
- self.delete_adv_rule()
-
- elif self.state == "delete_acl":
- if self.cur_acl_cfg["need_cfg"]:
- self.delete_acl()
-
- self.get_end_state()
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- self.results['updates'] = self.updates_cmd
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent',
- 'delete_acl'], default='present'),
- acl_name=dict(type='str', required=True),
- acl_num=dict(type='str'),
- acl_step=dict(type='str'),
- acl_description=dict(type='str'),
- rule_name=dict(type='str'),
- rule_id=dict(type='str'),
- rule_action=dict(choices=['permit', 'deny']),
- protocol=dict(choices=['ip', 'icmp', 'igmp',
- 'ipinip', 'tcp', 'udp', 'gre', 'ospf']),
- source_ip=dict(type='str'),
- src_mask=dict(type='str'),
- src_pool_name=dict(type='str'),
- dest_ip=dict(type='str'),
- dest_mask=dict(type='str'),
- dest_pool_name=dict(type='str'),
- src_port_op=dict(choices=['lt', 'eq', 'gt', 'range']),
- src_port_begin=dict(type='str'),
- src_port_end=dict(type='str'),
- src_port_pool_name=dict(type='str'),
- dest_port_op=dict(choices=['lt', 'eq', 'gt', 'range']),
- dest_port_begin=dict(type='str'),
- dest_port_end=dict(type='str'),
- dest_port_pool_name=dict(type='str'),
- frag_type=dict(choices=['fragment', 'clear_fragment']),
- precedence=dict(type='str'),
- tos=dict(type='str'),
- dscp=dict(type='str'),
- icmp_name=dict(choices=['unconfiged', 'echo', 'echo-reply', 'fragmentneed-DFset', 'host-redirect',
- 'host-tos-redirect', 'host-unreachable', 'information-reply', 'information-request',
- 'net-redirect', 'net-tos-redirect', 'net-unreachable', 'parameter-problem',
- 'port-unreachable', 'protocol-unreachable', 'reassembly-timeout', 'source-quench',
- 'source-route-failed', 'timestamp-reply', 'timestamp-request', 'ttl-exceeded',
- 'address-mask-reply', 'address-mask-request', 'custom']),
- icmp_type=dict(type='str'),
- icmp_code=dict(type='str'),
- ttl_expired=dict(required=False, default=False, type='bool'),
- vrf_name=dict(type='str'),
- syn_flag=dict(type='str'),
- tcp_flag_mask=dict(type='str'),
- established=dict(required=False, default=False, type='bool'),
- time_range=dict(type='str'),
- rule_description=dict(type='str'),
- igmp_type=dict(choices=['host-query', 'mrouter-adver', 'mrouter-solic', 'mrouter-termi', 'mtrace-resp',
- 'mtrace-route', 'v1host-report', 'v2host-report', 'v2leave-group', 'v3host-report']),
- log_flag=dict(required=False, default=False, type='bool')
- )
-
- argument_spec.update(ce_argument_spec)
- module = AdvanceAcl(argument_spec=argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_acl_interface.py b/plugins/modules/network/cloudengine/ce_acl_interface.py
deleted file mode 100644
index deb9c22f74..0000000000
--- a/plugins/modules/network/cloudengine/ce_acl_interface.py
+++ /dev/null
@@ -1,327 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_acl_interface
-short_description: Manages applying ACLs to interfaces on HUAWEI CloudEngine switches.
-description:
- - Manages applying ACLs to interfaces on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- acl_name:
- description:
- - ACL number or name.
- For a numbered rule group, the value ranging from 2000 to 4999.
- For a named rule group, the value is a string of 1 to 32 case-sensitive characters starting
- with a letter, spaces not supported.
- required: true
- interface:
- description:
- - Interface name.
- Only support interface full name, such as "40GE2/0/1".
- required: true
- direction:
- description:
- - Direction ACL to be applied in on the interface.
- required: true
- choices: ['inbound', 'outbound']
- state:
- description:
- - Determines whether the config should be present or not on the device.
- required: false
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine acl interface test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Apply acl to interface"
- ce_acl_interface:
- state: present
- acl_name: 2000
- interface: 40GE1/0/1
- direction: outbound
- provider: "{{ cli }}"
-
- - name: "Undo acl from interface"
- ce_acl_interface:
- state: absent
- acl_name: 2000
- interface: 40GE1/0/1
- direction: outbound
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"acl_name": "2000",
- "direction": "outbound",
- "interface": "40GE2/0/1",
- "state": "present"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {"acl interface": "traffic-filter acl lb inbound"}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"acl interface": ["traffic-filter acl lb inbound", "traffic-filter acl 2000 outbound"]}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["interface 40ge2/0/1",
- "traffic-filter acl 2000 outbound"]
-'''
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_config, exec_command, cli_err_msg
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec
-
-
-class AclInterface(object):
- """ Manages acl interface configuration """
-
- def __init__(self, **kwargs):
- """ Class init """
-
- # argument spec
- argument_spec = kwargs["argument_spec"]
- self.spec = argument_spec
- self.module = AnsibleModule(argument_spec=self.spec, supports_check_mode=True)
-
- # config
- self.cur_cfg = dict()
- self.cur_cfg["acl interface"] = []
-
- # module args
- self.state = self.module.params['state']
- self.acl_name = self.module.params['acl_name']
- self.interface = self.module.params['interface']
- self.direction = self.module.params['direction']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def check_args(self):
- """ Check args """
-
- if self.acl_name:
- if self.acl_name.isdigit():
- if int(self.acl_name) < 2000 or int(self.acl_name) > 4999:
- self.module.fail_json(
- msg='Error: The value of acl_name is out of [2000 - 4999].')
- else:
- if len(self.acl_name) < 1 or len(self.acl_name) > 32:
- self.module.fail_json(
- msg='Error: The len of acl_name is out of [1 - 32].')
-
- if self.interface:
- cmd = "display current-configuration | ignore-case section include interface %s" % self.interface
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- result = str(out).strip()
- if result:
- tmp = result.split('\n')
- if "display" in tmp[0]:
- tmp.pop(0)
- if not tmp:
- self.module.fail_json(
- msg='Error: The interface %s is not in the device.' % self.interface)
-
- def get_proposed(self):
- """ Get proposed config """
-
- self.proposed["state"] = self.state
-
- if self.acl_name:
- self.proposed["acl_name"] = self.acl_name
-
- if self.interface:
- self.proposed["interface"] = self.interface
-
- if self.direction:
- self.proposed["direction"] = self.direction
-
- def get_existing(self):
- """ Get existing config """
-
- cmd = "display current-configuration | ignore-case section include interface %s | include traffic-filter" % self.interface
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- result = str(out).strip()
- end = []
- if result:
- tmp = result.split('\n')
- if "display" in tmp[0]:
- tmp.pop(0)
- for item in tmp:
- end.append(item.strip())
- self.cur_cfg["acl interface"] = end
- self.existing["acl interface"] = end
-
- def get_end_state(self):
- """ Get config end state """
-
- cmd = "display current-configuration | ignore-case section include interface %s | include traffic-filter" % self.interface
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- result = str(out).strip()
- end = []
- if result:
- tmp = result.split('\n')
- if "display" in tmp[0]:
- tmp.pop(0)
- for item in tmp:
- end.append(item.strip())
- self.end_state["acl interface"] = end
-
- def load_config(self, config):
- """Sends configuration commands to the remote device"""
-
- rc, out, err = exec_command(self.module, 'mmi-mode enable')
- if rc != 0:
- self.module.fail_json(msg='unable to set mmi-mode enable', output=err)
- rc, out, err = exec_command(self.module, 'system-view immediately')
- if rc != 0:
- self.module.fail_json(msg='unable to enter system-view', output=err)
-
- for cmd in config:
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- if "unrecognized command found" in err.lower():
- self.module.fail_json(msg="Error:The parameter is incorrect or the interface does not support this parameter.")
- else:
- self.module.fail_json(msg=cli_err_msg(cmd.strip(), err))
-
- exec_command(self.module, 'return')
-
- def cli_load_config(self, commands):
- """ Cli method to load config """
-
- if not self.module.check_mode:
- self.load_config(commands)
-
- def work(self):
- """ Work function """
-
- self.check_args()
- self.get_proposed()
- self.get_existing()
-
- cmds = list()
- tmp_cmd = "traffic-filter acl %s %s" % (self.acl_name, self.direction)
- undo_tmp_cmd = "undo traffic-filter acl %s %s" % (
- self.acl_name, self.direction)
-
- if self.state == "present":
- if tmp_cmd not in self.cur_cfg["acl interface"]:
- interface_cmd = "interface %s" % self.interface.lower()
- cmds.append(interface_cmd)
- cmds.append(tmp_cmd)
-
- self.cli_load_config(cmds)
-
- self.changed = True
- self.updates_cmd.append(interface_cmd)
- self.updates_cmd.append(tmp_cmd)
-
- else:
- if tmp_cmd in self.cur_cfg["acl interface"]:
- interface_cmd = "interface %s" % self.interface
- cmds.append(interface_cmd)
- cmds.append(undo_tmp_cmd)
- self.cli_load_config(cmds)
-
- self.changed = True
- self.updates_cmd.append(interface_cmd)
- self.updates_cmd.append(undo_tmp_cmd)
-
- self.get_end_state()
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- self.results['updates'] = self.updates_cmd
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- acl_name=dict(type='str', required=True),
- interface=dict(type='str', required=True),
- direction=dict(choices=['inbound', 'outbound'], required=True)
- )
-
- argument_spec.update(ce_argument_spec)
- module = AclInterface(argument_spec=argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_bfd_global.py b/plugins/modules/network/cloudengine/ce_bfd_global.py
deleted file mode 100644
index 924fdbddd0..0000000000
--- a/plugins/modules/network/cloudengine/ce_bfd_global.py
+++ /dev/null
@@ -1,558 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_bfd_global
-short_description: Manages BFD global configuration on HUAWEI CloudEngine devices.
-description:
- - Manages BFD global configuration on HUAWEI CloudEngine devices.
-author: QijunPan (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- bfd_enable:
- description:
- - Enables the global Bidirectional Forwarding Detection (BFD) function.
- choices: ['enable', 'disable']
- default_ip:
- description:
- - Specifies the default multicast IP address.
- The value ranges from 224.0.0.107 to 224.0.0.250.
- tos_exp_dynamic:
- description:
- - Indicates the priority of BFD control packets for dynamic BFD sessions.
- The value is an integer ranging from 0 to 7.
- The default priority is 7, which is the highest priority of BFD control packets.
- tos_exp_static:
- description:
- - Indicates the priority of BFD control packets for static BFD sessions.
- The value is an integer ranging from 0 to 7.
- The default priority is 7, which is the highest priority of BFD control packets.
- damp_init_wait_time:
- description:
- - Specifies an initial flapping suppression time for a BFD session.
- The value is an integer ranging from 1 to 3600000, in milliseconds.
- The default value is 2000.
- damp_max_wait_time:
- description:
- - Specifies a maximum flapping suppression time for a BFD session.
- The value is an integer ranging from 1 to 3600000, in milliseconds.
- The default value is 15000.
- damp_second_wait_time:
- description:
- - Specifies a secondary flapping suppression time for a BFD session.
- The value is an integer ranging from 1 to 3600000, in milliseconds.
- The default value is 5000.
- delay_up_time:
- description:
- - Specifies the delay before a BFD session becomes Up.
- The value is an integer ranging from 1 to 600, in seconds.
- The default value is 0, indicating that a BFD session immediately becomes Up.
- state:
- description:
- - Determines whether the config should be present or not on the device.
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = '''
-- name: bfd global module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
- - name: Enable the global BFD function
- ce_bfd_global:
- bfd_enable: enable
- provider: '{{ cli }}'
-
- - name: Set the default multicast IP address to 224.0.0.150
- ce_bfd_global:
- bfd_enable: enable
- default_ip: 224.0.0.150
- state: present
- provider: '{{ cli }}'
-
- - name: Set the priority of BFD control packets for dynamic and static BFD sessions
- ce_bfd_global:
- bfd_enable: enable
- tos_exp_dynamic: 5
- tos_exp_static: 6
- state: present
- provider: '{{ cli }}'
-
- - name: Disable the global BFD function
- ce_bfd_global:
- bfd_enable: disable
- provider: '{{ cli }}'
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: verbose mode
- type: dict
- sample: {
- "bfd_enalbe": "enable",
- "damp_init_wait_time": null,
- "damp_max_wait_time": null,
- "damp_second_wait_time": null,
- "default_ip": null,
- "delayUpTimer": null,
- "state": "present",
- "tos_exp_dynamic": null,
- "tos_exp_static": null
- }
-existing:
- description: k/v pairs of existing configuration
- returned: verbose mode
- type: dict
- sample: {
- "global": {
- "bfdEnable": "false",
- "dampInitWaitTime": "2000",
- "dampMaxWaitTime": "12000",
- "dampSecondWaitTime": "5000",
- "defaultIp": "224.0.0.184",
- "delayUpTimer": null,
- "tosExp": "7",
- "tosExpStatic": "7"
- }
- }
-end_state:
- description: k/v pairs of configuration after module execution
- returned: verbose mode
- type: dict
- sample: {
- "global": {
- "bfdEnable": "true",
- "dampInitWaitTime": "2000",
- "dampMaxWaitTime": "12000",
- "dampSecondWaitTime": "5000",
- "defaultIp": "224.0.0.184",
- "delayUpTimer": null,
- "tosExp": "7",
- "tosExpStatic": "7"
- }
- }
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: [ "bfd" ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import sys
-import socket
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec, check_ip_addr
-
-CE_NC_GET_BFD = """
-
-
- %s
-
-
-"""
-
-CE_NC_GET_BFD_GLB = """
-
-
-
-
-
-
-
-
-
-
-"""
-
-
-def check_default_ip(ipaddr):
- """check the default multicast IP address"""
-
- # The value ranges from 224.0.0.107 to 224.0.0.250
- if not check_ip_addr(ipaddr):
- return False
-
- if ipaddr.count(".") != 3:
- return False
-
- ips = ipaddr.split(".")
- if ips[0] != "224" or ips[1] != "0" or ips[2] != "0":
- return False
-
- if not ips[3].isdigit() or int(ips[3]) < 107 or int(ips[3]) > 250:
- return False
-
- return True
-
-
-class BfdGlobal(object):
- """Manages BFD Global"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.__init_module__()
-
- # module input info
- self.bfd_enable = self.module.params['bfd_enable']
- self.default_ip = self.module.params['default_ip']
- self.tos_exp_dynamic = self.module.params['tos_exp_dynamic']
- self.tos_exp_static = self.module.params['tos_exp_static']
- self.damp_init_wait_time = self.module.params['damp_init_wait_time']
- self.damp_max_wait_time = self.module.params['damp_max_wait_time']
- self.damp_second_wait_time = self.module.params['damp_second_wait_time']
- self.delay_up_time = self.module.params['delay_up_time']
- self.state = self.module.params['state']
-
- # host info
- self.host = self.module.params['host']
- self.username = self.module.params['username']
- self.port = self.module.params['port']
-
- # state
- self.changed = False
- self.bfd_dict = dict()
- self.updates_cmd = list()
- self.commands = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def __init_module__(self):
- """init module"""
-
- required_together = [('damp_init_wait_time', 'damp_max_wait_time', 'damp_second_wait_time')]
- self.module = AnsibleModule(argument_spec=self.spec,
- required_together=required_together,
- supports_check_mode=True)
-
- def get_bfd_dict(self):
- """bfd config dict"""
-
- bfd_dict = dict()
- bfd_dict["global"] = dict()
- conf_str = CE_NC_GET_BFD % CE_NC_GET_BFD_GLB
-
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return bfd_dict
-
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
-
- # get bfd global info
- glb = root.find("bfd/bfdSchGlobal")
- if glb:
- for attr in glb:
- if attr.text is not None:
- bfd_dict["global"][attr.tag] = attr.text
-
- return bfd_dict
-
- def config_global(self):
- """configures bfd global params"""
-
- xml_str = ""
- damp_chg = False
-
- # bfd_enable
- if self.bfd_enable:
- if bool(self.bfd_dict["global"].get("bfdEnable", "false") == "true") != bool(self.bfd_enable == "enable"):
- if self.bfd_enable == "enable":
- xml_str = "true"
- self.updates_cmd.append("bfd")
- else:
- xml_str = "false"
- self.updates_cmd.append("undo bfd")
-
- # get bfd end state
- bfd_state = "disable"
- if self.bfd_enable:
- bfd_state = self.bfd_enable
- elif self.bfd_dict["global"].get("bfdEnable", "false") == "true":
- bfd_state = "enable"
-
- # default_ip
- if self.default_ip:
- if bfd_state == "enable":
- if self.state == "present" and self.default_ip != self.bfd_dict["global"].get("defaultIp"):
- xml_str += "%s" % self.default_ip
- if "bfd" not in self.updates_cmd:
- self.updates_cmd.append("bfd")
- self.updates_cmd.append("default-ip-address %s" % self.default_ip)
- elif self.state == "absent" and self.default_ip == self.bfd_dict["global"].get("defaultIp"):
- xml_str += ""
- if "bfd" not in self.updates_cmd:
- self.updates_cmd.append("bfd")
- self.updates_cmd.append("undo default-ip-address")
-
- # tos_exp_dynamic
- if self.tos_exp_dynamic is not None:
- if bfd_state == "enable":
- if self.state == "present" and self.tos_exp_dynamic != int(self.bfd_dict["global"].get("tosExp", "7")):
- xml_str += "%s" % self.tos_exp_dynamic
- if "bfd" not in self.updates_cmd:
- self.updates_cmd.append("bfd")
- self.updates_cmd.append("tos-exp %s dynamic" % self.tos_exp_dynamic)
- elif self.state == "absent" and self.tos_exp_dynamic == int(self.bfd_dict["global"].get("tosExp", "7")):
- xml_str += ""
- if "bfd" not in self.updates_cmd:
- self.updates_cmd.append("bfd")
- self.updates_cmd.append("undo tos-exp dynamic")
-
- # tos_exp_static
- if self.tos_exp_static is not None:
- if bfd_state == "enable":
- if self.state == "present" \
- and self.tos_exp_static != int(self.bfd_dict["global"].get("tosExpStatic", "7")):
- xml_str += "%s" % self.tos_exp_static
- if "bfd" not in self.updates_cmd:
- self.updates_cmd.append("bfd")
- self.updates_cmd.append("tos-exp %s static" % self.tos_exp_static)
- elif self.state == "absent" \
- and self.tos_exp_static == int(self.bfd_dict["global"].get("tosExpStatic", "7")):
- xml_str += ""
- if "bfd" not in self.updates_cmd:
- self.updates_cmd.append("bfd")
- self.updates_cmd.append("undo tos-exp static")
-
- # delay_up_time
- if self.delay_up_time is not None:
- if bfd_state == "enable":
- delay_time = self.bfd_dict["global"].get("delayUpTimer", "0")
- if not delay_time or not delay_time.isdigit():
- delay_time = "0"
- if self.state == "present" \
- and self.delay_up_time != int(delay_time):
- xml_str += "%s" % self.delay_up_time
- if "bfd" not in self.updates_cmd:
- self.updates_cmd.append("bfd")
- self.updates_cmd.append("delay-up %s" % self.delay_up_time)
- elif self.state == "absent" \
- and self.delay_up_time == int(delay_time):
- xml_str += ""
- if "bfd" not in self.updates_cmd:
- self.updates_cmd.append("bfd")
- self.updates_cmd.append("undo delay-up")
-
- # damp_init_wait_time damp_max_wait_time damp_second_wait_time
- if self.damp_init_wait_time is not None and self.damp_second_wait_time is not None \
- and self.damp_second_wait_time is not None:
- if bfd_state == "enable":
- if self.state == "present":
- if self.damp_max_wait_time != int(self.bfd_dict["global"].get("dampMaxWaitTime", "2000")):
- xml_str += "%s" % self.damp_max_wait_time
- damp_chg = True
- if self.damp_init_wait_time != int(self.bfd_dict["global"].get("dampInitWaitTime", "12000")):
- xml_str += "%s" % self.damp_init_wait_time
- damp_chg = True
- if self.damp_second_wait_time != int(self.bfd_dict["global"].get("dampSecondWaitTime", "5000")):
- xml_str += "%s" % self.damp_second_wait_time
- damp_chg = True
- if damp_chg:
- if "bfd" not in self.updates_cmd:
- self.updates_cmd.append("bfd")
- self.updates_cmd.append("dampening timer-interval maximum %s initial %s secondary %s" % (
- self.damp_max_wait_time, self.damp_init_wait_time, self.damp_second_wait_time))
- else:
- damp_chg = True
- if self.damp_max_wait_time != int(self.bfd_dict["global"].get("dampMaxWaitTime", "2000")):
- damp_chg = False
- if self.damp_init_wait_time != int(self.bfd_dict["global"].get("dampInitWaitTime", "12000")):
- damp_chg = False
- if self.damp_second_wait_time != int(self.bfd_dict["global"].get("dampSecondWaitTime", "5000")):
- damp_chg = False
-
- if damp_chg:
- xml_str += ""
- if "bfd" not in self.updates_cmd:
- self.updates_cmd.append("bfd")
- self.updates_cmd.append("undo dampening timer-interval maximum %s initial %s secondary %s" % (
- self.damp_max_wait_time, self.damp_init_wait_time, self.damp_second_wait_time))
- if xml_str:
- return '' + xml_str + ''
- else:
- return ""
-
- def netconf_load_config(self, xml_str):
- """load bfd config by netconf"""
-
- if not xml_str:
- return
-
- xml_cfg = """
-
-
- %s
-
- """ % xml_str
- set_nc_config(self.module, xml_cfg)
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- # check default_ip
- if self.default_ip:
- if not check_default_ip(self.default_ip):
- self.module.fail_json(msg="Error: Default ip is invalid.")
-
- # check tos_exp_dynamic
- if self.tos_exp_dynamic is not None:
- if self.tos_exp_dynamic < 0 or self.tos_exp_dynamic > 7:
- self.module.fail_json(msg="Error: Session tos_exp_dynamic is not ranges from 0 to 7.")
-
- # check tos_exp_static
- if self.tos_exp_static is not None:
- if self.tos_exp_static < 0 or self.tos_exp_static > 7:
- self.module.fail_json(msg="Error: Session tos_exp_static is not ranges from 0 to 7.")
-
- # check damp_init_wait_time
- if self.damp_init_wait_time is not None:
- if self.damp_init_wait_time < 1 or self.damp_init_wait_time > 3600000:
- self.module.fail_json(msg="Error: Session damp_init_wait_time is not ranges from 1 to 3600000.")
-
- # check damp_max_wait_time
- if self.damp_max_wait_time is not None:
- if self.damp_max_wait_time < 1 or self.damp_max_wait_time > 3600000:
- self.module.fail_json(msg="Error: Session damp_max_wait_time is not ranges from 1 to 3600000.")
-
- # check damp_second_wait_time
- if self.damp_second_wait_time is not None:
- if self.damp_second_wait_time < 1 or self.damp_second_wait_time > 3600000:
- self.module.fail_json(msg="Error: Session damp_second_wait_time is not ranges from 1 to 3600000.")
-
- # check delay_up_time
- if self.delay_up_time is not None:
- if self.delay_up_time < 1 or self.delay_up_time > 600:
- self.module.fail_json(msg="Error: Session delay_up_time is not ranges from 1 to 600.")
-
- def get_proposed(self):
- """get proposed info"""
-
- self.proposed["bfd_enalbe"] = self.bfd_enable
- self.proposed["default_ip"] = self.default_ip
- self.proposed["tos_exp_dynamic"] = self.tos_exp_dynamic
- self.proposed["tos_exp_static"] = self.tos_exp_static
- self.proposed["damp_init_wait_time"] = self.damp_init_wait_time
- self.proposed["damp_max_wait_time"] = self.damp_max_wait_time
- self.proposed["damp_second_wait_time"] = self.damp_second_wait_time
- self.proposed["delay_up_time"] = self.delay_up_time
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- if not self.bfd_dict:
- return
-
- self.existing["global"] = self.bfd_dict.get("global")
-
- def get_end_state(self):
- """get end state info"""
-
- bfd_dict = self.get_bfd_dict()
- if not bfd_dict:
- return
-
- self.end_state["global"] = bfd_dict.get("global")
- if self.existing == self.end_state:
- self.changed = False
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.bfd_dict = self.get_bfd_dict()
- self.get_existing()
- self.get_proposed()
-
- # deal present or absent
- xml_str = self.config_global()
-
- # update to device
- if xml_str:
- self.netconf_load_config(xml_str)
- self.changed = True
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- bfd_enable=dict(required=False, type='str', choices=['enable', 'disable']),
- default_ip=dict(required=False, type='str'),
- tos_exp_dynamic=dict(required=False, type='int'),
- tos_exp_static=dict(required=False, type='int'),
- damp_init_wait_time=dict(required=False, type='int'),
- damp_max_wait_time=dict(required=False, type='int'),
- damp_second_wait_time=dict(required=False, type='int'),
- delay_up_time=dict(required=False, type='int'),
- state=dict(required=False, default='present', choices=['present', 'absent'])
- )
-
- argument_spec.update(ce_argument_spec)
- module = BfdGlobal(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_bfd_session.py b/plugins/modules/network/cloudengine/ce_bfd_session.py
deleted file mode 100644
index 34538f6235..0000000000
--- a/plugins/modules/network/cloudengine/ce_bfd_session.py
+++ /dev/null
@@ -1,658 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_bfd_session
-short_description: Manages BFD session configuration on HUAWEI CloudEngine devices.
-description:
- - Manages BFD session configuration, creates a BFD session or deletes a specified BFD session
- on HUAWEI CloudEngine devices.
-author: QijunPan (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- session_name:
- description:
- - Specifies the name of a BFD session.
- The value is a string of 1 to 15 case-sensitive characters without spaces.
- required: true
- create_type:
- description:
- - BFD session creation mode, the currently created BFD session
- only supports static or static auto-negotiation mode.
- choices: ['static', 'auto']
- default: static
- addr_type:
- description:
- - Specifies the peer IP address type.
- choices: ['ipv4']
- out_if_name:
- description:
- - Specifies the type and number of the interface bound to the BFD session.
- dest_addr:
- description:
- - Specifies the peer IP address bound to the BFD session.
- src_addr:
- description:
- - Indicates the source IP address carried in BFD packets.
- local_discr:
- description:
- - The BFD session local identifier does not need to be configured when the mode is auto.
- remote_discr:
- description:
- - The BFD session remote identifier does not need to be configured when the mode is auto.
- vrf_name:
- description:
- - Specifies the name of a Virtual Private Network (VPN) instance that is bound to a BFD session.
- The value is a string of 1 to 31 case-sensitive characters, spaces not supported.
- When double quotation marks are used around the string, spaces are allowed in the string.
- The value _public_ is reserved and cannot be used as the VPN instance name.
- use_default_ip:
- description:
- - Indicates the default multicast IP address that is bound to a BFD session.
- By default, BFD uses the multicast IP address 224.0.0.184.
- You can set the multicast IP address by running the default-ip-address command.
- The value is a bool type.
- type: bool
- default: 'no'
- state:
- description:
- - Determines whether the config should be present or not on the device.
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = '''
-- name: bfd session module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
- - name: Configuring Single-hop BFD for Detecting Faults on a Layer 2 Link
- ce_bfd_session:
- session_name: bfd_l2link
- use_default_ip: true
- out_if_name: 10GE1/0/1
- local_discr: 163
- remote_discr: 163
- provider: '{{ cli }}'
-
- - name: Configuring Single-Hop BFD on a VLANIF Interface
- ce_bfd_session:
- session_name: bfd_vlanif
- dest_addr: 10.1.1.6
- out_if_name: Vlanif100
- local_discr: 163
- remote_discr: 163
- provider: '{{ cli }}'
-
- - name: Configuring Multi-Hop BFD
- ce_bfd_session:
- session_name: bfd_multi_hop
- dest_addr: 10.1.1.1
- local_discr: 163
- remote_discr: 163
- provider: '{{ cli }}'
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "addr_type": null,
- "create_type": null,
- "dest_addr": null,
- "out_if_name": "10GE1/0/1",
- "session_name": "bfd_l2link",
- "src_addr": null,
- "state": "present",
- "use_default_ip": true,
- "vrf_name": null
- }
-existing:
- description: k/v pairs of existing configuration
- returned: always
- type: dict
- sample: {
- "session": {}
- }
-end_state:
- description: k/v pairs of configuration after module execution
- returned: always
- type: dict
- sample: {
- "session": {
- "addrType": "IPV4",
- "createType": "SESS_STATIC",
- "destAddr": null,
- "outIfName": "10GE1/0/1",
- "sessName": "bfd_l2link",
- "srcAddr": null,
- "useDefaultIp": "true",
- "vrfName": null
- }
- }
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: [
- "bfd bfd_l2link bind peer-ip default-ip interface 10ge1/0/1"
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import sys
-import socket
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec, check_ip_addr
-
-
-CE_NC_GET_BFD = """
-
-
-
-
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-
-def is_valid_ip_vpn(vpname):
- """check ip vpn"""
-
- if not vpname:
- return False
-
- if vpname == "_public_":
- return False
-
- if len(vpname) < 1 or len(vpname) > 31:
- return False
-
- return True
-
-
-def check_default_ip(ipaddr):
- """check the default multicast IP address"""
-
- # The value ranges from 224.0.0.107 to 224.0.0.250
- if not check_ip_addr(ipaddr):
- return False
-
- if ipaddr.count(".") != 3:
- return False
-
- ips = ipaddr.split(".")
- if ips[0] != "224" or ips[1] != "0" or ips[2] != "0":
- return False
-
- if not ips[3].isdigit() or int(ips[3]) < 107 or int(ips[3]) > 250:
- return False
-
- return True
-
-
-def get_interface_type(interface):
- """get the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- if interface.upper().startswith('GE'):
- iftype = 'ge'
- elif interface.upper().startswith('10GE'):
- iftype = '10ge'
- elif interface.upper().startswith('25GE'):
- iftype = '25ge'
- elif interface.upper().startswith('4X10GE'):
- iftype = '4x10ge'
- elif interface.upper().startswith('40GE'):
- iftype = '40ge'
- elif interface.upper().startswith('100GE'):
- iftype = '100ge'
- elif interface.upper().startswith('VLANIF'):
- iftype = 'vlanif'
- elif interface.upper().startswith('LOOPBACK'):
- iftype = 'loopback'
- elif interface.upper().startswith('METH'):
- iftype = 'meth'
- elif interface.upper().startswith('ETH-TRUNK'):
- iftype = 'eth-trunk'
- elif interface.upper().startswith('VBDIF'):
- iftype = 'vbdif'
- elif interface.upper().startswith('NVE'):
- iftype = 'nve'
- elif interface.upper().startswith('TUNNEL'):
- iftype = 'tunnel'
- elif interface.upper().startswith('ETHERNET'):
- iftype = 'ethernet'
- elif interface.upper().startswith('FCOE-PORT'):
- iftype = 'fcoe-port'
- elif interface.upper().startswith('FABRIC-PORT'):
- iftype = 'fabric-port'
- elif interface.upper().startswith('STACK-PORT'):
- iftype = 'stack-port'
- elif interface.upper().startswith('NULL'):
- iftype = 'null'
- else:
- return None
-
- return iftype.lower()
-
-
-class BfdSession(object):
- """Manages BFD Session"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.__init_module__()
-
- # module input info
- self.session_name = self.module.params['session_name']
- self.create_type = self.module.params['create_type']
- self.addr_type = self.module.params['addr_type']
- self.out_if_name = self.module.params['out_if_name']
- self.dest_addr = self.module.params['dest_addr']
- self.src_addr = self.module.params['src_addr']
- self.vrf_name = self.module.params['vrf_name']
- self.use_default_ip = self.module.params['use_default_ip']
- self.state = self.module.params['state']
- self.local_discr = self.module.params['local_discr']
- self.remote_discr = self.module.params['remote_discr']
- # host info
- self.host = self.module.params['host']
- self.username = self.module.params['username']
- self.port = self.module.params['port']
-
- # state
- self.changed = False
- self.bfd_dict = dict()
- self.updates_cmd = list()
- self.commands = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def __init_module__(self):
- """init module"""
-
- mutually_exclusive = [('use_default_ip', 'dest_addr')]
- self.module = AnsibleModule(argument_spec=self.spec,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
-
- def get_bfd_dict(self):
- """bfd config dict"""
-
- bfd_dict = dict()
- bfd_dict["global"] = dict()
- bfd_dict["session"] = dict()
- conf_str = CE_NC_GET_BFD % self.session_name
-
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return bfd_dict
-
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
-
- # get bfd global info
- glb = root.find("bfd/bfdSchGlobal")
- if glb:
- for attr in glb:
- bfd_dict["global"][attr.tag] = attr.text
-
- # get bfd session info
- sess = root.find("bfd/bfdCfgSessions/bfdCfgSession")
- if sess:
- for attr in sess:
- bfd_dict["session"][attr.tag] = attr.text
-
- return bfd_dict
-
- def is_session_match(self):
- """is bfd session match"""
-
- if not self.bfd_dict["session"] or not self.session_name:
- return False
-
- session = self.bfd_dict["session"]
- if self.session_name != session.get("sessName", ""):
- return False
-
- if self.create_type and self.create_type.upper() not in session.get("createType", "").upper():
- return False
-
- if self.addr_type and self.addr_type != session.get("addrType").lower():
- return False
-
- if self.dest_addr and self.dest_addr != session.get("destAddr"):
- return False
-
- if self.src_addr and self.src_addr != session.get("srcAddr"):
- return False
-
- if self.out_if_name:
- if not session.get("outIfName"):
- return False
- if self.out_if_name.replace(" ", "").lower() != session.get("outIfName").replace(" ", "").lower():
- return False
-
- if self.vrf_name and self.vrf_name != session.get("vrfName"):
- return False
-
- if str(self.use_default_ip).lower() != session.get("useDefaultIp"):
- return False
-
- if self.create_type == "static" and self.state == "present":
- if str(self.local_discr).lower() != session.get("localDiscr", ""):
- return False
- if str(self.remote_discr).lower() != session.get("remoteDiscr", ""):
- return False
-
- return True
-
- def config_session(self):
- """configures bfd session"""
-
- xml_str = ""
- cmd_list = list()
- discr = list()
-
- if not self.session_name:
- return xml_str
-
- if self.bfd_dict["global"].get("bfdEnable", "false") != "true":
- self.module.fail_json(msg="Error: Please enable BFD globally first.")
-
- xml_str = "%s" % self.session_name
- cmd_session = "bfd %s" % self.session_name
-
- if self.state == "present":
- if not self.bfd_dict["session"]:
- # Parameter check
- if not self.dest_addr and not self.use_default_ip:
- self.module.fail_json(
- msg="Error: dest_addr or use_default_ip must be set when bfd session is creating.")
-
- # Creates a BFD session
- if self.create_type == "auto":
- xml_str += "SESS_%s" % self.create_type.upper()
- else:
- xml_str += "SESS_STATIC"
- xml_str += "IP"
- cmd_session += " bind"
- if self.addr_type:
- xml_str += "%s" % self.addr_type.upper()
- else:
- xml_str += "IPV4"
- if self.dest_addr:
- xml_str += "%s" % self.dest_addr
- cmd_session += " peer-%s %s" % ("ipv6" if self.addr_type == "ipv6" else "ip", self.dest_addr)
- if self.use_default_ip:
- xml_str += "%s" % str(self.use_default_ip).lower()
- cmd_session += " peer-ip default-ip"
- if self.vrf_name:
- xml_str += "%s" % self.vrf_name
- cmd_session += " vpn-instance %s" % self.vrf_name
- if self.out_if_name:
- xml_str += "%s" % self.out_if_name
- cmd_session += " interface %s" % self.out_if_name.lower()
- if self.src_addr:
- xml_str += "%s" % self.src_addr
- cmd_session += " source-%s %s" % ("ipv6" if self.addr_type == "ipv6" else "ip", self.src_addr)
-
- if self.create_type == "auto":
- cmd_session += " auto"
- else:
- xml_str += "%s" % self.local_discr
- discr.append("discriminator local %s" % self.local_discr)
- xml_str += "%s" % self.remote_discr
- discr.append("discriminator remote %s" % self.remote_discr)
-
- elif not self.is_session_match():
- # Bfd session is not match
- self.module.fail_json(msg="Error: The specified BFD configuration view has been created.")
- else:
- pass
- else: # absent
- if not self.bfd_dict["session"]:
- self.module.fail_json(msg="Error: BFD session is not exist.")
- if not self.is_session_match():
- self.module.fail_json(msg="Error: BFD session parameter is invalid.")
-
- if self.state == "present":
- if xml_str.endswith(""):
- # no config update
- return ""
- else:
- cmd_list.insert(0, cmd_session)
- cmd_list.extend(discr)
- self.updates_cmd.extend(cmd_list)
- return '' + xml_str\
- + ''
- else: # absent
- cmd_list.append("undo " + cmd_session)
- self.updates_cmd.extend(cmd_list)
- return '' + xml_str\
- + ''
-
- def netconf_load_config(self, xml_str):
- """load bfd config by netconf"""
-
- if not xml_str:
- return
-
- xml_cfg = """
-
-
- %s
-
- """ % xml_str
- set_nc_config(self.module, xml_cfg)
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- # check session_name
- if not self.session_name:
- self.module.fail_json(msg="Error: Missing required arguments: session_name.")
-
- if self.session_name:
- if len(self.session_name) < 1 or len(self.session_name) > 15:
- self.module.fail_json(msg="Error: Session name is invalid.")
-
- # check local_discr
- # check remote_discr
-
- if self.local_discr:
- if self.local_discr < 1 or self.local_discr > 16384:
- self.module.fail_json(msg="Error: Session local_discr is not ranges from 1 to 16384.")
- if self.remote_discr:
- if self.remote_discr < 1 or self.remote_discr > 4294967295:
- self.module.fail_json(msg="Error: Session remote_discr is not ranges from 1 to 4294967295.")
-
- if self.state == "present" and self.create_type == "static":
- if not self.local_discr:
- self.module.fail_json(msg="Error: Missing required arguments: local_discr.")
- if not self.remote_discr:
- self.module.fail_json(msg="Error: Missing required arguments: remote_discr.")
-
- # check out_if_name
- if self.out_if_name:
- if not get_interface_type(self.out_if_name):
- self.module.fail_json(msg="Error: Session out_if_name is invalid.")
-
- # check dest_addr
- if self.dest_addr:
- if not check_ip_addr(self.dest_addr):
- self.module.fail_json(msg="Error: Session dest_addr is invalid.")
-
- # check src_addr
- if self.src_addr:
- if not check_ip_addr(self.src_addr):
- self.module.fail_json(msg="Error: Session src_addr is invalid.")
-
- # check vrf_name
- if self.vrf_name:
- if not is_valid_ip_vpn(self.vrf_name):
- self.module.fail_json(msg="Error: Session vrf_name is invalid.")
- if not self.dest_addr:
- self.module.fail_json(msg="Error: vrf_name and dest_addr must set at the same time.")
-
- # check use_default_ip
- if self.use_default_ip and not self.out_if_name:
- self.module.fail_json(msg="Error: use_default_ip and out_if_name must set at the same time.")
-
- def get_proposed(self):
- """get proposed info"""
-
- # base config
- self.proposed["session_name"] = self.session_name
- self.proposed["create_type"] = self.create_type
- self.proposed["addr_type"] = self.addr_type
- self.proposed["out_if_name"] = self.out_if_name
- self.proposed["dest_addr"] = self.dest_addr
- self.proposed["src_addr"] = self.src_addr
- self.proposed["vrf_name"] = self.vrf_name
- self.proposed["use_default_ip"] = self.use_default_ip
- self.proposed["state"] = self.state
- self.proposed["local_discr"] = self.local_discr
- self.proposed["remote_discr"] = self.remote_discr
-
- def get_existing(self):
- """get existing info"""
-
- if not self.bfd_dict:
- return
-
- self.existing["session"] = self.bfd_dict.get("session")
-
- def get_end_state(self):
- """get end state info"""
-
- bfd_dict = self.get_bfd_dict()
- if not bfd_dict:
- return
-
- self.end_state["session"] = bfd_dict.get("session")
- if self.end_state == self.existing:
- self.changed = False
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.bfd_dict = self.get_bfd_dict()
- self.get_existing()
- self.get_proposed()
-
- # deal present or absent
- xml_str = ''
- if self.session_name:
- xml_str += self.config_session()
-
- # update to device
- if xml_str:
- self.netconf_load_config(xml_str)
- self.changed = True
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- session_name=dict(required=True, type='str'),
- create_type=dict(required=False, default='static', type='str', choices=['static', 'auto']),
- addr_type=dict(required=False, type='str', choices=['ipv4']),
- out_if_name=dict(required=False, type='str'),
- dest_addr=dict(required=False, type='str'),
- src_addr=dict(required=False, type='str'),
- vrf_name=dict(required=False, type='str'),
- use_default_ip=dict(required=False, type='bool', default=False),
- state=dict(required=False, default='present', choices=['present', 'absent']),
- local_discr=dict(required=False, type='int'),
- remote_discr=dict(required=False, type='int')
- )
-
- argument_spec.update(ce_argument_spec)
- module = BfdSession(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_bfd_view.py b/plugins/modules/network/cloudengine/ce_bfd_view.py
deleted file mode 100644
index 6f7fe79807..0000000000
--- a/plugins/modules/network/cloudengine/ce_bfd_view.py
+++ /dev/null
@@ -1,565 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_bfd_view
-short_description: Manages BFD session view configuration on HUAWEI CloudEngine devices.
-description:
- - Manages BFD session view configuration on HUAWEI CloudEngine devices.
-author: QijunPan (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- session_name:
- description:
- - Specifies the name of a BFD session.
- The value is a string of 1 to 15 case-sensitive characters without spaces.
- required: true
- local_discr:
- description:
- - Specifies the local discriminator of a BFD session.
- The value is an integer that ranges from 1 to 16384.
- remote_discr:
- description:
- - Specifies the remote discriminator of a BFD session.
- The value is an integer that ranges from 1 to 4294967295.
- min_tx_interval:
- description:
- - Specifies the minimum interval for receiving BFD packets.
- The value is an integer that ranges from 50 to 1000, in milliseconds.
- min_rx_interval:
- description:
- - Specifies the minimum interval for sending BFD packets.
- The value is an integer that ranges from 50 to 1000, in milliseconds.
- detect_multi:
- description:
- - Specifies the local detection multiplier of a BFD session.
- The value is an integer that ranges from 3 to 50.
- wtr_interval:
- description:
- - Specifies the WTR time of a BFD session.
- The value is an integer that ranges from 1 to 60, in minutes.
- The default value is 0.
- tos_exp:
- description:
- - Specifies a priority for BFD control packets.
- The value is an integer ranging from 0 to 7.
- The default value is 7, which is the highest priority.
- admin_down:
- description:
- - Enables the BFD session to enter the AdminDown state.
- By default, a BFD session is enabled.
- The default value is bool type.
- type: bool
- default: 'no'
- description:
- description:
- - Specifies the description of a BFD session.
- The value is a string of 1 to 51 case-sensitive characters with spaces.
- state:
- description:
- - Determines whether the config should be present or not on the device.
- default: present
- choices: ['present', 'absent']
-extends_documentation_fragment:
-- community.general.ce
-
-'''
-
-EXAMPLES = '''
-- name: bfd view module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
- - name: Set the local discriminator of a BFD session to 80 and the remote discriminator to 800
- ce_bfd_view:
- session_name: atob
- local_discr: 80
- remote_discr: 800
- state: present
- provider: '{{ cli }}'
-
- - name: Set the minimum interval for receiving BFD packets to 500 ms
- ce_bfd_view:
- session_name: atob
- min_rx_interval: 500
- state: present
- provider: '{{ cli }}'
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "admin_down": false,
- "description": null,
- "detect_multi": null,
- "local_discr": 80,
- "min_rx_interval": null,
- "min_tx_interval": null,
- "remote_discr": 800,
- "session_name": "atob",
- "state": "present",
- "tos_exp": null,
- "wtr_interval": null
- }
-existing:
- description: k/v pairs of existing configuration
- returned: always
- type: dict
- sample: {
- "session": {
- "adminDown": "false",
- "createType": "SESS_STATIC",
- "description": null,
- "detectMulti": "3",
- "localDiscr": null,
- "minRxInt": null,
- "minTxInt": null,
- "remoteDiscr": null,
- "sessName": "atob",
- "tosExp": null,
- "wtrTimerInt": null
- }
- }
-end_state:
- description: k/v pairs of configuration after module execution
- returned: always
- type: dict
- sample: {
- "session": {
- "adminDown": "false",
- "createType": "SESS_STATIC",
- "description": null,
- "detectMulti": "3",
- "localDiscr": "80",
- "minRxInt": null,
- "minTxInt": null,
- "remoteDiscr": "800",
- "sessName": "atob",
- "tosExp": null,
- "wtrTimerInt": null
- }
- }
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: [
- "bfd atob",
- "discriminator local 80",
- "discriminator remote 800"
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import sys
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-
-CE_NC_GET_BFD = """
-
-
- %s
-
-
-"""
-
-CE_NC_GET_BFD_GLB = """
-
-
-
-"""
-
-CE_NC_GET_BFD_SESSION = """
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-
-class BfdView(object):
- """Manages BFD View"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.__init_module__()
-
- # module input info
- self.session_name = self.module.params['session_name']
- self.local_discr = self.module.params['local_discr']
- self.remote_discr = self.module.params['remote_discr']
- self.min_tx_interval = self.module.params['min_tx_interval']
- self.min_rx_interval = self.module.params['min_rx_interval']
- self.detect_multi = self.module.params['detect_multi']
- self.wtr_interval = self.module.params['wtr_interval']
- self.tos_exp = self.module.params['tos_exp']
- self.admin_down = self.module.params['admin_down']
- self.description = self.module.params['description']
- self.state = self.module.params['state']
-
- # host info
- self.host = self.module.params['host']
- self.username = self.module.params['username']
- self.port = self.module.params['port']
-
- # state
- self.changed = False
- self.bfd_dict = dict()
- self.updates_cmd = list()
- self.commands = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def __init_module__(self):
- """init module"""
-
- self.module = AnsibleModule(argument_spec=self.spec,
- supports_check_mode=True)
-
- def get_bfd_dict(self):
- """bfd config dict"""
-
- bfd_dict = dict()
- bfd_dict["global"] = dict()
- bfd_dict["session"] = dict()
- conf_str = CE_NC_GET_BFD % (CE_NC_GET_BFD_GLB + (CE_NC_GET_BFD_SESSION % self.session_name))
-
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return bfd_dict
-
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
-
- # get bfd global info
- glb = root.find("bfd/bfdSchGlobal")
- if glb:
- for attr in glb:
- bfd_dict["global"][attr.tag] = attr.text
-
- # get bfd session info
- sess = root.find("bfd/bfdCfgSessions/bfdCfgSession")
- if sess:
- for attr in sess:
- bfd_dict["session"][attr.tag] = attr.text
-
- return bfd_dict
-
- def config_session(self):
- """configures bfd session"""
-
- xml_str = ""
- cmd_list = list()
- cmd_session = ""
-
- if not self.session_name:
- return xml_str
-
- if self.bfd_dict["global"].get("bfdEnable", "false") != "true":
- self.module.fail_json(msg="Error: Please enable BFD globally first.")
-
- if not self.bfd_dict["session"]:
- self.module.fail_json(msg="Error: BFD session is not exist.")
-
- session = self.bfd_dict["session"]
- xml_str = "%s" % self.session_name
- cmd_session = "bfd %s" % self.session_name
-
- # BFD session view
- if self.local_discr is not None:
- if self.state == "present" and str(self.local_discr) != session.get("localDiscr"):
- xml_str += "%s" % self.local_discr
- cmd_list.append("discriminator local %s" % self.local_discr)
- elif self.state == "absent" and str(self.local_discr) == session.get("localDiscr"):
- xml_str += ""
- cmd_list.append("undo discriminator local")
-
- if self.remote_discr is not None:
- if self.state == "present" and str(self.remote_discr) != session.get("remoteDiscr"):
- xml_str += "%s" % self.remote_discr
- cmd_list.append("discriminator remote %s" % self.remote_discr)
- elif self.state == "absent" and str(self.remote_discr) == session.get("remoteDiscr"):
- xml_str += ""
- cmd_list.append("undo discriminator remote")
-
- if self.min_tx_interval is not None:
- if self.state == "present" and str(self.min_tx_interval) != session.get("minTxInt"):
- xml_str += "%s" % self.min_tx_interval
- cmd_list.append("min-tx-interval %s" % self.min_tx_interval)
- elif self.state == "absent" and str(self.min_tx_interval) == session.get("minTxInt"):
- xml_str += ""
- cmd_list.append("undo min-tx-interval")
-
- if self.min_rx_interval is not None:
- if self.state == "present" and str(self.min_rx_interval) != session.get("minRxInt"):
- xml_str += "%s" % self.min_rx_interval
- cmd_list.append("min-rx-interval %s" % self.min_rx_interval)
- elif self.state == "absent" and str(self.min_rx_interval) == session.get("minRxInt"):
- xml_str += ""
- cmd_list.append("undo min-rx-interval")
-
- if self.detect_multi is not None:
- if self.state == "present" and str(self.detect_multi) != session.get("detectMulti"):
- xml_str += " %s" % self.detect_multi
- cmd_list.append("detect-multiplier %s" % self.detect_multi)
- elif self.state == "absent" and str(self.detect_multi) == session.get("detectMulti"):
- xml_str += " "
- cmd_list.append("undo detect-multiplier")
-
- if self.wtr_interval is not None:
- if self.state == "present" and str(self.wtr_interval) != session.get("wtrTimerInt"):
- xml_str += " %s" % self.wtr_interval
- cmd_list.append("wtr %s" % self.wtr_interval)
- elif self.state == "absent" and str(self.wtr_interval) == session.get("wtrTimerInt"):
- xml_str += " "
- cmd_list.append("undo wtr")
-
- if self.tos_exp is not None:
- if self.state == "present" and str(self.tos_exp) != session.get("tosExp"):
- xml_str += " %s" % self.tos_exp
- cmd_list.append("tos-exp %s" % self.tos_exp)
- elif self.state == "absent" and str(self.tos_exp) == session.get("tosExp"):
- xml_str += " "
- cmd_list.append("undo tos-exp")
-
- if self.admin_down and session.get("adminDown", "false") == "false":
- xml_str += " true"
- cmd_list.append("shutdown")
- elif not self.admin_down and session.get("adminDown", "false") == "true":
- xml_str += " false"
- cmd_list.append("undo shutdown")
-
- if self.description:
- if self.state == "present" and self.description != session.get("description"):
- xml_str += "%s" % self.description
- cmd_list.append("description %s" % self.description)
- elif self.state == "absent" and self.description == session.get("description"):
- xml_str += ""
- cmd_list.append("undo description")
-
- if xml_str.endswith(""):
- # no config update
- return ""
- else:
- cmd_list.insert(0, cmd_session)
- self.updates_cmd.extend(cmd_list)
- return '' + xml_str\
- + ''
-
- def netconf_load_config(self, xml_str):
- """load bfd config by netconf"""
-
- if not xml_str:
- return
-
- xml_cfg = """
-
-
- %s
-
- """ % xml_str
-
- set_nc_config(self.min_rx_interval, xml_cfg)
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- # check session_name
- if not self.session_name:
- self.module.fail_json(msg="Error: Missing required arguments: session_name.")
-
- if self.session_name:
- if len(self.session_name) < 1 or len(self.session_name) > 15:
- self.module.fail_json(msg="Error: Session name is invalid.")
-
- # check local_discr
- if self.local_discr is not None:
- if self.local_discr < 1 or self.local_discr > 16384:
- self.module.fail_json(msg="Error: Session local_discr is not ranges from 1 to 16384.")
-
- # check remote_discr
- if self.remote_discr is not None:
- if self.remote_discr < 1 or self.remote_discr > 4294967295:
- self.module.fail_json(msg="Error: Session remote_discr is not ranges from 1 to 4294967295.")
-
- # check min_tx_interval
- if self.min_tx_interval is not None:
- if self.min_tx_interval < 50 or self.min_tx_interval > 1000:
- self.module.fail_json(msg="Error: Session min_tx_interval is not ranges from 50 to 1000.")
-
- # check min_rx_interval
- if self.min_rx_interval is not None:
- if self.min_rx_interval < 50 or self.min_rx_interval > 1000:
- self.module.fail_json(msg="Error: Session min_rx_interval is not ranges from 50 to 1000.")
-
- # check detect_multi
- if self.detect_multi is not None:
- if self.detect_multi < 3 or self.detect_multi > 50:
- self.module.fail_json(msg="Error: Session detect_multi is not ranges from 3 to 50.")
-
- # check wtr_interval
- if self.wtr_interval is not None:
- if self.wtr_interval < 1 or self.wtr_interval > 60:
- self.module.fail_json(msg="Error: Session wtr_interval is not ranges from 1 to 60.")
-
- # check tos_exp
- if self.tos_exp is not None:
- if self.tos_exp < 0 or self.tos_exp > 7:
- self.module.fail_json(msg="Error: Session tos_exp is not ranges from 0 to 7.")
-
- # check description
- if self.description:
- if len(self.description) < 1 or len(self.description) > 51:
- self.module.fail_json(msg="Error: Session description is invalid.")
-
- def get_proposed(self):
- """get proposed info"""
-
- # base config
- self.proposed["session_name"] = self.session_name
- self.proposed["local_discr"] = self.local_discr
- self.proposed["remote_discr"] = self.remote_discr
- self.proposed["min_tx_interval"] = self.min_tx_interval
- self.proposed["min_rx_interval"] = self.min_rx_interval
- self.proposed["detect_multi"] = self.detect_multi
- self.proposed["wtr_interval"] = self.wtr_interval
- self.proposed["tos_exp"] = self.tos_exp
- self.proposed["admin_down"] = self.admin_down
- self.proposed["description"] = self.description
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- if not self.bfd_dict:
- return
-
- self.existing["session"] = self.bfd_dict.get("session")
-
- def get_end_state(self):
- """get end state info"""
-
- bfd_dict = self.get_bfd_dict()
- if not bfd_dict:
- return
-
- self.end_state["session"] = bfd_dict.get("session")
- if self.end_state == self.existing:
- self.changed = False
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.bfd_dict = self.get_bfd_dict()
- self.get_existing()
- self.get_proposed()
-
- # deal present or absent
- xml_str = ''
- if self.session_name:
- xml_str += self.config_session()
-
- # update to device
- if xml_str:
- self.netconf_load_config(xml_str)
- self.changed = True
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- session_name=dict(required=True, type='str'),
- local_discr=dict(required=False, type='int'),
- remote_discr=dict(required=False, type='int'),
- min_tx_interval=dict(required=False, type='int'),
- min_rx_interval=dict(required=False, type='int'),
- detect_multi=dict(required=False, type='int'),
- wtr_interval=dict(required=False, type='int'),
- tos_exp=dict(required=False, type='int'),
- admin_down=dict(required=False, type='bool', default=False),
- description=dict(required=False, type='str'),
- state=dict(required=False, default='present', choices=['present', 'absent'])
- )
-
- argument_spec.update(ce_argument_spec)
- module = BfdView(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_bgp.py b/plugins/modules/network/cloudengine/ce_bgp.py
deleted file mode 100644
index d4dcc87031..0000000000
--- a/plugins/modules/network/cloudengine/ce_bgp.py
+++ /dev/null
@@ -1,2331 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_bgp
-short_description: Manages BGP configuration on HUAWEI CloudEngine switches.
-description:
- - Manages BGP configurations on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- state:
- description:
- - Specify desired state of the resource.
- default: present
- choices: ['present','absent']
- as_number:
- description:
- - Local AS number.
- The value is a string of 1 to 11 characters.
- graceful_restart:
- description:
- - Enable GR of the BGP speaker in the specified address family, peer address, or peer group.
- default: no_use
- choices: ['no_use','true','false']
- time_wait_for_rib:
- description:
- - Period of waiting for the End-Of-RIB flag.
- The value is an integer ranging from 3 to 3000. The default value is 600.
- as_path_limit:
- description:
- - Maximum number of AS numbers in the AS_Path attribute. The default value is 255.
- check_first_as:
- description:
- - Check the first AS in the AS_Path of the update messages from EBGP peers.
- default: no_use
- choices: ['no_use','true','false']
- confed_id_number:
- description:
- - Confederation ID.
- The value is a string of 1 to 11 characters.
- confed_nonstanded:
- description:
- - Configure the device to be compatible with devices in a nonstandard confederation.
- default: no_use
- choices: ['no_use','true','false']
- bgp_rid_auto_sel:
- description:
- - The function to automatically select router IDs for all VPN BGP instances is enabled.
- default: no_use
- choices: ['no_use','true','false']
- keep_all_routes:
- description:
- - If the value is true, the system stores all route update messages received from all peers (groups) after
- BGP connection setup.
- If the value is false, the system stores only BGP update messages that are received from peers and pass
- the configured import policy.
- default: no_use
- choices: ['no_use','true','false']
- memory_limit:
- description:
- - Support BGP RIB memory protection.
- default: no_use
- choices: ['no_use','true','false']
- gr_peer_reset:
- description:
- - Peer disconnection through GR.
- default: no_use
- choices: ['no_use','true','false']
- is_shutdown:
- description:
- - Interrupt BGP all neighbor.
- default: no_use
- choices: ['no_use','true','false']
- suppress_interval:
- description:
- - Suppress interval.
- hold_interval:
- description:
- - Hold interval.
- clear_interval:
- description:
- - Clear interval.
- confed_peer_as_num:
- description:
- - Confederation AS number, in two-byte or four-byte format.
- The value is a string of 1 to 11 characters.
- vrf_name:
- description:
- - Name of a BGP instance. The name is a case-sensitive string of characters.
- vrf_rid_auto_sel:
- description:
- - If the value is true, VPN BGP instances are enabled to automatically select router IDs.
- If the value is false, VPN BGP instances are disabled from automatically selecting router IDs.
- default: no_use
- choices: ['no_use','true','false']
- router_id:
- description:
- - ID of a router that is in IPv4 address format.
- keepalive_time:
- description:
- - If the value of a timer changes, the BGP peer relationship between the routers is disconnected.
- The value is an integer ranging from 0 to 21845. The default value is 60.
- hold_time:
- description:
- - Hold time, in seconds. The value of the hold time can be 0 or range from 3 to 65535.
- min_hold_time:
- description:
- - Min hold time, in seconds. The value of the hold time can be 0 or range from 20 to 65535.
- conn_retry_time:
- description:
- - ConnectRetry interval. The value is an integer, in seconds. The default value is 32s.
- ebgp_if_sensitive:
- description:
- - If the value is true, After the fast EBGP interface awareness function is enabled, EBGP sessions on
- an interface are deleted immediately when the interface goes Down.
- If the value is false, After the fast EBGP interface awareness function is enabled, EBGP sessions
- on an interface are not deleted immediately when the interface goes Down.
- default: no_use
- choices: ['no_use','true','false']
- default_af_type:
- description:
- - Type of a created address family, which can be IPv4 unicast or IPv6 unicast.
- The default type is IPv4 unicast.
- choices: ['ipv4uni','ipv6uni']
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine BGP test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Enable BGP"
- ce_bgp:
- state: present
- as_number: 100
- confed_id_number: 250
- provider: "{{ cli }}"
-
- - name: "Disable BGP"
- ce_bgp:
- state: absent
- as_number: 100
- confed_id_number: 250
- provider: "{{ cli }}"
-
- - name: "Create confederation peer AS num"
- ce_bgp:
- state: present
- confed_peer_as_num: 260
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"as_number": "100", state": "present"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {"bgp_enable": [["100"], ["true"]]}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"bgp_enable": [["100"], ["true"]]}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["bgp 100"]
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-
-SUCCESS = """success"""
-FAILED = """failed"""
-
-
-# get bgp enable
-CE_GET_BGP_ENABLE = """
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_GET_BGP_ENABLE_HEADER = """
-
-
-
-
-"""
-
-CE_GET_BGP_ENABLE_TAIL = """
-
-
-
-
-"""
-
-# merge bgp enable
-CE_MERGE_BGP_ENABLE_HEADER = """
-
-
-
-
-"""
-CE_MERGE_BGP_ENABLE_TAIL = """
-
-
-
-
-"""
-
-# get bgp confederation peer as
-CE_GET_BGP_CONFED_PEER_AS = """
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge bgp confederation peer as
-CE_MERGE_BGP_CONFED_PEER_AS = """
-
-
-
-
-
- %s
-
-
-
-
-
-"""
-
-# create bgp confederation peer as
-CE_CREATE_BGP_CONFED_PEER_AS = """
-
-
-
-
-
- %s
-
-
-
-
-
-"""
-
-# delete bgp confederation peer as
-CE_DELETE_BGP_CONFED_PEER_AS = """
-
-
-
-
-
- %s
-
-
-
-
-
-"""
-
-# get bgp instance
-CE_GET_BGP_INSTANCE = """
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-# get bgp instance
-CE_GET_BGP_INSTANCE_HEADER = """
-
-
-
-
-
-"""
-CE_GET_BGP_INSTANCE_TAIL = """
-
-
-
-
-
-"""
-
-# merge bgp instance
-CE_MERGE_BGP_INSTANCE_HEADER = """
-
-
-
-
-
-"""
-CE_MERGE_BGP_INSTANCE_TAIL = """
-
-
-
-
-
-"""
-
-# create bgp instance
-CE_CREATE_BGP_INSTANCE_HEADER = """
-
-
-
-
-
-"""
-CE_CREATE_BGP_INSTANCE_TAIL = """
-
-
-
-
-
-"""
-
-# delete bgp instance
-CE_DELETE_BGP_INSTANCE_HEADER = """
-
-
-
-
-
-"""
-CE_DELETE_BGP_INSTANCE_TAIL = """
-
-
-
-
-
-"""
-
-
-def check_ip_addr(**kwargs):
- """ check_ip_addr """
-
- ipaddr = kwargs["ipaddr"]
-
- addr = ipaddr.strip().split('.')
-
- if len(addr) != 4:
- return FAILED
-
- for i in range(4):
- addr[i] = int(addr[i])
-
- if addr[i] <= 255 and addr[i] >= 0:
- pass
- else:
- return FAILED
- return SUCCESS
-
-
-def check_bgp_enable_args(**kwargs):
- """ check_bgp_enable_args """
-
- module = kwargs["module"]
-
- need_cfg = False
-
- as_number = module.params['as_number']
- if as_number:
- if len(as_number) > 11 or len(as_number) == 0:
- module.fail_json(
- msg='Error: The len of as_number %s is out of [1 - 11].' % as_number)
- else:
- need_cfg = True
-
- return need_cfg
-
-
-def check_bgp_confed_args(**kwargs):
- """ check_bgp_confed_args """
-
- module = kwargs["module"]
-
- need_cfg = False
-
- confed_peer_as_num = module.params['confed_peer_as_num']
- if confed_peer_as_num:
- if len(confed_peer_as_num) > 11 or len(confed_peer_as_num) == 0:
- module.fail_json(
- msg='Error: The len of confed_peer_as_num %s is out of [1 - 11].' % confed_peer_as_num)
- else:
- need_cfg = True
-
- return need_cfg
-
-
-class Bgp(object):
- """ Manages BGP configuration """
-
- def netconf_get_config(self, **kwargs):
- """ netconf_get_config """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- xml_str = get_nc_config(module, conf_str)
-
- return xml_str
-
- def netconf_set_config(self, **kwargs):
- """ netconf_set_config """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- xml_str = set_nc_config(module, conf_str)
-
- return xml_str
-
- def check_bgp_enable_other_args(self, **kwargs):
- """ check_bgp_enable_other_args """
-
- module = kwargs["module"]
- state = module.params['state']
- result = dict()
- need_cfg = False
-
- graceful_restart = module.params['graceful_restart']
- if graceful_restart != 'no_use':
-
- conf_str = CE_GET_BGP_ENABLE_HEADER + \
- "" + CE_GET_BGP_ENABLE_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["graceful_restart"] = re_find
- if re_find[0] != graceful_restart:
- need_cfg = True
- else:
- need_cfg = True
-
- time_wait_for_rib = module.params['time_wait_for_rib']
- if time_wait_for_rib:
- if int(time_wait_for_rib) > 3000 or int(time_wait_for_rib) < 3:
- module.fail_json(
- msg='Error: The time_wait_for_rib %s is out of [3 - 3000].' % time_wait_for_rib)
- else:
- conf_str = CE_GET_BGP_ENABLE_HEADER + \
- "" + CE_GET_BGP_ENABLE_TAIL
- recv_xml = self.netconf_get_config(
- module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["time_wait_for_rib"] = re_find
- if re_find[0] != time_wait_for_rib:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["time_wait_for_rib"] = re_find
- if re_find[0] == time_wait_for_rib:
- need_cfg = True
-
- as_path_limit = module.params['as_path_limit']
- if as_path_limit:
- if int(as_path_limit) > 2000 or int(as_path_limit) < 1:
- module.fail_json(
- msg='Error: The as_path_limit %s is out of [1 - 2000].' % as_path_limit)
- else:
- conf_str = CE_GET_BGP_ENABLE_HEADER + \
- "" + CE_GET_BGP_ENABLE_TAIL
- recv_xml = self.netconf_get_config(
- module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["as_path_limit"] = re_find
- if re_find[0] != as_path_limit:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["as_path_limit"] = re_find
- if re_find[0] == as_path_limit:
- need_cfg = True
-
- check_first_as = module.params['check_first_as']
- if check_first_as != 'no_use':
- conf_str = CE_GET_BGP_ENABLE_HEADER + \
- "" + CE_GET_BGP_ENABLE_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["check_first_as"] = re_find
- if re_find[0] != check_first_as:
- need_cfg = True
- else:
- need_cfg = True
-
- confed_id_number = module.params['confed_id_number']
- if confed_id_number:
- if len(confed_id_number) > 11 or len(confed_id_number) == 0:
- module.fail_json(
- msg='Error: The len of confed_id_number %s is out of [1 - 11].' % confed_id_number)
- else:
- conf_str = CE_GET_BGP_ENABLE_HEADER + \
- "" + CE_GET_BGP_ENABLE_TAIL
- recv_xml = self.netconf_get_config(
- module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["confed_id_number"] = re_find
- if re_find[0] != confed_id_number:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["confed_id_number"] = re_find
- if re_find[0] == confed_id_number:
- need_cfg = True
-
- confed_nonstanded = module.params['confed_nonstanded']
- if confed_nonstanded != 'no_use':
- conf_str = CE_GET_BGP_ENABLE_HEADER + \
- "" + CE_GET_BGP_ENABLE_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["confed_nonstanded"] = re_find
- if re_find[0] != confed_nonstanded:
- need_cfg = True
- else:
- need_cfg = True
-
- bgp_rid_auto_sel = module.params['bgp_rid_auto_sel']
- if bgp_rid_auto_sel != 'no_use':
- conf_str = CE_GET_BGP_ENABLE_HEADER + \
- "" + CE_GET_BGP_ENABLE_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["bgp_rid_auto_sel"] = re_find
- if re_find[0] != bgp_rid_auto_sel:
- need_cfg = True
- else:
- need_cfg = True
-
- keep_all_routes = module.params['keep_all_routes']
- if keep_all_routes != 'no_use':
- conf_str = CE_GET_BGP_ENABLE_HEADER + \
- "" + CE_GET_BGP_ENABLE_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["keep_all_routes"] = re_find
- if re_find[0] != keep_all_routes:
- need_cfg = True
- else:
- need_cfg = True
-
- memory_limit = module.params['memory_limit']
- if memory_limit != 'no_use':
- conf_str = CE_GET_BGP_ENABLE_HEADER + \
- "" + CE_GET_BGP_ENABLE_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["memory_limit"] = re_find
- if re_find[0] != memory_limit:
- need_cfg = True
- else:
- need_cfg = True
-
- gr_peer_reset = module.params['gr_peer_reset']
- if gr_peer_reset != 'no_use':
- conf_str = CE_GET_BGP_ENABLE_HEADER + \
- "" + CE_GET_BGP_ENABLE_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["gr_peer_reset"] = re_find
- if re_find[0] != gr_peer_reset:
- need_cfg = True
- else:
- need_cfg = True
-
- is_shutdown = module.params['is_shutdown']
- if is_shutdown != 'no_use':
- conf_str = CE_GET_BGP_ENABLE_HEADER + \
- "" + CE_GET_BGP_ENABLE_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["is_shutdown"] = re_find
- if re_find[0] != is_shutdown:
- need_cfg = True
- else:
- need_cfg = True
-
- suppress_interval = module.params['suppress_interval']
- hold_interval = module.params['hold_interval']
- clear_interval = module.params['clear_interval']
- if suppress_interval:
-
- if not hold_interval or not clear_interval:
- module.fail_json(
- msg='Error: Please input suppress_interval hold_interval clear_interval at the same time.')
-
- if int(suppress_interval) > 65535 or int(suppress_interval) < 1:
- module.fail_json(
- msg='Error: The suppress_interval %s is out of [1 - 65535].' % suppress_interval)
- else:
- conf_str = CE_GET_BGP_ENABLE_HEADER + \
- "" + CE_GET_BGP_ENABLE_TAIL
- recv_xml = self.netconf_get_config(
- module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["suppress_interval"] = re_find
- if re_find[0] != suppress_interval:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["suppress_interval"] = re_find
- if re_find[0] == suppress_interval:
- need_cfg = True
-
- if hold_interval:
-
- if not suppress_interval or not clear_interval:
- module.fail_json(
- msg='Error: Please input suppress_interval hold_interval clear_interval at the same time.')
-
- if int(hold_interval) > 65535 or int(hold_interval) < 1:
- module.fail_json(
- msg='Error: The hold_interval %s is out of [1 - 65535].' % hold_interval)
- else:
- conf_str = CE_GET_BGP_ENABLE_HEADER + \
- "" + CE_GET_BGP_ENABLE_TAIL
- recv_xml = self.netconf_get_config(
- module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["hold_interval"] = re_find
- if re_find[0] != hold_interval:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["hold_interval"] = re_find
- if re_find[0] == hold_interval:
- need_cfg = True
-
- if clear_interval:
-
- if not suppress_interval or not hold_interval:
- module.fail_json(
- msg='Error: Please input suppress_interval hold_interval clear_interval at the same time.')
-
- if int(clear_interval) > 65535 or int(clear_interval) < 1:
- module.fail_json(
- msg='Error: The clear_interval %s is out of [1 - 65535].' % clear_interval)
- else:
- conf_str = CE_GET_BGP_ENABLE_HEADER + \
- "" + CE_GET_BGP_ENABLE_TAIL
- recv_xml = self.netconf_get_config(
- module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["clear_interval"] = re_find
- if re_find[0] != clear_interval:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["clear_interval"] = re_find
- if re_find[0] == clear_interval:
- need_cfg = True
-
- result["need_cfg"] = need_cfg
- return result
-
- def check_bgp_instance_args(self, **kwargs):
- """ check_bgp_instance_args """
-
- module = kwargs["module"]
- state = module.params['state']
- need_cfg = False
-
- vrf_name = module.params['vrf_name']
- if vrf_name:
- if len(vrf_name) > 31 or len(vrf_name) == 0:
- module.fail_json(
- msg='the len of vrf_name %s is out of [1 - 31].' % vrf_name)
- conf_str = CE_GET_BGP_INSTANCE_HEADER + \
- "" + CE_GET_BGP_INSTANCE_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- check_vrf_name = vrf_name
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- if check_vrf_name not in re_find:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- if check_vrf_name in re_find:
- need_cfg = True
-
- return need_cfg
-
- def check_bgp_instance_other_args(self, **kwargs):
- """ check_bgp_instance_other_args """
-
- module = kwargs["module"]
- state = module.params['state']
- result = dict()
- need_cfg = False
-
- vrf_name = module.params['vrf_name']
-
- router_id = module.params['router_id']
- if router_id:
-
- if not vrf_name:
- module.fail_json(
- msg='Error: Please input vrf_name.')
-
- if check_ip_addr(ipaddr=router_id) == FAILED:
- module.fail_json(
- msg='Error: The router_id %s is invalid.' % router_id)
-
- conf_str = CE_GET_BGP_INSTANCE_HEADER + "%s" % vrf_name + \
- "" + CE_GET_BGP_INSTANCE_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["router_id"] = re_find
- if re_find[0] != router_id:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["router_id"] = re_find
- if re_find[0] == router_id:
- need_cfg = True
-
- vrf_rid_auto_sel = module.params['vrf_rid_auto_sel']
- if vrf_rid_auto_sel != 'no_use':
-
- if not vrf_name:
- module.fail_json(
- msg='Error: Please input vrf_name.')
-
- conf_str = CE_GET_BGP_INSTANCE_HEADER + "%s" % vrf_name + \
- "" + CE_GET_BGP_INSTANCE_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["vrf_rid_auto_sel"] = re_find
-
- if re_find[0] != vrf_rid_auto_sel:
- need_cfg = True
- else:
- need_cfg = True
-
- keepalive_time = module.params['keepalive_time']
- if keepalive_time:
-
- if not vrf_name:
- module.fail_json(
- msg='Error: Please input vrf_name.')
-
- if int(keepalive_time) > 21845 or int(keepalive_time) < 0:
- module.fail_json(
- msg='keepalive_time %s is out of [0 - 21845].' % keepalive_time)
- else:
- conf_str = CE_GET_BGP_INSTANCE_HEADER + "%s" % vrf_name + \
- "" + CE_GET_BGP_INSTANCE_TAIL
- recv_xml = self.netconf_get_config(
- module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["keepalive_time"] = re_find
- if re_find[0] != keepalive_time:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["keepalive_time"] = re_find
- if re_find[0] == keepalive_time:
- need_cfg = True
-
- hold_time = module.params['hold_time']
- if hold_time:
-
- if not vrf_name:
- module.fail_json(
- msg='Error: Please input vrf_name.')
-
- if int(hold_time) > 65535 or int(hold_time) < 3:
- module.fail_json(
- msg='hold_time %s is out of [3 - 65535].' % hold_time)
- else:
- conf_str = CE_GET_BGP_INSTANCE_HEADER + "%s" % vrf_name + \
- "" + CE_GET_BGP_INSTANCE_TAIL
- recv_xml = self.netconf_get_config(
- module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["hold_time"] = re_find
- if re_find[0] != hold_time:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["hold_time"] = re_find
- if re_find[0] == hold_time:
- need_cfg = True
-
- min_hold_time = module.params['min_hold_time']
- if min_hold_time:
-
- if not vrf_name:
- module.fail_json(
- msg='Error: Please input vrf_name.')
-
- if int(min_hold_time) != 0 and (int(min_hold_time) > 65535 or int(min_hold_time) < 20):
- module.fail_json(
- msg='min_hold_time %s is out of [0, or 20 - 65535].' % min_hold_time)
- else:
- conf_str = CE_GET_BGP_INSTANCE_HEADER + "%s" % vrf_name + \
- "" + CE_GET_BGP_INSTANCE_TAIL
- recv_xml = self.netconf_get_config(
- module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["min_hold_time"] = re_find
- if re_find[0] != min_hold_time:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["min_hold_time"] = re_find
- if re_find[0] == min_hold_time:
- need_cfg = True
-
- conn_retry_time = module.params['conn_retry_time']
- if conn_retry_time:
-
- if not vrf_name:
- module.fail_json(
- msg='Error: Please input vrf_name.')
-
- if int(conn_retry_time) > 65535 or int(conn_retry_time) < 1:
- module.fail_json(
- msg='conn_retry_time %s is out of [1 - 65535].' % conn_retry_time)
- else:
- conf_str = CE_GET_BGP_INSTANCE_HEADER + "%s" % vrf_name + \
- "" + CE_GET_BGP_INSTANCE_TAIL
- recv_xml = self.netconf_get_config(
- module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["conn_retry_time"] = re_find
- if re_find[0] != conn_retry_time:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["conn_retry_time"] = re_find
- if re_find[0] == conn_retry_time:
- need_cfg = True
- else:
- pass
-
- ebgp_if_sensitive = module.params['ebgp_if_sensitive']
- if ebgp_if_sensitive != 'no_use':
-
- if not vrf_name:
- module.fail_json(
- msg='Error: Please input vrf_name.')
-
- conf_str = CE_GET_BGP_INSTANCE_HEADER + "%s" % vrf_name + \
- "" + CE_GET_BGP_INSTANCE_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["ebgp_if_sensitive"] = re_find
- if re_find[0] != ebgp_if_sensitive:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["ebgp_if_sensitive"] = re_find
- if re_find[0] == ebgp_if_sensitive:
- need_cfg = True
- else:
- pass
-
- default_af_type = module.params['default_af_type']
- if default_af_type:
-
- if not vrf_name:
- module.fail_json(
- msg='Error: Please input vrf_name.')
-
- conf_str = CE_GET_BGP_INSTANCE_HEADER + "%s" % vrf_name + \
- "" + CE_GET_BGP_INSTANCE_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["default_af_type"] = re_find
- if re_find[0] != default_af_type:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["default_af_type"] = re_find
- if re_find[0] == default_af_type:
- need_cfg = True
- else:
- pass
-
- result["need_cfg"] = need_cfg
- return result
-
- def get_bgp_enable(self, **kwargs):
- """ get_bgp_enable """
-
- module = kwargs["module"]
-
- conf_str = CE_GET_BGP_ENABLE
-
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(
- r'.*(.*).*\s*(.*).*', xml_str)
-
- if re_find:
- return re_find
- else:
- return result
-
- def merge_bgp_enable(self, **kwargs):
- """ merge_bgp_enable """
-
- module = kwargs["module"]
- conf_str = CE_MERGE_BGP_ENABLE_HEADER
-
- state = module.params['state']
-
- if state == "present":
- conf_str += "true"
- else:
- conf_str += "false"
-
- as_number = module.params['as_number']
- if as_number:
- conf_str += "%s" % as_number
-
- conf_str += CE_MERGE_BGP_ENABLE_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge bgp enable failed.')
-
- cmds = []
- if state == "present":
- cmd = "bgp %s" % as_number
- else:
- cmd = "undo bgp %s" % as_number
- cmds.append(cmd)
-
- return cmds
-
- def merge_bgp_enable_other(self, **kwargs):
- """ merge_bgp_enable_other """
-
- module = kwargs["module"]
- conf_str = CE_MERGE_BGP_ENABLE_HEADER
-
- cmds = []
-
- graceful_restart = module.params['graceful_restart']
- if graceful_restart != 'no_use':
- conf_str += "%s" % graceful_restart
-
- if graceful_restart == "true":
- cmd = "graceful-restart"
- else:
- cmd = "undo graceful-restart"
- cmds.append(cmd)
-
- time_wait_for_rib = module.params['time_wait_for_rib']
- if time_wait_for_rib:
- conf_str += "%s" % time_wait_for_rib
-
- cmd = "graceful-restart timer wait-for-rib %s" % time_wait_for_rib
- cmds.append(cmd)
-
- as_path_limit = module.params['as_path_limit']
- if as_path_limit:
- conf_str += "%s" % as_path_limit
-
- cmd = "as-path-limit %s" % as_path_limit
- cmds.append(cmd)
-
- check_first_as = module.params['check_first_as']
- if check_first_as != 'no_use':
- conf_str += "%s" % check_first_as
-
- if check_first_as == "true":
- cmd = "check-first-as"
- else:
- cmd = "undo check-first-as"
- cmds.append(cmd)
-
- confed_id_number = module.params['confed_id_number']
- if confed_id_number:
- conf_str += "%s" % confed_id_number
-
- cmd = "confederation id %s" % confed_id_number
- cmds.append(cmd)
-
- confed_nonstanded = module.params['confed_nonstanded']
- if confed_nonstanded != 'no_use':
- conf_str += "%s" % confed_nonstanded
-
- if confed_nonstanded == "true":
- cmd = "confederation nonstandard"
- else:
- cmd = "undo confederation nonstandard"
- cmds.append(cmd)
-
- bgp_rid_auto_sel = module.params['bgp_rid_auto_sel']
- if bgp_rid_auto_sel != 'no_use':
- conf_str += "%s" % bgp_rid_auto_sel
-
- if bgp_rid_auto_sel == "true":
- cmd = "router-id vpn-instance auto-select"
- else:
- cmd = "undo router-id"
- cmds.append(cmd)
-
- keep_all_routes = module.params['keep_all_routes']
- if keep_all_routes != 'no_use':
- conf_str += "%s" % keep_all_routes
-
- if keep_all_routes == "true":
- cmd = "keep-all-routes"
- else:
- cmd = "undo keep-all-routes"
- cmds.append(cmd)
-
- memory_limit = module.params['memory_limit']
- if memory_limit != 'no_use':
- conf_str += "%s" % memory_limit
-
- if memory_limit == "true":
- cmd = "prefix memory-limit"
- else:
- cmd = "undo prefix memory-limit"
- cmds.append(cmd)
-
- gr_peer_reset = module.params['gr_peer_reset']
- if gr_peer_reset != 'no_use':
- conf_str += "%s" % gr_peer_reset
-
- if gr_peer_reset == "true":
- cmd = "graceful-restart peer-reset"
- else:
- cmd = "undo graceful-restart peer-reset"
- cmds.append(cmd)
-
- is_shutdown = module.params['is_shutdown']
- if is_shutdown != 'no_use':
- conf_str += "%s" % is_shutdown
-
- if is_shutdown == "true":
- cmd = "shutdown"
- else:
- cmd = "undo shutdown"
- cmds.append(cmd)
-
- suppress_interval = module.params['suppress_interval']
- hold_interval = module.params['hold_interval']
- clear_interval = module.params['clear_interval']
- if suppress_interval:
- conf_str += "%s" % suppress_interval
-
- cmd = "nexthop recursive-lookup restrain suppress-interval %s hold-interval %s " \
- "clear-interval %s" % (suppress_interval, hold_interval, clear_interval)
- cmds.append(cmd)
-
- if hold_interval:
- conf_str += "%s" % hold_interval
-
- if clear_interval:
- conf_str += "%s" % clear_interval
-
- conf_str += CE_MERGE_BGP_ENABLE_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge bgp enable failed.')
-
- return cmds
-
- def delete_bgp_enable_other(self, **kwargs):
- """ delete bgp enable other args """
-
- module = kwargs["module"]
- conf_str = CE_MERGE_BGP_ENABLE_HEADER
-
- cmds = []
-
- graceful_restart = module.params['graceful_restart']
- if graceful_restart != 'no_use':
- conf_str += "%s" % graceful_restart
-
- if graceful_restart == "true":
- cmd = "graceful-restart"
- else:
- cmd = "undo graceful-restart"
- cmds.append(cmd)
-
- time_wait_for_rib = module.params['time_wait_for_rib']
- if time_wait_for_rib:
- conf_str += "600"
-
- cmd = "undo graceful-restart timer wait-for-rib"
- cmds.append(cmd)
-
- as_path_limit = module.params['as_path_limit']
- if as_path_limit:
- conf_str += "255"
-
- cmd = "undo as-path-limit"
- cmds.append(cmd)
-
- check_first_as = module.params['check_first_as']
- if check_first_as != 'no_use':
- conf_str += "%s" % check_first_as
-
- if check_first_as == "true":
- cmd = "check-first-as"
- else:
- cmd = "undo check-first-as"
- cmds.append(cmd)
-
- confed_id_number = module.params['confed_id_number']
- confed_peer_as_num = module.params['confed_peer_as_num']
- if confed_id_number and not confed_peer_as_num:
- conf_str += ""
-
- cmd = "undo confederation id"
- cmds.append(cmd)
-
- confed_nonstanded = module.params['confed_nonstanded']
- if confed_nonstanded != 'no_use':
- conf_str += "%s" % confed_nonstanded
-
- if confed_nonstanded == "true":
- cmd = "confederation nonstandard"
- else:
- cmd = "undo confederation nonstandard"
- cmds.append(cmd)
-
- bgp_rid_auto_sel = module.params['bgp_rid_auto_sel']
- if bgp_rid_auto_sel != 'no_use':
- conf_str += "%s" % bgp_rid_auto_sel
-
- if bgp_rid_auto_sel == "true":
- cmd = "router-id vpn-instance auto-select"
- else:
- cmd = "undo router-id"
- cmds.append(cmd)
-
- keep_all_routes = module.params['keep_all_routes']
- if keep_all_routes != 'no_use':
- conf_str += "%s" % keep_all_routes
-
- if keep_all_routes == "true":
- cmd = "keep-all-routes"
- else:
- cmd = "undo keep-all-routes"
- cmds.append(cmd)
-
- memory_limit = module.params['memory_limit']
- if memory_limit != 'no_use':
- conf_str += "%s" % memory_limit
-
- if memory_limit == "true":
- cmd = "prefix memory-limit"
- else:
- cmd = "undo prefix memory-limit"
- cmds.append(cmd)
-
- gr_peer_reset = module.params['gr_peer_reset']
- if gr_peer_reset != 'no_use':
- conf_str += "%s" % gr_peer_reset
-
- if gr_peer_reset == "true":
- cmd = "graceful-restart peer-reset"
- else:
- cmd = "undo graceful-restart peer-reset"
- cmds.append(cmd)
-
- is_shutdown = module.params['is_shutdown']
- if is_shutdown != 'no_use':
- conf_str += "%s" % is_shutdown
-
- if is_shutdown == "true":
- cmd = "shutdown"
- else:
- cmd = "undo shutdown"
- cmds.append(cmd)
-
- suppress_interval = module.params['suppress_interval']
- hold_interval = module.params['hold_interval']
- clear_interval = module.params['clear_interval']
- if suppress_interval:
- conf_str += "60"
-
- cmd = "undo nexthop recursive-lookup restrain suppress-interval hold-interval clear-interval"
- cmds.append(cmd)
-
- if hold_interval:
- conf_str += "120"
-
- if clear_interval:
- conf_str += "600"
-
- conf_str += CE_MERGE_BGP_ENABLE_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Delete bgp enable failed.')
-
- return cmds
-
- def get_bgp_confed_peer_as(self, **kwargs):
- """ get_bgp_confed_peer_as """
-
- module = kwargs["module"]
-
- conf_str = CE_GET_BGP_CONFED_PEER_AS
-
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(
- r'.*(.*).*', xml_str)
-
- if re_find:
- return re_find
- else:
- return result
-
- def merge_bgp_confed_peer_as(self, **kwargs):
- """ merge_bgp_confed_peer_as """
-
- module = kwargs["module"]
- confed_peer_as_num = module.params['confed_peer_as_num']
-
- conf_str = CE_MERGE_BGP_CONFED_PEER_AS % confed_peer_as_num
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge bgp confed peer as failed.')
-
- cmds = []
- cmd = "confederation peer-as %s" % confed_peer_as_num
- cmds.append(cmd)
-
- return cmds
-
- def create_bgp_confed_peer_as(self, **kwargs):
- """ create_bgp_confed_peer_as """
-
- module = kwargs["module"]
- confed_peer_as_num = module.params['confed_peer_as_num']
-
- conf_str = CE_CREATE_BGP_CONFED_PEER_AS % confed_peer_as_num
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Create bgp confed peer as failed.')
-
- cmds = []
- cmd = "confederation peer-as %s" % confed_peer_as_num
- cmds.append(cmd)
-
- return cmds
-
- def delete_bgp_confed_peer_as(self, **kwargs):
- """ delete_bgp_confed_peer_as """
-
- module = kwargs["module"]
- confed_peer_as_num = module.params['confed_peer_as_num']
-
- conf_str = CE_DELETE_BGP_CONFED_PEER_AS % confed_peer_as_num
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Delete bgp confed peer as failed.')
-
- cmds = []
- cmd = "undo confederation peer-as %s" % confed_peer_as_num
- cmds.append(cmd)
-
- return cmds
-
- def get_bgp_instance(self, **kwargs):
- """ get_bgp_instance """
-
- module = kwargs["module"]
- conf_str = CE_GET_BGP_INSTANCE
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(
- r'.*(.*).*', xml_str)
-
- if re_find:
- return re_find
- else:
- return result
-
- def merge_bgp_instance(self, **kwargs):
- """ merge_bgp_instance """
-
- module = kwargs["module"]
- conf_str = CE_MERGE_BGP_INSTANCE_HEADER
-
- vrf_name = module.params['vrf_name']
- conf_str += "%s" % vrf_name
-
- conf_str += CE_MERGE_BGP_INSTANCE_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge bgp instance failed.')
-
- cmds = []
-
- if vrf_name != "_public_":
- cmd = "ipv4-family vpn-instance %s" % vrf_name
- cmds.append(cmd)
-
- return cmds
-
- def create_bgp_instance(self, **kwargs):
- """ create_bgp_instance """
-
- module = kwargs["module"]
- conf_str = CE_CREATE_BGP_INSTANCE_HEADER
-
- cmds = []
-
- vrf_name = module.params['vrf_name']
- if vrf_name:
- if vrf_name == "_public_":
- return cmds
- conf_str += "%s" % vrf_name
-
- conf_str += CE_CREATE_BGP_INSTANCE_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Create bgp instance failed.')
-
- if vrf_name != "_public_":
- cmd = "ipv4-family vpn-instance %s" % vrf_name
- cmds.append(cmd)
-
- return cmds
-
- def delete_bgp_instance(self, **kwargs):
- """ delete_bgp_instance """
-
- module = kwargs["module"]
- conf_str = CE_DELETE_BGP_INSTANCE_HEADER
-
- vrf_name = module.params['vrf_name']
- if vrf_name:
- conf_str += "%s" % vrf_name
-
- conf_str += CE_DELETE_BGP_INSTANCE_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Delete bgp instance failed.')
-
- cmds = []
- if vrf_name != "_public_":
- cmd = "undo ipv4-family vpn-instance %s" % vrf_name
- cmds.append(cmd)
-
- return cmds
-
- def merge_bgp_instance_other(self, **kwargs):
- """ merge_bgp_instance_other """
-
- module = kwargs["module"]
- conf_str = CE_MERGE_BGP_INSTANCE_HEADER
-
- vrf_name = module.params['vrf_name']
- conf_str += "%s" % vrf_name
-
- cmds = []
-
- default_af_type = module.params['default_af_type']
- if default_af_type:
- conf_str += "%s" % default_af_type
-
- if vrf_name != "_public_":
- if default_af_type == "ipv6uni":
- cmd = "ipv6-family vpn-instance %s" % vrf_name
- cmds.append(cmd)
-
- vrf_rid_auto_sel = module.params['vrf_rid_auto_sel']
- if vrf_rid_auto_sel != 'no_use':
- conf_str += "%s" % vrf_rid_auto_sel
-
- if vrf_rid_auto_sel == "true":
- cmd = "router-id auto-select"
- else:
- cmd = "undo router-id auto-select"
- cmds.append(cmd)
-
- router_id = module.params['router_id']
- if router_id:
- conf_str += "%s" % router_id
-
- cmd = "router-id %s" % router_id
- cmds.append(cmd)
-
- keepalive_time = module.params['keepalive_time']
- if keepalive_time:
- conf_str += "%s" % keepalive_time
-
- cmd = "timer keepalive %s" % keepalive_time
- cmds.append(cmd)
-
- hold_time = module.params['hold_time']
- if hold_time:
- conf_str += "%s" % hold_time
-
- cmd = "timer hold %s" % hold_time
- cmds.append(cmd)
-
- min_hold_time = module.params['min_hold_time']
- if min_hold_time:
- conf_str += "%s" % min_hold_time
-
- cmd = "timer min-holdtime %s" % min_hold_time
- cmds.append(cmd)
-
- conn_retry_time = module.params['conn_retry_time']
- if conn_retry_time:
- conf_str += "%s" % conn_retry_time
-
- cmd = "timer connect-retry %s" % conn_retry_time
- cmds.append(cmd)
-
- ebgp_if_sensitive = module.params['ebgp_if_sensitive']
- if ebgp_if_sensitive != 'no_use':
- conf_str += "%s" % ebgp_if_sensitive
-
- if ebgp_if_sensitive == "true":
- cmd = "ebgp-interface-sensitive"
- else:
- cmd = "undo ebgp-interface-sensitive"
- cmds.append(cmd)
-
- conf_str += CE_MERGE_BGP_INSTANCE_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge bgp instance other failed.')
-
- return cmds
-
- def delete_bgp_instance_other_comm(self, **kwargs):
- """ delete_bgp_instance_other_comm """
-
- module = kwargs["module"]
- conf_str = CE_DELETE_BGP_INSTANCE_HEADER
-
- vrf_name = module.params['vrf_name']
- conf_str += "%s" % vrf_name
-
- cmds = []
-
- router_id = module.params['router_id']
- if router_id:
- conf_str += "%s" % router_id
-
- cmd = "undo router-id"
- cmds.append(cmd)
-
- vrf_rid_auto_sel = module.params['vrf_rid_auto_sel']
- if vrf_rid_auto_sel != 'no_use':
- conf_str += "%s" % vrf_rid_auto_sel
-
- cmd = "undo router-id vpn-instance auto-select"
- cmds.append(cmd)
-
- keepalive_time = module.params['keepalive_time']
- if keepalive_time:
- conf_str += "%s" % keepalive_time
-
- cmd = "undo timer keepalive"
- cmds.append(cmd)
-
- hold_time = module.params['hold_time']
- if hold_time:
- conf_str += "%s" % hold_time
-
- cmd = "undo timer hold"
- cmds.append(cmd)
-
- min_hold_time = module.params['min_hold_time']
- if min_hold_time:
- conf_str += "%s" % min_hold_time
-
- cmd = "undo timer min-holdtime"
- cmds.append(cmd)
-
- conn_retry_time = module.params['conn_retry_time']
- if conn_retry_time:
- conf_str += "%s" % conn_retry_time
-
- cmd = "undo timer connect-retry"
- cmds.append(cmd)
-
- ebgp_if_sensitive = module.params['ebgp_if_sensitive']
- if ebgp_if_sensitive != 'no_use':
- conf_str += "%s" % ebgp_if_sensitive
-
- cmd = "undo ebgp-interface-sensitive"
- cmds.append(cmd)
-
- default_af_type = module.params['default_af_type']
- if default_af_type:
- conf_str += "%s" % default_af_type
-
- if vrf_name != "_public_":
- if default_af_type == "ipv6uni":
- cmd = "undo ipv6-family vpn-instance %s" % vrf_name
- cmds.append(cmd)
- else:
- cmd = "undo ipv4-family vpn-instance %s" % vrf_name
- cmds.append(cmd)
- else:
- if vrf_name != "_public_":
- cmd = "undo ipv4-family vpn-instance %s" % vrf_name
- cmds.append(cmd)
-
- conf_str += CE_DELETE_BGP_INSTANCE_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Delete common vpn bgp instance other args failed.')
-
- return cmds
-
- def delete_instance_other_public(self, **kwargs):
- """ delete_instance_other_public """
-
- module = kwargs["module"]
- conf_str = CE_MERGE_BGP_INSTANCE_HEADER
-
- vrf_name = module.params['vrf_name']
- conf_str += "%s" % vrf_name
-
- cmds = []
-
- router_id = module.params['router_id']
- if router_id:
- conf_str += ""
-
- cmd = "undo router-id"
- cmds.append(cmd)
-
- vrf_rid_auto_sel = module.params['vrf_rid_auto_sel']
- if vrf_rid_auto_sel != 'no_use':
- conf_str += "%s" % "false"
-
- cmd = "undo router-id vpn-instance auto-select"
- cmds.append(cmd)
-
- keepalive_time = module.params['keepalive_time']
- if keepalive_time:
- conf_str += "%s" % "60"
-
- cmd = "undo timer keepalive"
- cmds.append(cmd)
-
- hold_time = module.params['hold_time']
- if hold_time:
- conf_str += "%s" % "180"
-
- cmd = "undo timer hold"
- cmds.append(cmd)
-
- min_hold_time = module.params['min_hold_time']
- if min_hold_time:
- conf_str += "%s" % "0"
-
- cmd = "undo timer min-holdtime"
- cmds.append(cmd)
-
- conn_retry_time = module.params['conn_retry_time']
- if conn_retry_time:
- conf_str += "%s" % "32"
-
- cmd = "undo timer connect-retry"
- cmds.append(cmd)
-
- ebgp_if_sensitive = module.params['ebgp_if_sensitive']
- if ebgp_if_sensitive != 'no_use':
- conf_str += "%s" % "true"
-
- cmd = "ebgp-interface-sensitive"
- cmds.append(cmd)
-
- default_af_type = module.params['default_af_type']
- if default_af_type:
- conf_str += "%s" % "ipv4uni"
-
- if vrf_name != "_public_":
- if default_af_type == "ipv6uni":
- cmd = "undo ipv6-family vpn-instance %s" % vrf_name
- cmds.append(cmd)
- else:
- cmd = "undo ipv4-family vpn-instance %s" % vrf_name
- cmds.append(cmd)
- else:
- if vrf_name != "_public_":
- cmd = "undo ipv4-family vpn-instance %s" % vrf_name
- cmds.append(cmd)
-
- conf_str += CE_MERGE_BGP_INSTANCE_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Delete default vpn bgp instance other args failed.')
-
- return cmds
-
-
-def main():
- """ main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- as_number=dict(type='str'),
- graceful_restart=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- time_wait_for_rib=dict(type='str'),
- as_path_limit=dict(type='str'),
- check_first_as=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- confed_id_number=dict(type='str'),
- confed_nonstanded=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- bgp_rid_auto_sel=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- keep_all_routes=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- memory_limit=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- gr_peer_reset=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- is_shutdown=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- suppress_interval=dict(type='str'),
- hold_interval=dict(type='str'),
- clear_interval=dict(type='str'),
- confed_peer_as_num=dict(type='str'),
- vrf_name=dict(type='str'),
- vrf_rid_auto_sel=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- router_id=dict(type='str'),
- keepalive_time=dict(type='str'),
- hold_time=dict(type='str'),
- min_hold_time=dict(type='str'),
- conn_retry_time=dict(type='str'),
- ebgp_if_sensitive=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- default_af_type=dict(type='str', choices=['ipv4uni', 'ipv6uni'])
- )
-
- argument_spec.update(ce_argument_spec)
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
-
- changed = False
- proposed = dict()
- existing = dict()
- end_state = dict()
- updates = []
-
- state = module.params['state']
- as_number = module.params['as_number']
- graceful_restart = module.params['graceful_restart']
- time_wait_for_rib = module.params['time_wait_for_rib']
- as_path_limit = module.params['as_path_limit']
- check_first_as = module.params['check_first_as']
- confed_id_number = module.params['confed_id_number']
- confed_nonstanded = module.params['confed_nonstanded']
- bgp_rid_auto_sel = module.params['bgp_rid_auto_sel']
- keep_all_routes = module.params['keep_all_routes']
- memory_limit = module.params['memory_limit']
- gr_peer_reset = module.params['gr_peer_reset']
- is_shutdown = module.params['is_shutdown']
- suppress_interval = module.params['suppress_interval']
- hold_interval = module.params['hold_interval']
- clear_interval = module.params['clear_interval']
- confed_peer_as_num = module.params['confed_peer_as_num']
- router_id = module.params['router_id']
- vrf_name = module.params['vrf_name']
- vrf_rid_auto_sel = module.params['vrf_rid_auto_sel']
- keepalive_time = module.params['keepalive_time']
- hold_time = module.params['hold_time']
- min_hold_time = module.params['min_hold_time']
- conn_retry_time = module.params['conn_retry_time']
- ebgp_if_sensitive = module.params['ebgp_if_sensitive']
- default_af_type = module.params['default_af_type']
-
- ce_bgp_obj = Bgp()
-
- if not ce_bgp_obj:
- module.fail_json(msg='Error: Init module failed.')
-
- # get proposed
- proposed["state"] = state
- if as_number:
- proposed["as_number"] = as_number
- if graceful_restart != 'no_use':
- proposed["graceful_restart"] = graceful_restart
- if time_wait_for_rib:
- proposed["time_wait_for_rib"] = time_wait_for_rib
- if as_path_limit:
- proposed["as_path_limit"] = as_path_limit
- if check_first_as != 'no_use':
- proposed["check_first_as"] = check_first_as
- if confed_id_number:
- proposed["confed_id_number"] = confed_id_number
- if confed_nonstanded != 'no_use':
- proposed["confed_nonstanded"] = confed_nonstanded
- if bgp_rid_auto_sel != 'no_use':
- proposed["bgp_rid_auto_sel"] = bgp_rid_auto_sel
- if keep_all_routes != 'no_use':
- proposed["keep_all_routes"] = keep_all_routes
- if memory_limit != 'no_use':
- proposed["memory_limit"] = memory_limit
- if gr_peer_reset != 'no_use':
- proposed["gr_peer_reset"] = gr_peer_reset
- if is_shutdown != 'no_use':
- proposed["is_shutdown"] = is_shutdown
- if suppress_interval:
- proposed["suppress_interval"] = suppress_interval
- if hold_interval:
- proposed["hold_interval"] = hold_interval
- if clear_interval:
- proposed["clear_interval"] = clear_interval
- if confed_peer_as_num:
- proposed["confed_peer_as_num"] = confed_peer_as_num
- if router_id:
- proposed["router_id"] = router_id
- if vrf_name:
- proposed["vrf_name"] = vrf_name
- if vrf_rid_auto_sel != 'no_use':
- proposed["vrf_rid_auto_sel"] = vrf_rid_auto_sel
- if keepalive_time:
- proposed["keepalive_time"] = keepalive_time
- if hold_time:
- proposed["hold_time"] = hold_time
- if min_hold_time:
- proposed["min_hold_time"] = min_hold_time
- if conn_retry_time:
- proposed["conn_retry_time"] = conn_retry_time
- if ebgp_if_sensitive != 'no_use':
- proposed["ebgp_if_sensitive"] = ebgp_if_sensitive
- if default_af_type:
- proposed["default_af_type"] = default_af_type
-
- need_bgp_enable = check_bgp_enable_args(module=module)
- need_bgp_enable_other_rst = ce_bgp_obj.check_bgp_enable_other_args(
- module=module)
- need_bgp_confed = check_bgp_confed_args(module=module)
- need_bgp_instance = ce_bgp_obj.check_bgp_instance_args(module=module)
- need_bgp_instance_other_rst = ce_bgp_obj.check_bgp_instance_other_args(
- module=module)
-
- router_id_exist = ce_bgp_obj.get_bgp_instance(module=module)
- existing["bgp instance"] = router_id_exist
-
- # bgp enable/disable
- if need_bgp_enable:
-
- bgp_enable_exist = ce_bgp_obj.get_bgp_enable(module=module)
- existing["bgp enable"] = bgp_enable_exist
- if bgp_enable_exist:
- asnumber_exist = bgp_enable_exist[0][1]
- bgpenable_exist = bgp_enable_exist[0][0]
- else:
- asnumber_exist = None
- bgpenable_exist = None
-
- if state == "present":
- bgp_enable_new = ("true", as_number)
-
- if bgp_enable_new in bgp_enable_exist:
- pass
- elif bgpenable_exist == "true" and asnumber_exist != as_number:
- module.fail_json(
- msg='Error: BGP is already running. The AS is %s.' % asnumber_exist)
- else:
- cmd = ce_bgp_obj.merge_bgp_enable(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- else:
- if need_bgp_enable_other_rst["need_cfg"] or need_bgp_confed or \
- need_bgp_instance_other_rst["need_cfg"] or need_bgp_instance:
- pass
- elif bgpenable_exist == "false":
- pass
- elif bgpenable_exist == "true" and asnumber_exist == as_number:
- cmd = ce_bgp_obj.merge_bgp_enable(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- else:
- module.fail_json(
- msg='Error: BGP is already running. The AS is %s.' % asnumber_exist)
-
- bgp_enable_end = ce_bgp_obj.get_bgp_enable(module=module)
- end_state["bgp enable"] = bgp_enable_end
-
- # bgp enable/disable other args
- exist_tmp = dict()
- for item in need_bgp_enable_other_rst:
- if item != "need_cfg":
- exist_tmp[item] = need_bgp_enable_other_rst[item]
-
- if exist_tmp:
- existing["bgp enable other"] = exist_tmp
-
- if need_bgp_enable_other_rst["need_cfg"]:
- if state == "present":
- cmd = ce_bgp_obj.merge_bgp_enable_other(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
- else:
- cmd = ce_bgp_obj.delete_bgp_enable_other(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- need_bgp_enable_other_rst = ce_bgp_obj.check_bgp_enable_other_args(
- module=module)
-
- end_tmp = dict()
- for item in need_bgp_enable_other_rst:
- if item != "need_cfg":
- end_tmp[item] = need_bgp_enable_other_rst[item]
-
- if end_tmp:
- end_state["bgp enable other"] = end_tmp
-
- # bgp confederation peer as
- if need_bgp_confed:
- confed_exist = ce_bgp_obj.get_bgp_confed_peer_as(module=module)
- existing["confederation peer as"] = confed_exist
- confed_new = (confed_peer_as_num)
-
- if state == "present":
- if len(confed_exist) == 0:
- cmd = ce_bgp_obj.create_bgp_confed_peer_as(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- elif confed_new not in confed_exist:
- cmd = ce_bgp_obj.merge_bgp_confed_peer_as(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- else:
- if len(confed_exist) == 0:
- pass
-
- elif confed_new not in confed_exist:
- pass
-
- else:
- cmd = ce_bgp_obj.delete_bgp_confed_peer_as(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- confed_end = ce_bgp_obj.get_bgp_confed_peer_as(module=module)
- end_state["confederation peer as"] = confed_end
-
- # bgp instance
- if need_bgp_instance and default_af_type != "ipv6uni":
- router_id_new = vrf_name
-
- if state == "present":
- if len(router_id_exist) == 0:
- cmd = ce_bgp_obj.create_bgp_instance(module=module)
- changed = True
- updates.extend(cmd)
- elif router_id_new not in router_id_exist:
- cmd = ce_bgp_obj.merge_bgp_instance(module=module)
- changed = True
- updates.extend(cmd)
- else:
- if not need_bgp_instance_other_rst["need_cfg"]:
- if vrf_name != "_public_":
- if len(router_id_exist) == 0:
- pass
- elif router_id_new not in router_id_exist:
- pass
- else:
- cmd = ce_bgp_obj.delete_bgp_instance(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- # bgp instance other
- exist_tmp = dict()
- for item in need_bgp_instance_other_rst:
- if item != "need_cfg":
- exist_tmp[item] = need_bgp_instance_other_rst[item]
-
- if exist_tmp:
- existing["bgp instance other"] = exist_tmp
-
- if need_bgp_instance_other_rst["need_cfg"]:
- if state == "present":
- cmd = ce_bgp_obj.merge_bgp_instance_other(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- else:
- if vrf_name == "_public_":
- cmd = ce_bgp_obj.delete_instance_other_public(
- module=module)
- changed = True
- for item in cmd:
- updates.append(item)
- else:
- cmd = ce_bgp_obj.delete_bgp_instance_other_comm(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- need_bgp_instance_other_rst = ce_bgp_obj.check_bgp_instance_other_args(
- module=module)
-
- router_id_end = ce_bgp_obj.get_bgp_instance(module=module)
- end_state["bgp instance"] = router_id_end
-
- end_tmp = dict()
- for item in need_bgp_instance_other_rst:
- if item != "need_cfg":
- end_tmp[item] = need_bgp_instance_other_rst[item]
-
- if end_tmp:
- end_state["bgp instance other"] = end_tmp
- if end_state == existing:
- changed = False
- updates = list()
- results = dict()
- results['proposed'] = proposed
- results['existing'] = existing
- results['changed'] = changed
- results['end_state'] = end_state
- results['updates'] = updates
-
- module.exit_json(**results)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_bgp_af.py b/plugins/modules/network/cloudengine/ce_bgp_af.py
deleted file mode 100644
index 089b3b3231..0000000000
--- a/plugins/modules/network/cloudengine/ce_bgp_af.py
+++ /dev/null
@@ -1,3434 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_bgp_af
-short_description: Manages BGP Address-family configuration on HUAWEI CloudEngine switches.
-description:
- - Manages BGP Address-family configurations on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- state:
- description:
- - Specify desired state of the resource.
- default: present
- choices: ['present','absent']
- vrf_name:
- description:
- - Name of a BGP instance. The name is a case-sensitive string of characters.
- The BGP instance can be used only after the corresponding VPN instance is created.
- The value is a string of 1 to 31 case-sensitive characters.
- required: true
- af_type:
- description:
- - Address family type of a BGP instance.
- required: true
- choices: ['ipv4uni','ipv4multi', 'ipv4vpn', 'ipv6uni', 'ipv6vpn', 'evpn']
- max_load_ibgp_num:
- description:
- - Specify the maximum number of equal-cost IBGP routes.
- The value is an integer ranging from 1 to 65535.
- ibgp_ecmp_nexthop_changed:
- description:
- - If the value is true, the next hop of an advertised route is changed to the advertiser itself in IBGP
- load-balancing scenarios.
- If the value is false, the next hop of an advertised route is not changed to the advertiser itself in
- IBGP load-balancing scenarios.
- choices: ['no_use','true','false']
- default: no_use
- max_load_ebgp_num:
- description:
- - Specify the maximum number of equal-cost EBGP routes.
- The value is an integer ranging from 1 to 65535.
- ebgp_ecmp_nexthop_changed:
- description:
- - If the value is true, the next hop of an advertised route is changed to the advertiser itself in EBGP
- load-balancing scenarios.
- If the value is false, the next hop of an advertised route is not changed to the advertiser itself in
- EBGP load-balancing scenarios.
- choices: ['no_use','true','false']
- default: no_use
- maximum_load_balance:
- description:
- - Specify the maximum number of equal-cost routes in the BGP routing table.
- The value is an integer ranging from 1 to 65535.
- ecmp_nexthop_changed:
- description:
- - If the value is true, the next hop of an advertised route is changed to the advertiser itself in BGP
- load-balancing scenarios.
- If the value is false, the next hop of an advertised route is not changed to the advertiser itself
- in BGP load-balancing scenarios.
- choices: ['no_use','true','false']
- default: no_use
- default_local_pref:
- description:
- - Set the Local-Preference attribute. The value is an integer.
- The value is an integer ranging from 0 to 4294967295.
- default_med:
- description:
- - Specify the Multi-Exit-Discriminator (MED) of BGP routes.
- The value is an integer ranging from 0 to 4294967295.
- default_rt_import_enable:
- description:
- - If the value is true, importing default routes to the BGP routing table is allowed.
- If the value is false, importing default routes to the BGP routing table is not allowed.
- choices: ['no_use','true','false']
- default: no_use
- router_id:
- description:
- - ID of a router that is in IPv4 address format.
- The value is a string of 0 to 255 characters.
- The value is in dotted decimal notation.
- vrf_rid_auto_sel:
- description:
- - If the value is true, VPN BGP instances are enabled to automatically select router IDs.
- If the value is false, VPN BGP instances are disabled from automatically selecting router IDs.
- choices: ['no_use','true','false']
- default: no_use
- nexthop_third_party:
- description:
- - If the value is true, the third-party next hop function is enabled.
- If the value is false, the third-party next hop function is disabled.
- choices: ['no_use','true','false']
- default: no_use
- summary_automatic:
- description:
- - If the value is true, automatic aggregation is enabled for locally imported routes.
- If the value is false, automatic aggregation is disabled for locally imported routes.
- choices: ['no_use','true','false']
- default: no_use
- auto_frr_enable:
- description:
- - If the value is true, BGP auto FRR is enabled.
- If the value is false, BGP auto FRR is disabled.
- choices: ['no_use','true','false']
- default: no_use
- load_balancing_as_path_ignore:
- description:
- - Load balancing as path ignore.
- choices: ['no_use','true','false']
- default: no_use
- rib_only_enable:
- description:
- - If the value is true, BGP routes cannot be advertised to the IP routing table.
- If the value is false, Routes preferred by BGP are advertised to the IP routing table.
- choices: ['no_use','true','false']
- default: no_use
- rib_only_policy_name:
- description:
- - Specify the name of a routing policy.
- The value is a string of 1 to 40 characters.
- active_route_advertise:
- description:
- - If the value is true, BGP is enabled to advertise only optimal routes in the RM to peers.
- If the value is false, BGP is not enabled to advertise only optimal routes in the RM to peers.
- choices: ['no_use','true','false']
- default: no_use
- as_path_neglect:
- description:
- - If the value is true, the AS path attribute is ignored when BGP selects an optimal route.
- If the value is false, the AS path attribute is not ignored when BGP selects an optimal route.
- An AS path with a smaller length has a higher priority.
- choices: ['no_use','true','false']
- default: no_use
- med_none_as_maximum:
- description:
- - If the value is true, when BGP selects an optimal route, the system uses 4294967295 as the
- MED value of a route if the route's attribute does not carry a MED value.
- If the value is false, the system uses 0 as the MED value of a route if the route's attribute
- does not carry a MED value.
- choices: ['no_use','true','false']
- default: no_use
- router_id_neglect:
- description:
- - If the value is true, the router ID attribute is ignored when BGP selects the optimal route.
- If the value is false, the router ID attribute is not ignored when BGP selects the optimal route.
- choices: ['no_use','true','false']
- default: no_use
- igp_metric_ignore:
- description:
- - If the value is true, the metrics of next-hop IGP routes are not compared when BGP selects
- an optimal route.
- If the value is false, the metrics of next-hop IGP routes are not compared when BGP selects
- an optimal route.
- A route with a smaller metric has a higher priority.
- choices: ['no_use','true','false']
- default: no_use
- always_compare_med:
- description:
- - If the value is true, the MEDs of routes learned from peers in different autonomous systems
- are compared when BGP selects an optimal route.
- If the value is false, the MEDs of routes learned from peers in different autonomous systems
- are not compared when BGP selects an optimal route.
- choices: ['no_use','true','false']
- default: no_use
- determin_med:
- description:
- - If the value is true, BGP deterministic-MED is enabled.
- If the value is false, BGP deterministic-MED is disabled.
- choices: ['no_use','true','false']
- default: no_use
- preference_external:
- description:
- - Set the protocol priority of EBGP routes.
- The value is an integer ranging from 1 to 255.
- preference_internal:
- description:
- - Set the protocol priority of IBGP routes.
- The value is an integer ranging from 1 to 255.
- preference_local:
- description:
- - Set the protocol priority of a local BGP route.
- The value is an integer ranging from 1 to 255.
- prefrence_policy_name:
- description:
- - Set a routing policy to filter routes so that a configured priority is applied to
- the routes that match the specified policy.
- The value is a string of 1 to 40 characters.
- reflect_between_client:
- description:
- - If the value is true, route reflection is enabled between clients.
- If the value is false, route reflection is disabled between clients.
- choices: ['no_use','true','false']
- default: no_use
- reflector_cluster_id:
- description:
- - Set a cluster ID. Configuring multiple RRs in a cluster can enhance the stability of the network.
- The value is an integer ranging from 1 to 4294967295.
- reflector_cluster_ipv4:
- description:
- - Set a cluster ipv4 address. The value is expressed in the format of an IPv4 address.
- rr_filter_number:
- description:
- - Set the number of the extended community filter supported by an RR group.
- The value is a string of 1 to 51 characters.
- policy_vpn_target:
- description:
- - If the value is true, VPN-Target filtering function is performed for received VPN routes.
- If the value is false, VPN-Target filtering function is not performed for received VPN routes.
- choices: ['no_use','true','false']
- default: no_use
- next_hop_sel_depend_type:
- description:
- - Next hop select depend type.
- choices: ['default','dependTunnel', 'dependIp']
- default: default
- nhp_relay_route_policy_name:
- description:
- - Specify the name of a route-policy for route iteration.
- The value is a string of 1 to 40 characters.
- ebgp_if_sensitive:
- description:
- - If the value is true, after the fast EBGP interface awareness function is enabled,
- EBGP sessions on an interface are deleted immediately when the interface goes Down.
- If the value is false, after the fast EBGP interface awareness function is enabled,
- EBGP sessions on an interface are not deleted immediately when the interface goes Down.
- choices: ['no_use','true','false']
- default: no_use
- reflect_chg_path:
- description:
- - If the value is true, the route reflector is enabled to modify route path attributes
- based on an export policy.
- If the value is false, the route reflector is disabled from modifying route path attributes
- based on an export policy.
- choices: ['no_use','true','false']
- default: no_use
- add_path_sel_num:
- description:
- - Number of Add-Path routes.
- The value is an integer ranging from 2 to 64.
- route_sel_delay:
- description:
- - Route selection delay.
- The value is an integer ranging from 0 to 3600.
- allow_invalid_as:
- description:
- - Allow routes with BGP origin AS validation result Invalid to be selected.
- If the value is true, invalid routes can participate in route selection.
- If the value is false, invalid routes cannot participate in route selection.
- choices: ['no_use','true','false']
- default: no_use
- policy_ext_comm_enable:
- description:
- - If the value is true, modifying extended community attributes is allowed.
- If the value is false, modifying extended community attributes is not allowed.
- choices: ['no_use','true','false']
- default: no_use
- supernet_uni_adv:
- description:
- - If the value is true, the function to advertise supernetwork unicast routes is enabled.
- If the value is false, the function to advertise supernetwork unicast routes is disabled.
- choices: ['no_use','true','false']
- default: no_use
- supernet_label_adv:
- description:
- - If the value is true, the function to advertise supernetwork label is enabled.
- If the value is false, the function to advertise supernetwork label is disabled.
- choices: ['no_use','true','false']
- default: no_use
- ingress_lsp_policy_name:
- description:
- - Ingress lsp policy name.
- originator_prior:
- description:
- - Originator prior.
- choices: ['no_use','true','false']
- default: no_use
- lowest_priority:
- description:
- - If the value is true, enable reduce priority to advertise route.
- If the value is false, disable reduce priority to advertise route.
- choices: ['no_use','true','false']
- default: no_use
- relay_delay_enable:
- description:
- - If the value is true, relay delay enable.
- If the value is false, relay delay disable.
- choices: ['no_use','true','false']
- default: no_use
- import_protocol:
- description:
- - Routing protocol from which routes can be imported.
- choices: ['direct', 'ospf', 'isis', 'static', 'rip', 'ospfv3', 'ripng']
- import_process_id:
- description:
- - Process ID of an imported routing protocol.
- The value is an integer ranging from 0 to 4294967295.
- network_address:
- description:
- - Specify the IP address advertised by BGP.
- The value is a string of 0 to 255 characters.
- mask_len:
- description:
- - Specify the mask length of an IP address.
- The value is an integer ranging from 0 to 128.
-'''
-
-EXAMPLES = '''
-- name: CloudEngine BGP address family test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
- tasks:
- - name: "Config BGP Address_Family"
- ce_bgp_af:
- state: present
- vrf_name: js
- af_type: ipv4uni
- provider: "{{ cli }}"
- - name: "Undo BGP Address_Family"
- ce_bgp_af:
- state: absent
- vrf_name: js
- af_type: ipv4uni
- provider: "{{ cli }}"
- - name: "Config import route"
- ce_bgp_af:
- state: present
- vrf_name: js
- af_type: ipv4uni
- import_protocol: ospf
- import_process_id: 123
- provider: "{{ cli }}"
- - name: "Undo import route"
- ce_bgp_af:
- state: absent
- vrf_name: js
- af_type: ipv4uni
- import_protocol: ospf
- import_process_id: 123
- provider: "{{ cli }}"
- - name: "Config network route"
- ce_bgp_af:
- state: present
- vrf_name: js
- af_type: ipv4uni
- network_address: 1.1.1.1
- mask_len: 24
- provider: "{{ cli }}"
- - name: "Undo network route"
- ce_bgp_af:
- state: absent
- vrf_name: js
- af_type: ipv4uni
- network_address: 1.1.1.1
- mask_len: 24
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"af_type": "ipv4uni",
- "state": "present", "vrf_name": "js"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"af_type": "ipv4uni", "vrf_name": "js"}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["ipv4-family vpn-instance js"]
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec, check_ip_addr
-
-# get bgp address family
-CE_GET_BGP_ADDRESS_FAMILY_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-"""
-CE_GET_BGP_ADDRESS_FAMILY_TAIL = """
-
-
-
-
-
-
-
-"""
-
-# merge bgp address family
-CE_MERGE_BGP_ADDRESS_FAMILY_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-"""
-CE_MERGE_BGP_ADDRESS_FAMILY_TAIL = """
-
-
-
-
-
-
-
-"""
-
-# create bgp address family
-CE_CREATE_BGP_ADDRESS_FAMILY_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-"""
-CE_CREATE_BGP_ADDRESS_FAMILY_TAIL = """
-
-
-
-
-
-
-
-"""
-
-# delete bgp address family
-CE_DELETE_BGP_ADDRESS_FAMILY_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-"""
-CE_DELETE_BGP_ADDRESS_FAMILY_TAIL = """
-
-
-
-
-
-
-
-"""
-
-# get bgp import route
-CE_GET_BGP_IMPORT_AND_NETWORK_ROUTE = """
-
-
-
-
-
- %s
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-# merge bgp import route
-CE_MERGE_BGP_IMPORT_ROUTE_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-
-
- %s
- %s
-"""
-CE_MERGE_BGP_IMPORT_ROUTE_TAIL = """
-
-
-
-
-
-
-
-
-
-"""
-
-# create bgp import route
-CE_CREATE_BGP_IMPORT_ROUTE = """
-
-
-
-
-
- %s
-
-
- %s
-
-
- %s
- %s
-
-
-
-
-
-
-
-
-
-"""
-
-# delete bgp import route
-CE_DELETE_BGP_IMPORT_ROUTE = """
-
-
-
-
-
- %s
-
-
- %s
-
-
- %s
- %s
-
-
-
-
-
-
-
-
-
-"""
-
-# get bgp network route
-CE_GET_BGP_NETWORK_ROUTE_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-
-
-
-
-"""
-CE_GET_BGP_NETWORK_ROUTE_TAIL = """
-
-
-
-
-
-
-
-
-
-"""
-
-# merge bgp network route
-CE_MERGE_BGP_NETWORK_ROUTE_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-
-
- %s
- %s
-"""
-CE_MERGE_BGP_NETWORK_ROUTE_TAIL = """
-
-
-
-
-
-
-
-
-
-"""
-
-# create bgp network route
-CE_CREATE_BGP_NETWORK_ROUTE = """
-
-
-
-
-
- %s
-
-
- %s
-
-
- %s
- %s
-
-
-
-
-
-
-
-
-
-"""
-
-# delete bgp network route
-CE_DELETE_BGP_NETWORK_ROUTE = """
-
-
-
-
-
- %s
-
-
- %s
-
-
- %s
- %s
-
-
-
-
-
-
-
-
-
-"""
-
-# bgp import and network route header
-CE_BGP_IMPORT_NETWORK_ROUTE_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-"""
-CE_BGP_IMPORT_NETWORK_ROUTE_TAIL = """
-
-
-
-
-
-
-
-"""
-CE_BGP_MERGE_IMPORT_UNIT = """
-
-
- %s
- %s
-
-
-"""
-CE_BGP_CREATE_IMPORT_UNIT = """
-
-
- %s
- %s
-
-
-"""
-CE_BGP_DELETE_IMPORT_UNIT = """
-
-
- %s
- %s
-
-
-"""
-CE_BGP_MERGE_NETWORK_UNIT = """
-
-
- %s
- %s
-
-
-"""
-CE_BGP_CREATE_NETWORK_UNIT = """
-
-
- %s
- %s
-
-
-"""
-CE_BGP_DELETE_NETWORK_UNIT = """
-
-
- %s
- %s
-
-
-"""
-
-
-class BgpAf(object):
- """ Manages BGP Address-family configuration """
-
- def netconf_get_config(self, **kwargs):
- """ netconf_get_config """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- xml_str = get_nc_config(module, conf_str)
-
- return xml_str
-
- def netconf_set_config(self, **kwargs):
- """ netconf_set_config """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- xml_str = set_nc_config(module, conf_str)
-
- return xml_str
-
- def check_bgp_af_args(self, **kwargs):
- """ check_bgp_af_args """
-
- module = kwargs["module"]
- result = dict()
- need_cfg = False
-
- vrf_name = module.params['vrf_name']
- af_type = module.params['af_type']
- if vrf_name:
- if len(vrf_name) > 31 or len(vrf_name) == 0:
- module.fail_json(
- msg='Error: The len of vrf_name %s is out of [1 - 31].' % vrf_name)
- else:
- module.fail_json(msg='Error: Please input vrf_name.')
-
- state = module.params['state']
- af_type = module.params['af_type']
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["af_type"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != af_type:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["af_type"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] == af_type:
- need_cfg = True
-
- result["need_cfg"] = need_cfg
- return result
-
- def check_bgp_af_other_can_del(self, **kwargs):
- """ check_bgp_af_other_can_del """
- module = kwargs["module"]
- result = dict()
- need_cfg = False
-
- state = module.params['state']
- vrf_name = module.params['vrf_name']
- af_type = module.params['af_type']
-
- router_id = module.params['router_id']
- if router_id:
- if len(router_id) > 255:
- module.fail_json(
- msg='Error: The len of router_id %s is out of [0 - 255].' % router_id)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- if re_find[0] != router_id:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- if re_find[0] == router_id:
- need_cfg = True
- else:
- pass
-
- determin_med = module.params['determin_med']
- if determin_med != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- if re_find[0] != determin_med:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- if re_find[0] == determin_med:
- need_cfg = True
- else:
- pass
-
- ebgp_if_sensitive = module.params['ebgp_if_sensitive']
- if ebgp_if_sensitive != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- if re_find[0] != ebgp_if_sensitive:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- if re_find[0] == ebgp_if_sensitive:
- need_cfg = True
- else:
- pass
-
- relay_delay_enable = module.params['relay_delay_enable']
- if relay_delay_enable != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- if re_find[0] != relay_delay_enable:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- if re_find[0] == relay_delay_enable:
- need_cfg = True
- else:
- pass
-
- result["need_cfg"] = need_cfg
- return result
-
- def check_bgp_af_other_args(self, **kwargs):
- """ check_bgp_af_other_args """
-
- module = kwargs["module"]
- result = dict()
- need_cfg = False
-
- vrf_name = module.params['vrf_name']
- af_type = module.params['af_type']
-
- max_load_ibgp_num = module.params['max_load_ibgp_num']
- if max_load_ibgp_num:
- if int(max_load_ibgp_num) > 65535 or int(max_load_ibgp_num) < 1:
- module.fail_json(
- msg='Error: The value of max_load_ibgp_num %s is out of [1 - 65535].' % max_load_ibgp_num)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["max_load_ibgp_num"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != max_load_ibgp_num:
- need_cfg = True
- else:
- need_cfg = True
-
- ibgp_ecmp_nexthop_changed = module.params['ibgp_ecmp_nexthop_changed']
- if ibgp_ecmp_nexthop_changed != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["ibgp_ecmp_nexthop_changed"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != ibgp_ecmp_nexthop_changed:
- need_cfg = True
- else:
- need_cfg = True
-
- max_load_ebgp_num = module.params['max_load_ebgp_num']
- if max_load_ebgp_num:
- if int(max_load_ebgp_num) > 65535 or int(max_load_ebgp_num) < 1:
- module.fail_json(
- msg='Error: The value of max_load_ebgp_num %s is out of [1 - 65535].' % max_load_ebgp_num)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["max_load_ebgp_num"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != max_load_ebgp_num:
- need_cfg = True
- else:
- need_cfg = True
-
- ebgp_ecmp_nexthop_changed = module.params['ebgp_ecmp_nexthop_changed']
- if ebgp_ecmp_nexthop_changed != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["ebgp_ecmp_nexthop_changed"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != ebgp_ecmp_nexthop_changed:
- need_cfg = True
- else:
- need_cfg = True
-
- maximum_load_balance = module.params['maximum_load_balance']
- if maximum_load_balance:
- if int(maximum_load_balance) > 65535 or int(maximum_load_balance) < 1:
- module.fail_json(
- msg='Error: The value of maximum_load_balance %s is out of [1 - 65535].' % maximum_load_balance)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["maximum_load_balance"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != maximum_load_balance:
- need_cfg = True
- else:
- need_cfg = True
-
- ecmp_nexthop_changed = module.params['ecmp_nexthop_changed']
- if ecmp_nexthop_changed != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["ecmp_nexthop_changed"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != ecmp_nexthop_changed:
- need_cfg = True
- else:
- need_cfg = True
-
- default_local_pref = module.params['default_local_pref']
- if default_local_pref:
- if int(default_local_pref) < 0:
- module.fail_json(
- msg='Error: The value of default_local_pref %s is out of [0 - 4294967295].' % default_local_pref)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["default_local_pref"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != default_local_pref:
- need_cfg = True
- else:
- need_cfg = True
-
- default_med = module.params['default_med']
- if default_med:
- if int(default_med) < 0:
- module.fail_json(
- msg='Error: The value of default_med %s is out of [0 - 4294967295].' % default_med)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["default_med"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != default_med:
- need_cfg = True
- else:
- need_cfg = True
-
- default_rt_import_enable = module.params['default_rt_import_enable']
- if default_rt_import_enable != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["default_rt_import_enable"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != default_rt_import_enable:
- need_cfg = True
- else:
- need_cfg = True
-
- router_id = module.params['router_id']
- if router_id:
- if len(router_id) > 255:
- module.fail_json(
- msg='Error: The len of router_id %s is out of [0 - 255].' % router_id)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["router_id"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != router_id:
- need_cfg = True
- else:
- need_cfg = True
-
- vrf_rid_auto_sel = module.params['vrf_rid_auto_sel']
- if vrf_rid_auto_sel != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["vrf_rid_auto_sel"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != vrf_rid_auto_sel:
- need_cfg = True
- else:
- need_cfg = True
-
- nexthop_third_party = module.params['nexthop_third_party']
- if nexthop_third_party != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["nexthop_third_party"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != nexthop_third_party:
- need_cfg = True
- else:
- need_cfg = True
-
- summary_automatic = module.params['summary_automatic']
- if summary_automatic != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["summary_automatic"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != summary_automatic:
- need_cfg = True
- else:
- need_cfg = True
-
- auto_frr_enable = module.params['auto_frr_enable']
- if auto_frr_enable != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["auto_frr_enable"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != auto_frr_enable:
- need_cfg = True
- else:
- need_cfg = True
-
- load_balancing_as_path_ignore = module.params['load_balancing_as_path_ignore']
- if load_balancing_as_path_ignore != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + \
- CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["load_balancing_as_path_ignore"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != load_balancing_as_path_ignore:
- need_cfg = True
- else:
- need_cfg = True
-
- rib_only_enable = module.params['rib_only_enable']
- if rib_only_enable != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["rib_only_enable"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != rib_only_enable:
- need_cfg = True
- else:
- need_cfg = True
-
- rib_only_policy_name = module.params['rib_only_policy_name']
- if rib_only_policy_name:
- if len(rib_only_policy_name) > 40 or len(rib_only_policy_name) < 1:
- module.fail_json(
- msg='Error: The len of rib_only_policy_name %s is out of [1 - 40].' % rib_only_policy_name)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["rib_only_policy_name"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != rib_only_policy_name:
- need_cfg = True
- else:
- need_cfg = True
-
- active_route_advertise = module.params['active_route_advertise']
- if active_route_advertise != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["active_route_advertise"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != active_route_advertise:
- need_cfg = True
- else:
- need_cfg = True
-
- as_path_neglect = module.params['as_path_neglect']
- if as_path_neglect != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["as_path_neglect"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != as_path_neglect:
- need_cfg = True
- else:
- need_cfg = True
-
- med_none_as_maximum = module.params['med_none_as_maximum']
- if med_none_as_maximum != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["med_none_as_maximum"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != med_none_as_maximum:
- need_cfg = True
- else:
- need_cfg = True
-
- router_id_neglect = module.params['router_id_neglect']
- if router_id_neglect != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["router_id_neglect"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != router_id_neglect:
- need_cfg = True
- else:
- need_cfg = True
-
- igp_metric_ignore = module.params['igp_metric_ignore']
- if igp_metric_ignore != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["igp_metric_ignore"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != igp_metric_ignore:
- need_cfg = True
- else:
- need_cfg = True
-
- always_compare_med = module.params['always_compare_med']
- if always_compare_med != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["always_compare_med"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != always_compare_med:
- need_cfg = True
- else:
- need_cfg = True
-
- determin_med = module.params['determin_med']
- if determin_med != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["determin_med"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != determin_med:
- need_cfg = True
- else:
- need_cfg = True
-
- preference_external = module.params['preference_external']
- if preference_external:
- if int(preference_external) > 255 or int(preference_external) < 1:
- module.fail_json(
- msg='Error: The value of preference_external %s is out of [1 - 255].' % preference_external)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["preference_external"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != preference_external:
- need_cfg = True
- else:
- need_cfg = True
-
- preference_internal = module.params['preference_internal']
- if preference_internal:
- if int(preference_internal) > 255 or int(preference_internal) < 1:
- module.fail_json(
- msg='Error: The value of preference_internal %s is out of [1 - 255].' % preference_internal)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["preference_internal"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != preference_internal:
- need_cfg = True
- else:
- need_cfg = True
-
- preference_local = module.params['preference_local']
- if preference_local:
- if int(preference_local) > 255 or int(preference_local) < 1:
- module.fail_json(
- msg='Error: The value of preference_local %s is out of [1 - 255].' % preference_local)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["preference_local"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != preference_local:
- need_cfg = True
- else:
- need_cfg = True
-
- prefrence_policy_name = module.params['prefrence_policy_name']
- if prefrence_policy_name:
- if len(prefrence_policy_name) > 40 or len(prefrence_policy_name) < 1:
- module.fail_json(
- msg='Error: The len of prefrence_policy_name %s is out of [1 - 40].' % prefrence_policy_name)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["prefrence_policy_name"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != prefrence_policy_name:
- need_cfg = True
- else:
- need_cfg = True
-
- reflect_between_client = module.params['reflect_between_client']
- if reflect_between_client != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["reflect_between_client"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != reflect_between_client:
- need_cfg = True
- else:
- need_cfg = True
-
- reflector_cluster_id = module.params['reflector_cluster_id']
- if reflector_cluster_id:
- if int(reflector_cluster_id) < 0:
- module.fail_json(
- msg='Error: The value of reflector_cluster_id %s is out of '
- '[1 - 4294967295].' % reflector_cluster_id)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["reflector_cluster_id"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != reflector_cluster_id:
- need_cfg = True
- else:
- need_cfg = True
-
- reflector_cluster_ipv4 = module.params['reflector_cluster_ipv4']
- if reflector_cluster_ipv4:
- if len(reflector_cluster_ipv4) > 255:
- module.fail_json(
- msg='Error: The len of reflector_cluster_ipv4 %s is out of [0 - 255].' % reflector_cluster_ipv4)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["reflector_cluster_ipv4"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != reflector_cluster_ipv4:
- need_cfg = True
- else:
- need_cfg = True
-
- rr_filter_number = module.params['rr_filter_number']
- if rr_filter_number:
- if len(rr_filter_number) > 51 or len(rr_filter_number) < 1:
- module.fail_json(
- msg='Error: The len of rr_filter_number %s is out of [1 - 51].' % rr_filter_number)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["rr_filter_number"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != rr_filter_number:
- need_cfg = True
- else:
- need_cfg = True
-
- policy_vpn_target = module.params['policy_vpn_target']
- if policy_vpn_target != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["policy_vpn_target"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != policy_vpn_target:
- need_cfg = True
- else:
- need_cfg = True
-
- next_hop_sel_depend_type = module.params['next_hop_sel_depend_type']
- if next_hop_sel_depend_type:
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["next_hop_sel_depend_type"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != next_hop_sel_depend_type:
- need_cfg = True
- else:
- need_cfg = True
-
- nhp_relay_route_policy_name = module.params[
- 'nhp_relay_route_policy_name']
- if nhp_relay_route_policy_name:
- if len(nhp_relay_route_policy_name) > 40 or len(nhp_relay_route_policy_name) < 1:
- module.fail_json(
- msg='Error: The len of nhp_relay_route_policy_name %s is '
- 'out of [1 - 40].' % nhp_relay_route_policy_name)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + \
- CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["nhp_relay_route_policy_name"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != nhp_relay_route_policy_name:
- need_cfg = True
- else:
- need_cfg = True
-
- ebgp_if_sensitive = module.params['ebgp_if_sensitive']
- if ebgp_if_sensitive != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["ebgp_if_sensitive"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != ebgp_if_sensitive:
- need_cfg = True
- else:
- need_cfg = True
-
- reflect_chg_path = module.params['reflect_chg_path']
- if reflect_chg_path != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["reflect_chg_path"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != reflect_chg_path:
- need_cfg = True
- else:
- need_cfg = True
-
- add_path_sel_num = module.params['add_path_sel_num']
- if add_path_sel_num:
- if int(add_path_sel_num) > 64 or int(add_path_sel_num) < 2:
- module.fail_json(
- msg='Error: The value of add_path_sel_num %s is out of [2 - 64].' % add_path_sel_num)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["add_path_sel_num"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != add_path_sel_num:
- need_cfg = True
- else:
- need_cfg = True
-
- route_sel_delay = module.params['route_sel_delay']
- if route_sel_delay:
- if int(route_sel_delay) > 3600 or int(route_sel_delay) < 0:
- module.fail_json(
- msg='Error: The value of route_sel_delay %s is out of [0 - 3600].' % route_sel_delay)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["route_sel_delay"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != route_sel_delay:
- need_cfg = True
- else:
- need_cfg = True
-
- allow_invalid_as = module.params['allow_invalid_as']
- if allow_invalid_as != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["allow_invalid_as"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != allow_invalid_as:
- need_cfg = True
- else:
- need_cfg = True
-
- policy_ext_comm_enable = module.params['policy_ext_comm_enable']
- if policy_ext_comm_enable != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["policy_ext_comm_enable"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != policy_ext_comm_enable:
- need_cfg = True
- else:
- need_cfg = True
-
- supernet_uni_adv = module.params['supernet_uni_adv']
- if supernet_uni_adv != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["supernet_uni_adv"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != supernet_uni_adv:
- need_cfg = True
- else:
- need_cfg = True
-
- supernet_label_adv = module.params['supernet_label_adv']
- if supernet_label_adv != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["supernet_label_adv"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != supernet_label_adv:
- need_cfg = True
- else:
- need_cfg = True
-
- ingress_lsp_policy_name = module.params['ingress_lsp_policy_name']
- if ingress_lsp_policy_name:
- if len(ingress_lsp_policy_name) > 40 or len(ingress_lsp_policy_name) < 1:
- module.fail_json(
- msg='Error: The len of ingress_lsp_policy_name %s is out of [1 - 40].' % ingress_lsp_policy_name)
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["ingress_lsp_policy_name"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != ingress_lsp_policy_name:
- need_cfg = True
- else:
- need_cfg = True
-
- originator_prior = module.params['originator_prior']
- if originator_prior != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["originator_prior"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != originator_prior:
- need_cfg = True
- else:
- need_cfg = True
-
- lowest_priority = module.params['lowest_priority']
- if lowest_priority != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["lowest_priority"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != lowest_priority:
- need_cfg = True
- else:
- need_cfg = True
-
- relay_delay_enable = module.params['relay_delay_enable']
- if relay_delay_enable != 'no_use':
-
- conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
- "" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["relay_delay_enable"] = re_find
- result["vrf_name"] = vrf_name
- if re_find[0] != relay_delay_enable:
- need_cfg = True
- else:
- need_cfg = True
-
- result["need_cfg"] = need_cfg
- return result
-
- def check_bgp_import_network_route(self, **kwargs):
- """ check_bgp_import_network_route """
-
- module = kwargs["module"]
- result = dict()
- import_need_cfg = False
- network_need_cfg = False
-
- vrf_name = module.params['vrf_name']
-
- state = module.params['state']
- af_type = module.params['af_type']
- import_protocol = module.params['import_protocol']
- import_process_id = module.params['import_process_id']
-
- if import_protocol and (import_protocol != "direct" and import_protocol != "static"):
- if not import_process_id:
- module.fail_json(
- msg='Error: Please input import_protocol and import_process_id value at the same time.')
- else:
- if int(import_process_id) < 0:
- module.fail_json(
- msg='Error: The value of import_process_id %s is out of [0 - 4294967295].' % import_process_id)
-
- if import_process_id:
- if not import_protocol:
- module.fail_json(
- msg='Error: Please input import_protocol and import_process_id value at the same time.')
-
- network_address = module.params['network_address']
- mask_len = module.params['mask_len']
-
- if network_address:
- if not mask_len:
- module.fail_json(
- msg='Error: Please input network_address and mask_len value at the same time.')
- if mask_len:
- if not network_address:
- module.fail_json(
- msg='Error: Please input network_address and mask_len value at the same time.')
-
- conf_str = CE_GET_BGP_IMPORT_AND_NETWORK_ROUTE % (vrf_name, af_type)
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if import_protocol:
-
- if import_protocol == "direct" or import_protocol == "static":
- import_process_id = "0"
- else:
- if not import_process_id or import_process_id == "0":
- module.fail_json(
- msg='Error: Please input import_process_id not 0 when import_protocol is '
- '[ospf, isis, rip, ospfv3, ripng].')
-
- bgp_import_route_new = (import_protocol, import_process_id)
-
- if state == "present":
- if "" in recv_xml:
- import_need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*\s.*(.*).*',
- recv_xml)
-
- if re_find:
- result["bgp_import_route"] = re_find
- result["vrf_name"] = vrf_name
- if bgp_import_route_new not in re_find:
- import_need_cfg = True
- else:
- import_need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*\s.*(.*).*',
- recv_xml)
-
- if re_find:
- result["bgp_import_route"] = re_find
- result["vrf_name"] = vrf_name
- if bgp_import_route_new in re_find:
- import_need_cfg = True
-
- if network_address and mask_len:
-
- bgp_network_route_new = (network_address, mask_len)
-
- if not check_ip_addr(ipaddr=network_address):
- module.fail_json(
- msg='Error: The network_address %s is invalid.' % network_address)
-
- if len(mask_len) > 128:
- module.fail_json(
- msg='Error: The len of mask_len %s is out of [0 - 128].' % mask_len)
-
- if state == "present":
- if "" in recv_xml:
- network_need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*\s.*(.*).*', recv_xml)
-
- if re_find:
- result["bgp_network_route"] = re_find
- result["vrf_name"] = vrf_name
- if bgp_network_route_new not in re_find:
- network_need_cfg = True
- else:
- network_need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*\s.*(.*).*', recv_xml)
-
- if re_find:
- result["bgp_network_route"] = re_find
- result["vrf_name"] = vrf_name
- if bgp_network_route_new in re_find:
- network_need_cfg = True
-
- result["import_need_cfg"] = import_need_cfg
- result["network_need_cfg"] = network_need_cfg
- return result
-
- def merge_bgp_af(self, **kwargs):
- """ merge_bgp_af """
-
- module = kwargs["module"]
-
- vrf_name = module.params['vrf_name']
-
- af_type = module.params['af_type']
-
- conf_str = CE_MERGE_BGP_ADDRESS_FAMILY_HEADER % (
- vrf_name, af_type) + CE_MERGE_BGP_ADDRESS_FAMILY_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge bgp address family failed.')
-
- cmds = []
-
- cmd = "ipv4-family vpn-instance %s" % vrf_name
-
- if af_type == "ipv4multi":
- cmd = "ipv4-family multicast"
- elif af_type == "ipv4vpn":
- cmd = "ipv4-family vpnv4"
- elif af_type == "ipv6uni":
- cmd = "ipv6-family vpn-instance %s" % vrf_name
- if vrf_name == "_public_":
- cmd = "ipv6-family unicast"
- elif af_type == "ipv6vpn":
- cmd = "ipv6-family vpnv6"
- elif af_type == "evpn":
- cmd = "l2vpn-family evpn"
- cmds.append(cmd)
-
- return cmds
-
- def create_bgp_af(self, **kwargs):
- """ create_bgp_af """
-
- module = kwargs["module"]
-
- vrf_name = module.params['vrf_name']
-
- af_type = module.params['af_type']
-
- conf_str = CE_CREATE_BGP_ADDRESS_FAMILY_HEADER % (
- vrf_name, af_type) + CE_CREATE_BGP_ADDRESS_FAMILY_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Create bgp address family failed.')
-
- cmds = []
-
- cmd = "ipv4-family vpn-instance %s" % vrf_name
-
- if af_type == "ipv4multi":
- cmd = "ipv4-family multicast"
- elif af_type == "ipv4vpn":
- cmd = "ipv4-family vpnv4"
- elif af_type == "ipv6uni":
- cmd = "ipv6-family vpn-instance %s" % vrf_name
- if vrf_name == "_public_":
- cmd = "ipv6-family unicast"
- elif af_type == "ipv6vpn":
- cmd = "ipv6-family vpnv6"
- elif af_type == "evpn":
- cmd = "l2vpn-family evpn"
- cmds.append(cmd)
-
- return cmds
-
- def delete_bgp_af(self, **kwargs):
- """ delete_bgp_af """
-
- module = kwargs["module"]
-
- vrf_name = module.params['vrf_name']
-
- af_type = module.params['af_type']
-
- conf_str = CE_DELETE_BGP_ADDRESS_FAMILY_HEADER % (
- vrf_name, af_type) + CE_DELETE_BGP_ADDRESS_FAMILY_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Delete bgp address family failed.')
-
- cmds = []
-
- cmd = "undo ipv4-family vpn-instance %s" % vrf_name
-
- if af_type == "ipv4multi":
- cmd = "undo ipv4-family multicast"
- elif af_type == "ipv4vpn":
- cmd = "undo ipv4-family vpnv4"
- elif af_type == "ipv6uni":
- cmd = "undo ipv6-family vpn-instance %s" % vrf_name
- if vrf_name == "_public_":
- cmd = "undo ipv6-family unicast"
- elif af_type == "ipv6vpn":
- cmd = "undo ipv6-family vpnv6"
- elif af_type == "evpn":
- cmd = "l2vpn-family evpn"
- cmds.append(cmd)
-
- return cmds
-
- def merge_bgp_af_other(self, **kwargs):
- """ merge_bgp_af_other """
-
- module = kwargs["module"]
- vrf_name = module.params['vrf_name']
- af_type = module.params['af_type']
-
- conf_str = CE_MERGE_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type)
-
- cmds = []
-
- max_load_ibgp_num = module.params['max_load_ibgp_num']
- if max_load_ibgp_num:
- conf_str += "%s" % max_load_ibgp_num
-
- cmd = "maximum load-balancing ibgp %s" % max_load_ibgp_num
- cmds.append(cmd)
-
- ibgp_ecmp_nexthop_changed = module.params['ibgp_ecmp_nexthop_changed']
- if ibgp_ecmp_nexthop_changed != 'no_use':
- conf_str += "%s" % ibgp_ecmp_nexthop_changed
-
- if ibgp_ecmp_nexthop_changed == "true":
- cmd = "maximum load-balancing ibgp %s ecmp-nexthop-changed" % max_load_ibgp_num
- cmds.append(cmd)
- else:
- cmd = "undo maximum load-balancing ibgp %s ecmp-nexthop-changed" % max_load_ibgp_num
- cmds.append(cmd)
- max_load_ebgp_num = module.params['max_load_ebgp_num']
- if max_load_ebgp_num:
- conf_str += "%s" % max_load_ebgp_num
-
- cmd = "maximum load-balancing ebgp %s" % max_load_ebgp_num
- cmds.append(cmd)
-
- ebgp_ecmp_nexthop_changed = module.params['ebgp_ecmp_nexthop_changed']
- if ebgp_ecmp_nexthop_changed != 'no_use':
- conf_str += "%s" % ebgp_ecmp_nexthop_changed
-
- if ebgp_ecmp_nexthop_changed == "true":
- cmd = "maximum load-balancing ebgp %s ecmp-nexthop-changed" % max_load_ebgp_num
- else:
- cmd = "undo maximum load-balancing ebgp %s ecmp-nexthop-changed" % max_load_ebgp_num
- cmds.append(cmd)
-
- maximum_load_balance = module.params['maximum_load_balance']
- if maximum_load_balance:
- conf_str += "%s" % maximum_load_balance
-
- cmd = "maximum load-balancing %s" % maximum_load_balance
- cmds.append(cmd)
-
- ecmp_nexthop_changed = module.params['ecmp_nexthop_changed']
- if ecmp_nexthop_changed != 'no_use':
- conf_str += "%s" % ecmp_nexthop_changed
-
- if ecmp_nexthop_changed == "true":
- cmd = "maximum load-balancing %s ecmp-nexthop-changed" % maximum_load_balance
- else:
- cmd = "undo maximum load-balancing %s ecmp-nexthop-changed" % maximum_load_balance
- cmds.append(cmd)
-
- default_local_pref = module.params['default_local_pref']
- if default_local_pref:
- conf_str += "%s" % default_local_pref
-
- cmd = "default local-preference %s" % default_local_pref
- cmds.append(cmd)
-
- default_med = module.params['default_med']
- if default_med:
- conf_str += "%s" % default_med
-
- cmd = "default med %s" % default_med
- cmds.append(cmd)
-
- default_rt_import_enable = module.params['default_rt_import_enable']
- if default_rt_import_enable != 'no_use':
- conf_str += "%s" % default_rt_import_enable
-
- if default_rt_import_enable == "true":
- cmd = "default-route imported"
- else:
- cmd = "undo default-route imported"
- cmds.append(cmd)
-
- router_id = module.params['router_id']
- if router_id:
- conf_str += "%s" % router_id
-
- cmd = "router-id %s" % router_id
- cmds.append(cmd)
-
- vrf_rid_auto_sel = module.params['vrf_rid_auto_sel']
- if vrf_rid_auto_sel != 'no_use':
- conf_str += "%s" % vrf_rid_auto_sel
- family = "ipv4-family"
- if af_type == "ipv6uni":
- family = "ipv6-family"
- if vrf_rid_auto_sel == "true":
- cmd = "%s vpn-instance %s" % (family, vrf_name)
- cmds.append(cmd)
- cmd = "router-id auto-select"
- cmds.append(cmd)
- else:
- cmd = "%s vpn-instance %s" % (family, vrf_name)
- cmds.append(cmd)
- cmd = "undo router-id auto-select"
- cmds.append(cmd)
-
- nexthop_third_party = module.params['nexthop_third_party']
- if nexthop_third_party != 'no_use':
- conf_str += "%s" % nexthop_third_party
-
- if nexthop_third_party == "true":
- cmd = "nexthop third-party"
- else:
- cmd = "undo nexthop third-party"
- cmds.append(cmd)
-
- summary_automatic = module.params['summary_automatic']
- if summary_automatic != 'no_use':
- conf_str += "%s" % summary_automatic
-
- if summary_automatic == "true":
- cmd = "summary automatic"
- else:
- cmd = "undo summary automatic"
- cmds.append(cmd)
-
- auto_frr_enable = module.params['auto_frr_enable']
- if auto_frr_enable != 'no_use':
- conf_str += "%s" % auto_frr_enable
-
- if auto_frr_enable == "true":
- cmd = "auto-frr"
- else:
- cmd = "undo auto-frr"
- cmds.append(cmd)
-
- load_balancing_as_path_ignore = module.params[
- 'load_balancing_as_path_ignore']
- if load_balancing_as_path_ignore != 'no_use':
- conf_str += "%s" % load_balancing_as_path_ignore
-
- if load_balancing_as_path_ignore == "true":
- cmd = "load-balancing as-path-ignore"
- else:
- cmd = "undo load-balancing as-path-ignore"
- cmds.append(cmd)
-
- rib_only_enable = module.params['rib_only_enable']
- if rib_only_enable != 'no_use':
- conf_str += "%s" % rib_only_enable
-
- if rib_only_enable == "true":
- cmd = "routing-table rib-only"
- else:
- cmd = "undo routing-table rib-only"
- cmds.append(cmd)
-
- rib_only_policy_name = module.params['rib_only_policy_name']
- if rib_only_policy_name and rib_only_enable == "true":
- conf_str += "%s" % rib_only_policy_name
-
- cmd = "routing-table rib-only route-policy %s" % rib_only_policy_name
- cmds.append(cmd)
-
- active_route_advertise = module.params['active_route_advertise']
- if active_route_advertise != 'no_use':
- conf_str += "%s" % active_route_advertise
-
- if active_route_advertise == "true":
- cmd = "active-route-advertise"
- else:
- cmd = "undo active-route-advertise"
- cmds.append(cmd)
-
- as_path_neglect = module.params['as_path_neglect']
- if as_path_neglect != 'no_use':
- conf_str += "%s" % as_path_neglect
-
- if as_path_neglect == "true":
- cmd = "bestroute as-path-ignore"
- else:
- cmd = "undo bestroute as-path-ignore"
- cmds.append(cmd)
-
- med_none_as_maximum = module.params['med_none_as_maximum']
- if med_none_as_maximum != 'no_use':
- conf_str += "%s" % med_none_as_maximum
-
- if med_none_as_maximum == "true":
- cmd = "bestroute med-none-as-maximum"
- else:
- cmd = "undo bestroute med-none-as-maximum"
- cmds.append(cmd)
-
- router_id_neglect = module.params['router_id_neglect']
- if router_id_neglect != 'no_use':
- conf_str += "%s" % router_id_neglect
-
- if router_id_neglect == "true":
- cmd = "bestroute router-id-ignore"
- else:
- cmd = "undo bestroute router-id-ignore"
- cmds.append(cmd)
-
- igp_metric_ignore = module.params['igp_metric_ignore']
- if igp_metric_ignore != 'no_use':
- conf_str += "%s" % igp_metric_ignore
-
- if igp_metric_ignore == "true":
- cmd = "bestroute igp-metric-ignore"
- cmds.append(cmd)
- else:
- cmd = "undo bestroute igp-metric-ignore"
- cmds.append(cmd)
- always_compare_med = module.params['always_compare_med']
- if always_compare_med != 'no_use':
- conf_str += "%s" % always_compare_med
-
- if always_compare_med == "true":
- cmd = "compare-different-as-med"
- cmds.append(cmd)
- else:
- cmd = "undo compare-different-as-med"
- cmds.append(cmd)
- determin_med = module.params['determin_med']
- if determin_med != 'no_use':
- conf_str += "%s" % determin_med
-
- if determin_med == "true":
- cmd = "deterministic-med"
- cmds.append(cmd)
- else:
- cmd = "undo deterministic-med"
- cmds.append(cmd)
-
- preference_external = module.params['preference_external']
- preference_internal = module.params['preference_internal']
- preference_local = module.params['preference_local']
- if any([preference_external, preference_internal, preference_local]):
- preference_external = preference_external or "255"
- preference_internal = preference_internal or "255"
- preference_local = preference_local or "255"
-
- conf_str += "%s" % preference_external
- conf_str += "%s" % preference_internal
- conf_str += "%s" % preference_local
-
- cmd = "preference %s %s %s" % (
- preference_external, preference_internal, preference_local)
- cmds.append(cmd)
-
- prefrence_policy_name = module.params['prefrence_policy_name']
- if prefrence_policy_name:
- conf_str += "%s" % prefrence_policy_name
-
- cmd = "preference route-policy %s" % prefrence_policy_name
- cmds.append(cmd)
-
- reflect_between_client = module.params['reflect_between_client']
- if reflect_between_client != 'no_use':
- conf_str += "%s" % reflect_between_client
-
- if reflect_between_client == "true":
- cmd = "reflect between-clients"
- else:
- cmd = "undo reflect between-clients"
- cmds.append(cmd)
-
- reflector_cluster_id = module.params['reflector_cluster_id']
- if reflector_cluster_id:
- conf_str += "%s" % reflector_cluster_id
-
- cmd = "reflector cluster-id %s" % reflector_cluster_id
- cmds.append(cmd)
-
- reflector_cluster_ipv4 = module.params['reflector_cluster_ipv4']
- if reflector_cluster_ipv4:
- conf_str += "%s" % reflector_cluster_ipv4
-
- cmd = "reflector cluster-id %s" % reflector_cluster_ipv4
- cmds.append(cmd)
-
- rr_filter_number = module.params['rr_filter_number']
- if rr_filter_number:
- conf_str += "%s" % rr_filter_number
- cmd = 'rr-filter %s' % rr_filter_number
- cmds.append(cmd)
-
- policy_vpn_target = module.params['policy_vpn_target']
- if policy_vpn_target != 'no_use':
- conf_str += "%s" % policy_vpn_target
- if policy_vpn_target == 'true':
- cmd = 'policy vpn-target'
- else:
- cmd = 'undo policy vpn-target'
- cmds.append(cmd)
-
- next_hop_sel_depend_type = module.params['next_hop_sel_depend_type']
- if next_hop_sel_depend_type:
- conf_str += "%s" % next_hop_sel_depend_type
-
- nhp_relay_route_policy_name = module.params[
- 'nhp_relay_route_policy_name']
- if nhp_relay_route_policy_name:
- conf_str += "%s" % nhp_relay_route_policy_name
-
- cmd = "nexthop recursive-lookup route-policy %s" % nhp_relay_route_policy_name
- cmds.append(cmd)
-
- ebgp_if_sensitive = module.params['ebgp_if_sensitive']
- if ebgp_if_sensitive != 'no_use':
- conf_str += "%s" % ebgp_if_sensitive
-
- if ebgp_if_sensitive == "true":
- cmd = "ebgp-interface-sensitive"
- else:
- cmd = "undo ebgp-interface-sensitive"
- cmds.append(cmd)
-
- reflect_chg_path = module.params['reflect_chg_path']
- if reflect_chg_path != 'no_use':
- conf_str += "%s" % reflect_chg_path
-
- if reflect_chg_path == "true":
- cmd = "reflect change-path-attribute"
- else:
- cmd = "undo reflect change-path-attribute"
- cmds.append(cmd)
-
- add_path_sel_num = module.params['add_path_sel_num']
- if add_path_sel_num:
- conf_str += "%s" % add_path_sel_num
-
- cmd = "bestroute add-path path-number %s" % add_path_sel_num
- cmds.append(cmd)
-
- route_sel_delay = module.params['route_sel_delay']
- if route_sel_delay:
- conf_str += "%s" % route_sel_delay
-
- cmd = "route-select delay %s" % route_sel_delay
- cmds.append(cmd)
-
- allow_invalid_as = module.params['allow_invalid_as']
- if allow_invalid_as != 'no_use':
- conf_str += "%s" % allow_invalid_as
-
- policy_ext_comm_enable = module.params['policy_ext_comm_enable']
- if policy_ext_comm_enable != 'no_use':
- conf_str += "%s" % policy_ext_comm_enable
-
- if policy_ext_comm_enable == "true":
- cmd = "ext-community-change enable"
- else:
- cmd = "undo ext-community-change enable"
- cmds.append(cmd)
-
- supernet_uni_adv = module.params['supernet_uni_adv']
- if supernet_uni_adv != 'no_use':
- conf_str += "%s" % supernet_uni_adv
-
- if supernet_uni_adv == "true":
- cmd = "supernet unicast advertise enable"
- else:
- cmd = "undo supernet unicast advertise enable"
- cmds.append(cmd)
-
- supernet_label_adv = module.params['supernet_label_adv']
- if supernet_label_adv != 'no_use':
- conf_str += "%s" % supernet_label_adv
-
- if supernet_label_adv == "true":
- cmd = "supernet label-route advertise enable"
- else:
- cmd = "undo supernet label-route advertise enable"
- cmds.append(cmd)
-
- ingress_lsp_policy_name = module.params['ingress_lsp_policy_name']
- if ingress_lsp_policy_name:
- conf_str += "%s" % ingress_lsp_policy_name
- cmd = "ingress-lsp trigger route-policy %s" % ingress_lsp_policy_name
- cmds.append(cmd)
-
- originator_prior = module.params['originator_prior']
- if originator_prior != 'no_use':
- conf_str += "%s" % originator_prior
- if originator_prior == "true":
- cmd = "bestroute routerid-prior-clusterlist"
- else:
- cmd = "undo bestroute routerid-prior-clusterlist"
- cmds.append(cmd)
-
- lowest_priority = module.params['lowest_priority']
- if lowest_priority != 'no_use':
- conf_str += "%s" % lowest_priority
-
- if lowest_priority == "true":
- cmd = "advertise lowest-priority on-startup"
- else:
- cmd = "undo advertise lowest-priority on-startup"
- cmds.append(cmd)
-
- relay_delay_enable = module.params['relay_delay_enable']
- if relay_delay_enable != 'no_use':
- conf_str += "%s" % relay_delay_enable
-
- if relay_delay_enable == "true":
- cmd = "nexthop recursive-lookup restrain enable"
- else:
- cmd = "nexthop recursive-lookup restrain disable"
- cmds.append(cmd)
- conf_str += CE_MERGE_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Merge bgp address family other agrus failed.')
-
- return cmds
-
- def delete_bgp_af_other(self, **kwargs):
- """ delete_bgp_af_other """
-
- module = kwargs["module"]
- vrf_name = module.params['vrf_name']
- af_type = module.params['af_type']
-
- conf_str = CE_MERGE_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type)
-
- cmds = []
-
- router_id = module.params['router_id']
- if router_id:
- conf_str += ""
-
- cmd = "undo router-id %s" % router_id
- cmds.append(cmd)
-
- determin_med = module.params['determin_med']
- if determin_med != 'no_use':
- conf_str += ""
-
- cmd = "undo deterministic-med"
- cmds.append(cmd)
-
- ebgp_if_sensitive = module.params['ebgp_if_sensitive']
- if ebgp_if_sensitive != 'no_use':
- conf_str += ""
-
- cmd = "undo ebgp-interface-sensitive"
- cmds.append(cmd)
-
- relay_delay_enable = module.params['relay_delay_enable']
- if relay_delay_enable != 'no_use':
- conf_str += ""
-
- conf_str += CE_MERGE_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Merge bgp address family other agrus failed.')
-
- return cmds
-
- def merge_bgp_import_route(self, **kwargs):
- """ merge_bgp_import_route """
-
- module = kwargs["module"]
-
- vrf_name = module.params['vrf_name']
-
- af_type = module.params['af_type']
- import_protocol = module.params['import_protocol']
- import_process_id = module.params['import_process_id']
-
- if import_protocol == "direct" or import_protocol == "static":
- import_process_id = "0"
-
- conf_str = CE_MERGE_BGP_IMPORT_ROUTE_HEADER % (
- vrf_name, af_type, import_protocol, import_process_id) + CE_MERGE_BGP_IMPORT_ROUTE_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge bgp import route failed.')
-
- cmds = []
- cmd = "import-route %s %s" % (import_protocol, import_process_id)
- if import_protocol == "direct" or import_protocol == "static":
- cmd = "import-route %s" % import_protocol
- cmds.append(cmd)
-
- return cmds
-
- def create_bgp_import_route(self, **kwargs):
- """ create_bgp_import_route """
-
- module = kwargs["module"]
-
- vrf_name = module.params['vrf_name']
-
- af_type = module.params['af_type']
- import_protocol = module.params['import_protocol']
- import_process_id = module.params['import_process_id']
-
- if import_protocol == "direct" or import_protocol == "static":
- import_process_id = "0"
-
- conf_str = CE_CREATE_BGP_IMPORT_ROUTE % (
- vrf_name, af_type, import_protocol, import_process_id)
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Create bgp import route failed.')
-
- cmds = []
- cmd = "import-route %s %s" % (import_protocol, import_process_id)
- if import_protocol == "direct" or import_protocol == "static":
- cmd = "import-route %s" % import_protocol
- cmds.append(cmd)
-
- return cmds
-
- def delete_bgp_import_route(self, **kwargs):
- """ delete_bgp_import_route """
-
- module = kwargs["module"]
-
- vrf_name = module.params['vrf_name']
-
- af_type = module.params['af_type']
- import_protocol = module.params['import_protocol']
- import_process_id = module.params['import_process_id']
-
- if import_protocol == "direct" or import_protocol == "static":
- import_process_id = "0"
-
- conf_str = CE_DELETE_BGP_IMPORT_ROUTE % (
- vrf_name, af_type, import_protocol, import_process_id)
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Delete bgp import route failed.')
-
- cmds = []
- cmd = "undo import-route %s %s" % (import_protocol, import_process_id)
- if import_protocol == "direct" or import_protocol == "static":
- cmd = "undo import-route %s" % import_protocol
- cmds.append(cmd)
-
- return cmds
-
- def merge_bgp_network_route(self, **kwargs):
- """ merge_bgp_network_route """
-
- module = kwargs["module"]
-
- vrf_name = module.params['vrf_name']
-
- af_type = module.params['af_type']
- network_address = module.params['network_address']
- mask_len = module.params['mask_len']
-
- conf_str = CE_MERGE_BGP_NETWORK_ROUTE_HEADER % (
- vrf_name, af_type, network_address, mask_len) + CE_MERGE_BGP_NETWORK_ROUTE_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge bgp network route failed.')
-
- cmds = []
- cmd = "network %s %s" % (network_address, mask_len)
- cmds.append(cmd)
-
- return cmds
-
- def create_bgp_network_route(self, **kwargs):
- """ create_bgp_network_route """
-
- module = kwargs["module"]
-
- vrf_name = module.params['vrf_name']
-
- af_type = module.params['af_type']
- network_address = module.params['network_address']
- mask_len = module.params['mask_len']
-
- conf_str = CE_CREATE_BGP_NETWORK_ROUTE % (
- vrf_name, af_type, network_address, mask_len)
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Create bgp network route failed.')
-
- cmds = []
- cmd = "network %s %s" % (network_address, mask_len)
- cmds.append(cmd)
-
- return cmds
-
- def delete_bgp_network_route(self, **kwargs):
- """ delete_bgp_network_route """
-
- module = kwargs["module"]
-
- vrf_name = module.params['vrf_name']
-
- af_type = module.params['af_type']
- network_address = module.params['network_address']
- mask_len = module.params['mask_len']
-
- conf_str = CE_DELETE_BGP_NETWORK_ROUTE % (
- vrf_name, af_type, network_address, mask_len)
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Delete bgp network route failed.')
-
- cmds = []
- cmd = "undo network %s %s" % (network_address, mask_len)
- cmds.append(cmd)
-
- return cmds
-
-
-def main():
- """ main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- vrf_name=dict(type='str', required=True),
- af_type=dict(choices=['ipv4uni', 'ipv4multi', 'ipv4vpn',
- 'ipv6uni', 'ipv6vpn', 'evpn'], required=True),
- max_load_ibgp_num=dict(type='str'),
- ibgp_ecmp_nexthop_changed=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- max_load_ebgp_num=dict(type='str'),
- ebgp_ecmp_nexthop_changed=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- maximum_load_balance=dict(type='str'),
- ecmp_nexthop_changed=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- default_local_pref=dict(type='str'),
- default_med=dict(type='str'),
- default_rt_import_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- router_id=dict(type='str'),
- vrf_rid_auto_sel=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- nexthop_third_party=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- summary_automatic=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- auto_frr_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- load_balancing_as_path_ignore=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- rib_only_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- rib_only_policy_name=dict(type='str'),
- active_route_advertise=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- as_path_neglect=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- med_none_as_maximum=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- router_id_neglect=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- igp_metric_ignore=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- always_compare_med=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- determin_med=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- preference_external=dict(type='str'),
- preference_internal=dict(type='str'),
- preference_local=dict(type='str'),
- prefrence_policy_name=dict(type='str'),
- reflect_between_client=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- reflector_cluster_id=dict(type='str'),
- reflector_cluster_ipv4=dict(type='str'),
- rr_filter_number=dict(type='str'),
- policy_vpn_target=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- next_hop_sel_depend_type=dict(
- choices=['default', 'dependTunnel', 'dependIp']),
- nhp_relay_route_policy_name=dict(type='str'),
- ebgp_if_sensitive=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- reflect_chg_path=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- add_path_sel_num=dict(type='str'),
- route_sel_delay=dict(type='str'),
- allow_invalid_as=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- policy_ext_comm_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- supernet_uni_adv=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- supernet_label_adv=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- ingress_lsp_policy_name=dict(type='str'),
- originator_prior=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- lowest_priority=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- relay_delay_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- import_protocol=dict(
- choices=['direct', 'ospf', 'isis', 'static', 'rip', 'ospfv3', 'ripng']),
- import_process_id=dict(type='str'),
- network_address=dict(type='str'),
- mask_len=dict(type='str'))
-
- argument_spec.update(ce_argument_spec)
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
-
- changed = False
- proposed = dict()
- existing = dict()
- end_state = dict()
- updates = []
-
- state = module.params['state']
- vrf_name = module.params['vrf_name']
- af_type = module.params['af_type']
- max_load_ibgp_num = module.params['max_load_ibgp_num']
- ibgp_ecmp_nexthop_changed = module.params['ibgp_ecmp_nexthop_changed']
- max_load_ebgp_num = module.params['max_load_ebgp_num']
- ebgp_ecmp_nexthop_changed = module.params['ebgp_ecmp_nexthop_changed']
- maximum_load_balance = module.params['maximum_load_balance']
- ecmp_nexthop_changed = module.params['ecmp_nexthop_changed']
- default_local_pref = module.params['default_local_pref']
- default_med = module.params['default_med']
- default_rt_import_enable = module.params['default_rt_import_enable']
- router_id = module.params['router_id']
- vrf_rid_auto_sel = module.params['vrf_rid_auto_sel']
- nexthop_third_party = module.params['nexthop_third_party']
- summary_automatic = module.params['summary_automatic']
- auto_frr_enable = module.params['auto_frr_enable']
- load_balancing_as_path_ignore = module.params[
- 'load_balancing_as_path_ignore']
- rib_only_enable = module.params['rib_only_enable']
- rib_only_policy_name = module.params['rib_only_policy_name']
- active_route_advertise = module.params['active_route_advertise']
- as_path_neglect = module.params['as_path_neglect']
- med_none_as_maximum = module.params['med_none_as_maximum']
- router_id_neglect = module.params['router_id_neglect']
- igp_metric_ignore = module.params['igp_metric_ignore']
- always_compare_med = module.params['always_compare_med']
- determin_med = module.params['determin_med']
- preference_external = module.params['preference_external']
- preference_internal = module.params['preference_internal']
- preference_local = module.params['preference_local']
- prefrence_policy_name = module.params['prefrence_policy_name']
- reflect_between_client = module.params['reflect_between_client']
- reflector_cluster_id = module.params['reflector_cluster_id']
- reflector_cluster_ipv4 = module.params['reflector_cluster_ipv4']
- rr_filter_number = module.params['rr_filter_number']
- policy_vpn_target = module.params['policy_vpn_target']
- next_hop_sel_depend_type = module.params['next_hop_sel_depend_type']
- nhp_relay_route_policy_name = module.params['nhp_relay_route_policy_name']
- ebgp_if_sensitive = module.params['ebgp_if_sensitive']
- reflect_chg_path = module.params['reflect_chg_path']
- add_path_sel_num = module.params['add_path_sel_num']
- route_sel_delay = module.params['route_sel_delay']
- allow_invalid_as = module.params['allow_invalid_as']
- policy_ext_comm_enable = module.params['policy_ext_comm_enable']
- supernet_uni_adv = module.params['supernet_uni_adv']
- supernet_label_adv = module.params['supernet_label_adv']
- ingress_lsp_policy_name = module.params['ingress_lsp_policy_name']
- originator_prior = module.params['originator_prior']
- lowest_priority = module.params['lowest_priority']
- relay_delay_enable = module.params['relay_delay_enable']
- import_protocol = module.params['import_protocol']
- import_process_id = module.params['import_process_id']
- network_address = module.params['network_address']
- mask_len = module.params['mask_len']
-
- ce_bgp_af_obj = BgpAf()
-
- if not ce_bgp_af_obj:
- module.fail_json(msg='Error: Init module failed.')
-
- # get proposed
- proposed["state"] = state
- if vrf_name:
- proposed["vrf_name"] = vrf_name
- if af_type:
- proposed["af_type"] = af_type
- if max_load_ibgp_num:
- proposed["max_load_ibgp_num"] = max_load_ibgp_num
- if ibgp_ecmp_nexthop_changed != 'no_use':
- proposed["ibgp_ecmp_nexthop_changed"] = ibgp_ecmp_nexthop_changed
- if max_load_ebgp_num:
- proposed["max_load_ebgp_num"] = max_load_ebgp_num
- if ebgp_ecmp_nexthop_changed != 'no_use':
- proposed["ebgp_ecmp_nexthop_changed"] = ebgp_ecmp_nexthop_changed
- if maximum_load_balance:
- proposed["maximum_load_balance"] = maximum_load_balance
- if ecmp_nexthop_changed != 'no_use':
- proposed["ecmp_nexthop_changed"] = ecmp_nexthop_changed
- if default_local_pref:
- proposed["default_local_pref"] = default_local_pref
- if default_med:
- proposed["default_med"] = default_med
- if default_rt_import_enable != 'no_use':
- proposed["default_rt_import_enable"] = default_rt_import_enable
- if router_id:
- proposed["router_id"] = router_id
- if vrf_rid_auto_sel != 'no_use':
- proposed["vrf_rid_auto_sel"] = vrf_rid_auto_sel
- if nexthop_third_party != 'no_use':
- proposed["nexthop_third_party"] = nexthop_third_party
- if summary_automatic != 'no_use':
- proposed["summary_automatic"] = summary_automatic
- if auto_frr_enable != 'no_use':
- proposed["auto_frr_enable"] = auto_frr_enable
- if load_balancing_as_path_ignore != 'no_use':
- proposed["load_balancing_as_path_ignore"] = load_balancing_as_path_ignore
- if rib_only_enable != 'no_use':
- proposed["rib_only_enable"] = rib_only_enable
- if rib_only_policy_name:
- proposed["rib_only_policy_name"] = rib_only_policy_name
- if active_route_advertise != 'no_use':
- proposed["active_route_advertise"] = active_route_advertise
- if as_path_neglect != 'no_use':
- proposed["as_path_neglect"] = as_path_neglect
- if med_none_as_maximum != 'no_use':
- proposed["med_none_as_maximum"] = med_none_as_maximum
- if router_id_neglect != 'no_use':
- proposed["router_id_neglect"] = router_id_neglect
- if igp_metric_ignore != 'no_use':
- proposed["igp_metric_ignore"] = igp_metric_ignore
- if always_compare_med != 'no_use':
- proposed["always_compare_med"] = always_compare_med
- if determin_med != 'no_use':
- proposed["determin_med"] = determin_med
- if preference_external:
- proposed["preference_external"] = preference_external
- if preference_internal:
- proposed["preference_internal"] = preference_internal
- if preference_local:
- proposed["preference_local"] = preference_local
- if prefrence_policy_name:
- proposed["prefrence_policy_name"] = prefrence_policy_name
- if reflect_between_client != 'no_use':
- proposed["reflect_between_client"] = reflect_between_client
- if reflector_cluster_id:
- proposed["reflector_cluster_id"] = reflector_cluster_id
- if reflector_cluster_ipv4:
- proposed["reflector_cluster_ipv4"] = reflector_cluster_ipv4
- if rr_filter_number:
- proposed["rr_filter_number"] = rr_filter_number
- if policy_vpn_target != 'no_use':
- proposed["policy_vpn_target"] = policy_vpn_target
- if next_hop_sel_depend_type:
- proposed["next_hop_sel_depend_type"] = next_hop_sel_depend_type
- if nhp_relay_route_policy_name:
- proposed["nhp_relay_route_policy_name"] = nhp_relay_route_policy_name
- if ebgp_if_sensitive != 'no_use':
- proposed["ebgp_if_sensitive"] = ebgp_if_sensitive
- if reflect_chg_path != 'no_use':
- proposed["reflect_chg_path"] = reflect_chg_path
- if add_path_sel_num:
- proposed["add_path_sel_num"] = add_path_sel_num
- if route_sel_delay:
- proposed["route_sel_delay"] = route_sel_delay
- if allow_invalid_as != 'no_use':
- proposed["allow_invalid_as"] = allow_invalid_as
- if policy_ext_comm_enable != 'no_use':
- proposed["policy_ext_comm_enable"] = policy_ext_comm_enable
- if supernet_uni_adv != 'no_use':
- proposed["supernet_uni_adv"] = supernet_uni_adv
- if supernet_label_adv != 'no_use':
- proposed["supernet_label_adv"] = supernet_label_adv
- if ingress_lsp_policy_name:
- proposed["ingress_lsp_policy_name"] = ingress_lsp_policy_name
- if originator_prior != 'no_use':
- proposed["originator_prior"] = originator_prior
- if lowest_priority != 'no_use':
- proposed["lowest_priority"] = lowest_priority
- if relay_delay_enable != 'no_use':
- proposed["relay_delay_enable"] = relay_delay_enable
- if import_protocol:
- proposed["import_protocol"] = import_protocol
- if import_process_id:
- proposed["import_process_id"] = import_process_id
- if network_address:
- proposed["network_address"] = network_address
- if mask_len:
- proposed["mask_len"] = mask_len
-
- bgp_af_rst = ce_bgp_af_obj.check_bgp_af_args(module=module)
- bgp_af_other_rst = ce_bgp_af_obj.check_bgp_af_other_args(module=module)
- bgp_af_other_can_del_rst = ce_bgp_af_obj.check_bgp_af_other_can_del(
- module=module)
- bgp_import_network_route_rst = ce_bgp_af_obj.check_bgp_import_network_route(
- module=module)
-
- # state exist bgp address family config
- exist_tmp = dict()
- for item in bgp_af_rst:
- if item != "need_cfg":
- exist_tmp[item] = bgp_af_rst[item]
-
- if exist_tmp:
- existing["bgp af"] = exist_tmp
- # state exist bgp address family other config
- exist_tmp = dict()
- for item in bgp_af_other_rst:
- if item != "need_cfg":
- exist_tmp[item] = bgp_af_other_rst[item]
- if exist_tmp:
- existing["bgp af other"] = exist_tmp
- # state exist bgp import route config
- exist_tmp = dict()
- for item in bgp_import_network_route_rst:
- if item != "need_cfg":
- exist_tmp[item] = bgp_import_network_route_rst[item]
-
- if exist_tmp:
- existing["bgp import & network route"] = exist_tmp
-
- if state == "present":
- if bgp_af_rst["need_cfg"] and bgp_import_network_route_rst["import_need_cfg"] and \
- bgp_import_network_route_rst["network_need_cfg"]:
- changed = True
- if "af_type" in bgp_af_rst.keys():
- conf_str = CE_MERGE_BGP_ADDRESS_FAMILY_HEADER % (
- vrf_name, af_type)
- else:
- conf_str = CE_CREATE_BGP_ADDRESS_FAMILY_HEADER % (
- vrf_name, af_type)
-
- if "bgp_import_route" in bgp_import_network_route_rst.keys():
- conf_str += CE_BGP_MERGE_IMPORT_UNIT % (
- import_protocol, import_process_id)
- else:
- conf_str += CE_BGP_CREATE_IMPORT_UNIT % (
- import_protocol, import_process_id)
-
- if "bgp_network_route" in bgp_import_network_route_rst.keys():
- conf_str += CE_BGP_MERGE_NETWORK_UNIT % (
- network_address, mask_len)
- else:
- conf_str += CE_BGP_CREATE_NETWORK_UNIT % (
- network_address, mask_len)
-
- conf_str += CE_MERGE_BGP_ADDRESS_FAMILY_TAIL
- recv_xml = ce_bgp_af_obj.netconf_set_config(
- module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Present bgp af_type import and network route failed.')
-
- cmd = "import-route %s %s" % (import_protocol, import_process_id)
- updates.append(cmd)
- cmd = "network %s %s" % (network_address, mask_len)
- updates.append(cmd)
-
- elif bgp_import_network_route_rst["import_need_cfg"] and bgp_import_network_route_rst["network_need_cfg"]:
- changed = True
- conf_str = CE_BGP_IMPORT_NETWORK_ROUTE_HEADER % (vrf_name, af_type)
-
- if "bgp_import_route" in bgp_import_network_route_rst.keys():
- conf_str += CE_BGP_MERGE_IMPORT_UNIT % (
- import_protocol, import_process_id)
- else:
- conf_str += CE_BGP_CREATE_IMPORT_UNIT % (
- import_protocol, import_process_id)
-
- if "bgp_network_route" in bgp_import_network_route_rst.keys():
- conf_str += CE_BGP_MERGE_NETWORK_UNIT % (
- network_address, mask_len)
- else:
- conf_str += CE_BGP_CREATE_NETWORK_UNIT % (
- network_address, mask_len)
-
- conf_str += CE_BGP_IMPORT_NETWORK_ROUTE_TAIL
- recv_xml = ce_bgp_af_obj.netconf_set_config(
- module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Present bgp import and network route failed.')
-
- cmd = "import-route %s %s" % (import_protocol, import_process_id)
- updates.append(cmd)
- cmd = "network %s %s" % (network_address, mask_len)
- updates.append(cmd)
-
- else:
- if bgp_af_rst["need_cfg"]:
- if "af_type" in bgp_af_rst.keys():
- cmd = ce_bgp_af_obj.merge_bgp_af(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
- else:
- cmd = ce_bgp_af_obj.create_bgp_af(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- if bgp_af_other_rst["need_cfg"]:
- cmd = ce_bgp_af_obj.merge_bgp_af_other(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- if bgp_import_network_route_rst["import_need_cfg"]:
- if "bgp_import_route" in bgp_import_network_route_rst.keys():
- cmd = ce_bgp_af_obj.merge_bgp_import_route(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
- else:
- cmd = ce_bgp_af_obj.create_bgp_import_route(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- if bgp_import_network_route_rst["network_need_cfg"]:
- if "bgp_network_route" in bgp_import_network_route_rst.keys():
- cmd = ce_bgp_af_obj.merge_bgp_network_route(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
- else:
- cmd = ce_bgp_af_obj.create_bgp_network_route(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- else:
- if bgp_import_network_route_rst["import_need_cfg"] and bgp_import_network_route_rst["network_need_cfg"]:
- changed = True
- conf_str = CE_BGP_IMPORT_NETWORK_ROUTE_HEADER % (vrf_name, af_type)
- conf_str += CE_BGP_DELETE_IMPORT_UNIT % (
- import_protocol, import_process_id)
- conf_str += CE_BGP_DELETE_NETWORK_UNIT % (
- network_address, mask_len)
-
- conf_str += CE_BGP_IMPORT_NETWORK_ROUTE_TAIL
- recv_xml = ce_bgp_af_obj.netconf_set_config(
- module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(
- msg='Error: Absent bgp import and network route failed.')
-
- cmd = "undo import-route %s %s" % (import_protocol,
- import_process_id)
- updates.append(cmd)
- cmd = "undo network %s %s" % (network_address, mask_len)
- updates.append(cmd)
-
- else:
- if bgp_import_network_route_rst["import_need_cfg"]:
- cmd = ce_bgp_af_obj.delete_bgp_import_route(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- if bgp_import_network_route_rst["network_need_cfg"]:
- cmd = ce_bgp_af_obj.delete_bgp_network_route(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- if bgp_af_other_can_del_rst["need_cfg"]:
- cmd = ce_bgp_af_obj.delete_bgp_af_other(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- if bgp_af_rst["need_cfg"] and not bgp_af_other_can_del_rst["need_cfg"]:
- cmd = ce_bgp_af_obj.delete_bgp_af(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- if bgp_af_other_rst["need_cfg"]:
- pass
-
- # state end bgp address family config
- bgp_af_rst = ce_bgp_af_obj.check_bgp_af_args(module=module)
- end_tmp = dict()
- for item in bgp_af_rst:
- if item != "need_cfg":
- end_tmp[item] = bgp_af_rst[item]
- if end_tmp:
- end_state["bgp af"] = end_tmp
- # state end bgp address family other config
- bgp_af_other_rst = ce_bgp_af_obj.check_bgp_af_other_args(module=module)
- end_tmp = dict()
- for item in bgp_af_other_rst:
- if item != "need_cfg":
- end_tmp[item] = bgp_af_other_rst[item]
- if end_tmp:
- end_state["bgp af other"] = end_tmp
- # state end bgp import route config
- bgp_import_network_route_rst = ce_bgp_af_obj.check_bgp_import_network_route(
- module=module)
- end_tmp = dict()
- for item in bgp_import_network_route_rst:
- if item != "need_cfg":
- end_tmp[item] = bgp_import_network_route_rst[item]
- if end_tmp:
- end_state["bgp import & network route"] = end_tmp
- if end_state == existing:
- changed = False
- updates = list()
-
- results = dict()
- results['proposed'] = proposed
- results['existing'] = existing
- results['changed'] = changed
- results['end_state'] = end_state
- results['updates'] = updates
-
- module.exit_json(**results)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_bgp_neighbor.py b/plugins/modules/network/cloudengine/ce_bgp_neighbor.py
deleted file mode 100644
index a61eaf1a11..0000000000
--- a/plugins/modules/network/cloudengine/ce_bgp_neighbor.py
+++ /dev/null
@@ -1,2051 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_bgp_neighbor
-short_description: Manages BGP peer configuration on HUAWEI CloudEngine switches.
-description:
- - Manages BGP peer configurations on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- state:
- description:
- - Specify desired state of the resource.
- default: present
- choices: ['present','absent']
- vrf_name:
- description:
- - Name of a BGP instance. The name is a case-sensitive string of characters.
- The BGP instance can be used only after the corresponding VPN instance is created.
- required: true
- peer_addr:
- description:
- - Connection address of a peer, which can be an IPv4 or IPv6 address.
- required: true
- remote_as:
- description:
- - AS number of a peer.
- The value is a string of 1 to 11 characters.
- required: true
- description:
- description:
- - Description of a peer, which can be letters or digits.
- The value is a string of 1 to 80 characters.
- fake_as:
- description:
- - Fake AS number that is specified for a local peer.
- The value is a string of 1 to 11 characters.
- dual_as:
- description:
- - If the value is true, the EBGP peer can use either a fake AS number or the actual AS number.
- If the value is false, the EBGP peer can only use a fake AS number.
- choices: ['no_use','true','false']
- default: no_use
- conventional:
- description:
- - If the value is true, the router has all extended capabilities.
- If the value is false, the router does not have all extended capabilities.
- choices: ['no_use','true','false']
- default: no_use
- route_refresh:
- description:
- - If the value is true, BGP is enabled to advertise REFRESH packets.
- If the value is false, the route refresh function is enabled.
- choices: ['no_use','true','false']
- default: no_use
- is_ignore:
- description:
- - If the value is true, the session with a specified peer is torn down and all related
- routing entries are cleared.
- If the value is false, the session with a specified peer is retained.
- choices: ['no_use','true','false']
- default: no_use
- local_if_name:
- description:
- - Name of a source interface that sends BGP packets.
- The value is a string of 1 to 63 characters.
- ebgp_max_hop:
- description:
- - Maximum number of hops in an indirect EBGP connection.
- The value is an ranging from 1 to 255.
- valid_ttl_hops:
- description:
- - Enable GTSM on a peer or peer group.
- The valid-TTL-Value parameter is used to specify the number of TTL hops to be detected.
- The value is an integer ranging from 1 to 255.
- connect_mode:
- description:
- - The value can be Connect-only, Listen-only, or Both.
- is_log_change:
- description:
- - If the value is true, BGP is enabled to record peer session status and event information.
- If the value is false, BGP is disabled from recording peer session status and event information.
- choices: ['no_use','true','false']
- default: no_use
- pswd_type:
- description:
- - Enable BGP peers to establish a TCP connection and perform the Message Digest 5 (MD5)
- authentication for BGP messages.
- choices: ['null','cipher','simple']
- pswd_cipher_text:
- description:
- - The character string in a password identifies the contents of the password, spaces not supported.
- The value is a string of 1 to 255 characters.
- keep_alive_time:
- description:
- - Specify the Keepalive time of a peer or peer group.
- The value is an integer ranging from 0 to 21845. The default value is 60.
- hold_time:
- description:
- - Specify the Hold time of a peer or peer group.
- The value is 0 or an integer ranging from 3 to 65535.
- min_hold_time:
- description:
- - Specify the Min hold time of a peer or peer group.
- key_chain_name:
- description:
- - Specify the Keychain authentication name used when BGP peers establish a TCP connection.
- The value is a string of 1 to 47 case-insensitive characters.
- conn_retry_time:
- description:
- - ConnectRetry interval.
- The value is an integer ranging from 1 to 65535.
- tcp_MSS:
- description:
- - Maximum TCP MSS value used for TCP connection establishment for a peer.
- The value is an integer ranging from 176 to 4096.
- mpls_local_ifnet_disable:
- description:
- - If the value is true, peer create MPLS Local IFNET disable.
- If the value is false, peer create MPLS Local IFNET enable.
- choices: ['no_use','true','false']
- default: no_use
- prepend_global_as:
- description:
- - Add the global AS number to the Update packets to be advertised.
- choices: ['no_use','true','false']
- default: no_use
- prepend_fake_as:
- description:
- - Add the Fake AS number to received Update packets.
- choices: ['no_use','true','false']
- default: no_use
- is_bfd_block:
- description:
- - If the value is true, peers are enabled to inherit the BFD function from the peer group.
- If the value is false, peers are disabled to inherit the BFD function from the peer group.
- choices: ['no_use','true','false']
- default: no_use
- multiplier:
- description:
- - Specify the detection multiplier. The default value is 3.
- The value is an integer ranging from 3 to 50.
- is_bfd_enable:
- description:
- - If the value is true, BFD is enabled.
- If the value is false, BFD is disabled.
- choices: ['no_use','true','false']
- default: no_use
- rx_interval:
- description:
- - Specify the minimum interval at which BFD packets are received.
- The value is an integer ranging from 50 to 1000, in milliseconds.
- tx_interval:
- description:
- - Specify the minimum interval at which BFD packets are sent.
- The value is an integer ranging from 50 to 1000, in milliseconds.
- is_single_hop:
- description:
- - If the value is true, the system is enabled to preferentially use the single-hop mode for
- BFD session setup between IBGP peers.
- If the value is false, the system is disabled from preferentially using the single-hop
- mode for BFD session setup between IBGP peers.
- choices: ['no_use','true','false']
- default: no_use
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine BGP neighbor test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Config bgp peer"
- ce_bgp_neighbor:
- state: present
- vrf_name: js
- peer_addr: 192.168.10.10
- remote_as: 500
- provider: "{{ cli }}"
-
- - name: "Config bgp route id"
- ce_bgp_neighbor:
- state: absent
- vrf_name: js
- peer_addr: 192.168.10.10
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"peer_addr": "192.168.10.10", "remote_as": "500", "state": "present", "vrf_name": "js"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {"bgp peer": []}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"bgp peer": [["192.168.10.10", "500"]]}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["peer 192.168.10.10 as-number 500"]
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec, check_ip_addr
-
-
-# get bgp peer
-CE_GET_BGP_PEER_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-"""
-CE_GET_BGP_PEER_TAIL = """
-
-
-
-
-
-
-
-"""
-
-# merge bgp peer
-CE_MERGE_BGP_PEER_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-"""
-CE_MERGE_BGP_PEER_TAIL = """
-
-
-
-
-
-
-
-"""
-
-# create bgp peer
-CE_CREATE_BGP_PEER_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-"""
-CE_CREATE_BGP_PEER_TAIL = """
-
-
-
-
-
-
-
-"""
-
-# delete bgp peer
-CE_DELETE_BGP_PEER_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-"""
-CE_DELETE_BGP_PEER_TAIL = """
-
-
-
-
-
-
-
-"""
-
-# get peer bfd
-CE_GET_PEER_BFD_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-
-"""
-CE_GET_PEER_BFD_TAIL = """
-
-
-
-
-
-
-
-
-"""
-
-# merge peer bfd
-CE_MERGE_PEER_BFD_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-
-"""
-CE_MERGE_PEER_BFD_TAIL = """
-
-
-
-
-
-
-
-
-"""
-
-# delete peer bfd
-CE_DELETE_PEER_BFD_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-
-"""
-CE_DELETE_PEER_BFD_TAIL = """
-
-
-
-
-
-
-
-
-"""
-
-
-class BgpNeighbor(object):
- """ Manages BGP peer configuration """
-
- def netconf_get_config(self, **kwargs):
- """ netconf_get_config """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- xml_str = get_nc_config(module, conf_str)
-
- return xml_str
-
- def netconf_set_config(self, **kwargs):
- """ netconf_set_config """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- xml_str = set_nc_config(module, conf_str)
-
- return xml_str
-
- def check_bgp_peer_args(self, **kwargs):
- """ check_bgp_peer_args """
-
- module = kwargs["module"]
- result = dict()
- need_cfg = False
-
- vrf_name = module.params['vrf_name']
- if vrf_name:
- if len(vrf_name) > 31 or len(vrf_name) == 0:
- module.fail_json(
- msg='Error: The len of vrf_name %s is out of [1 - 31].' % vrf_name)
-
- peer_addr = module.params['peer_addr']
- if peer_addr:
- if not check_ip_addr(ipaddr=peer_addr):
- module.fail_json(
- msg='Error: The peer_addr %s is invalid.' % peer_addr)
-
- need_cfg = True
-
- remote_as = module.params['remote_as']
- if remote_as:
- if len(remote_as) > 11 or len(remote_as) < 1:
- module.fail_json(
- msg='Error: The len of remote_as %s is out of [1 - 11].' % remote_as)
-
- need_cfg = True
-
- result["need_cfg"] = need_cfg
- return result
-
- def check_bgp_peer_other_args(self, **kwargs):
- """ check_bgp_peer_other_args """
-
- module = kwargs["module"]
- result = dict()
- need_cfg = False
-
- peerip = module.params['peer_addr']
- vrf_name = module.params['vrf_name']
- if vrf_name:
- if len(vrf_name) > 31 or len(vrf_name) == 0:
- module.fail_json(
- msg='Error: The len of vrf_name %s is out of [1 - 31].' % vrf_name)
-
- description = module.params['description']
- if description:
- if len(description) > 80 or len(description) < 1:
- module.fail_json(
- msg='Error: The len of description %s is out of [1 - 80].' % description)
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["description"] = re_find
- if re_find[0] != description:
- need_cfg = True
- else:
- need_cfg = True
-
- fake_as = module.params['fake_as']
- if fake_as:
- if len(fake_as) > 11 or len(fake_as) < 1:
- module.fail_json(
- msg='Error: The len of fake_as %s is out of [1 - 11].' % fake_as)
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["fake_as"] = re_find
- if re_find[0] != fake_as:
- need_cfg = True
- else:
- need_cfg = True
-
- dual_as = module.params['dual_as']
- if dual_as != 'no_use':
- if not fake_as:
- module.fail_json(msg='fake_as must exist.')
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["dual_as"] = re_find
- if re_find[0] != dual_as:
- need_cfg = True
- else:
- need_cfg = True
-
- conventional = module.params['conventional']
- if conventional != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["conventional"] = re_find
- if re_find[0] != conventional:
- need_cfg = True
- else:
- need_cfg = True
-
- route_refresh = module.params['route_refresh']
- if route_refresh != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["route_refresh"] = re_find
- if re_find[0] != route_refresh:
- need_cfg = True
- else:
- need_cfg = True
-
- four_byte_as = module.params['four_byte_as']
- if four_byte_as != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["four_byte_as"] = re_find
- if re_find[0] != four_byte_as:
- need_cfg = True
- else:
- need_cfg = True
-
- is_ignore = module.params['is_ignore']
- if is_ignore != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["is_ignore"] = re_find
- if re_find[0] != is_ignore:
- need_cfg = True
- else:
- need_cfg = True
-
- local_if_name = module.params['local_if_name']
- if local_if_name:
- if len(local_if_name) > 63 or len(local_if_name) < 1:
- module.fail_json(
- msg='Error: The len of local_if_name %s is out of [1 - 63].' % local_if_name)
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["local_if_name"] = re_find
- if re_find[0].lower() != local_if_name.lower():
- need_cfg = True
- else:
- need_cfg = True
-
- ebgp_max_hop = module.params['ebgp_max_hop']
- if ebgp_max_hop:
- if int(ebgp_max_hop) > 255 or int(ebgp_max_hop) < 1:
- module.fail_json(
- msg='Error: The value of ebgp_max_hop %s is out of [1 - 255].' % ebgp_max_hop)
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["ebgp_max_hop"] = re_find
- if re_find[0] != ebgp_max_hop:
- need_cfg = True
- else:
- need_cfg = True
-
- valid_ttl_hops = module.params['valid_ttl_hops']
- if valid_ttl_hops:
- if int(valid_ttl_hops) > 255 or int(valid_ttl_hops) < 1:
- module.fail_json(
- msg='Error: The value of valid_ttl_hops %s is out of [1 - 255].' % valid_ttl_hops)
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["valid_ttl_hops"] = re_find
- if re_find[0] != valid_ttl_hops:
- need_cfg = True
- else:
- need_cfg = True
-
- connect_mode = module.params['connect_mode']
- if connect_mode:
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["connect_mode"] = re_find
- if re_find[0] != connect_mode:
- need_cfg = True
- else:
- need_cfg = True
-
- is_log_change = module.params['is_log_change']
- if is_log_change != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["is_log_change"] = re_find
- if re_find[0] != is_log_change:
- need_cfg = True
- else:
- need_cfg = True
-
- pswd_type = module.params['pswd_type']
- if pswd_type:
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["pswd_type"] = re_find
- if re_find[0] != pswd_type:
- need_cfg = True
- else:
- need_cfg = True
-
- pswd_cipher_text = module.params['pswd_cipher_text']
- if pswd_cipher_text:
- if len(pswd_cipher_text) > 255 or len(pswd_cipher_text) < 1:
- module.fail_json(
- msg='Error: The len of pswd_cipher_text %s is out of [1 - 255].' % pswd_cipher_text)
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["pswd_cipher_text"] = re_find
- if re_find[0] != pswd_cipher_text:
- need_cfg = True
- else:
- need_cfg = True
-
- keep_alive_time = module.params['keep_alive_time']
- if keep_alive_time:
- if int(keep_alive_time) > 21845 or len(keep_alive_time) < 0:
- module.fail_json(
- msg='Error: The len of keep_alive_time %s is out of [0 - 21845].' % keep_alive_time)
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["keep_alive_time"] = re_find
- if re_find[0] != keep_alive_time:
- need_cfg = True
- else:
- need_cfg = True
-
- hold_time = module.params['hold_time']
- if hold_time:
- if int(hold_time) != 0 and (int(hold_time) > 65535 or int(hold_time) < 3):
- module.fail_json(
- msg='Error: The value of hold_time %s is out of [0 or 3 - 65535].' % hold_time)
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["hold_time"] = re_find
- if re_find[0] != hold_time:
- need_cfg = True
- else:
- need_cfg = True
-
- min_hold_time = module.params['min_hold_time']
- if min_hold_time:
- if int(min_hold_time) != 0 and (int(min_hold_time) > 65535 or int(min_hold_time) < 20):
- module.fail_json(
- msg='Error: The value of min_hold_time %s is out of [0 or 20 - 65535].' % min_hold_time)
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["min_hold_time"] = re_find
- if re_find[0] != min_hold_time:
- need_cfg = True
- else:
- need_cfg = True
-
- key_chain_name = module.params['key_chain_name']
- if key_chain_name:
- if len(key_chain_name) > 47 or len(key_chain_name) < 1:
- module.fail_json(
- msg='Error: The len of key_chain_name %s is out of [1 - 47].' % key_chain_name)
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["key_chain_name"] = re_find
- if re_find[0] != key_chain_name:
- need_cfg = True
- else:
- need_cfg = True
-
- conn_retry_time = module.params['conn_retry_time']
- if conn_retry_time:
- if int(conn_retry_time) > 65535 or int(conn_retry_time) < 1:
- module.fail_json(
- msg='Error: The value of conn_retry_time %s is out of [1 - 65535].' % conn_retry_time)
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["conn_retry_time"] = re_find
- if re_find[0] != conn_retry_time:
- need_cfg = True
- else:
- need_cfg = True
-
- tcp_mss = module.params['tcp_MSS']
- if tcp_mss:
- if int(tcp_mss) > 4096 or int(tcp_mss) < 176:
- module.fail_json(
- msg='Error: The value of tcp_mss %s is out of [176 - 4096].' % tcp_mss)
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["tcp_MSS"] = re_find
- if re_find[0] != tcp_mss:
- need_cfg = True
- else:
- need_cfg = True
-
- mpls_local_ifnet_disable = module.params['mpls_local_ifnet_disable']
- if mpls_local_ifnet_disable != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["mpls_local_ifnet_disable"] = re_find
- if re_find[0] != mpls_local_ifnet_disable:
- need_cfg = True
- else:
- need_cfg = True
-
- prepend_global_as = module.params['prepend_global_as']
- if prepend_global_as != 'no_use':
- if not fake_as:
- module.fail_json(msg='fake_as must exist.')
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["prepend_global_as"] = re_find
- if re_find[0] != prepend_global_as:
- need_cfg = True
- else:
- need_cfg = True
-
- prepend_fake_as = module.params['prepend_fake_as']
- if prepend_fake_as != 'no_use':
- if not fake_as:
- module.fail_json(msg='fake_as must exist.')
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["prepend_fake_as"] = re_find
- if re_find[0] != prepend_fake_as:
- need_cfg = True
- else:
- need_cfg = True
-
- result["need_cfg"] = need_cfg
- return result
-
- def check_peer_bfd_merge_args(self, **kwargs):
- """ check_peer_bfd_merge_args """
-
- module = kwargs["module"]
- result = dict()
- need_cfg = False
-
- state = module.params['state']
- if state == "absent":
- result["need_cfg"] = need_cfg
- return result
-
- vrf_name = module.params['vrf_name']
- if vrf_name:
- if len(vrf_name) > 31 or len(vrf_name) == 0:
- module.fail_json(
- msg='Error: The len of vrf_name %s is out of [1 - 31].' % vrf_name)
-
- peer_addr = module.params['peer_addr']
-
- is_bfd_block = module.params['is_bfd_block']
- if is_bfd_block != 'no_use':
-
- conf_str = CE_GET_PEER_BFD_HEADER % (
- vrf_name, peer_addr) + "" + CE_GET_PEER_BFD_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["is_bfd_block"] = re_find
- if re_find[0] != is_bfd_block:
- need_cfg = True
- else:
- need_cfg = True
-
- multiplier = module.params['multiplier']
- if multiplier:
- if int(multiplier) > 50 or int(multiplier) < 3:
- module.fail_json(
- msg='Error: The value of multiplier %s is out of [3 - 50].' % multiplier)
-
- conf_str = CE_GET_PEER_BFD_HEADER % (
- vrf_name, peer_addr) + "" + CE_GET_PEER_BFD_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["multiplier"] = re_find
- if re_find[0] != multiplier:
- need_cfg = True
- else:
- need_cfg = True
-
- is_bfd_enable = module.params['is_bfd_enable']
- if is_bfd_enable != 'no_use':
-
- conf_str = CE_GET_PEER_BFD_HEADER % (
- vrf_name, peer_addr) + "" + CE_GET_PEER_BFD_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["is_bfd_enable"] = re_find
- if re_find[0] != is_bfd_enable:
- need_cfg = True
- else:
- need_cfg = True
-
- rx_interval = module.params['rx_interval']
- if rx_interval:
- if int(rx_interval) > 1000 or int(rx_interval) < 50:
- module.fail_json(
- msg='Error: The value of rx_interval %s is out of [50 - 1000].' % rx_interval)
-
- conf_str = CE_GET_PEER_BFD_HEADER % (
- vrf_name, peer_addr) + "" + CE_GET_PEER_BFD_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["rx_interval"] = re_find
- if re_find[0] != rx_interval:
- need_cfg = True
- else:
- need_cfg = True
-
- tx_interval = module.params['tx_interval']
- if tx_interval:
- if int(tx_interval) > 1000 or int(tx_interval) < 50:
- module.fail_json(
- msg='Error: The value of tx_interval %s is out of [50 - 1000].' % tx_interval)
-
- conf_str = CE_GET_PEER_BFD_HEADER % (
- vrf_name, peer_addr) + "" + CE_GET_PEER_BFD_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["tx_interval"] = re_find
- if re_find[0] != tx_interval:
- need_cfg = True
- else:
- need_cfg = True
-
- is_single_hop = module.params['is_single_hop']
- if is_single_hop != 'no_use':
-
- conf_str = CE_GET_PEER_BFD_HEADER % (
- vrf_name, peer_addr) + "" + CE_GET_PEER_BFD_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["is_single_hop"] = re_find
- if re_find[0] != is_single_hop:
- need_cfg = True
- else:
- need_cfg = True
-
- result["need_cfg"] = need_cfg
- return result
-
- def check_peer_bfd_delete_args(self, **kwargs):
- """ check_peer_bfd_delete_args """
-
- module = kwargs["module"]
- result = dict()
- need_cfg = False
-
- state = module.params['state']
- if state == "present":
- result["need_cfg"] = need_cfg
- return result
-
- vrf_name = module.params['vrf_name']
- if vrf_name:
- if len(vrf_name) > 31 or len(vrf_name) == 0:
- module.fail_json(
- msg='Error: The len of vrf_name %s is out of [1 - 31].' % vrf_name)
-
- peer_addr = module.params['peer_addr']
-
- is_bfd_block = module.params['is_bfd_block']
- if is_bfd_block != 'no_use':
-
- conf_str = CE_GET_PEER_BFD_HEADER % (
- vrf_name, peer_addr) + "" + CE_GET_PEER_BFD_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["is_bfd_block"] = re_find
- if re_find[0] == is_bfd_block:
- need_cfg = True
-
- multiplier = module.params['multiplier']
- if multiplier:
- if int(multiplier) > 50 or int(multiplier) < 3:
- module.fail_json(
- msg='Error: The value of multiplier %s is out of [3 - 50].' % multiplier)
-
- conf_str = CE_GET_PEER_BFD_HEADER % (
- vrf_name, peer_addr) + "" + CE_GET_PEER_BFD_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["multiplier"] = re_find
- if re_find[0] == multiplier:
- need_cfg = True
-
- is_bfd_enable = module.params['is_bfd_enable']
- if is_bfd_enable != 'no_use':
-
- conf_str = CE_GET_PEER_BFD_HEADER % (
- vrf_name, peer_addr) + "" + CE_GET_PEER_BFD_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["is_bfd_enable"] = re_find
- if re_find[0] == is_bfd_enable:
- need_cfg = True
-
- rx_interval = module.params['rx_interval']
- if rx_interval:
- if int(rx_interval) > 1000 or int(rx_interval) < 50:
- module.fail_json(
- msg='Error: The value of rx_interval %s is out of [50 - 1000].' % rx_interval)
-
- conf_str = CE_GET_PEER_BFD_HEADER % (
- vrf_name, peer_addr) + "" + CE_GET_PEER_BFD_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["rx_interval"] = re_find
- if re_find[0] == rx_interval:
- need_cfg = True
-
- tx_interval = module.params['tx_interval']
- if tx_interval:
- if int(tx_interval) > 1000 or int(tx_interval) < 50:
- module.fail_json(
- msg='Error: The value of tx_interval %s is out of [50 - 1000].' % tx_interval)
-
- conf_str = CE_GET_PEER_BFD_HEADER % (
- vrf_name, peer_addr) + "" + CE_GET_PEER_BFD_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["tx_interval"] = re_find
- if re_find[0] == tx_interval:
- need_cfg = True
-
- is_single_hop = module.params['is_single_hop']
- if is_single_hop != 'no_use':
-
- conf_str = CE_GET_PEER_BFD_HEADER % (
- vrf_name, peer_addr) + "" + CE_GET_PEER_BFD_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["is_single_hop"] = re_find
- if re_find[0] == is_single_hop:
- need_cfg = True
-
- result["need_cfg"] = need_cfg
- return result
-
- def get_bgp_peer(self, **kwargs):
- """ get_bgp_peer """
-
- module = kwargs["module"]
- peerip = module.params['peer_addr']
- vrf_name = module.params['vrf_name']
- if vrf_name:
- if len(vrf_name) > 31 or len(vrf_name) == 0:
- module.fail_json(
- msg='Error: The len of vrf_name %s is out of [1 - 31].' % vrf_name)
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + \
- "" + CE_GET_BGP_PEER_TAIL
-
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
-
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(
- r'.*(.*).*\s.*(.*).*', xml_str)
-
- if re_find:
- return re_find
- else:
- return result
-
- def get_bgp_del_peer(self, **kwargs):
- """ get_bgp_del_peer """
-
- module = kwargs["module"]
- peerip = module.params['peer_addr']
- vrf_name = module.params['vrf_name']
- if vrf_name:
- if len(vrf_name) > 31 or len(vrf_name) == 0:
- module.fail_json(
- msg='Error: The len of vrf_name %s is out of [1 - 31].' % vrf_name)
-
- conf_str = CE_GET_BGP_PEER_HEADER % (vrf_name, peerip) + CE_GET_BGP_PEER_TAIL
-
- xml_str = self.netconf_get_config(module=module, conf_str=conf_str)
-
- result = list()
-
- if "" in xml_str:
- return result
- else:
- re_find = re.findall(
- r'.*(.*).*', xml_str)
-
- if re_find:
- return re_find
- else:
- return result
-
- def merge_bgp_peer(self, **kwargs):
- """ merge_bgp_peer """
-
- module = kwargs["module"]
- vrf_name = module.params['vrf_name']
- peer_addr = module.params['peer_addr']
- remote_as = module.params['remote_as']
-
- conf_str = CE_MERGE_BGP_PEER_HEADER % (
- vrf_name, peer_addr) + "%s" % remote_as + CE_MERGE_BGP_PEER_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge bgp peer failed.')
-
- cmds = []
- cmd = "peer %s as-number %s" % (peer_addr, remote_as)
- cmds.append(cmd)
-
- return cmds
-
- def create_bgp_peer(self, **kwargs):
- """ create_bgp_peer """
-
- module = kwargs["module"]
-
- vrf_name = module.params['vrf_name']
-
- peer_addr = module.params['peer_addr']
- remote_as = module.params['remote_as']
-
- conf_str = CE_CREATE_BGP_PEER_HEADER % (
- vrf_name, peer_addr) + "%s" % remote_as + CE_CREATE_BGP_PEER_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Create bgp peer failed.')
-
- cmds = []
- cmd = "peer %s as-number %s" % (peer_addr, remote_as)
- cmds.append(cmd)
-
- return cmds
-
- def delete_bgp_peer(self, **kwargs):
- """ delete_bgp_peer """
-
- module = kwargs["module"]
- vrf_name = module.params['vrf_name']
- peer_addr = module.params['peer_addr']
-
- conf_str = CE_DELETE_BGP_PEER_HEADER % (
- vrf_name, peer_addr) + CE_DELETE_BGP_PEER_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Delete bgp peer failed.')
-
- cmds = []
- cmd = "undo peer %s" % peer_addr
- cmds.append(cmd)
-
- return cmds
-
- def merge_bgp_peer_other(self, **kwargs):
- """ merge_bgp_peer """
-
- module = kwargs["module"]
- vrf_name = module.params['vrf_name']
- peer_addr = module.params['peer_addr']
-
- conf_str = CE_MERGE_BGP_PEER_HEADER % (vrf_name, peer_addr)
-
- cmds = []
-
- description = module.params['description']
- if description:
- conf_str += "%s" % description
-
- cmd = "peer %s description %s" % (peer_addr, description)
- cmds.append(cmd)
-
- fake_as = module.params['fake_as']
- if fake_as:
- conf_str += "%s" % fake_as
-
- cmd = "peer %s local-as %s" % (peer_addr, fake_as)
- cmds.append(cmd)
-
- dual_as = module.params['dual_as']
- if dual_as != 'no_use':
- conf_str += "%s" % dual_as
-
- if dual_as == "true":
- cmd = "peer %s local-as %s dual-as" % (peer_addr, fake_as)
- else:
- cmd = "peer %s local-as %s" % (peer_addr, fake_as)
- cmds.append(cmd)
-
- conventional = module.params['conventional']
- if conventional != 'no_use':
- conf_str += "%s" % conventional
- if conventional == "true":
- cmd = "peer %s capability-advertise conventional" % peer_addr
- else:
- cmd = "undo peer %s capability-advertise conventional" % peer_addr
- cmds.append(cmd)
-
- route_refresh = module.params['route_refresh']
- if route_refresh != 'no_use':
- conf_str += "%s" % route_refresh
-
- if route_refresh == "true":
- cmd = "peer %s capability-advertise route-refresh" % peer_addr
- else:
- cmd = "undo peer %s capability-advertise route-refresh" % peer_addr
- cmds.append(cmd)
-
- four_byte_as = module.params['four_byte_as']
- if four_byte_as != 'no_use':
- conf_str += "%s" % four_byte_as
-
- if four_byte_as == "true":
- cmd = "peer %s capability-advertise 4-byte-as" % peer_addr
- else:
- cmd = "undo peer %s capability-advertise 4-byte-as" % peer_addr
- cmds.append(cmd)
-
- is_ignore = module.params['is_ignore']
- if is_ignore != 'no_use':
- conf_str += "%s" % is_ignore
-
- if is_ignore == "true":
- cmd = "peer %s ignore" % peer_addr
- else:
- cmd = "undo peer %s ignore" % peer_addr
- cmds.append(cmd)
-
- local_if_name = module.params['local_if_name']
- if local_if_name:
- conf_str += "%s" % local_if_name
-
- cmd = "peer %s connect-interface %s" % (peer_addr, local_if_name)
- cmds.append(cmd)
-
- ebgp_max_hop = module.params['ebgp_max_hop']
- if ebgp_max_hop:
- conf_str += "%s" % ebgp_max_hop
-
- cmd = "peer %s ebgp-max-hop %s" % (peer_addr, ebgp_max_hop)
- cmds.append(cmd)
-
- valid_ttl_hops = module.params['valid_ttl_hops']
- if valid_ttl_hops:
- conf_str += "%s" % valid_ttl_hops
-
- cmd = "peer %s valid-ttl-hops %s" % (peer_addr, valid_ttl_hops)
- cmds.append(cmd)
-
- connect_mode = module.params['connect_mode']
- if connect_mode:
-
- if connect_mode == "listenOnly":
- cmd = "peer %s listen-only" % peer_addr
- cmds.append(cmd)
- elif connect_mode == "connectOnly":
- cmd = "peer %s connect-only" % peer_addr
- cmds.append(cmd)
- elif connect_mode == "both":
- connect_mode = "null"
- cmd = "peer %s listen-only" % peer_addr
- cmds.append(cmd)
- cmd = "peer %s connect-only" % peer_addr
- cmds.append(cmd)
- conf_str += "%s" % connect_mode
-
- is_log_change = module.params['is_log_change']
- if is_log_change != 'no_use':
- conf_str += "%s" % is_log_change
-
- if is_log_change == "true":
- cmd = "peer %s log-change" % peer_addr
- else:
- cmd = "undo peer %s log-change" % peer_addr
- cmds.append(cmd)
-
- pswd_type = module.params['pswd_type']
- if pswd_type:
- conf_str += "%s" % pswd_type
-
- pswd_cipher_text = module.params['pswd_cipher_text']
- if pswd_cipher_text:
- conf_str += "%s" % pswd_cipher_text
-
- if pswd_type == "cipher":
- cmd = "peer %s password cipher %s" % (
- peer_addr, pswd_cipher_text)
- elif pswd_type == "simple":
- cmd = "peer %s password simple %s" % (
- peer_addr, pswd_cipher_text)
- cmds.append(cmd)
-
- keep_alive_time = module.params['keep_alive_time']
- if keep_alive_time:
- conf_str += "%s" % keep_alive_time
-
- cmd = "peer %s timer keepalive %s" % (peer_addr, keep_alive_time)
- cmds.append(cmd)
-
- hold_time = module.params['hold_time']
- if hold_time:
- conf_str += "%s" % hold_time
-
- cmd = "peer %s timer hold %s" % (peer_addr, hold_time)
- cmds.append(cmd)
-
- min_hold_time = module.params['min_hold_time']
- if min_hold_time:
- conf_str += "%s" % min_hold_time
-
- cmd = "peer %s timer min-holdtime %s" % (peer_addr, min_hold_time)
- cmds.append(cmd)
-
- key_chain_name = module.params['key_chain_name']
- if key_chain_name:
- conf_str += "%s" % key_chain_name
-
- cmd = "peer %s keychain %s" % (peer_addr, key_chain_name)
- cmds.append(cmd)
-
- conn_retry_time = module.params['conn_retry_time']
- if conn_retry_time:
- conf_str += "%s" % conn_retry_time
-
- cmd = "peer %s timer connect-retry %s" % (
- peer_addr, conn_retry_time)
- cmds.append(cmd)
-
- tcp_mss = module.params['tcp_MSS']
- if tcp_mss:
- conf_str += "%s" % tcp_mss
-
- cmd = "peer %s tcp-mss %s" % (peer_addr, tcp_mss)
- cmds.append(cmd)
-
- mpls_local_ifnet_disable = module.params['mpls_local_ifnet_disable']
- if mpls_local_ifnet_disable != 'no_use':
- conf_str += "%s" % mpls_local_ifnet_disable
-
- if mpls_local_ifnet_disable == "false":
- cmd = "undo peer %s mpls-local-ifnet disable" % peer_addr
- else:
- cmd = "peer %s mpls-local-ifnet disable" % peer_addr
- cmds.append(cmd)
-
- prepend_global_as = module.params['prepend_global_as']
- if prepend_global_as != 'no_use':
- conf_str += "%s" % prepend_global_as
-
- if prepend_global_as == "true":
- cmd = "peer %s local-as %s prepend-global-as" % (peer_addr, fake_as)
- else:
- cmd = "undo peer %s local-as %s prepend-global-as" % (peer_addr, fake_as)
- cmds.append(cmd)
-
- prepend_fake_as = module.params['prepend_fake_as']
- if prepend_fake_as != 'no_use':
- conf_str += "%s" % prepend_fake_as
-
- if prepend_fake_as == "true":
- cmd = "peer %s local-as %s prepend-local-as" % (peer_addr, fake_as)
- else:
- cmd = "undo peer %s local-as %s prepend-local-as" % (peer_addr, fake_as)
- cmds.append(cmd)
-
- conf_str += CE_MERGE_BGP_PEER_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge bgp peer other failed.')
-
- return cmds
-
- def merge_peer_bfd(self, **kwargs):
- """ merge_peer_bfd """
-
- module = kwargs["module"]
- vrf_name = module.params['vrf_name']
- peer_addr = module.params['peer_addr']
-
- conf_str = CE_MERGE_PEER_BFD_HEADER % (vrf_name, peer_addr)
-
- cmds = []
-
- is_bfd_block = module.params['is_bfd_block']
- if is_bfd_block != 'no_use':
- conf_str += "%s" % is_bfd_block
-
- if is_bfd_block == "true":
- cmd = "peer %s bfd block" % peer_addr
- else:
- cmd = "undo peer %s bfd block" % peer_addr
- cmds.append(cmd)
-
- multiplier = module.params['multiplier']
- if multiplier:
- conf_str += "%s" % multiplier
-
- cmd = "peer %s bfd detect-multiplier %s" % (peer_addr, multiplier)
- cmds.append(cmd)
-
- is_bfd_enable = module.params['is_bfd_enable']
- if is_bfd_enable != 'no_use':
- conf_str += "%s" % is_bfd_enable
-
- if is_bfd_enable == "true":
- cmd = "peer %s bfd enable" % peer_addr
- else:
- cmd = "undo peer %s bfd enable" % peer_addr
- cmds.append(cmd)
-
- rx_interval = module.params['rx_interval']
- if rx_interval:
- conf_str += "%s" % rx_interval
-
- cmd = "peer %s bfd min-rx-interval %s" % (peer_addr, rx_interval)
- cmds.append(cmd)
-
- tx_interval = module.params['tx_interval']
- if tx_interval:
- conf_str += "%s" % tx_interval
-
- cmd = "peer %s bfd min-tx-interval %s" % (peer_addr, tx_interval)
- cmds.append(cmd)
-
- is_single_hop = module.params['is_single_hop']
- if is_single_hop != 'no_use':
- conf_str += "%s" % is_single_hop
-
- if is_single_hop == "true":
- cmd = "peer %s bfd enable single-hop-prefer" % peer_addr
- else:
- cmd = "undo peer %s bfd enable single-hop-prefer" % peer_addr
- cmds.append(cmd)
-
- conf_str += CE_MERGE_PEER_BFD_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge peer bfd failed.')
-
- return cmds
-
- def delete_peer_bfd(self, **kwargs):
- """ delete_peer_bfd """
-
- module = kwargs["module"]
- vrf_name = module.params['vrf_name']
- peer_addr = module.params['peer_addr']
-
- conf_str = CE_DELETE_PEER_BFD_HEADER % (vrf_name, peer_addr)
-
- cmds = []
-
- is_bfd_block = module.params['is_bfd_block']
- if is_bfd_block != 'no_use':
- conf_str += "%s" % is_bfd_block
-
- cmd = "undo peer %s bfd block" % peer_addr
- cmds.append(cmd)
-
- multiplier = module.params['multiplier']
- if multiplier:
- conf_str += "%s" % multiplier
-
- cmd = "undo peer %s bfd detect-multiplier %s" % (
- peer_addr, multiplier)
- cmds.append(cmd)
-
- is_bfd_enable = module.params['is_bfd_enable']
- if is_bfd_enable != 'no_use':
- conf_str += "%s" % is_bfd_enable
-
- cmd = "undo peer %s bfd enable" % peer_addr
- cmds.append(cmd)
-
- rx_interval = module.params['rx_interval']
- if rx_interval:
- conf_str += "%s" % rx_interval
-
- cmd = "undo peer %s bfd min-rx-interval %s" % (
- peer_addr, rx_interval)
- cmds.append(cmd)
-
- tx_interval = module.params['tx_interval']
- if tx_interval:
- conf_str += "%s" % tx_interval
-
- cmd = "undo peer %s bfd min-tx-interval %s" % (
- peer_addr, tx_interval)
- cmds.append(cmd)
-
- is_single_hop = module.params['is_single_hop']
- if is_single_hop != 'no_use':
- conf_str += "%s" % is_single_hop
-
- cmd = "undo peer %s bfd enable single-hop-prefer" % peer_addr
- cmds.append(cmd)
-
- conf_str += CE_DELETE_PEER_BFD_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Delete peer bfd failed.')
-
- return cmds
-
-
-def main():
- """ main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- vrf_name=dict(type='str', required=True),
- peer_addr=dict(type='str', required=True),
- remote_as=dict(type='str', required=True),
- description=dict(type='str'),
- fake_as=dict(type='str'),
- dual_as=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- conventional=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- route_refresh=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- four_byte_as=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- is_ignore=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- local_if_name=dict(type='str'),
- ebgp_max_hop=dict(type='str'),
- valid_ttl_hops=dict(type='str'),
- connect_mode=dict(choices=['listenOnly', 'connectOnly', 'both']),
- is_log_change=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- pswd_type=dict(choices=['null', 'cipher', 'simple']),
- pswd_cipher_text=dict(type='str', no_log=True),
- keep_alive_time=dict(type='str'),
- hold_time=dict(type='str'),
- min_hold_time=dict(type='str'),
- key_chain_name=dict(type='str'),
- conn_retry_time=dict(type='str'),
- tcp_MSS=dict(type='str'),
- mpls_local_ifnet_disable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- prepend_global_as=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- prepend_fake_as=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- is_bfd_block=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- multiplier=dict(type='str'),
- is_bfd_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- rx_interval=dict(type='str'),
- tx_interval=dict(type='str'),
- is_single_hop=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']))
-
- argument_spec.update(ce_argument_spec)
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
-
- changed = False
- proposed = dict()
- existing = dict()
- end_state = dict()
- updates = []
-
- state = module.params['state']
- vrf_name = module.params['vrf_name']
- peer_addr = module.params['peer_addr']
- remote_as = module.params['remote_as']
- description = module.params['description']
- fake_as = module.params['fake_as']
- dual_as = module.params['dual_as']
- conventional = module.params['conventional']
- route_refresh = module.params['route_refresh']
- four_byte_as = module.params['four_byte_as']
- is_ignore = module.params['is_ignore']
- local_if_name = module.params['local_if_name']
- ebgp_max_hop = module.params['ebgp_max_hop']
- valid_ttl_hops = module.params['valid_ttl_hops']
- connect_mode = module.params['connect_mode']
- is_log_change = module.params['is_log_change']
- pswd_type = module.params['pswd_type']
- pswd_cipher_text = module.params['pswd_cipher_text']
- keep_alive_time = module.params['keep_alive_time']
- hold_time = module.params['hold_time']
- min_hold_time = module.params['min_hold_time']
- key_chain_name = module.params['key_chain_name']
- conn_retry_time = module.params['conn_retry_time']
- tcp_mss = module.params['tcp_MSS']
- mpls_local_ifnet_disable = module.params['mpls_local_ifnet_disable']
- prepend_global_as = module.params['prepend_global_as']
- prepend_fake_as = module.params['prepend_fake_as']
- is_bfd_block = module.params['is_bfd_block']
- multiplier = module.params['multiplier']
- is_bfd_enable = module.params['is_bfd_enable']
- rx_interval = module.params['rx_interval']
- tx_interval = module.params['tx_interval']
- is_single_hop = module.params['is_single_hop']
-
- ce_bgp_peer_obj = BgpNeighbor()
-
- # get proposed
- proposed["state"] = state
- if vrf_name:
- proposed["vrf_name"] = vrf_name
- if peer_addr:
- proposed["peer_addr"] = peer_addr
- if remote_as:
- proposed["remote_as"] = remote_as
- if description:
- proposed["description"] = description
- if fake_as:
- proposed["fake_as"] = fake_as
- if dual_as != 'no_use':
- proposed["dual_as"] = dual_as
- if conventional != 'no_use':
- proposed["conventional"] = conventional
- if route_refresh != 'no_use':
- proposed["route_refresh"] = route_refresh
- if four_byte_as != 'no_use':
- proposed["four_byte_as"] = four_byte_as
- if is_ignore != 'no_use':
- proposed["is_ignore"] = is_ignore
- if local_if_name:
- proposed["local_if_name"] = local_if_name
- if ebgp_max_hop:
- proposed["ebgp_max_hop"] = ebgp_max_hop
- if valid_ttl_hops:
- proposed["valid_ttl_hops"] = valid_ttl_hops
- if connect_mode:
- proposed["connect_mode"] = connect_mode
- if is_log_change != 'no_use':
- proposed["is_log_change"] = is_log_change
- if pswd_type:
- proposed["pswd_type"] = pswd_type
- if pswd_cipher_text:
- proposed["pswd_cipher_text"] = pswd_cipher_text
- if keep_alive_time:
- proposed["keep_alive_time"] = keep_alive_time
- if hold_time:
- proposed["hold_time"] = hold_time
- if min_hold_time:
- proposed["min_hold_time"] = min_hold_time
- if key_chain_name:
- proposed["key_chain_name"] = key_chain_name
- if conn_retry_time:
- proposed["conn_retry_time"] = conn_retry_time
- if tcp_mss:
- proposed["tcp_MSS"] = tcp_mss
- if mpls_local_ifnet_disable != 'no_use':
- proposed["mpls_local_ifnet_disable"] = mpls_local_ifnet_disable
- if prepend_global_as != 'no_use':
- proposed["prepend_global_as"] = prepend_global_as
- if prepend_fake_as != 'no_use':
- proposed["prepend_fake_as"] = prepend_fake_as
- if is_bfd_block != 'no_use':
- proposed["is_bfd_block"] = is_bfd_block
- if multiplier:
- proposed["multiplier"] = multiplier
- if is_bfd_enable != 'no_use':
- proposed["is_bfd_enable"] = is_bfd_enable
- if rx_interval:
- proposed["rx_interval"] = rx_interval
- if tx_interval:
- proposed["tx_interval"] = tx_interval
- if is_single_hop != 'no_use':
- proposed["is_single_hop"] = is_single_hop
-
- if not ce_bgp_peer_obj:
- module.fail_json(msg='Error: Init module failed.')
-
- need_bgp_peer_enable = ce_bgp_peer_obj.check_bgp_peer_args(module=module)
- need_bgp_peer_other_rst = ce_bgp_peer_obj.check_bgp_peer_other_args(
- module=module)
- need_peer_bfd_merge_rst = ce_bgp_peer_obj.check_peer_bfd_merge_args(
- module=module)
- need_peer_bfd_del_rst = ce_bgp_peer_obj.check_peer_bfd_delete_args(
- module=module)
-
- # bgp peer config
- if need_bgp_peer_enable["need_cfg"]:
-
- if state == "present":
-
- if remote_as:
-
- bgp_peer_exist = ce_bgp_peer_obj.get_bgp_peer(module=module)
- existing["bgp peer"] = bgp_peer_exist
-
- bgp_peer_new = (peer_addr, remote_as)
- if len(bgp_peer_exist) == 0:
- cmd = ce_bgp_peer_obj.create_bgp_peer(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- elif bgp_peer_new in bgp_peer_exist:
- pass
-
- else:
- cmd = ce_bgp_peer_obj.merge_bgp_peer(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- bgp_peer_end = ce_bgp_peer_obj.get_bgp_peer(module=module)
- end_state["bgp peer"] = bgp_peer_end
-
- else:
-
- bgp_peer_exist = ce_bgp_peer_obj.get_bgp_del_peer(module=module)
- existing["bgp peer"] = bgp_peer_exist
-
- bgp_peer_new = (peer_addr)
-
- if len(bgp_peer_exist) == 0:
- pass
-
- elif bgp_peer_new in bgp_peer_exist:
- cmd = ce_bgp_peer_obj.delete_bgp_peer(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- bgp_peer_end = ce_bgp_peer_obj.get_bgp_del_peer(module=module)
- end_state["bgp peer"] = bgp_peer_end
-
- # bgp peer other args
- exist_tmp = dict()
- for item in need_bgp_peer_other_rst:
- if item != "need_cfg":
- exist_tmp[item] = need_bgp_peer_other_rst[item]
- if exist_tmp:
- existing["bgp peer other"] = exist_tmp
-
- if need_bgp_peer_other_rst["need_cfg"]:
-
- if state == "present":
- cmd = ce_bgp_peer_obj.merge_bgp_peer_other(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- need_bgp_peer_other_rst = ce_bgp_peer_obj.check_bgp_peer_other_args(
- module=module)
- end_tmp = dict()
- for item in need_bgp_peer_other_rst:
- if item != "need_cfg":
- end_tmp[item] = need_bgp_peer_other_rst[item]
- if end_tmp:
- end_state["bgp peer other"] = end_tmp
-
- # peer bfd args
- if state == "present":
- exist_tmp = dict()
- for item in need_peer_bfd_merge_rst:
- if item != "need_cfg":
- exist_tmp[item] = need_peer_bfd_merge_rst[item]
- if exist_tmp:
- existing["peer bfd"] = exist_tmp
-
- if need_peer_bfd_merge_rst["need_cfg"]:
- cmd = ce_bgp_peer_obj.merge_peer_bfd(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- need_peer_bfd_merge_rst = ce_bgp_peer_obj.check_peer_bfd_merge_args(
- module=module)
- end_tmp = dict()
- for item in need_peer_bfd_merge_rst:
- if item != "need_cfg":
- end_tmp[item] = need_peer_bfd_merge_rst[item]
- if end_tmp:
- end_state["peer bfd"] = end_tmp
- else:
- exist_tmp = dict()
- for item in need_peer_bfd_del_rst:
- if item != "need_cfg":
- exist_tmp[item] = need_peer_bfd_del_rst[item]
- if exist_tmp:
- existing["peer bfd"] = exist_tmp
-
- # has already delete with bgp peer
-
- need_peer_bfd_del_rst = ce_bgp_peer_obj.check_peer_bfd_delete_args(
- module=module)
- end_tmp = dict()
- for item in need_peer_bfd_del_rst:
- if item != "need_cfg":
- end_tmp[item] = need_peer_bfd_del_rst[item]
- if end_tmp:
- end_state["peer bfd"] = end_tmp
-
- results = dict()
- results['proposed'] = proposed
- results['existing'] = existing
- results['changed'] = changed
- results['end_state'] = end_state
- results['updates'] = updates
-
- module.exit_json(**results)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_bgp_neighbor_af.py b/plugins/modules/network/cloudengine/ce_bgp_neighbor_af.py
deleted file mode 100644
index cf9339ef82..0000000000
--- a/plugins/modules/network/cloudengine/ce_bgp_neighbor_af.py
+++ /dev/null
@@ -1,2679 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_bgp_neighbor_af
-short_description: Manages BGP neighbor Address-family configuration on HUAWEI CloudEngine switches.
-description:
- - Manages BGP neighbor Address-family configurations on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- vrf_name:
- description:
- - Name of a BGP instance. The name is a case-sensitive string of characters.
- The BGP instance can be used only after the corresponding VPN instance is created.
- required: true
- af_type:
- description:
- - Address family type of a BGP instance.
- required: true
- choices: ['ipv4uni', 'ipv4multi', 'ipv4vpn', 'ipv6uni', 'ipv6vpn', 'evpn']
- remote_address:
- description:
- - IPv4 or IPv6 peer connection address.
- required: true
- advertise_irb:
- description:
- - If the value is true, advertised IRB routes are distinguished.
- If the value is false, advertised IRB routes are not distinguished.
- default: no_use
- choices: ['no_use','true','false']
- advertise_arp:
- description:
- - If the value is true, advertised ARP routes are distinguished.
- If the value is false, advertised ARP routes are not distinguished.
- default: no_use
- choices: ['no_use','true','false']
- advertise_remote_nexthop:
- description:
- - If the value is true, the remote next-hop attribute is advertised to peers.
- If the value is false, the remote next-hop attribute is not advertised to any peers.
- default: no_use
- choices: ['no_use','true','false']
- advertise_community:
- description:
- - If the value is true, the community attribute is advertised to peers.
- If the value is false, the community attribute is not advertised to peers.
- default: no_use
- choices: ['no_use','true','false']
- advertise_ext_community:
- description:
- - If the value is true, the extended community attribute is advertised to peers.
- If the value is false, the extended community attribute is not advertised to peers.
- default: no_use
- choices: ['no_use','true','false']
- discard_ext_community:
- description:
- - If the value is true, the extended community attribute in the peer route information is discarded.
- If the value is false, the extended community attribute in the peer route information is not discarded.
- default: no_use
- choices: ['no_use','true','false']
- allow_as_loop_enable:
- description:
- - If the value is true, repetitive local AS numbers are allowed.
- If the value is false, repetitive local AS numbers are not allowed.
- default: no_use
- choices: ['no_use','true','false']
- allow_as_loop_limit:
- description:
- - Set the maximum number of repetitive local AS number.
- The value is an integer ranging from 1 to 10.
- keep_all_routes:
- description:
- - If the value is true, the system stores all route update messages received from all peers (groups)
- after BGP connection setup.
- If the value is false, the system stores only BGP update messages that are received from peers
- and pass the configured import policy.
- default: no_use
- choices: ['no_use','true','false']
- nexthop_configure:
- description:
- - null, The next hop is not changed.
- local, The next hop is changed to the local IP address.
- invariable, Prevent the device from changing the next hop of each imported IGP route
- when advertising it to its BGP peers.
- choices: ['null', 'local', 'invariable']
- preferred_value:
- description:
- - Assign a preferred value for the routes learned from a specified peer.
- The value is an integer ranging from 0 to 65535.
- public_as_only:
- description:
- - If the value is true, sent BGP update messages carry only the public AS number but do not carry
- private AS numbers.
- If the value is false, sent BGP update messages can carry private AS numbers.
- default: no_use
- choices: ['no_use','true','false']
- public_as_only_force:
- description:
- - If the value is true, sent BGP update messages carry only the public AS number but do not carry
- private AS numbers.
- If the value is false, sent BGP update messages can carry private AS numbers.
- default: no_use
- choices: ['no_use','true','false']
- public_as_only_limited:
- description:
- - Limited use public as number.
- default: no_use
- choices: ['no_use','true','false']
- public_as_only_replace:
- description:
- - Private as replaced by public as number.
- default: no_use
- choices: ['no_use','true','false']
- public_as_only_skip_peer_as:
- description:
- - Public as only skip peer as.
- default: no_use
- choices: ['no_use','true','false']
- route_limit:
- description:
- - Configure the maximum number of routes that can be accepted from a peer.
- The value is an integer ranging from 1 to 4294967295.
- route_limit_percent:
- description:
- - Specify the percentage of routes when a router starts to generate an alarm.
- The value is an integer ranging from 1 to 100.
- route_limit_type:
- description:
- - Noparameter, After the number of received routes exceeds the threshold and the timeout
- timer expires,no action.
- AlertOnly, An alarm is generated and no additional routes will be accepted if the maximum
- number of routes allowed have been received.
- IdleForever, The connection that is interrupted is not automatically re-established if the
- maximum number of routes allowed have been received.
- IdleTimeout, After the number of received routes exceeds the threshold and the timeout timer
- expires, the connection that is interrupted is automatically re-established.
- choices: ['noparameter', 'alertOnly', 'idleForever', 'idleTimeout']
- route_limit_idle_timeout:
- description:
- - Specify the value of the idle-timeout timer to automatically reestablish the connections after
- they are cut off when the number of routes exceeds the set threshold.
- The value is an integer ranging from 1 to 1200.
- rt_updt_interval:
- description:
- - Specify the minimum interval at which Update packets are sent. The value is an integer, in seconds.
- The value is an integer ranging from 0 to 600.
- redirect_ip:
- description:
- - Redirect ip.
- default: no_use
- choices: ['no_use','true','false']
- redirect_ip_validation:
- description:
- - Redirect ip validation.
- default: no_use
- choices: ['no_use','true','false']
- aliases: ['redirect_ip_vaildation']
- reflect_client:
- description:
- - If the value is true, the local device functions as the route reflector and a peer functions
- as a client of the route reflector.
- If the value is false, the route reflector and client functions are not configured.
- default: no_use
- choices: ['no_use','true','false']
- substitute_as_enable:
- description:
- - If the value is true, the function to replace a specified peer's AS number in the AS-Path attribute with
- the local AS number is enabled.
- If the value is false, the function to replace a specified peer's AS number in the AS-Path attribute with
- the local AS number is disabled.
- default: no_use
- choices: ['no_use','true','false']
- import_rt_policy_name:
- description:
- - Specify the filtering policy applied to the routes learned from a peer.
- The value is a string of 1 to 40 characters.
- export_rt_policy_name:
- description:
- - Specify the filtering policy applied to the routes to be advertised to a peer.
- The value is a string of 1 to 40 characters.
- import_pref_filt_name:
- description:
- - Specify the IPv4 filtering policy applied to the routes received from a specified peer.
- The value is a string of 1 to 169 characters.
- export_pref_filt_name:
- description:
- - Specify the IPv4 filtering policy applied to the routes to be advertised to a specified peer.
- The value is a string of 1 to 169 characters.
- import_as_path_filter:
- description:
- - Apply an AS_Path-based filtering policy to the routes received from a specified peer.
- The value is an integer ranging from 1 to 256.
- export_as_path_filter:
- description:
- - Apply an AS_Path-based filtering policy to the routes to be advertised to a specified peer.
- The value is an integer ranging from 1 to 256.
- import_as_path_name_or_num:
- description:
- - A routing strategy based on the AS path list for routing received by a designated peer.
- export_as_path_name_or_num:
- description:
- - Application of a AS path list based filtering policy to the routing of a specified peer.
- import_acl_name_or_num:
- description:
- - Apply an IPv4 ACL-based filtering policy to the routes received from a specified peer.
- The value is a string of 1 to 32 characters.
- export_acl_name_or_num:
- description:
- - Apply an IPv4 ACL-based filtering policy to the routes to be advertised to a specified peer.
- The value is a string of 1 to 32 characters.
- ipprefix_orf_enable:
- description:
- - If the value is true, the address prefix-based Outbound Route Filter (ORF) capability is
- enabled for peers.
- If the value is false, the address prefix-based Outbound Route Filter (ORF) capability is
- disabled for peers.
- default: no_use
- choices: ['no_use','true','false']
- is_nonstd_ipprefix_mod:
- description:
- - If the value is true, Non-standard capability codes are used during capability negotiation.
- If the value is false, RFC-defined standard ORF capability codes are used during capability negotiation.
- default: no_use
- choices: ['no_use','true','false']
- orftype:
- description:
- - ORF Type.
- The value is an integer ranging from 0 to 65535.
- orf_mode:
- description:
- - ORF mode.
- null, Default value.
- receive, ORF for incoming packets.
- send, ORF for outgoing packets.
- both, ORF for incoming and outgoing packets.
- choices: ['null', 'receive', 'send', 'both']
- soostring:
- description:
- - Configure the Site-of-Origin (SoO) extended community attribute.
- The value is a string of 3 to 21 characters.
- default_rt_adv_enable:
- description:
- - If the value is true, the function to advertise default routes to peers is enabled.
- If the value is false, the function to advertise default routes to peers is disabled.
- default: no_use
- choices: ['no_use','true', 'false']
- default_rt_adv_policy:
- description:
- - Specify the name of a used policy. The value is a string.
- The value is a string of 1 to 40 characters.
- default_rt_match_mode:
- description:
- - null, Null.
- matchall, Advertise the default route if all matching conditions are met.
- matchany, Advertise the default route if any matching condition is met.
- choices: ['null', 'matchall', 'matchany']
- add_path_mode:
- description:
- - null, Null.
- receive, Support receiving Add-Path routes.
- send, Support sending Add-Path routes.
- both, Support receiving and sending Add-Path routes.
- choices: ['null', 'receive', 'send', 'both']
- adv_add_path_num:
- description:
- - The number of addPath advertise route.
- The value is an integer ranging from 2 to 64.
- origin_as_valid:
- description:
- - If the value is true, Application results of route announcement.
- If the value is false, Routing application results are not notified.
- default: no_use
- choices: ['no_use','true', 'false']
- vpls_enable:
- description:
- - If the value is true, vpls enable.
- If the value is false, vpls disable.
- default: no_use
- choices: ['no_use','true', 'false']
- vpls_ad_disable:
- description:
- - If the value is true, enable vpls-ad.
- If the value is false, disable vpls-ad.
- default: no_use
- choices: ['no_use','true', 'false']
- update_pkt_standard_compatible:
- description:
- - If the value is true, When the vpnv4 multicast neighbor receives and updates the message,
- the message has no label.
- If the value is false, When the vpnv4 multicast neighbor receives and updates the message,
- the message has label.
- default: no_use
- choices: ['no_use','true', 'false']
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine BGP neighbor address family test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Config BGP peer Address_Family"
- ce_bgp_neighbor_af:
- state: present
- vrf_name: js
- af_type: ipv4uni
- remote_address: 192.168.10.10
- nexthop_configure: local
- provider: "{{ cli }}"
-
- - name: "Undo BGP peer Address_Family"
- ce_bgp_neighbor_af:
- state: absent
- vrf_name: js
- af_type: ipv4uni
- remote_address: 192.168.10.10
- nexthop_configure: local
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"af_type": "ipv4uni", "nexthop_configure": "local",
- "remote_address": "192.168.10.10",
- "state": "present", "vrf_name": "js"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {"bgp neighbor af": {"af_type": "ipv4uni", "remote_address": "192.168.10.10",
- "vrf_name": "js"},
- "bgp neighbor af other": {"af_type": "ipv4uni", "nexthop_configure": "null",
- "vrf_name": "js"}}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"bgp neighbor af": {"af_type": "ipv4uni", "remote_address": "192.168.10.10",
- "vrf_name": "js"},
- "bgp neighbor af other": {"af_type": "ipv4uni", "nexthop_configure": "local",
- "vrf_name": "js"}}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["peer 192.168.10.10 next-hop-local"]
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec, check_ip_addr
-
-# get bgp peer af
-CE_GET_BGP_PEER_AF_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-
-
- %s
-"""
-CE_GET_BGP_PEER_AF_TAIL = """
-
-
-
-
-
-
-
-
-
-"""
-
-# merge bgp peer af
-CE_MERGE_BGP_PEER_AF_HEADER = """
-
-
-
-
-
- %s
-
-
- %s
-
-
- %s
-"""
-CE_MERGE_BGP_PEER_AF_TAIL = """
-
-
-
-
-
-
-
-
-
-"""
-
-# create bgp peer af
-CE_CREATE_BGP_PEER_AF = """
-
-
-
-
-
- %s
-
-
- %s
-
-
- %s
-
-
-
-
-
-
-
-
-
-"""
-
-# delete bgp peer af
-CE_DELETE_BGP_PEER_AF = """
-
-
-
-
-
- %s
-
-
- %s
-
-
- %s
-
-
-
-
-
-
-
-
-
-"""
-
-
-class BgpNeighborAf(object):
- """ Manages BGP neighbor Address-family configuration """
-
- def netconf_get_config(self, **kwargs):
- """ netconf_get_config """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- xml_str = get_nc_config(module, conf_str)
-
- return xml_str
-
- def netconf_set_config(self, **kwargs):
- """ netconf_set_config """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- xml_str = set_nc_config(module, conf_str)
-
- return xml_str
-
- def check_bgp_neighbor_af_args(self, **kwargs):
- """ check_bgp_neighbor_af_args """
-
- module = kwargs["module"]
- result = dict()
- need_cfg = False
-
- vrf_name = module.params['vrf_name']
- if vrf_name:
- if len(vrf_name) > 31 or len(vrf_name) == 0:
- module.fail_json(
- msg='Error: The len of vrf_name %s is out of [1 - 31].' % vrf_name)
-
- state = module.params['state']
- af_type = module.params['af_type']
- remote_address = module.params['remote_address']
-
- if not check_ip_addr(ipaddr=remote_address):
- module.fail_json(
- msg='Error: The remote_address %s is invalid.' % remote_address)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if state == "present":
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
- if re_find:
- result["remote_address"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if remote_address not in re_find:
- need_cfg = True
- else:
- need_cfg = True
- else:
- if "" in recv_xml:
- pass
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["remote_address"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] == remote_address:
- need_cfg = True
-
- result["need_cfg"] = need_cfg
- return result
-
- def check_bgp_neighbor_af_other(self, **kwargs):
- """ check_bgp_neighbor_af_other """
-
- module = kwargs["module"]
- result = dict()
- need_cfg = False
-
- state = module.params['state']
- vrf_name = module.params['vrf_name']
- af_type = module.params['af_type']
- remote_address = module.params['remote_address']
-
- if state == "absent":
- result["need_cfg"] = need_cfg
- return result
-
- advertise_irb = module.params['advertise_irb']
- if advertise_irb != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(r'.*%s\s*'
- r'(.*).*' % remote_address, recv_xml)
- if re_find:
- result["advertise_irb"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != advertise_irb:
- need_cfg = True
- else:
- need_cfg = True
-
- advertise_arp = module.params['advertise_arp']
- if advertise_arp != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(r'.*%s\s*'
- r'.*(.*).*' % remote_address, recv_xml)
-
- if re_find:
- result["advertise_arp"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != advertise_arp:
- need_cfg = True
- else:
- need_cfg = True
-
- advertise_remote_nexthop = module.params['advertise_remote_nexthop']
- if advertise_remote_nexthop != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["advertise_remote_nexthop"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != advertise_remote_nexthop:
- need_cfg = True
- else:
- need_cfg = True
-
- advertise_community = module.params['advertise_community']
- if advertise_community != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["advertise_community"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != advertise_community:
- need_cfg = True
- else:
- need_cfg = True
-
- advertise_ext_community = module.params['advertise_ext_community']
- if advertise_ext_community != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["advertise_ext_community"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != advertise_ext_community:
- need_cfg = True
- else:
- need_cfg = True
-
- discard_ext_community = module.params['discard_ext_community']
- if discard_ext_community != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["discard_ext_community"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != discard_ext_community:
- need_cfg = True
- else:
- need_cfg = True
-
- allow_as_loop_enable = module.params['allow_as_loop_enable']
- if allow_as_loop_enable != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["allow_as_loop_enable"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != allow_as_loop_enable:
- need_cfg = True
- else:
- need_cfg = True
-
- allow_as_loop_limit = module.params['allow_as_loop_limit']
- if allow_as_loop_limit:
- if int(allow_as_loop_limit) > 10 or int(allow_as_loop_limit) < 1:
- module.fail_json(
- msg='the value of allow_as_loop_limit %s is out of [1 - 10].' % allow_as_loop_limit)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["allow_as_loop_limit"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != allow_as_loop_limit:
- need_cfg = True
- else:
- need_cfg = True
-
- keep_all_routes = module.params['keep_all_routes']
- if keep_all_routes != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["keep_all_routes"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != keep_all_routes:
- need_cfg = True
- else:
- need_cfg = True
-
- nexthop_configure = module.params['nexthop_configure']
- if nexthop_configure:
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
- self.exist_nexthop_configure = "null"
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- self.exist_nexthop_configure = re_find[0]
- result["nexthop_configure"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != nexthop_configure:
- need_cfg = True
- else:
- need_cfg = True
-
- preferred_value = module.params['preferred_value']
- if preferred_value:
- if int(preferred_value) > 65535 or int(preferred_value) < 0:
- module.fail_json(
- msg='the value of preferred_value %s is out of [0 - 65535].' % preferred_value)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["preferred_value"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != preferred_value:
- need_cfg = True
- else:
- need_cfg = True
-
- public_as_only = module.params['public_as_only']
- if public_as_only != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["public_as_only"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != public_as_only:
- need_cfg = True
- else:
- need_cfg = True
-
- public_as_only_force = module.params['public_as_only_force']
- if public_as_only_force != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["public_as_only_force"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != public_as_only_force:
- need_cfg = True
- else:
- need_cfg = True
-
- public_as_only_limited = module.params['public_as_only_limited']
- if public_as_only_limited != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["public_as_only_limited"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != public_as_only_limited:
- need_cfg = True
- else:
- need_cfg = True
-
- public_as_only_replace = module.params['public_as_only_replace']
- if public_as_only_replace != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["public_as_only_replace"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != public_as_only_replace:
- need_cfg = True
- else:
- need_cfg = True
-
- public_as_only_skip_peer_as = module.params[
- 'public_as_only_skip_peer_as']
- if public_as_only_skip_peer_as != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["public_as_only_skip_peer_as"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != public_as_only_skip_peer_as:
- need_cfg = True
- else:
- need_cfg = True
-
- route_limit = module.params['route_limit']
- if route_limit:
-
- if int(route_limit) < 1:
- module.fail_json(
- msg='the value of route_limit %s is out of [1 - 4294967295].' % route_limit)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["route_limit"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != route_limit:
- need_cfg = True
- else:
- need_cfg = True
-
- route_limit_percent = module.params['route_limit_percent']
- if route_limit_percent:
-
- if int(route_limit_percent) < 1 or int(route_limit_percent) > 100:
- module.fail_json(
- msg='Error: The value of route_limit_percent %s is out of [1 - 100].' % route_limit_percent)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["route_limit_percent"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != route_limit_percent:
- need_cfg = True
- else:
- need_cfg = True
-
- route_limit_type = module.params['route_limit_type']
- if route_limit_type:
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["route_limit_type"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != route_limit_type:
- need_cfg = True
- else:
- need_cfg = True
-
- route_limit_idle_timeout = module.params['route_limit_idle_timeout']
- if route_limit_idle_timeout:
-
- if int(route_limit_idle_timeout) < 1 or int(route_limit_idle_timeout) > 1200:
- module.fail_json(
- msg='Error: The value of route_limit_idle_timeout %s is out of '
- '[1 - 1200].' % route_limit_idle_timeout)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["route_limit_idle_timeout"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != route_limit_idle_timeout:
- need_cfg = True
- else:
- need_cfg = True
-
- rt_updt_interval = module.params['rt_updt_interval']
- if rt_updt_interval:
-
- if int(rt_updt_interval) < 0 or int(rt_updt_interval) > 600:
- module.fail_json(
- msg='Error: The value of rt_updt_interval %s is out of [0 - 600].' % rt_updt_interval)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["rt_updt_interval"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != rt_updt_interval:
- need_cfg = True
- else:
- need_cfg = True
-
- redirect_ip = module.params['redirect_ip']
- if redirect_ip != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["redirect_ip"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != redirect_ip:
- need_cfg = True
- else:
- need_cfg = True
-
- redirect_ip_validation = module.params['redirect_ip_validation']
- if redirect_ip_validation != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["redirect_ip_validation"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != redirect_ip_validation:
- need_cfg = True
- else:
- need_cfg = True
-
- reflect_client = module.params['reflect_client']
- if reflect_client != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["reflect_client"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != reflect_client:
- need_cfg = True
- else:
- need_cfg = True
-
- substitute_as_enable = module.params['substitute_as_enable']
- if substitute_as_enable != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["substitute_as_enable"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != substitute_as_enable:
- need_cfg = True
- else:
- need_cfg = True
-
- import_rt_policy_name = module.params['import_rt_policy_name']
- if import_rt_policy_name:
-
- if len(import_rt_policy_name) < 1 or len(import_rt_policy_name) > 40:
- module.fail_json(
- msg='Error: The len of import_rt_policy_name %s is out of [1 - 40].' % import_rt_policy_name)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["import_rt_policy_name"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != import_rt_policy_name:
- need_cfg = True
- else:
- need_cfg = True
-
- export_rt_policy_name = module.params['export_rt_policy_name']
- if export_rt_policy_name:
-
- if len(export_rt_policy_name) < 1 or len(export_rt_policy_name) > 40:
- module.fail_json(
- msg='Error: The len of export_rt_policy_name %s is out of [1 - 40].' % export_rt_policy_name)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["export_rt_policy_name"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != export_rt_policy_name:
- need_cfg = True
- else:
- need_cfg = True
-
- import_pref_filt_name = module.params['import_pref_filt_name']
- if import_pref_filt_name:
-
- if len(import_pref_filt_name) < 1 or len(import_pref_filt_name) > 169:
- module.fail_json(
- msg='Error: The len of import_pref_filt_name %s is out of [1 - 169].' % import_pref_filt_name)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["import_pref_filt_name"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != import_pref_filt_name:
- need_cfg = True
- else:
- need_cfg = True
-
- export_pref_filt_name = module.params['export_pref_filt_name']
- if export_pref_filt_name:
-
- if len(export_pref_filt_name) < 1 or len(export_pref_filt_name) > 169:
- module.fail_json(
- msg='Error: The len of export_pref_filt_name %s is out of [1 - 169].' % export_pref_filt_name)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["export_pref_filt_name"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != export_pref_filt_name:
- need_cfg = True
- else:
- need_cfg = True
-
- import_as_path_filter = module.params['import_as_path_filter']
- if import_as_path_filter:
-
- if int(import_as_path_filter) < 1 or int(import_as_path_filter) > 256:
- module.fail_json(
- msg='Error: The value of import_as_path_filter %s is out of [1 - 256].' % import_as_path_filter)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["import_as_path_filter"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != import_as_path_filter:
- need_cfg = True
- else:
- need_cfg = True
-
- export_as_path_filter = module.params['export_as_path_filter']
- if export_as_path_filter:
-
- if int(export_as_path_filter) < 1 or int(export_as_path_filter) > 256:
- module.fail_json(
- msg='Error: The value of export_as_path_filter %s is out of [1 - 256].' % export_as_path_filter)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["export_as_path_filter"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != export_as_path_filter:
- need_cfg = True
- else:
- need_cfg = True
-
- import_as_path_name_or_num = module.params[
- 'import_as_path_name_or_num']
- if import_as_path_name_or_num:
-
- if len(import_as_path_name_or_num) < 1 or len(import_as_path_name_or_num) > 51:
- module.fail_json(
- msg='Error: The len of import_as_path_name_or_num %s is out '
- 'of [1 - 51].' % import_as_path_name_or_num)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["import_as_path_name_or_num"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != import_as_path_name_or_num:
- need_cfg = True
- else:
- need_cfg = True
-
- export_as_path_name_or_num = module.params[
- 'export_as_path_name_or_num']
- if export_as_path_name_or_num:
-
- if len(export_as_path_name_or_num) < 1 or len(export_as_path_name_or_num) > 51:
- module.fail_json(
- msg='Error: The len of export_as_path_name_or_num %s is out '
- 'of [1 - 51].' % export_as_path_name_or_num)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["export_as_path_name_or_num"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != export_as_path_name_or_num:
- need_cfg = True
- else:
- need_cfg = True
-
- import_acl_name_or_num = module.params['import_acl_name_or_num']
- if import_acl_name_or_num:
-
- if len(import_acl_name_or_num) < 1 or len(import_acl_name_or_num) > 32:
- module.fail_json(
- msg='Error: The len of import_acl_name_or_num %s is out of [1 - 32].' % import_acl_name_or_num)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["import_acl_name_or_num"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != import_acl_name_or_num:
- need_cfg = True
- else:
- need_cfg = True
-
- export_acl_name_or_num = module.params['export_acl_name_or_num']
- if export_acl_name_or_num:
-
- if len(export_acl_name_or_num) < 1 or len(export_acl_name_or_num) > 32:
- module.fail_json(
- msg='Error: The len of export_acl_name_or_num %s is out of [1 - 32].' % export_acl_name_or_num)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["export_acl_name_or_num"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != export_acl_name_or_num:
- need_cfg = True
- else:
- need_cfg = True
-
- ipprefix_orf_enable = module.params['ipprefix_orf_enable']
- if ipprefix_orf_enable != 'no_use':
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["ipprefix_orf_enable"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != ipprefix_orf_enable:
- need_cfg = True
- else:
- need_cfg = True
-
- is_nonstd_ipprefix_mod = module.params['is_nonstd_ipprefix_mod']
- if is_nonstd_ipprefix_mod != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["is_nonstd_ipprefix_mod"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != is_nonstd_ipprefix_mod:
- need_cfg = True
- else:
- need_cfg = True
-
- orftype = module.params['orftype']
- if orftype:
-
- if int(orftype) < 0 or int(orftype) > 65535:
- module.fail_json(
- msg='Error: The value of orftype %s is out of [0 - 65535].' % orftype)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["orftype"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != orftype:
- need_cfg = True
- else:
- need_cfg = True
-
- orf_mode = module.params['orf_mode']
- if orf_mode:
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["orf_mode"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != orf_mode:
- need_cfg = True
- else:
- need_cfg = True
-
- soostring = module.params['soostring']
- if soostring:
-
- if len(soostring) < 3 or len(soostring) > 21:
- module.fail_json(
- msg='Error: The len of soostring %s is out of [3 - 21].' % soostring)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["soostring"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != soostring:
- need_cfg = True
- else:
- need_cfg = True
-
- default_rt_adv_enable = module.params['default_rt_adv_enable']
- if default_rt_adv_enable != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["default_rt_adv_enable"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != default_rt_adv_enable:
- need_cfg = True
- else:
- need_cfg = True
-
- default_rt_adv_policy = module.params['default_rt_adv_policy']
- if default_rt_adv_policy:
-
- if len(default_rt_adv_policy) < 1 or len(default_rt_adv_policy) > 40:
- module.fail_json(
- msg='Error: The len of default_rt_adv_policy %s is out of [1 - 40].' % default_rt_adv_policy)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["default_rt_adv_policy"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != default_rt_adv_policy:
- need_cfg = True
- else:
- need_cfg = True
-
- default_rt_match_mode = module.params['default_rt_match_mode']
- if default_rt_match_mode:
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["default_rt_match_mode"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != default_rt_match_mode:
- need_cfg = True
- else:
- need_cfg = True
-
- add_path_mode = module.params['add_path_mode']
- if add_path_mode:
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["add_path_mode"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != add_path_mode:
- need_cfg = True
- else:
- need_cfg = True
-
- adv_add_path_num = module.params['adv_add_path_num']
- if adv_add_path_num:
-
- if int(adv_add_path_num) < 2 or int(adv_add_path_num) > 64:
- module.fail_json(
- msg='Error: The value of adv_add_path_num %s is out of [2 - 64].' % adv_add_path_num)
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["adv_add_path_num"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != adv_add_path_num:
- need_cfg = True
- else:
- need_cfg = True
-
- origin_as_valid = module.params['origin_as_valid']
- if origin_as_valid != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["origin_as_valid"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != origin_as_valid:
- need_cfg = True
- else:
- need_cfg = True
-
- vpls_enable = module.params['vpls_enable']
- if vpls_enable != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["vpls_enable"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != vpls_enable:
- need_cfg = True
- else:
- need_cfg = True
-
- vpls_ad_disable = module.params['vpls_ad_disable']
- if vpls_ad_disable != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["vpls_ad_disable"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != vpls_ad_disable:
- need_cfg = True
- else:
- need_cfg = True
-
- update_pkt_standard_compatible = module.params[
- 'update_pkt_standard_compatible']
- if update_pkt_standard_compatible != 'no_use':
-
- conf_str = CE_GET_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + "" + \
- CE_GET_BGP_PEER_AF_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- need_cfg = True
- else:
- re_find = re.findall(
- r'.*(.*).*', recv_xml)
-
- if re_find:
- result["update_pkt_standard_compatible"] = re_find
- result["vrf_name"] = vrf_name
- result["af_type"] = af_type
- if re_find[0] != update_pkt_standard_compatible:
- need_cfg = True
- else:
- need_cfg = True
-
- result["need_cfg"] = need_cfg
- return result
-
- def merge_bgp_peer_af(self, **kwargs):
- """ merge_bgp_peer_af """
-
- module = kwargs["module"]
-
- vrf_name = module.params['vrf_name']
- af_type = module.params['af_type']
- remote_address = module.params['remote_address']
-
- conf_str = CE_MERGE_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address) + CE_MERGE_BGP_PEER_AF_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge bgp peer address family failed.')
-
- cmds = []
- cmd = af_type
- if af_type == "ipv4uni":
- if vrf_name == "_public_":
- cmd = "ipv4-family unicast"
- else:
- cmd = "ipv4-family vpn-instance %s" % vrf_name
- elif af_type == "ipv4multi":
- cmd = "ipv4-family multicast"
- elif af_type == "ipv6uni":
- if vrf_name == "_public_":
- cmd = "ipv6-family unicast"
- else:
- cmd = "ipv6-family vpn-instance %s" % vrf_name
- elif af_type == "evpn":
- cmd = "l2vpn-family evpn"
- elif af_type == "ipv4vpn":
- cmd = "ipv4-family vpnv4"
- elif af_type == "ipv6vpn":
- cmd = "ipv6-family vpnv6"
- cmds.append(cmd)
- if vrf_name == "_public_":
- cmd = "peer %s enable" % remote_address
- else:
- cmd = "peer %s" % remote_address
- cmds.append(cmd)
-
- return cmds
-
- def create_bgp_peer_af(self, **kwargs):
- """ create_bgp_peer_af """
-
- module = kwargs["module"]
-
- vrf_name = module.params['vrf_name']
- af_type = module.params['af_type']
- remote_address = module.params['remote_address']
-
- conf_str = CE_CREATE_BGP_PEER_AF % (vrf_name, af_type, remote_address)
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Create bgp peer address family failed.')
-
- cmds = []
- cmd = af_type
- if af_type == "ipv4uni":
- if vrf_name == "_public_":
- cmd = "ipv4-family unicast"
- else:
- cmd = "ipv4-family vpn-instance %s" % vrf_name
- elif af_type == "ipv4multi":
- cmd = "ipv4-family multicast"
- elif af_type == "ipv6uni":
- if vrf_name == "_public_":
- cmd = "ipv6-family unicast"
- else:
- cmd = "ipv6-family vpn-instance %s" % vrf_name
- elif af_type == "evpn":
- cmd = "l2vpn-family evpn"
- elif af_type == "ipv4vpn":
- cmd = "ipv4-family vpnv4"
- elif af_type == "ipv6vpn":
- cmd = "ipv6-family vpnv6"
- cmds.append(cmd)
- if vrf_name == "_public_":
- cmd = "peer %s enable" % remote_address
- else:
- cmd = "peer %s" % remote_address
- cmds.append(cmd)
-
- return cmds
-
- def delete_bgp_peer_af(self, **kwargs):
- """ delete_bgp_peer_af """
-
- module = kwargs["module"]
-
- vrf_name = module.params['vrf_name']
- af_type = module.params['af_type']
- remote_address = module.params['remote_address']
-
- conf_str = CE_DELETE_BGP_PEER_AF % (vrf_name, af_type, remote_address)
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Delete bgp peer address family failed.')
-
- cmds = []
- cmd = af_type
- if af_type == "ipv4uni":
- if vrf_name == "_public_":
- cmd = "ipv4-family unicast"
- else:
- cmd = "ipv4-family vpn-instance %s" % vrf_name
- elif af_type == "ipv4multi":
- cmd = "ipv4-family multicast"
- elif af_type == "ipv6uni":
- if vrf_name == "_public_":
- cmd = "ipv6-family unicast"
- else:
- cmd = "ipv6-family vpn-instance %s" % vrf_name
- elif af_type == "evpn":
- cmd = "l2vpn-family evpn"
- elif af_type == "ipv4vpn":
- cmd = "ipv4-family vpnv4"
- elif af_type == "ipv6vpn":
- cmd = "ipv6-family vpnv6"
- cmds.append(cmd)
- if vrf_name == "_public_":
- cmd = "undo peer %s enable" % remote_address
- else:
- cmd = "undo peer %s" % remote_address
- cmds.append(cmd)
-
- return cmds
-
- def merge_bgp_peer_af_other(self, **kwargs):
- """ merge_bgp_peer_af_other """
-
- module = kwargs["module"]
-
- vrf_name = module.params['vrf_name']
- af_type = module.params['af_type']
- remote_address = module.params['remote_address']
-
- conf_str = CE_MERGE_BGP_PEER_AF_HEADER % (
- vrf_name, af_type, remote_address)
-
- cmds = []
-
- advertise_irb = module.params['advertise_irb']
- if advertise_irb != 'no_use':
- conf_str += "%s" % advertise_irb
-
- if advertise_irb == "true":
- cmd = "peer %s advertise irb" % remote_address
- else:
- cmd = "undo peer %s advertise irb" % remote_address
- cmds.append(cmd)
-
- advertise_arp = module.params['advertise_arp']
- if advertise_arp != 'no_use':
- conf_str += "%s" % advertise_arp
-
- if advertise_arp == "true":
- cmd = "peer %s advertise arp" % remote_address
- else:
- cmd = "undo peer %s advertise arp" % remote_address
- cmds.append(cmd)
-
- advertise_remote_nexthop = module.params['advertise_remote_nexthop']
- if advertise_remote_nexthop != 'no_use':
- conf_str += "%s" % advertise_remote_nexthop
-
- if advertise_remote_nexthop == "true":
- cmd = "peer %s advertise remote-nexthop" % remote_address
- else:
- cmd = "undo peer %s advertise remote-nexthop" % remote_address
- cmds.append(cmd)
-
- advertise_community = module.params['advertise_community']
- if advertise_community != 'no_use':
- conf_str += "%s" % advertise_community
-
- if advertise_community == "true":
- cmd = "peer %s advertise-community" % remote_address
- else:
- cmd = "undo peer %s advertise-community" % remote_address
- cmds.append(cmd)
-
- advertise_ext_community = module.params['advertise_ext_community']
- if advertise_ext_community != 'no_use':
- conf_str += "%s" % advertise_ext_community
-
- if advertise_ext_community == "true":
- cmd = "peer %s advertise-ext-community" % remote_address
- else:
- cmd = "undo peer %s advertise-ext-community" % remote_address
- cmds.append(cmd)
-
- discard_ext_community = module.params['discard_ext_community']
- if discard_ext_community != 'no_use':
- conf_str += "%s" % discard_ext_community
-
- if discard_ext_community == "true":
- cmd = "peer %s discard-ext-community" % remote_address
- else:
- cmd = "undo peer %s discard-ext-community" % remote_address
- cmds.append(cmd)
-
- allow_as_loop_enable = module.params['allow_as_loop_enable']
- if allow_as_loop_enable != 'no_use':
- conf_str += "%s" % allow_as_loop_enable
-
- if allow_as_loop_enable == "true":
- cmd = "peer %s allow-as-loop" % remote_address
- else:
- cmd = "undo peer %s allow-as-loop" % remote_address
- cmds.append(cmd)
-
- allow_as_loop_limit = module.params['allow_as_loop_limit']
- if allow_as_loop_limit:
- conf_str += "%s" % allow_as_loop_limit
-
- if allow_as_loop_enable == "true":
- cmd = "peer %s allow-as-loop %s" % (remote_address, allow_as_loop_limit)
- else:
- cmd = "undo peer %s allow-as-loop" % remote_address
- cmds.append(cmd)
-
- keep_all_routes = module.params['keep_all_routes']
- if keep_all_routes != 'no_use':
- conf_str += "%s" % keep_all_routes
-
- if keep_all_routes == "true":
- cmd = "peer %s keep-all-routes" % remote_address
- else:
- cmd = "undo peer %s keep-all-routes" % remote_address
- cmds.append(cmd)
-
- nexthop_configure = module.params['nexthop_configure']
- if nexthop_configure:
- conf_str += "%s" % nexthop_configure
-
- if nexthop_configure == "local":
- cmd = "peer %s next-hop-local" % remote_address
- cmds.append(cmd)
- elif nexthop_configure == "invariable":
- cmd = "peer %s next-hop-invariable" % remote_address
- cmds.append(cmd)
- else:
- if self.exist_nexthop_configure != "null":
- if self.exist_nexthop_configure == "local":
- cmd = "undo peer %s next-hop-local" % remote_address
- cmds.append(cmd)
- elif self.exist_nexthop_configure == "invariable":
- cmd = "undo peer %s next-hop-invariable" % remote_address
- cmds.append(cmd)
- preferred_value = module.params['preferred_value']
- if preferred_value:
- conf_str += "%s" % preferred_value
-
- cmd = "peer %s preferred-value %s" % (remote_address, preferred_value)
- cmds.append(cmd)
-
- public_as_only = module.params['public_as_only']
- if public_as_only != 'no_use':
- conf_str += "%s" % public_as_only
-
- if public_as_only == "true":
- cmd = "peer %s public-as-only" % remote_address
- else:
- cmd = "undo peer %s public-as-only" % remote_address
- cmds.append(cmd)
-
- public_as_only_force = module.params['public_as_only_force']
- if public_as_only_force != 'no_use':
- conf_str += "%s" % public_as_only_force
-
- if public_as_only_force == "true":
- cmd = "peer %s public-as-only force" % remote_address
- else:
- cmd = "undo peer %s public-as-only force" % remote_address
- cmds.append(cmd)
-
- public_as_only_limited = module.params['public_as_only_limited']
- if public_as_only_limited != 'no_use':
- conf_str += "%s" % public_as_only_limited
-
- if public_as_only_limited == "true":
- cmd = "peer %s public-as-only limited" % remote_address
- else:
- cmd = "undo peer %s public-as-only limited" % remote_address
- cmds.append(cmd)
-
- public_as_only_replace = module.params['public_as_only_replace']
- if public_as_only_replace != 'no_use':
- conf_str += "%s" % public_as_only_replace
-
- if public_as_only_replace == "true":
- if public_as_only_force != "no_use":
- cmd = "peer %s public-as-only force replace" % remote_address
- if public_as_only_limited != "no_use":
- cmd = "peer %s public-as-only limited replace" % remote_address
- else:
- if public_as_only_force != "no_use":
- cmd = "undo peer %s public-as-only force replace" % remote_address
- if public_as_only_limited != "no_use":
- cmd = "undo peer %s public-as-only limited replace" % remote_address
- cmds.append(cmd)
-
- public_as_only_skip_peer_as = module.params[
- 'public_as_only_skip_peer_as']
- if public_as_only_skip_peer_as != 'no_use':
- conf_str += "%s" % public_as_only_skip_peer_as
-
- if public_as_only_skip_peer_as == "true":
- if public_as_only_force != "no_use":
- cmd = "peer %s public-as-only force include-peer-as" % remote_address
- if public_as_only_limited != "no_use":
- cmd = "peer %s public-as-only limited include-peer-as" % remote_address
- else:
- if public_as_only_force != "no_use":
- cmd = "undo peer %s public-as-only force include-peer-as" % remote_address
- if public_as_only_limited != "no_use":
- cmd = "undo peer %s public-as-only limited include-peer-as" % remote_address
- cmds.append(cmd)
-
- route_limit_sign = "route-limit"
- if af_type == "evpn":
- route_limit_sign = "mac-limit"
- route_limit = module.params['route_limit']
- if route_limit:
- conf_str += "%s" % route_limit
-
- cmd = "peer %s %s %s" % (remote_address, route_limit_sign, route_limit)
- cmds.append(cmd)
-
- route_limit_percent = module.params['route_limit_percent']
- if route_limit_percent:
- conf_str += "%s" % route_limit_percent
-
- cmd = "peer %s %s %s %s" % (remote_address, route_limit_sign, route_limit, route_limit_percent)
- cmds.append(cmd)
-
- route_limit_type = module.params['route_limit_type']
- if route_limit_type:
- conf_str += "%s" % route_limit_type
-
- if route_limit_type == "alertOnly":
- cmd = "peer %s %s %s %s alert-only" % (remote_address, route_limit_sign, route_limit, route_limit_percent)
- cmds.append(cmd)
- elif route_limit_type == "idleForever":
- cmd = "peer %s %s %s %s idle-forever" % (remote_address, route_limit_sign, route_limit, route_limit_percent)
- cmds.append(cmd)
- elif route_limit_type == "idleTimeout":
- cmd = "peer %s %s %s %s idle-timeout" % (remote_address, route_limit_sign, route_limit, route_limit_percent)
- cmds.append(cmd)
-
- route_limit_idle_timeout = module.params['route_limit_idle_timeout']
- if route_limit_idle_timeout:
- conf_str += "%s" % route_limit_idle_timeout
-
- cmd = "peer %s %s %s %s idle-timeout %s" % (remote_address, route_limit_sign, route_limit, route_limit_percent, route_limit_idle_timeout)
- cmds.append(cmd)
-
- rt_updt_interval = module.params['rt_updt_interval']
- if rt_updt_interval:
- conf_str += "%s" % rt_updt_interval
-
- cmd = "peer %s route-update-interval %s" % (remote_address, rt_updt_interval)
- cmds.append(cmd)
-
- redirect_ip = module.params['redirect_ip']
- if redirect_ip != 'no_use':
- conf_str += "%s" % redirect_ip
-
- redirect_ip_validation = module.params['redirect_ip_validation']
- if redirect_ip_validation != 'no_use':
- conf_str += "%s" % redirect_ip_validation
-
- reflect_client = module.params['reflect_client']
- if reflect_client != 'no_use':
- conf_str += "%s" % reflect_client
-
- if reflect_client == "true":
- cmd = "peer %s reflect-client" % remote_address
- else:
- cmd = "undo peer %s reflect-client" % remote_address
- cmds.append(cmd)
-
- substitute_as_enable = module.params['substitute_as_enable']
- if substitute_as_enable != 'no_use':
- conf_str += "%s" % substitute_as_enable
-
- if substitute_as_enable == "true":
- cmd = "peer %s substitute-as" % remote_address
- else:
- cmd = "undo peer %s substitute-as" % remote_address
- cmds.append(cmd)
-
- import_rt_policy_name = module.params['import_rt_policy_name']
- if import_rt_policy_name:
- conf_str += "%s" % import_rt_policy_name
-
- cmd = "peer %s route-policy %s import" % (remote_address, import_rt_policy_name)
- cmds.append(cmd)
-
- export_rt_policy_name = module.params['export_rt_policy_name']
- if export_rt_policy_name:
- conf_str += "%s" % export_rt_policy_name
-
- cmd = "peer %s route-policy %s export" % (remote_address, export_rt_policy_name)
- cmds.append(cmd)
-
- import_pref_filt_name = module.params['import_pref_filt_name']
- if import_pref_filt_name:
- conf_str += "%s" % import_pref_filt_name
-
- cmd = "peer %s ip-prefix %s import" % (remote_address, import_pref_filt_name)
- cmds.append(cmd)
-
- export_pref_filt_name = module.params['export_pref_filt_name']
- if export_pref_filt_name:
- conf_str += "%s" % export_pref_filt_name
-
- cmd = "peer %s ip-prefix %s export" % (remote_address, export_pref_filt_name)
- cmds.append(cmd)
-
- import_as_path_filter = module.params['import_as_path_filter']
- if import_as_path_filter:
- conf_str += "%s" % import_as_path_filter
-
- cmd = "peer %s as-path-filter %s import" % (remote_address, import_as_path_filter)
- cmds.append(cmd)
-
- export_as_path_filter = module.params['export_as_path_filter']
- if export_as_path_filter:
- conf_str += "%s" % export_as_path_filter
-
- cmd = "peer %s as-path-filter %s export" % (remote_address, export_as_path_filter)
- cmds.append(cmd)
-
- import_as_path_name_or_num = module.params[
- 'import_as_path_name_or_num']
- if import_as_path_name_or_num:
- conf_str += "%s" % import_as_path_name_or_num
-
- cmd = "peer %s as-path-filter %s import" % (remote_address, import_as_path_name_or_num)
- cmds.append(cmd)
-
- export_as_path_name_or_num = module.params[
- 'export_as_path_name_or_num']
- if export_as_path_name_or_num:
- conf_str += "%s" % export_as_path_name_or_num
-
- cmd = "peer %s as-path-filter %s export" % (remote_address, export_as_path_name_or_num)
- cmds.append(cmd)
-
- import_acl_name_or_num = module.params['import_acl_name_or_num']
- if import_acl_name_or_num:
- conf_str += "%s" % import_acl_name_or_num
- if import_acl_name_or_num.isdigit():
- cmd = "peer %s filter-policy %s import" % (remote_address, import_acl_name_or_num)
- else:
- cmd = "peer %s filter-policy acl-name %s import" % (remote_address, import_acl_name_or_num)
- cmds.append(cmd)
-
- export_acl_name_or_num = module.params['export_acl_name_or_num']
- if export_acl_name_or_num:
- conf_str += "%s" % export_acl_name_or_num
- if export_acl_name_or_num.isdigit():
- cmd = "peer %s filter-policy %s export" % (remote_address, export_acl_name_or_num)
- else:
- cmd = "peer %s filter-policy acl-name %s export" % (remote_address, export_acl_name_or_num)
- cmds.append(cmd)
-
- ipprefix_orf_enable = module.params['ipprefix_orf_enable']
- if ipprefix_orf_enable != 'no_use':
- conf_str += "%s" % ipprefix_orf_enable
-
- if ipprefix_orf_enable == "true":
- cmd = "peer %s capability-advertise orf ip-prefix" % remote_address
- else:
- cmd = "undo peer %s capability-advertise orf ip-prefix" % remote_address
- cmds.append(cmd)
-
- is_nonstd_ipprefix_mod = module.params['is_nonstd_ipprefix_mod']
- if is_nonstd_ipprefix_mod != 'no_use':
- conf_str += "%s" % is_nonstd_ipprefix_mod
-
- if is_nonstd_ipprefix_mod == "true":
- if ipprefix_orf_enable == "true":
- cmd = "peer %s capability-advertise orf non-standard-compatible" % remote_address
- else:
- cmd = "undo peer %s capability-advertise orf non-standard-compatible" % remote_address
- cmds.append(cmd)
- else:
- if ipprefix_orf_enable == "true":
- cmd = "peer %s capability-advertise orf" % remote_address
- else:
- cmd = "undo peer %s capability-advertise orf" % remote_address
- cmds.append(cmd)
-
- orftype = module.params['orftype']
- if orftype:
- conf_str += "%s" % orftype
-
- orf_mode = module.params['orf_mode']
- if orf_mode:
- conf_str += "%s" % orf_mode
-
- if ipprefix_orf_enable == "true":
- cmd = "peer %s capability-advertise orf ip-prefix %s" % (remote_address, orf_mode)
- else:
- cmd = "undo peer %s capability-advertise orf ip-prefix %s" % (remote_address, orf_mode)
- cmds.append(cmd)
-
- soostring = module.params['soostring']
- if soostring:
- conf_str += "%s" % soostring
-
- cmd = "peer %s soo %s" % (remote_address, soostring)
- cmds.append(cmd)
-
- cmd = ""
- default_rt_adv_enable = module.params['default_rt_adv_enable']
- if default_rt_adv_enable != 'no_use':
- conf_str += "%s" % default_rt_adv_enable
-
- if default_rt_adv_enable == "true":
- cmd += "peer %s default-route-advertise" % remote_address
- else:
- cmd += "undo peer %s default-route-advertise" % remote_address
-
- default_rt_adv_policy = module.params['default_rt_adv_policy']
- if default_rt_adv_policy:
- conf_str += "%s" % default_rt_adv_policy
- cmd += " route-policy %s" % default_rt_adv_policy
-
- default_rt_match_mode = module.params['default_rt_match_mode']
- if default_rt_match_mode:
- conf_str += "%s" % default_rt_match_mode
-
- if default_rt_match_mode == "matchall":
- cmd += " conditional-route-match-all"
- elif default_rt_match_mode == "matchany":
- cmd += " conditional-route-match-any"
-
- if cmd:
- cmds.append(cmd)
-
- add_path_mode = module.params['add_path_mode']
- if add_path_mode:
- conf_str += "%s" % add_path_mode
- if add_path_mode == "receive":
- cmd = "peer %s capability-advertise add-path receive" % remote_address
- elif add_path_mode == "send":
- cmd = "peer %s capability-advertise add-path send" % remote_address
- elif add_path_mode == "both":
- cmd = "peer %s capability-advertise add-path both" % remote_address
- cmds.append(cmd)
-
- adv_add_path_num = module.params['adv_add_path_num']
- if adv_add_path_num:
- conf_str += "%s" % adv_add_path_num
- cmd = "peer %s advertise add-path path-number %s" % (remote_address, adv_add_path_num)
- cmds.append(cmd)
- origin_as_valid = module.params['origin_as_valid']
- if origin_as_valid != 'no_use':
- conf_str += "%s" % origin_as_valid
-
- vpls_enable = module.params['vpls_enable']
- if vpls_enable != 'no_use':
- conf_str += "%s" % vpls_enable
-
- vpls_ad_disable = module.params['vpls_ad_disable']
- if vpls_ad_disable != 'no_use':
- conf_str += "%s" % vpls_ad_disable
-
- update_pkt_standard_compatible = module.params[
- 'update_pkt_standard_compatible']
- if update_pkt_standard_compatible != 'no_use':
- conf_str += "%s" % update_pkt_standard_compatible
-
- conf_str += CE_MERGE_BGP_PEER_AF_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge bgp peer address family other failed.')
-
- return cmds
-
-
-def main():
- """ main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- vrf_name=dict(type='str', required=True),
- af_type=dict(choices=['ipv4uni', 'ipv4multi', 'ipv4vpn',
- 'ipv6uni', 'ipv6vpn', 'evpn'], required=True),
- remote_address=dict(type='str', required=True),
- advertise_irb=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- advertise_arp=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- advertise_remote_nexthop=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- advertise_community=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- advertise_ext_community=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- discard_ext_community=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- allow_as_loop_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- allow_as_loop_limit=dict(type='str'),
- keep_all_routes=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- nexthop_configure=dict(choices=['null', 'local', 'invariable']),
- preferred_value=dict(type='str'),
- public_as_only=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- public_as_only_force=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- public_as_only_limited=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- public_as_only_replace=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- public_as_only_skip_peer_as=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- route_limit=dict(type='str'),
- route_limit_percent=dict(type='str'),
- route_limit_type=dict(
- choices=['noparameter', 'alertOnly', 'idleForever', 'idleTimeout']),
- route_limit_idle_timeout=dict(type='str'),
- rt_updt_interval=dict(type='str'),
- redirect_ip=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- redirect_ip_validation=dict(
- type='str', default='no_use',
- choices=['no_use', 'true', 'false'], aliases=['redirect_ip_vaildation']),
- reflect_client=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- substitute_as_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- import_rt_policy_name=dict(type='str'),
- export_rt_policy_name=dict(type='str'),
- import_pref_filt_name=dict(type='str'),
- export_pref_filt_name=dict(type='str'),
- import_as_path_filter=dict(type='str'),
- export_as_path_filter=dict(type='str'),
- import_as_path_name_or_num=dict(type='str'),
- export_as_path_name_or_num=dict(type='str'),
- import_acl_name_or_num=dict(type='str'),
- export_acl_name_or_num=dict(type='str'),
- ipprefix_orf_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- is_nonstd_ipprefix_mod=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- orftype=dict(type='str'),
- orf_mode=dict(choices=['null', 'receive', 'send', 'both']),
- soostring=dict(type='str'),
- default_rt_adv_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- default_rt_adv_policy=dict(type='str'),
- default_rt_match_mode=dict(choices=['null', 'matchall', 'matchany']),
- add_path_mode=dict(choices=['null', 'receive', 'send', 'both']),
- adv_add_path_num=dict(type='str'),
- origin_as_valid=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- vpls_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- vpls_ad_disable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- update_pkt_standard_compatible=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']))
-
- argument_spec.update(ce_argument_spec)
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
-
- changed = False
- proposed = dict()
- existing = dict()
- end_state = dict()
- updates = []
-
- state = module.params['state']
- vrf_name = module.params['vrf_name']
- af_type = module.params['af_type']
- remote_address = module.params['remote_address']
- advertise_irb = module.params['advertise_irb']
- advertise_arp = module.params['advertise_arp']
- advertise_remote_nexthop = module.params['advertise_remote_nexthop']
- advertise_community = module.params['advertise_community']
- advertise_ext_community = module.params['advertise_ext_community']
- discard_ext_community = module.params['discard_ext_community']
- allow_as_loop_enable = module.params['allow_as_loop_enable']
- allow_as_loop_limit = module.params['allow_as_loop_limit']
- keep_all_routes = module.params['keep_all_routes']
- nexthop_configure = module.params['nexthop_configure']
- preferred_value = module.params['preferred_value']
- public_as_only = module.params['public_as_only']
- public_as_only_force = module.params['public_as_only_force']
- public_as_only_limited = module.params['public_as_only_limited']
- public_as_only_replace = module.params['public_as_only_replace']
- public_as_only_skip_peer_as = module.params['public_as_only_skip_peer_as']
- route_limit = module.params['route_limit']
- route_limit_percent = module.params['route_limit_percent']
- route_limit_type = module.params['route_limit_type']
- route_limit_idle_timeout = module.params['route_limit_idle_timeout']
- rt_updt_interval = module.params['rt_updt_interval']
- redirect_ip = module.params['redirect_ip']
- redirect_ip_validation = module.params['redirect_ip_validation']
- reflect_client = module.params['reflect_client']
- substitute_as_enable = module.params['substitute_as_enable']
- import_rt_policy_name = module.params['import_rt_policy_name']
- export_rt_policy_name = module.params['export_rt_policy_name']
- import_pref_filt_name = module.params['import_pref_filt_name']
- export_pref_filt_name = module.params['export_pref_filt_name']
- import_as_path_filter = module.params['import_as_path_filter']
- export_as_path_filter = module.params['export_as_path_filter']
- import_as_path_name_or_num = module.params['import_as_path_name_or_num']
- export_as_path_name_or_num = module.params['export_as_path_name_or_num']
- import_acl_name_or_num = module.params['import_acl_name_or_num']
- export_acl_name_or_num = module.params['export_acl_name_or_num']
- ipprefix_orf_enable = module.params['ipprefix_orf_enable']
- is_nonstd_ipprefix_mod = module.params['is_nonstd_ipprefix_mod']
- orftype = module.params['orftype']
- orf_mode = module.params['orf_mode']
- soostring = module.params['soostring']
- default_rt_adv_enable = module.params['default_rt_adv_enable']
- default_rt_adv_policy = module.params['default_rt_adv_policy']
- default_rt_match_mode = module.params['default_rt_match_mode']
- add_path_mode = module.params['add_path_mode']
- adv_add_path_num = module.params['adv_add_path_num']
- origin_as_valid = module.params['origin_as_valid']
- vpls_enable = module.params['vpls_enable']
- vpls_ad_disable = module.params['vpls_ad_disable']
- update_pkt_standard_compatible = module.params[
- 'update_pkt_standard_compatible']
-
- ce_bgp_peer_af_obj = BgpNeighborAf()
-
- # get proposed
- proposed["state"] = state
- if vrf_name:
- proposed["vrf_name"] = vrf_name
- if af_type:
- proposed["af_type"] = af_type
- if remote_address:
- proposed["remote_address"] = remote_address
- if advertise_irb != 'no_use':
- proposed["advertise_irb"] = advertise_irb
- if advertise_arp != 'no_use':
- proposed["advertise_arp"] = advertise_arp
- if advertise_remote_nexthop != 'no_use':
- proposed["advertise_remote_nexthop"] = advertise_remote_nexthop
- if advertise_community != 'no_use':
- proposed["advertise_community"] = advertise_community
- if advertise_ext_community != 'no_use':
- proposed["advertise_ext_community"] = advertise_ext_community
- if discard_ext_community != 'no_use':
- proposed["discard_ext_community"] = discard_ext_community
- if allow_as_loop_enable != 'no_use':
- proposed["allow_as_loop_enable"] = allow_as_loop_enable
- if allow_as_loop_limit:
- proposed["allow_as_loop_limit"] = allow_as_loop_limit
- if keep_all_routes != 'no_use':
- proposed["keep_all_routes"] = keep_all_routes
- if nexthop_configure:
- proposed["nexthop_configure"] = nexthop_configure
- if preferred_value:
- proposed["preferred_value"] = preferred_value
- if public_as_only != 'no_use':
- proposed["public_as_only"] = public_as_only
- if public_as_only_force != 'no_use':
- proposed["public_as_only_force"] = public_as_only_force
- if public_as_only_limited != 'no_use':
- proposed["public_as_only_limited"] = public_as_only_limited
- if public_as_only_replace != 'no_use':
- proposed["public_as_only_replace"] = public_as_only_replace
- if public_as_only_skip_peer_as != 'no_use':
- proposed["public_as_only_skip_peer_as"] = public_as_only_skip_peer_as
- if route_limit:
- proposed["route_limit"] = route_limit
- if route_limit_percent:
- proposed["route_limit_percent"] = route_limit_percent
- if route_limit_type:
- proposed["route_limit_type"] = route_limit_type
- if route_limit_idle_timeout:
- proposed["route_limit_idle_timeout"] = route_limit_idle_timeout
- if rt_updt_interval:
- proposed["rt_updt_interval"] = rt_updt_interval
- if redirect_ip != 'no_use':
- proposed["redirect_ip"] = redirect_ip
- if redirect_ip_validation != 'no_use':
- proposed["redirect_ip_validation"] = redirect_ip_validation
- if reflect_client != 'no_use':
- proposed["reflect_client"] = reflect_client
- if substitute_as_enable != 'no_use':
- proposed["substitute_as_enable"] = substitute_as_enable
- if import_rt_policy_name:
- proposed["import_rt_policy_name"] = import_rt_policy_name
- if export_rt_policy_name:
- proposed["export_rt_policy_name"] = export_rt_policy_name
- if import_pref_filt_name:
- proposed["import_pref_filt_name"] = import_pref_filt_name
- if export_pref_filt_name:
- proposed["export_pref_filt_name"] = export_pref_filt_name
- if import_as_path_filter:
- proposed["import_as_path_filter"] = import_as_path_filter
- if export_as_path_filter:
- proposed["export_as_path_filter"] = export_as_path_filter
- if import_as_path_name_or_num:
- proposed["import_as_path_name_or_num"] = import_as_path_name_or_num
- if export_as_path_name_or_num:
- proposed["export_as_path_name_or_num"] = export_as_path_name_or_num
- if import_acl_name_or_num:
- proposed["import_acl_name_or_num"] = import_acl_name_or_num
- if export_acl_name_or_num:
- proposed["export_acl_name_or_num"] = export_acl_name_or_num
- if ipprefix_orf_enable != 'no_use':
- proposed["ipprefix_orf_enable"] = ipprefix_orf_enable
- if is_nonstd_ipprefix_mod != 'no_use':
- proposed["is_nonstd_ipprefix_mod"] = is_nonstd_ipprefix_mod
- if orftype:
- proposed["orftype"] = orftype
- if orf_mode:
- proposed["orf_mode"] = orf_mode
- if soostring:
- proposed["soostring"] = soostring
- if default_rt_adv_enable != 'no_use':
- proposed["default_rt_adv_enable"] = default_rt_adv_enable
- if default_rt_adv_policy:
- proposed["default_rt_adv_policy"] = default_rt_adv_policy
- if default_rt_match_mode:
- proposed["default_rt_match_mode"] = default_rt_match_mode
- if add_path_mode:
- proposed["add_path_mode"] = add_path_mode
- if adv_add_path_num:
- proposed["adv_add_path_num"] = adv_add_path_num
- if origin_as_valid != 'no_use':
- proposed["origin_as_valid"] = origin_as_valid
- if vpls_enable != 'no_use':
- proposed["vpls_enable"] = vpls_enable
- if vpls_ad_disable != 'no_use':
- proposed["vpls_ad_disable"] = vpls_ad_disable
- if update_pkt_standard_compatible != 'no_use':
- proposed["update_pkt_standard_compatible"] = update_pkt_standard_compatible
-
- if not ce_bgp_peer_af_obj:
- module.fail_json(msg='Error: Init module failed.')
-
- bgp_peer_af_rst = ce_bgp_peer_af_obj.check_bgp_neighbor_af_args(
- module=module)
- bgp_peer_af_other_rst = ce_bgp_peer_af_obj.check_bgp_neighbor_af_other(
- module=module)
-
- # state exist bgp peer address family config
- exist_tmp = dict()
- for item in bgp_peer_af_rst:
- if item != "need_cfg":
- exist_tmp[item] = bgp_peer_af_rst[item]
- if exist_tmp:
- existing["bgp neighbor af"] = exist_tmp
- # state exist bgp peer address family other config
- exist_tmp = dict()
- for item in bgp_peer_af_other_rst:
- if item != "need_cfg":
- exist_tmp[item] = bgp_peer_af_other_rst[item]
- if exist_tmp:
- existing["bgp neighbor af other"] = exist_tmp
-
- if state == "present":
- if bgp_peer_af_rst["need_cfg"]:
- if "remote_address" in bgp_peer_af_rst.keys():
- cmd = ce_bgp_peer_af_obj.merge_bgp_peer_af(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
- else:
- cmd = ce_bgp_peer_af_obj.create_bgp_peer_af(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- if bgp_peer_af_other_rst["need_cfg"]:
- cmd = ce_bgp_peer_af_obj.merge_bgp_peer_af_other(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- else:
- if bgp_peer_af_rst["need_cfg"]:
- cmd = ce_bgp_peer_af_obj.delete_bgp_peer_af(module=module)
- changed = True
- for item in cmd:
- updates.append(item)
-
- if bgp_peer_af_other_rst["need_cfg"]:
- pass
-
- # state end bgp peer address family config
- bgp_peer_af_rst = ce_bgp_peer_af_obj.check_bgp_neighbor_af_args(
- module=module)
- end_tmp = dict()
- for item in bgp_peer_af_rst:
- if item != "need_cfg":
- end_tmp[item] = bgp_peer_af_rst[item]
- if end_tmp:
- end_state["bgp neighbor af"] = end_tmp
- # state end bgp peer address family other config
- bgp_peer_af_other_rst = ce_bgp_peer_af_obj.check_bgp_neighbor_af_other(
- module=module)
- end_tmp = dict()
- for item in bgp_peer_af_other_rst:
- if item != "need_cfg":
- end_tmp[item] = bgp_peer_af_other_rst[item]
- if end_tmp:
- end_state["bgp neighbor af other"] = end_tmp
- if end_state == existing:
- changed = False
- updates = list()
-
- results = dict()
- results['proposed'] = proposed
- results['existing'] = existing
- results['changed'] = changed
- results['end_state'] = end_state
- results['updates'] = updates
-
- module.exit_json(**results)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_command.py b/plugins/modules/network/cloudengine/ce_command.py
deleted file mode 100644
index c7aaf16919..0000000000
--- a/plugins/modules/network/cloudengine/ce_command.py
+++ /dev/null
@@ -1,263 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-
-module: ce_command
-author: "JackyGao2016 (@CloudEngine-Ansible)"
-short_description: Run arbitrary command on HUAWEI CloudEngine devices.
-description:
- - Sends an arbitrary command to an HUAWEI CloudEngine node and returns
- the results read from the device. The ce_command module includes an
- argument that will cause the module to wait for a specific condition
- before returning or timing out if the condition is not met.
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- commands:
- description:
- - The commands to send to the remote HUAWEI CloudEngine device
- over the configured provider. The resulting output from the
- command is returned. If the I(wait_for) argument is provided,
- the module is not returned until the condition is satisfied
- or the number of I(retries) has been exceeded.
- required: true
- wait_for:
- description:
- - Specifies what to evaluate from the output of the command
- and what conditionals to apply. This argument will cause
- the task to wait for a particular conditional to be true
- before moving forward. If the conditional is not true
- by the configured retries, the task fails. See examples.
- match:
- description:
- - The I(match) argument is used in conjunction with the
- I(wait_for) argument to specify the match policy. Valid
- values are C(all) or C(any). If the value is set to C(all)
- then all conditionals in the I(wait_for) must be satisfied. If
- the value is set to C(any) then only one of the values must be
- satisfied.
- default: all
- retries:
- description:
- - Specifies the number of retries a command should by tried
- before it is considered failed. The command is run on the
- target device every retry and evaluated against the I(wait_for)
- conditionals.
- default: 10
- interval:
- description:
- - Configures the interval in seconds to wait between retries
- of the command. If the command does not pass the specified
- conditional, the interval indicates how to long to wait before
- trying the command again.
- default: 1
-'''
-
-EXAMPLES = """
-# Note: examples below use the following provider dict to handle
-# transport and authentication to the node.
-
-- name: CloudEngine command test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
- - name: "Run display version on remote devices"
- ce_command:
- commands: display version
- provider: "{{ cli }}"
-
- - name: "Run display version and check to see if output contains HUAWEI"
- ce_command:
- commands: display version
- wait_for: result[0] contains HUAWEI
- provider: "{{ cli }}"
-
- - name: "Run multiple commands on remote nodes"
- ce_command:
- commands:
- - display version
- - display device
- provider: "{{ cli }}"
-
- - name: "Run multiple commands and evaluate the output"
- ce_command:
- commands:
- - display version
- - display device
- wait_for:
- - result[0] contains HUAWEI
- - result[1] contains Device
- provider: "{{ cli }}"
-"""
-
-RETURN = """
-stdout:
- description: the set of responses from the commands
- returned: always
- type: list
- sample: ['...', '...']
-
-stdout_lines:
- description: The value of stdout split into a list
- returned: always
- type: list
- sample: [['...', '...'], ['...'], ['...']]
-
-failed_conditions:
- description: the conditionals that failed
- returned: failed
- type: list
- sample: ['...', '...']
-"""
-
-
-import time
-import traceback
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec, check_args
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import run_commands
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import Conditional
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ComplexList
-from ansible.module_utils.six import string_types
-from ansible.module_utils._text import to_native
-
-
-def to_lines(stdout):
- lines = list()
- for item in stdout:
- if isinstance(item, string_types):
- item = str(item).split('\n')
- lines.append(item)
- return lines
-
-
-def parse_commands(module, warnings):
- transform = ComplexList(dict(
- command=dict(key=True),
- output=dict(),
- prompt=dict(),
- answer=dict()
- ), module)
-
- commands = transform(module.params['commands'])
-
- for _, item in enumerate(commands):
- if module.check_mode and not item['command'].startswith('dis'):
- warnings.append(
- 'Only display commands are supported when using check_mode, not '
- 'executing %s' % item['command']
- )
-
- return commands
-
-
-def to_cli(obj):
- cmd = obj['command']
- return cmd
-
-
-def main():
- """entry point for module execution
- """
- argument_spec = dict(
- # { command: , output: , prompt: , response: }
- commands=dict(type='list', required=True),
-
- wait_for=dict(type='list'),
- match=dict(default='all', choices=['any', 'all']),
-
- retries=dict(default=10, type='int'),
- interval=dict(default=1, type='int')
- )
-
- argument_spec.update(ce_argument_spec)
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- result = {'changed': False}
-
- warnings = list()
- check_args(module, warnings)
- commands = parse_commands(module, warnings)
- result['warnings'] = warnings
-
- wait_for = module.params['wait_for'] or list()
-
- try:
- conditionals = [Conditional(c) for c in wait_for]
- except AttributeError as exc:
- module.fail_json(msg=to_native(exc), exception=traceback.format_exc())
-
- retries = module.params['retries']
- interval = module.params['interval']
- match = module.params['match']
-
- while retries > 0:
- responses = run_commands(module, commands)
-
- for item in list(conditionals):
- if item(responses):
- if match == 'any':
- conditionals = list()
- break
- conditionals.remove(item)
-
- if not conditionals:
- break
-
- time.sleep(interval)
- retries -= 1
-
- if conditionals:
- failed_conditions = [item.raw for item in conditionals]
- msg = 'One or more conditional statements have not been satisfied'
- module.fail_json(msg=msg, failed_conditions=failed_conditions)
-
- result.update({
- 'stdout': responses,
- 'stdout_lines': to_lines(responses)
- })
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_config.py b/plugins/modules/network/cloudengine/ce_config.py
deleted file mode 100644
index d4b3ab9652..0000000000
--- a/plugins/modules/network/cloudengine/ce_config.py
+++ /dev/null
@@ -1,496 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_config
-author: "QijunPan (@QijunPan)"
-short_description: Manage Huawei CloudEngine configuration sections.
-description:
- - Huawei CloudEngine configurations use a simple block indent file syntax
- for segmenting configuration into sections. This module provides
- an implementation for working with CloudEngine configuration sections in
- a deterministic way. This module works with CLI transports.
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- lines:
- description:
- - The ordered set of commands that should be configured in the
- section. The commands must be the exact same commands as found
- in the device current-configuration. Be sure to note the configuration
- command syntax as some commands are automatically modified by the
- device config parser.
- parents:
- description:
- - The ordered set of parents that uniquely identify the section or hierarchy
- the commands should be checked against. If the parents argument
- is omitted, the commands are checked against the set of top
- level or global commands.
- src:
- description:
- - The I(src) argument provides a path to the configuration file
- to load into the remote system. The path can either be a full
- system path to the configuration file if the value starts with /
- or relative to the root of the implemented role or playbook.
- This argument is mutually exclusive with the I(lines) and
- I(parents) arguments.
- before:
- description:
- - The ordered set of commands to push on to the command stack if
- a change needs to be made. This allows the playbook designer
- the opportunity to perform configuration commands prior to pushing
- any changes without affecting how the set of commands are matched
- against the system.
- after:
- description:
- - The ordered set of commands to append to the end of the command
- stack if a change needs to be made. Just like with I(before) this
- allows the playbook designer to append a set of commands to be
- executed after the command set.
- match:
- description:
- - Instructs the module on the way to perform the matching of
- the set of commands against the current device config. If
- match is set to I(line), commands are matched line by line. If
- match is set to I(strict), command lines are matched with respect
- to position. If match is set to I(exact), command lines
- must be an equal match. Finally, if match is set to I(none), the
- module will not attempt to compare the source configuration with
- the current-configuration on the remote device.
- default: line
- choices: ['line', 'strict', 'exact', 'none']
- replace:
- description:
- - Instructs the module on the way to perform the configuration
- on the device. If the replace argument is set to I(line) then
- the modified lines are pushed to the device in configuration
- mode. If the replace argument is set to I(block) then the entire
- command block is pushed to the device in configuration mode if any
- line is not correct.
- default: line
- choices: ['line', 'block']
- backup:
- description:
- - This argument will cause the module to create a full backup of
- the current C(current-configuration) from the remote device before any
- changes are made. If the C(backup_options) value is not given,
- the backup file is written to the C(backup) folder in the playbook
- root directory. If the directory does not exist, it is created.
- type: bool
- default: 'no'
- config:
- description:
- - The module, by default, will connect to the remote device and
- retrieve the current current-configuration to use as a base for comparing
- against the contents of source. There are times when it is not
- desirable to have the task get the current-configuration for
- every task in a playbook. The I(config) argument allows the
- implementer to pass in the configuration to use as the base
- config for comparison.
- defaults:
- description:
- - The I(defaults) argument will influence how the current-configuration
- is collected from the device. When the value is set to true,
- the command used to collect the current-configuration is append with
- the all keyword. When the value is set to false, the command
- is issued without the all keyword.
- type: bool
- default: 'no'
- save:
- description:
- - The C(save) argument instructs the module to save the
- current-configuration to saved-configuration. This operation is performed
- after any changes are made to the current running config. If
- no changes are made, the configuration is still saved to the
- startup config. This option will always cause the module to
- return changed.
- type: bool
- default: 'no'
- backup_options:
- description:
- - This is a dict object containing configurable options related to backup file path.
- The value of this option is read only when C(backup) is set to I(yes), if C(backup) is set
- to I(no) this option will be silently ignored.
- suboptions:
- filename:
- description:
- - The filename to be used to store the backup configuration. If the filename
- is not given it will be generated based on the hostname, current time and date
- in format defined by _config.@
- dir_path:
- description:
- - This option provides the path ending with directory name in which the backup
- configuration file will be stored. If the directory does not exist it will be first
- created and the filename is either the value of C(filename) or default filename
- as described in C(filename) options description. If the path value is not given
- in that case a I(backup) directory will be created in the current working directory
- and backup configuration will be copied in C(filename) within I(backup) directory.
- type: path
- type: dict
-'''
-
-EXAMPLES = """
-# Note: examples below use the following provider dict to handle
-# transport and authentication to the node.
-
-- name: CloudEngine config test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
- - name: "Configure top level configuration and save it"
- ce_config:
- lines: sysname {{ inventory_hostname }}
- save: yes
- provider: "{{ cli }}"
-
- - name: "Configure acl configuration and save it"
- ce_config:
- lines:
- - rule 10 permit source 1.1.1.1 32
- - rule 20 permit source 2.2.2.2 32
- - rule 30 permit source 3.3.3.3 32
- - rule 40 permit source 4.4.4.4 32
- - rule 50 permit source 5.5.5.5 32
- parents: acl 2000
- before: undo acl 2000
- match: exact
- provider: "{{ cli }}"
-
- - name: "Configure acl configuration and save it"
- ce_config:
- lines:
- - rule 10 permit source 1.1.1.1 32
- - rule 20 permit source 2.2.2.2 32
- - rule 30 permit source 3.3.3.3 32
- - rule 40 permit source 4.4.4.4 32
- parents: acl 2000
- before: undo acl 2000
- replace: block
- provider: "{{ cli }}"
-
- - name: configurable backup path
- ce_config:
- lines: sysname {{ inventory_hostname }}
- provider: "{{ cli }}"
- backup: yes
- backup_options:
- filename: backup.cfg
- dir_path: /home/user
-"""
-
-RETURN = """
-updates:
- description: The set of commands that will be pushed to the remote device
- returned: Only when lines is specified.
- type: list
- sample: ['...', '...']
-backup_path:
- description: The full path to the backup file
- returned: when backup is yes
- type: str
- sample: /playbooks/ansible/backup/ce_config.2016-07-16@22:28:34
-"""
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import ConnectionError, Connection
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig as _NetworkConfig
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import dumps, ConfigLine, ignore_line
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_config, run_commands, exec_command, cli_err_msg
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec, load_config
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import check_args as ce_check_args
-import re
-
-
-def check_args(module, warnings):
- ce_check_args(module, warnings)
-
-
-def not_user_view(prompt):
- return prompt is not None and prompt.strip().startswith("[")
-
-
-def command_level(command):
- regex_level = re.search(r"^(\s*)\S+", command)
- if regex_level is not None:
- level = str(regex_level.group(1))
- return len(level)
- return 0
-
-
-def _load_config(module, config):
- """Sends configuration commands to the remote device
- """
- connection = Connection(module._socket_path)
- rc, out, err = exec_command(module, 'mmi-mode enable')
- if rc != 0:
- module.fail_json(msg='unable to set mmi-mode enable', output=err)
- rc, out, err = exec_command(module, 'system-view immediately')
- if rc != 0:
- module.fail_json(msg='unable to enter system-view', output=err)
- current_view_prompt = system_view_prompt = connection.get_prompt()
-
- for index, cmd in enumerate(config):
- level = command_level(cmd)
- current_view_prompt = connection.get_prompt()
- rc, out, err = exec_command(module, cmd)
- if rc != 0:
- print_msg = cli_err_msg(cmd.strip(), err)
- # re-try command max 3 times
- for i in (1, 2, 3):
- current_view_prompt = connection.get_prompt()
- if current_view_prompt != system_view_prompt and not_user_view(current_view_prompt):
- exec_command(module, "quit")
- current_view_prompt = connection.get_prompt()
- # if current view is system-view, break.
- if current_view_prompt == system_view_prompt and level > 0:
- break
- elif current_view_prompt == system_view_prompt or not not_user_view(current_view_prompt):
- break
- rc, out, err = exec_command(module, cmd)
- if rc == 0:
- print_msg = None
- break
- if print_msg is not None:
- module.fail_json(msg=print_msg)
-
-
-def get_running_config(module):
- contents = module.params['config']
- if not contents:
- command = "display current-configuration "
- if module.params['defaults']:
- command += 'include-default'
- resp = run_commands(module, command)
- contents = resp[0]
- return NetworkConfig(indent=1, contents=contents)
-
-
-def get_candidate(module):
- candidate = NetworkConfig(indent=1)
- if module.params['src']:
- config = module.params['src']
- candidate.load(config)
- elif module.params['lines']:
- parents = module.params['parents'] or list()
- candidate.add(module.params['lines'], parents=parents)
- return candidate
-
-
-def run(module, result):
- match = module.params['match']
- replace = module.params['replace']
-
- candidate = get_candidate(module)
-
- if match != 'none':
- before = get_running_config(module)
- path = module.params['parents']
- configobjs = candidate.difference(before, match=match, replace=replace, path=path)
- else:
- configobjs = candidate.items
-
- if configobjs:
- out_type = "commands"
- if module.params["src"] is not None:
- out_type = "raw"
- commands = dumps(configobjs, out_type).split('\n')
-
- if module.params['lines']:
- if module.params['before']:
- commands[:0] = module.params['before']
-
- if module.params['after']:
- commands.extend(module.params['after'])
-
- command_display = []
- for per_command in commands:
- if per_command.strip() not in ['quit', 'return', 'system-view']:
- command_display.append(per_command)
-
- result['commands'] = command_display
- result['updates'] = command_display
-
- if not module.check_mode:
- if module.params['parents'] is not None:
- load_config(module, commands)
- else:
- _load_config(module, commands)
- if match != "none":
- after = get_running_config(module)
- path = module.params["parents"]
- if path is not None and match != 'line':
- before_objs = before.get_block(path)
- after_objs = after.get_block(path)
- update = []
- if len(before_objs) == len(after_objs):
- for b_item, a_item in zip(before_objs, after_objs):
- if b_item != a_item:
- update.append(a_item.text)
- else:
- update = [item.text for item in after_objs]
- if len(update) == 0:
- result["changed"] = False
- result['updates'] = []
- else:
- result["changed"] = True
- result['updates'] = update
- else:
- configobjs = after.difference(before, match=match, replace=replace, path=path)
- if len(configobjs) > 0:
- result["changed"] = True
- else:
- result["changed"] = False
- result['updates'] = []
- else:
- result['changed'] = True
-
-
-class NetworkConfig(_NetworkConfig):
-
- def add(self, lines, parents=None):
- ancestors = list()
- offset = 0
- obj = None
-
- # global config command
- if not parents:
- for line in lines:
- # handle ignore lines
- if ignore_line(line):
- continue
-
- item = ConfigLine(line)
- item.raw = line
- self.items.append(item)
-
- else:
- for index, p in enumerate(parents):
- try:
- i = index + 1
- obj = self.get_block(parents[:i])[0]
- ancestors.append(obj)
-
- except ValueError:
- # add parent to config
- offset = index * self._indent
- obj = ConfigLine(p)
- obj.raw = p.rjust(len(p) + offset)
- if ancestors:
- obj._parents = list(ancestors)
- ancestors[-1]._children.append(obj)
- self.items.append(obj)
- ancestors.append(obj)
-
- # add child objects
- for line in lines:
- # handle ignore lines
- if ignore_line(line):
- continue
-
- # check if child already exists
- for child in ancestors[-1]._children:
- if child.text == line:
- break
- else:
- offset = len(parents) * self._indent
- item = ConfigLine(line)
- item.raw = line.rjust(len(line) + offset)
- item._parents = ancestors
- ancestors[-1]._children.append(item)
- self.items.append(item)
-
-
-def main():
- """ main entry point for module execution
- """
- backup_spec = dict(
- filename=dict(),
- dir_path=dict(type='path')
- )
- argument_spec = dict(
- src=dict(type='path'),
-
- lines=dict(aliases=['commands'], type='list'),
- parents=dict(type='list'),
-
- before=dict(type='list'),
- after=dict(type='list'),
-
- match=dict(default='line', choices=['line', 'strict', 'exact', 'none']),
- replace=dict(default='line', choices=['line', 'block']),
- config=dict(),
- defaults=dict(type='bool', default=False),
-
- backup=dict(type='bool', default=False),
- backup_options=dict(type='dict', options=backup_spec),
- save=dict(type='bool', default=False),
- )
-
- argument_spec.update(ce_argument_spec)
-
- mutually_exclusive = [('lines', 'src'),
- ('parents', 'src')]
-
- required_if = [('match', 'strict', ['lines']),
- ('match', 'exact', ['lines']),
- ('replace', 'block', ['lines'])]
-
- module = AnsibleModule(argument_spec=argument_spec,
- mutually_exclusive=mutually_exclusive,
- required_if=required_if,
- supports_check_mode=True)
-
- warnings = list()
- check_args(module, warnings)
-
- result = dict(changed=False, warnings=warnings)
-
- if module.params['backup']:
- result['__backup__'] = get_config(module)
-
- if any((module.params['src'], module.params['lines'])):
- run(module, result)
-
- if module.params['save']:
- if not module.check_mode:
- run_commands(module, ['return', 'mmi-mode enable', 'save'])
- result["changed"] = True
- run_commands(module, ['return', 'undo mmi-mode enable'])
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_dldp.py b/plugins/modules/network/cloudengine/ce_dldp.py
deleted file mode 100644
index 926e9e50ba..0000000000
--- a/plugins/modules/network/cloudengine/ce_dldp.py
+++ /dev/null
@@ -1,553 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-
-module: ce_dldp
-short_description: Manages global DLDP configuration on HUAWEI CloudEngine switches.
-description:
- - Manages global DLDP configuration on HUAWEI CloudEngine switches.
-author:
- - Zhijin Zhou (@QijunPan)
-notes:
- - The relevant configurations will be deleted if DLDP is disabled using enable=disable.
- - When using auth_mode=none, it will restore the default DLDP authentication mode. By default,
- DLDP packets are not authenticated.
- - By default, the working mode of DLDP is enhance, so you are advised to use work_mode=enhance to restore default
- DLDP working mode.
- - The default interval for sending Advertisement packets is 5 seconds, so you are advised to use time_interval=5 to
- restore default DLDP interval.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- enable:
- description:
- - Set global DLDP enable state.
- choices: ['enable', 'disable']
- work_mode:
- description:
- - Set global DLDP work-mode.
- choices: ['enhance', 'normal']
- time_internal:
- description:
- - Specifies the interval for sending Advertisement packets.
- The value is an integer ranging from 1 to 100, in seconds.
- The default interval for sending Advertisement packets is 5 seconds.
- auth_mode:
- description:
- - Specifies authentication algorithm of DLDP.
- choices: ['md5', 'simple', 'sha', 'hmac-sha256', 'none']
- auth_pwd:
- description:
- - Specifies authentication password.
- The value is a string of 1 to 16 case-sensitive plaintexts or 24/32/48/108/128 case-sensitive encrypted
- characters. The string excludes a question mark (?).
- reset:
- description:
- - Specify whether reset DLDP state of disabled interfaces.
- choices: ['enable', 'disable']
-'''
-
-EXAMPLES = '''
-- name: DLDP test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Configure global DLDP enable state"
- ce_dldp:
- enable: enable
- provider: "{{ cli }}"
-
- - name: "Configure DLDP work-mode and ensure global DLDP state is already enabled"
- ce_dldp:
- enable: enable
- work_mode: normal
- provider: "{{ cli }}"
-
- - name: "Configure advertisement message time interval in seconds and ensure global DLDP state is already enabled"
- ce_dldp:
- enable: enable
- time_interval: 6
- provider: "{{ cli }}"
-
- - name: "Configure a DLDP authentication mode and ensure global DLDP state is already enabled"
- ce_dldp:
- enable: enable
- auth_mode: md5
- auth_pwd: abc
- provider: "{{ cli }}"
-
- - name: "Reset DLDP state of disabled interfaces and ensure global DLDP state is already enabled"
- ce_dldp:
- enable: enable
- reset: enable
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "enable": "enable",
- "reset": "enable",
- "time_internal": "12",
- "work_mode": "normal"
- }
-existing:
- description: k/v pairs of existing global DLDP configuration
- returned: always
- type: dict
- sample: {
- "enable": "disable",
- "reset": "disable",
- "time_internal": "5",
- "work_mode": "enhance"
- }
-end_state:
- description: k/v pairs of global DLDP configuration after module execution
- returned: always
- type: dict
- sample: {
- "enable": "enable",
- "reset": "enable",
- "time_internal": "12",
- "work_mode": "normal"
- }
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: [
- "dldp enable",
- "dldp work-mode normal",
- "dldp interval 12",
- "dldp reset"
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import copy
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec, set_nc_config, get_nc_config, execute_nc_action
-
-CE_NC_ACTION_RESET_DLDP = """
-
-
-
-
-
-"""
-
-CE_NC_GET_GLOBAL_DLDP_CONFIG = """
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_DLDP_GLOBAL_CONFIG_HEAD = """
-
-
-
- %s
- %s
- %s
-"""
-
-CE_NC_MERGE_DLDP_GLOBAL_CONFIG_TAIL = """
-
-
-
-"""
-
-
-class Dldp(object):
- """Manage global dldp configuration"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # DLDP global configuration info
- self.enable = self.module.params['enable'] or None
- self.work_mode = self.module.params['work_mode'] or None
- self.internal = self.module.params['time_interval'] or None
- self.reset = self.module.params['reset'] or None
- self.auth_mode = self.module.params['auth_mode']
- self.auth_pwd = self.module.params['auth_pwd']
-
- self.dldp_conf = dict()
- self.same_conf = False
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = list()
- self.end_state = list()
-
- def check_config_if_same(self):
- """Judge whether current config is the same as what we excepted"""
-
- if self.enable and self.enable != self.dldp_conf['dldpEnable']:
- return False
-
- if self.internal and self.internal != self.dldp_conf['dldpInterval']:
- return False
-
- work_mode = 'normal'
- if self.dldp_conf['dldpWorkMode'] == 'dldpEnhance':
- work_mode = 'enhance'
- if self.work_mode and self.work_mode != work_mode:
- return False
-
- if self.auth_mode:
- if self.auth_mode != 'none':
- return False
-
- if self.auth_mode == 'none' and self.dldp_conf['dldpAuthMode'] != 'dldpAuthNone':
- return False
-
- if self.reset and self.reset == 'enable':
- return False
-
- return True
-
- def check_params(self):
- """Check all input params"""
-
- if (self.auth_mode and self.auth_mode != 'none' and not self.auth_pwd) \
- or (self.auth_pwd and not self.auth_mode):
- self.module.fail_json(msg="Error: auth_mode and auth_pwd must both exist or not exist.")
-
- if self.dldp_conf['dldpEnable'] == 'disable' and not self.enable:
- if self.work_mode or self.reset or self.internal or self.auth_mode:
- self.module.fail_json(msg="Error: when DLDP is already disabled globally, "
- "work_mode, time_internal auth_mode and reset parameters are not "
- "expected to configure.")
-
- if self.enable == 'disable' and (self.work_mode or self.internal or self.reset or self.auth_mode):
- self.module.fail_json(msg="Error: when using enable=disable, work_mode, "
- "time_internal auth_mode and reset parameters are not expected "
- "to configure.")
-
- if self.internal:
- if not self.internal.isdigit():
- self.module.fail_json(
- msg='Error: time_interval must be digit.')
-
- if int(self.internal) < 1 or int(self.internal) > 100:
- self.module.fail_json(
- msg='Error: The value of time_internal should be between 1 and 100.')
-
- if self.auth_pwd:
- if '?' in self.auth_pwd:
- self.module.fail_json(
- msg='Error: The auth_pwd string excludes a question mark (?).')
- if (len(self.auth_pwd) != 24) and (len(self.auth_pwd) != 32) and (len(self.auth_pwd) != 48) and \
- (len(self.auth_pwd) != 108) and (len(self.auth_pwd) != 128):
- if (len(self.auth_pwd) < 1) or (len(self.auth_pwd) > 16):
- self.module.fail_json(
- msg='Error: The value is a string of 1 to 16 case-sensitive plaintexts or 24/32/48/108/128 '
- 'case-sensitive encrypted characters.')
-
- def init_module(self):
- """Init module object"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed"""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_dldp_exist_config(self):
- """Get current dldp existed configuration"""
-
- dldp_conf = dict()
- xml_str = CE_NC_GET_GLOBAL_DLDP_CONFIG
- con_obj = get_nc_config(self.module, xml_str)
- if "" in con_obj:
- return dldp_conf
-
- xml_str = con_obj.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get global DLDP info
- root = ElementTree.fromstring(xml_str)
- topo = root.find("dldp/dldpSys")
- if not topo:
- self.module.fail_json(
- msg="Error: Get current DLDP configuration failed.")
-
- for eles in topo:
- if eles.tag in ["dldpEnable", "dldpInterval", "dldpWorkMode", "dldpAuthMode"]:
- if eles.tag == 'dldpEnable':
- if eles.text == 'true':
- value = 'enable'
- else:
- value = 'disable'
- else:
- value = eles.text
- dldp_conf[eles.tag] = value
-
- return dldp_conf
-
- def config_global_dldp(self):
- """Config global dldp"""
-
- if self.same_conf:
- return
-
- enable = self.enable
- if not self.enable:
- enable = self.dldp_conf['dldpEnable']
- if enable == 'enable':
- enable = 'true'
- else:
- enable = 'false'
-
- internal = self.internal
- if not self.internal:
- internal = self.dldp_conf['dldpInterval']
-
- work_mode = self.work_mode
- if not self.work_mode:
- work_mode = self.dldp_conf['dldpWorkMode']
-
- if work_mode == 'enhance' or work_mode == 'dldpEnhance':
- work_mode = 'dldpEnhance'
- else:
- work_mode = 'dldpNormal'
-
- auth_mode = self.auth_mode
- if not self.auth_mode:
- auth_mode = self.dldp_conf['dldpAuthMode']
- if auth_mode == 'md5':
- auth_mode = 'dldpAuthMD5'
- elif auth_mode == 'simple':
- auth_mode = 'dldpAuthSimple'
- elif auth_mode == 'sha':
- auth_mode = 'dldpAuthSHA'
- elif auth_mode == 'hmac-sha256':
- auth_mode = 'dldpAuthHMAC-SHA256'
- elif auth_mode == 'none':
- auth_mode = 'dldpAuthNone'
-
- xml_str = CE_NC_MERGE_DLDP_GLOBAL_CONFIG_HEAD % (
- enable, internal, work_mode)
- if self.auth_mode:
- if self.auth_mode == 'none':
- xml_str += "dldpAuthNone"
- else:
- xml_str += "%s" % auth_mode
- xml_str += "%s" % self.auth_pwd
-
- xml_str += CE_NC_MERGE_DLDP_GLOBAL_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "MERGE_DLDP_GLOBAL_CONFIG")
-
- if self.reset == 'enable':
- xml_str = CE_NC_ACTION_RESET_DLDP
- ret_xml = execute_nc_action(self.module, xml_str)
- self.check_response(ret_xml, "ACTION_RESET_DLDP")
-
- self.changed = True
-
- def get_existing(self):
- """Get existing info"""
-
- dldp_conf = dict()
-
- dldp_conf['enable'] = self.dldp_conf.get('dldpEnable', None)
- dldp_conf['time_interval'] = self.dldp_conf.get('dldpInterval', None)
- work_mode = self.dldp_conf.get('dldpWorkMode', None)
- if work_mode == 'dldpEnhance':
- dldp_conf['work_mode'] = 'enhance'
- else:
- dldp_conf['work_mode'] = 'normal'
-
- auth_mode = self.dldp_conf.get('dldpAuthMode', None)
- if auth_mode == 'dldpAuthNone':
- dldp_conf['auth_mode'] = 'none'
- elif auth_mode == 'dldpAuthSimple':
- dldp_conf['auth_mode'] = 'simple'
- elif auth_mode == 'dldpAuthMD5':
- dldp_conf['auth_mode'] = 'md5'
- elif auth_mode == 'dldpAuthSHA':
- dldp_conf['auth_mode'] = 'sha'
- else:
- dldp_conf['auth_mode'] = 'hmac-sha256'
-
- dldp_conf['reset'] = 'disable'
-
- self.existing = copy.deepcopy(dldp_conf)
-
- def get_proposed(self):
- """Get proposed result"""
-
- self.proposed = dict(enable=self.enable, work_mode=self.work_mode,
- time_interval=self.internal, reset=self.reset,
- auth_mode=self.auth_mode, auth_pwd=self.auth_pwd)
-
- def get_update_cmd(self):
- """Get update commands"""
- if self.same_conf:
- return
-
- if self.enable and self.enable != self.dldp_conf['dldpEnable']:
- if self.enable == 'enable':
- self.updates_cmd.append("dldp enable")
- elif self.enable == 'disable':
- self.updates_cmd.append("undo dldp enable")
- return
-
- work_mode = 'normal'
- if self.dldp_conf['dldpWorkMode'] == 'dldpEnhance':
- work_mode = 'enhance'
- if self.work_mode and self.work_mode != work_mode:
- if self.work_mode == 'enhance':
- self.updates_cmd.append("dldp work-mode enhance")
- else:
- self.updates_cmd.append("dldp work-mode normal")
-
- if self.internal and self.internal != self.dldp_conf['dldpInterval']:
- self.updates_cmd.append("dldp interval %s" % self.internal)
-
- if self.auth_mode:
- if self.auth_mode == 'none':
- self.updates_cmd.append("undo dldp authentication-mode")
- else:
- self.updates_cmd.append("dldp authentication-mode %s %s" % (self.auth_mode, self.auth_pwd))
-
- if self.reset and self.reset == 'enable':
- self.updates_cmd.append('dldp reset')
-
- def get_end_state(self):
- """Get end state info"""
-
- dldp_conf = dict()
- self.dldp_conf = self.get_dldp_exist_config()
-
- dldp_conf['enable'] = self.dldp_conf.get('dldpEnable', None)
- dldp_conf['time_interval'] = self.dldp_conf.get('dldpInterval', None)
- work_mode = self.dldp_conf.get('dldpWorkMode', None)
- if work_mode == 'dldpEnhance':
- dldp_conf['work_mode'] = 'enhance'
- else:
- dldp_conf['work_mode'] = 'normal'
-
- auth_mode = self.dldp_conf.get('dldpAuthMode', None)
- if auth_mode == 'dldpAuthNone':
- dldp_conf['auth_mode'] = 'none'
- elif auth_mode == 'dldpAuthSimple':
- dldp_conf['auth_mode'] = 'simple'
- elif auth_mode == 'dldpAuthMD5':
- dldp_conf['auth_mode'] = 'md5'
- elif auth_mode == 'dldpAuthSHA':
- dldp_conf['auth_mode'] = 'sha'
- else:
- dldp_conf['auth_mode'] = 'hmac-sha256'
-
- dldp_conf['reset'] = 'disable'
- if self.reset == 'enable':
- dldp_conf['reset'] = 'enable'
- self.end_state = copy.deepcopy(dldp_conf)
-
- def show_result(self):
- """Show result"""
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
- def work(self):
- """Worker"""
-
- self.dldp_conf = self.get_dldp_exist_config()
- self.check_params()
- self.same_conf = self.check_config_if_same()
- self.get_existing()
- self.get_proposed()
- self.config_global_dldp()
- self.get_update_cmd()
- self.get_end_state()
- self.show_result()
-
-
-def main():
- """Main function entry"""
-
- argument_spec = dict(
- enable=dict(choices=['enable', 'disable'], type='str'),
- work_mode=dict(choices=['enhance', 'normal'], type='str'),
- time_interval=dict(type='str'),
- reset=dict(choices=['enable', 'disable'], type='str'),
- auth_mode=dict(choices=['md5', 'simple', 'sha', 'hmac-sha256', 'none'], type='str'),
- auth_pwd=dict(type='str', no_log=True),
- )
- argument_spec.update(ce_argument_spec)
- dldp_obj = Dldp(argument_spec)
- dldp_obj.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_dldp_interface.py b/plugins/modules/network/cloudengine/ce_dldp_interface.py
deleted file mode 100644
index 3efdd21a3b..0000000000
--- a/plugins/modules/network/cloudengine/ce_dldp_interface.py
+++ /dev/null
@@ -1,662 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-
-module: ce_dldp_interface
-short_description: Manages interface DLDP configuration on HUAWEI CloudEngine switches.
-description:
- - Manages interface DLDP configuration on HUAWEI CloudEngine switches.
-author:
- - Zhou Zhijin (@QijunPan)
-notes:
- - If C(state=present, enable=disable), interface DLDP enable will be turned off and
- related interface DLDP configuration will be cleared.
- - If C(state=absent), only local_mac is supported to configure.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- interface:
- description:
- - Must be fully qualified interface name, i.e. GE1/0/1, 10GE1/0/1, 40GE1/0/22, 100GE1/0/1.
- required: true
- enable:
- description:
- - Set interface DLDP enable state.
- choices: ['enable', 'disable']
- mode_enable:
- description:
- - Set DLDP compatible-mode enable state.
- choices: ['enable', 'disable']
- local_mac:
- description:
- - Set the source MAC address for DLDP packets sent in the DLDP-compatible mode.
- The value of MAC address is in H-H-H format. H contains 1 to 4 hexadecimal digits.
- reset:
- description:
- - Specify whether reseting interface DLDP state.
- choices: ['enable', 'disable']
- state:
- description:
- - Manage the state of the resource.
- default: present
- choices: ['present','absent']
-'''
-
-EXAMPLES = '''
-- name: DLDP interface test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Configure interface DLDP enable state and ensure global dldp enable is turned on"
- ce_dldp_interface:
- interface: 40GE2/0/1
- enable: enable
- provider: "{{ cli }}"
-
- - name: "Configuire interface DLDP compatible-mode enable state and ensure interface DLDP state is already enabled"
- ce_dldp_interface:
- interface: 40GE2/0/1
- enable: enable
- mode_enable: enable
- provider: "{{ cli }}"
-
- - name: "Configuire the source MAC address for DLDP packets sent in the DLDP-compatible mode and
- ensure interface DLDP state and compatible-mode enable state is already enabled"
- ce_dldp_interface:
- interface: 40GE2/0/1
- enable: enable
- mode_enable: enable
- local_mac: aa-aa-aa
- provider: "{{ cli }}"
-
- - name: "Reset DLDP state of specified interface and ensure interface DLDP state is already enabled"
- ce_dldp_interface:
- interface: 40GE2/0/1
- enable: enable
- reset: enable
- provider: "{{ cli }}"
-
- - name: "Unconfigure interface DLDP local mac address when C(state=absent)"
- ce_dldp_interface:
- interface: 40GE2/0/1
- state: absent
- local_mac: aa-aa-aa
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "enable": "enalbe",
- "interface": "40GE2/0/22",
- "local_mac": "aa-aa-aa",
- "mode_enable": "enable",
- "reset": "enable"
- }
-existing:
- description: k/v pairs of existing interface DLDP configuration
- returned: always
- type: dict
- sample: {
- "enable": "disable",
- "interface": "40GE2/0/22",
- "local_mac": null,
- "mode_enable": null,
- "reset": "disable"
- }
-end_state:
- description: k/v pairs of interface DLDP configuration after module execution
- returned: always
- type: dict
- sample: {
- "enable": "enable",
- "interface": "40GE2/0/22",
- "local_mac": "00aa-00aa-00aa",
- "mode_enable": "enable",
- "reset": "enable"
- }
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: [
- "dldp enable",
- "dldp compatible-mode enable",
- "dldp compatible-mode local-mac aa-aa-aa",
- "dldp reset"
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import copy
-import re
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec, set_nc_config, get_nc_config, execute_nc_action
-
-
-CE_NC_ACTION_RESET_INTF_DLDP = """
-
-
-
- %s
-
-
-
-"""
-
-CE_NC_GET_INTF_DLDP_CONFIG = """
-
-
-
-
- %s
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_DLDP_INTF_CONFIG = """
-
-
-
-
- %s
- %s
- %s
- %s
-
-
-
-
-"""
-
-CE_NC_CREATE_DLDP_INTF_CONFIG = """
-
-
-
-
- %s
- %s
- %s
- %s
-
-
-
-
-"""
-
-CE_NC_DELETE_DLDP_INTF_CONFIG = """
-
-
-
-
- %s
-
-
-
-
-"""
-
-
-def judge_is_mac_same(mac1, mac2):
- """Judge whether two macs are the same"""
-
- if mac1 == mac2:
- return True
-
- list1 = re.findall(r'([0-9A-Fa-f]+)', mac1)
- list2 = re.findall(r'([0-9A-Fa-f]+)', mac2)
- if len(list1) != len(list2):
- return False
-
- for index, value in enumerate(list1, start=0):
- if value.lstrip('0').lower() != list2[index].lstrip('0').lower():
- return False
-
- return True
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- iftype = None
-
- if interface.upper().startswith('GE'):
- iftype = 'ge'
- elif interface.upper().startswith('10GE'):
- iftype = '10ge'
- elif interface.upper().startswith('25GE'):
- iftype = '25ge'
- elif interface.upper().startswith('4X10GE'):
- iftype = '4x10ge'
- elif interface.upper().startswith('40GE'):
- iftype = '40ge'
- elif interface.upper().startswith('100GE'):
- iftype = '100ge'
- elif interface.upper().startswith('VLANIF'):
- iftype = 'vlanif'
- elif interface.upper().startswith('LOOPBACK'):
- iftype = 'loopback'
- elif interface.upper().startswith('METH'):
- iftype = 'meth'
- elif interface.upper().startswith('ETH-TRUNK'):
- iftype = 'eth-trunk'
- elif interface.upper().startswith('VBDIF'):
- iftype = 'vbdif'
- elif interface.upper().startswith('NVE'):
- iftype = 'nve'
- elif interface.upper().startswith('TUNNEL'):
- iftype = 'tunnel'
- elif interface.upper().startswith('ETHERNET'):
- iftype = 'ethernet'
- elif interface.upper().startswith('FCOE-PORT'):
- iftype = 'fcoe-port'
- elif interface.upper().startswith('FABRIC-PORT'):
- iftype = 'fabric-port'
- elif interface.upper().startswith('STACK-PORT'):
- iftype = 'stack-Port'
- elif interface.upper().startswith('NULL'):
- iftype = 'null'
- else:
- return None
-
- return iftype.lower()
-
-
-class DldpInterface(object):
- """Manage interface dldp configuration"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # DLDP interface configuration info
- self.interface = self.module.params['interface']
- self.enable = self.module.params['enable'] or None
- self.reset = self.module.params['reset'] or None
- self.mode_enable = self.module.params['mode_enable'] or None
- self.local_mac = self.module.params['local_mac'] or None
- self.state = self.module.params['state']
-
- self.dldp_intf_conf = dict()
- self.same_conf = False
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = list()
- self.end_state = list()
-
- def check_config_if_same(self):
- """Judge whether current config is the same as what we excepted"""
-
- if self.state == 'absent':
- return False
- else:
- if self.enable and self.enable != self.dldp_intf_conf['dldpEnable']:
- return False
-
- if self.mode_enable and self.mode_enable != self.dldp_intf_conf['dldpCompatibleEnable']:
- return False
-
- if self.local_mac:
- flag = judge_is_mac_same(
- self.local_mac, self.dldp_intf_conf['dldpLocalMac'])
- if not flag:
- return False
-
- if self.reset and self.reset == 'enable':
- return False
- return True
-
- def check_macaddr(self):
- """Check mac-address whether valid"""
-
- valid_char = '0123456789abcdef-'
- mac = self.local_mac
-
- if len(mac) > 16:
- return False
-
- mac_list = re.findall(r'([0-9a-fA-F]+)', mac)
- if len(mac_list) != 3:
- return False
-
- if mac.count('-') != 2:
- return False
-
- for _, value in enumerate(mac, start=0):
- if value.lower() not in valid_char:
- return False
-
- return True
-
- def check_params(self):
- """Check all input params"""
-
- if not self.interface:
- self.module.fail_json(msg='Error: Interface name cannot be empty.')
-
- if self.interface:
- intf_type = get_interface_type(self.interface)
- if not intf_type:
- self.module.fail_json(
- msg='Error: Interface name of %s '
- 'is error.' % self.interface)
-
- if (self.state == 'absent') and (self.reset or self.mode_enable or self.enable):
- self.module.fail_json(msg="Error: It's better to use state=present when "
- "configuring or unconfiguring enable, mode_enable "
- "or using reset flag. state=absent is just for "
- "when using local_mac param.")
-
- if self.state == 'absent' and not self.local_mac:
- self.module.fail_json(
- msg="Error: Please specify local_mac parameter.")
-
- if self.state == 'present':
- if (self.dldp_intf_conf['dldpEnable'] == 'disable' and not self.enable and
- (self.mode_enable or self.local_mac or self.reset)):
- self.module.fail_json(msg="Error: when DLDP is already disabled on this port, "
- "mode_enable, local_mac and reset parameters are not "
- "expected to configure.")
-
- if self.enable == 'disable' and (self.mode_enable or self.local_mac or self.reset):
- self.module.fail_json(msg="Error: when using enable=disable, "
- "mode_enable, local_mac and reset parameters "
- "are not expected to configure.")
-
- if self.local_mac and (self.mode_enable == 'disable' or
- (self.dldp_intf_conf['dldpCompatibleEnable'] == 'disable' and self.mode_enable != 'enable')):
- self.module.fail_json(msg="Error: when DLDP compatible-mode is disabled on this port, "
- "Configuring local_mac is not allowed.")
-
- if self.local_mac:
- if not self.check_macaddr():
- self.module.fail_json(
- msg="Error: local_mac has invalid value %s." % self.local_mac)
-
- def init_module(self):
- """Init module object"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed"""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_dldp_intf_exist_config(self):
- """Get current dldp existed config"""
-
- dldp_conf = dict()
- xml_str = CE_NC_GET_INTF_DLDP_CONFIG % self.interface
- con_obj = get_nc_config(self.module, xml_str)
- if "" in con_obj:
- dldp_conf['dldpEnable'] = 'disable'
- dldp_conf['dldpCompatibleEnable'] = ""
- dldp_conf['dldpLocalMac'] = ""
- return dldp_conf
-
- xml_str = con_obj.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get global DLDP info
- root = ElementTree.fromstring(xml_str)
- topo = root.find("dldp/dldpInterfaces/dldpInterface")
- if topo is None:
- self.module.fail_json(
- msg="Error: Get current DLDP configuration failed.")
- for eles in topo:
- if eles.tag in ["dldpEnable", "dldpCompatibleEnable", "dldpLocalMac"]:
- if not eles.text:
- dldp_conf[eles.tag] = ""
- else:
- if eles.tag == "dldpEnable" or eles.tag == "dldpCompatibleEnable":
- if eles.text == 'true':
- value = 'enable'
- else:
- value = 'disable'
- else:
- value = eles.text
- dldp_conf[eles.tag] = value
-
- return dldp_conf
-
- def config_intf_dldp(self):
- """Config global dldp"""
-
- if self.same_conf:
- return
-
- if self.state == "present":
- enable = self.enable
- if not self.enable:
- enable = self.dldp_intf_conf['dldpEnable']
- if enable == 'enable':
- enable = 'true'
- else:
- enable = 'false'
-
- mode_enable = self.mode_enable
- if not self.mode_enable:
- mode_enable = self.dldp_intf_conf['dldpCompatibleEnable']
- if mode_enable == 'enable':
- mode_enable = 'true'
- else:
- mode_enable = 'false'
-
- local_mac = self.local_mac
- if not self.local_mac:
- local_mac = self.dldp_intf_conf['dldpLocalMac']
-
- if self.enable == 'disable' and self.enable != self.dldp_intf_conf['dldpEnable']:
- xml_str = CE_NC_DELETE_DLDP_INTF_CONFIG % self.interface
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "DELETE_DLDP_INTF_CONFIG")
- elif self.dldp_intf_conf['dldpEnable'] == 'disable' and self.enable == 'enable':
- xml_str = CE_NC_CREATE_DLDP_INTF_CONFIG % (
- self.interface, 'true', mode_enable, local_mac)
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "CREATE_DLDP_INTF_CONFIG")
- elif self.dldp_intf_conf['dldpEnable'] == 'enable':
- if mode_enable == 'false':
- local_mac = ''
- xml_str = CE_NC_MERGE_DLDP_INTF_CONFIG % (
- self.interface, enable, mode_enable, local_mac)
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "MERGE_DLDP_INTF_CONFIG")
-
- if self.reset == 'enable':
- xml_str = CE_NC_ACTION_RESET_INTF_DLDP % self.interface
- ret_xml = execute_nc_action(self.module, xml_str)
- self.check_response(ret_xml, "ACTION_RESET_INTF_DLDP")
-
- self.changed = True
- else:
- if self.local_mac and judge_is_mac_same(self.local_mac, self.dldp_intf_conf['dldpLocalMac']):
- if self.dldp_intf_conf['dldpEnable'] == 'enable':
- dldp_enable = 'true'
- else:
- dldp_enable = 'false'
- if self.dldp_intf_conf['dldpCompatibleEnable'] == 'enable':
- dldp_compat_enable = 'true'
- else:
- dldp_compat_enable = 'false'
- xml_str = CE_NC_MERGE_DLDP_INTF_CONFIG % (self.interface, dldp_enable, dldp_compat_enable, '')
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "UNDO_DLDP_INTF_LOCAL_MAC_CONFIG")
- self.changed = True
-
- def get_existing(self):
- """Get existing info"""
-
- dldp_conf = dict()
-
- dldp_conf['interface'] = self.interface
- dldp_conf['enable'] = self.dldp_intf_conf.get('dldpEnable', None)
- dldp_conf['mode_enable'] = self.dldp_intf_conf.get(
- 'dldpCompatibleEnable', None)
- dldp_conf['local_mac'] = self.dldp_intf_conf.get('dldpLocalMac', None)
- dldp_conf['reset'] = 'disable'
-
- self.existing = copy.deepcopy(dldp_conf)
-
- def get_proposed(self):
- """Get proposed result """
-
- self.proposed = dict(interface=self.interface, enable=self.enable,
- mode_enable=self.mode_enable, local_mac=self.local_mac,
- reset=self.reset, state=self.state)
-
- def get_update_cmd(self):
- """Get updated commands"""
-
- if self.same_conf:
- return
-
- if self.state == "present":
- if self.enable and self.enable != self.dldp_intf_conf['dldpEnable']:
- if self.enable == 'enable':
- self.updates_cmd.append("dldp enable")
- elif self.enable == 'disable':
- self.updates_cmd.append("undo dldp enable")
-
- if self.mode_enable and self.mode_enable != self.dldp_intf_conf['dldpCompatibleEnable']:
- if self.mode_enable == 'enable':
- self.updates_cmd.append("dldp compatible-mode enable")
- else:
- self.updates_cmd.append("undo dldp compatible-mode enable")
-
- if self.local_mac:
- flag = judge_is_mac_same(
- self.local_mac, self.dldp_intf_conf['dldpLocalMac'])
- if not flag:
- self.updates_cmd.append(
- "dldp compatible-mode local-mac %s" % self.local_mac)
-
- if self.reset and self.reset == 'enable':
- self.updates_cmd.append('dldp reset')
- else:
- if self.changed:
- self.updates_cmd.append("undo dldp compatible-mode local-mac")
-
- def get_end_state(self):
- """Get end state info"""
-
- dldp_conf = dict()
- self.dldp_intf_conf = self.get_dldp_intf_exist_config()
-
- dldp_conf['interface'] = self.interface
- dldp_conf['enable'] = self.dldp_intf_conf.get('dldpEnable', None)
- dldp_conf['mode_enable'] = self.dldp_intf_conf.get(
- 'dldpCompatibleEnable', None)
- dldp_conf['local_mac'] = self.dldp_intf_conf.get('dldpLocalMac', None)
- dldp_conf['reset'] = 'disable'
- if self.reset == 'enable':
- dldp_conf['reset'] = 'enable'
-
- self.end_state = copy.deepcopy(dldp_conf)
-
- def show_result(self):
- """Show result"""
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
- def work(self):
- """Execute task"""
-
- self.dldp_intf_conf = self.get_dldp_intf_exist_config()
- self.check_params()
- self.same_conf = self.check_config_if_same()
- self.get_existing()
- self.get_proposed()
- self.config_intf_dldp()
- self.get_update_cmd()
- self.get_end_state()
- self.show_result()
-
-
-def main():
- """Main function entry"""
-
- argument_spec = dict(
- interface=dict(required=True, type='str'),
- enable=dict(choices=['enable', 'disable'], type='str'),
- reset=dict(choices=['enable', 'disable'], type='str'),
- mode_enable=dict(choices=['enable', 'disable'], type='str'),
- local_mac=dict(type='str'),
- state=dict(choices=['absent', 'present'], default='present'),
- )
- argument_spec.update(ce_argument_spec)
- dldp_intf_obj = DldpInterface(argument_spec)
- dldp_intf_obj.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_eth_trunk.py b/plugins/modules/network/cloudengine/ce_eth_trunk.py
deleted file mode 100644
index 3f2dde7ec4..0000000000
--- a/plugins/modules/network/cloudengine/ce_eth_trunk.py
+++ /dev/null
@@ -1,676 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_eth_trunk
-short_description: Manages Eth-Trunk interfaces on HUAWEI CloudEngine switches.
-description:
- - Manages Eth-Trunk specific configuration parameters on HUAWEI CloudEngine switches.
-author: QijunPan (@QijunPan)
-notes:
- - C(state=absent) removes the Eth-Trunk config and interface if it
- already exists. If members to be removed are not explicitly
- passed, all existing members (if any), are removed,
- and Eth-Trunk removed.
- - Members must be a list.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- trunk_id:
- description:
- - Eth-Trunk interface number.
- The value is an integer.
- The value range depends on the assign forward eth-trunk mode command.
- When 256 is specified, the value ranges from 0 to 255.
- When 512 is specified, the value ranges from 0 to 511.
- When 1024 is specified, the value ranges from 0 to 1023.
- required: true
- mode:
- description:
- - Specifies the working mode of an Eth-Trunk interface.
- choices: ['manual','lacp-dynamic','lacp-static']
- min_links:
- description:
- - Specifies the minimum number of Eth-Trunk member links in the Up state.
- The value is an integer ranging from 1 to the maximum number of interfaces
- that can be added to a Eth-Trunk interface.
- hash_type:
- description:
- - Hash algorithm used for load balancing among Eth-Trunk member interfaces.
- choices: ['src-dst-ip', 'src-dst-mac', 'enhanced', 'dst-ip', 'dst-mac', 'src-ip', 'src-mac']
- members:
- description:
- - List of interfaces that will be managed in a given Eth-Trunk.
- The interface name must be full name.
- force:
- description:
- - When true it forces Eth-Trunk members to match what is
- declared in the members param. This can be used to remove
- members.
- type: bool
- default: 'no'
- state:
- description:
- - Manage the state of the resource.
- default: present
- choices: ['present','absent']
-'''
-EXAMPLES = '''
-- name: eth_trunk module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
- - name: Ensure Eth-Trunk100 is created, add two members, and set to mode lacp-static
- ce_eth_trunk:
- trunk_id: 100
- members: ['10GE1/0/24','10GE1/0/25']
- mode: 'lacp-static'
- state: present
- provider: '{{ cli }}'
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"trunk_id": "100", "members": ['10GE1/0/24','10GE1/0/25'], "mode": "lacp-static"}
-existing:
- description: k/v pairs of existing Eth-Trunk
- returned: always
- type: dict
- sample: {"trunk_id": "100", "hash_type": "mac", "members_detail": [
- {"memberIfName": "10GE1/0/25", "memberIfState": "Down"}],
- "min_links": "1", "mode": "manual"}
-end_state:
- description: k/v pairs of Eth-Trunk info after module execution
- returned: always
- type: dict
- sample: {"trunk_id": "100", "hash_type": "mac", "members_detail": [
- {"memberIfName": "10GE1/0/24", "memberIfState": "Down"},
- {"memberIfName": "10GE1/0/25", "memberIfState": "Down"}],
- "min_links": "1", "mode": "lacp-static"}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["interface Eth-Trunk 100",
- "mode lacp-static",
- "interface 10GE1/0/25",
- "eth-trunk 100"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-CE_NC_GET_TRUNK = """
-
-
-
-
- Eth-Trunk%s
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_XML_BUILD_TRUNK_CFG = """
-
-
- %s
-
-
-"""
-
-CE_NC_XML_DELETE_TRUNK = """
-
- Eth-Trunk%s
-
-"""
-
-CE_NC_XML_CREATE_TRUNK = """
-
- Eth-Trunk%s
-
-"""
-
-CE_NC_XML_MERGE_MINUPNUM = """
-
- Eth-Trunk%s
- %s
-
-"""
-
-CE_NC_XML_MERGE_HASHTYPE = """
-
- Eth-Trunk%s
- %s
-
-"""
-
-CE_NC_XML_MERGE_WORKMODE = """
-
- Eth-Trunk%s
- %s
-
-"""
-
-CE_NC_XML_BUILD_MEMBER_CFG = """
-
- Eth-Trunk%s
- %s
-
-"""
-
-CE_NC_XML_MERGE_MEMBER = """
-
- %s
-
-"""
-
-CE_NC_XML_DELETE_MEMBER = """
-
- %s
-
-"""
-
-MODE_XML2CLI = {"Manual": "manual", "Dynamic": "lacp-dynamic", "Static": "lacp-static"}
-MODE_CLI2XML = {"manual": "Manual", "lacp-dynamic": "Dynamic", "lacp-static": "Static"}
-HASH_XML2CLI = {"IP": "src-dst-ip", "MAC": "src-dst-mac", "Enhanced": "enhanced",
- "Desip": "dst-ip", "Desmac": "dst-mac", "Sourceip": "src-ip", "Sourcemac": "src-mac"}
-HASH_CLI2XML = {"src-dst-ip": "IP", "src-dst-mac": "MAC", "enhanced": "Enhanced",
- "dst-ip": "Desip", "dst-mac": "Desmac", "src-ip": "Sourceip", "src-mac": "Sourcemac"}
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- iftype = None
-
- if interface.upper().startswith('GE'):
- iftype = 'ge'
- elif interface.upper().startswith('10GE'):
- iftype = '10ge'
- elif interface.upper().startswith('25GE'):
- iftype = '25ge'
- elif interface.upper().startswith('4X10GE'):
- iftype = '4x10ge'
- elif interface.upper().startswith('40GE'):
- iftype = '40ge'
- elif interface.upper().startswith('100GE'):
- iftype = '100ge'
- elif interface.upper().startswith('VLANIF'):
- iftype = 'vlanif'
- elif interface.upper().startswith('LOOPBACK'):
- iftype = 'loopback'
- elif interface.upper().startswith('METH'):
- iftype = 'meth'
- elif interface.upper().startswith('ETH-TRUNK'):
- iftype = 'eth-trunk'
- elif interface.upper().startswith('VBDIF'):
- iftype = 'vbdif'
- elif interface.upper().startswith('NVE'):
- iftype = 'nve'
- elif interface.upper().startswith('TUNNEL'):
- iftype = 'tunnel'
- elif interface.upper().startswith('ETHERNET'):
- iftype = 'ethernet'
- elif interface.upper().startswith('FCOE-PORT'):
- iftype = 'fcoe-port'
- elif interface.upper().startswith('FABRIC-PORT'):
- iftype = 'fabric-port'
- elif interface.upper().startswith('STACK-PORT'):
- iftype = 'stack-port'
- elif interface.upper().startswith('NULL'):
- iftype = 'null'
- else:
- return None
-
- return iftype.lower()
-
-
-def mode_xml_to_cli_str(mode):
- """convert mode to cli format string"""
-
- if not mode:
- return ""
-
- return MODE_XML2CLI.get(mode)
-
-
-def hash_type_xml_to_cli_str(hash_type):
- """convert trunk hash type netconf xml to cli format string"""
-
- if not hash_type:
- return ""
-
- return HASH_XML2CLI.get(hash_type)
-
-
-class EthTrunk(object):
- """
- Manages Eth-Trunk interfaces.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.__init_module__()
-
- # module input info
- self.trunk_id = self.module.params['trunk_id']
- self.mode = self.module.params['mode']
- self.min_links = self.module.params['min_links']
- self.hash_type = self.module.params['hash_type']
- self.members = self.module.params['members']
- self.state = self.module.params['state']
- self.force = self.module.params['force']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- # interface info
- self.trunk_info = dict()
-
- def __init_module__(self):
- """ init module """
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def netconf_set_config(self, xml_str, xml_name):
- """ netconf set config """
-
- recv_xml = set_nc_config(self.module, xml_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_trunk_dict(self, trunk_id):
- """ get one interface attributes dict."""
-
- trunk_info = dict()
- conf_str = CE_NC_GET_TRUNK % trunk_id
- recv_xml = get_nc_config(self.module, conf_str)
-
- if "" in recv_xml:
- return trunk_info
-
- # get trunk base info
- base = re.findall(
- r'.*(.*).*\s*'
- r'(.*).*\s*'
- r'(.*).*\s*'
- r'(.*).*\s*'
- r'(.*).*\s*'
- r'(.*).*\s*'
- r'(.*).*\s*'
- r'(.*).*', recv_xml)
-
- if base:
- trunk_info = dict(ifName=base[0][0],
- trunkId=base[0][0].lower().replace("eth-trunk", "").replace(" ", ""),
- minUpNum=base[0][1],
- maxUpNum=base[0][2],
- trunkType=base[0][3],
- hashType=base[0][4],
- workMode=base[0][5],
- upMemberIfNum=base[0][6],
- memberIfNum=base[0][7])
-
- # get trunk member interface info
- member = re.findall(
- r'.*(.*).*\s*'
- r'(.*).*', recv_xml)
- trunk_info["TrunkMemberIfs"] = list()
-
- for mem in member:
- trunk_info["TrunkMemberIfs"].append(
- dict(memberIfName=mem[0], memberIfState=mem[1]))
-
- return trunk_info
-
- def is_member_exist(self, ifname):
- """is trunk member exist"""
-
- if not self.trunk_info["TrunkMemberIfs"]:
- return False
-
- for mem in self.trunk_info["TrunkMemberIfs"]:
- if ifname.replace(" ", "").upper() == mem["memberIfName"].replace(" ", "").upper():
- return True
-
- return False
-
- def get_mode_xml_str(self):
- """trunk mode netconf xml format string"""
-
- return MODE_CLI2XML.get(self.mode)
-
- def get_hash_type_xml_str(self):
- """trunk hash type netconf xml format string"""
-
- return HASH_CLI2XML.get(self.hash_type)
-
- def create_eth_trunk(self):
- """Create Eth-Trunk interface"""
-
- xml_str = CE_NC_XML_CREATE_TRUNK % self.trunk_id
- self.updates_cmd.append("interface Eth-Trunk %s" % self.trunk_id)
-
- if self.hash_type:
- self.updates_cmd.append("load-balance %s" % self.hash_type)
- xml_str += CE_NC_XML_MERGE_HASHTYPE % (self.trunk_id, self.get_hash_type_xml_str())
-
- if self.mode:
- self.updates_cmd.append("mode %s" % self.mode)
- xml_str += CE_NC_XML_MERGE_WORKMODE % (self.trunk_id, self.get_mode_xml_str())
-
- if self.min_links:
- self.updates_cmd.append("least active-linknumber %s" % self.min_links)
- xml_str += CE_NC_XML_MERGE_MINUPNUM % (self.trunk_id, self.min_links)
-
- if self.members:
- mem_xml = ""
- for mem in self.members:
- mem_xml += CE_NC_XML_MERGE_MEMBER % mem.upper()
- self.updates_cmd.append("interface %s" % mem)
- self.updates_cmd.append("eth-trunk %s" % self.trunk_id)
- xml_str += CE_NC_XML_BUILD_MEMBER_CFG % (self.trunk_id, mem_xml)
- cfg_xml = CE_NC_XML_BUILD_TRUNK_CFG % xml_str
- self.netconf_set_config(cfg_xml, "CREATE_TRUNK")
- self.changed = True
-
- def delete_eth_trunk(self):
- """Delete Eth-Trunk interface and remove all member"""
-
- if not self.trunk_info:
- return
-
- xml_str = ""
- mem_str = ""
- if self.trunk_info["TrunkMemberIfs"]:
- for mem in self.trunk_info["TrunkMemberIfs"]:
- mem_str += CE_NC_XML_DELETE_MEMBER % mem["memberIfName"]
- self.updates_cmd.append("interface %s" % mem["memberIfName"])
- self.updates_cmd.append("undo eth-trunk")
- if mem_str:
- xml_str += CE_NC_XML_BUILD_MEMBER_CFG % (self.trunk_id, mem_str)
-
- xml_str += CE_NC_XML_DELETE_TRUNK % self.trunk_id
- self.updates_cmd.append("undo interface Eth-Trunk %s" % self.trunk_id)
- cfg_xml = CE_NC_XML_BUILD_TRUNK_CFG % xml_str
- self.netconf_set_config(cfg_xml, "DELETE_TRUNK")
- self.changed = True
-
- def remove_member(self):
- """delete trunk member"""
-
- if not self.members:
- return
-
- change = False
- mem_xml = ""
- xml_str = ""
- for mem in self.members:
- if self.is_member_exist(mem):
- mem_xml += CE_NC_XML_DELETE_MEMBER % mem.upper()
- self.updates_cmd.append("interface %s" % mem)
- self.updates_cmd.append("undo eth-trunk")
- if mem_xml:
- xml_str += CE_NC_XML_BUILD_MEMBER_CFG % (self.trunk_id, mem_xml)
- change = True
-
- if not change:
- return
-
- cfg_xml = CE_NC_XML_BUILD_TRUNK_CFG % xml_str
- self.netconf_set_config(cfg_xml, "REMOVE_TRUNK_MEMBER")
- self.changed = True
-
- def merge_eth_trunk(self):
- """Create or merge Eth-Trunk"""
-
- change = False
- xml_str = ""
- self.updates_cmd.append("interface Eth-Trunk %s" % self.trunk_id)
- if self.hash_type and self.get_hash_type_xml_str() != self.trunk_info["hashType"]:
- self.updates_cmd.append("load-balance %s" %
- self.hash_type)
- xml_str += CE_NC_XML_MERGE_HASHTYPE % (
- self.trunk_id, self.get_hash_type_xml_str())
- change = True
- if self.min_links and self.min_links != self.trunk_info["minUpNum"]:
- self.updates_cmd.append(
- "least active-linknumber %s" % self.min_links)
- xml_str += CE_NC_XML_MERGE_MINUPNUM % (
- self.trunk_id, self.min_links)
- change = True
- if self.mode and self.get_mode_xml_str() != self.trunk_info["workMode"]:
- self.updates_cmd.append("mode %s" % self.mode)
- xml_str += CE_NC_XML_MERGE_WORKMODE % (
- self.trunk_id, self.get_mode_xml_str())
- change = True
-
- if not change:
- self.updates_cmd.pop() # remove 'interface Eth-Trunk' command
-
- # deal force:
- # When true it forces Eth-Trunk members to match
- # what is declared in the members param.
- if self.force and self.trunk_info["TrunkMemberIfs"]:
- mem_xml = ""
- for mem in self.trunk_info["TrunkMemberIfs"]:
- if not self.members or mem["memberIfName"].replace(" ", "").upper() not in self.members:
- mem_xml += CE_NC_XML_DELETE_MEMBER % mem["memberIfName"]
- self.updates_cmd.append("interface %s" % mem["memberIfName"])
- self.updates_cmd.append("undo eth-trunk")
- if mem_xml:
- xml_str += CE_NC_XML_BUILD_MEMBER_CFG % (self.trunk_id, mem_xml)
- change = True
-
- if self.members:
- mem_xml = ""
- for mem in self.members:
- if not self.is_member_exist(mem):
- mem_xml += CE_NC_XML_MERGE_MEMBER % mem.upper()
- self.updates_cmd.append("interface %s" % mem)
- self.updates_cmd.append("eth-trunk %s" % self.trunk_id)
- if mem_xml:
- xml_str += CE_NC_XML_BUILD_MEMBER_CFG % (
- self.trunk_id, mem_xml)
- change = True
-
- if not change:
- return
-
- cfg_xml = CE_NC_XML_BUILD_TRUNK_CFG % xml_str
- self.netconf_set_config(cfg_xml, "MERGE_TRUNK")
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- # trunk_id check
- if not self.trunk_id.isdigit():
- self.module.fail_json(msg='The parameter of trunk_id is invalid.')
-
- # min_links check
- if self.min_links and not self.min_links.isdigit():
- self.module.fail_json(msg='The parameter of min_links is invalid.')
-
- # members check and convert members to upper
- if self.members:
- for mem in self.members:
- if not get_interface_type(mem.replace(" ", "")):
- self.module.fail_json(
- msg='The parameter of members is invalid.')
-
- for mem_id in range(len(self.members)):
- self.members[mem_id] = self.members[mem_id].replace(" ", "").upper()
-
- def get_proposed(self):
- """get proposed info"""
-
- self.proposed["trunk_id"] = self.trunk_id
- self.proposed["mode"] = self.mode
- if self.min_links:
- self.proposed["min_links"] = self.min_links
- self.proposed["hash_type"] = self.hash_type
- if self.members:
- self.proposed["members"] = self.members
- self.proposed["state"] = self.state
- self.proposed["force"] = self.force
-
- def get_existing(self):
- """get existing info"""
-
- if not self.trunk_info:
- return
-
- self.existing["trunk_id"] = self.trunk_info["trunkId"]
- self.existing["min_links"] = self.trunk_info["minUpNum"]
- self.existing["hash_type"] = hash_type_xml_to_cli_str(self.trunk_info["hashType"])
- self.existing["mode"] = mode_xml_to_cli_str(self.trunk_info["workMode"])
- self.existing["members_detail"] = self.trunk_info["TrunkMemberIfs"]
-
- def get_end_state(self):
- """get end state info"""
-
- trunk_info = self.get_trunk_dict(self.trunk_id)
- if not trunk_info:
- return
-
- self.end_state["trunk_id"] = trunk_info["trunkId"]
- self.end_state["min_links"] = trunk_info["minUpNum"]
- self.end_state["hash_type"] = hash_type_xml_to_cli_str(trunk_info["hashType"])
- self.end_state["mode"] = mode_xml_to_cli_str(trunk_info["workMode"])
- self.end_state["members_detail"] = trunk_info["TrunkMemberIfs"]
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.trunk_info = self.get_trunk_dict(self.trunk_id)
- self.get_existing()
- self.get_proposed()
-
- # deal present or absent
- if self.state == "present":
- if not self.trunk_info:
- # create
- self.create_eth_trunk()
- else:
- # merge trunk
- self.merge_eth_trunk()
- else:
- if self.trunk_info:
- if not self.members:
- # remove all members and delete trunk
- self.delete_eth_trunk()
- else:
- # remove some trunk members
- self.remove_member()
- else:
- self.module.fail_json(msg='Error: Eth-Trunk does not exist.')
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- trunk_id=dict(required=True),
- mode=dict(required=False,
- choices=['manual', 'lacp-dynamic', 'lacp-static'],
- type='str'),
- min_links=dict(required=False, type='str'),
- hash_type=dict(required=False,
- choices=['src-dst-ip', 'src-dst-mac', 'enhanced',
- 'dst-ip', 'dst-mac', 'src-ip', 'src-mac'],
- type='str'),
- members=dict(required=False, default=None, type='list'),
- force=dict(required=False, default=False, type='bool'),
- state=dict(required=False, default='present',
- choices=['present', 'absent'])
- )
-
- argument_spec.update(ce_argument_spec)
- module = EthTrunk(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_evpn_bd_vni.py b/plugins/modules/network/cloudengine/ce_evpn_bd_vni.py
deleted file mode 100644
index caf396d912..0000000000
--- a/plugins/modules/network/cloudengine/ce_evpn_bd_vni.py
+++ /dev/null
@@ -1,1057 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_evpn_bd_vni
-short_description: Manages EVPN VXLAN Network Identifier (VNI) on HUAWEI CloudEngine switches.
-description:
- - Manages Ethernet Virtual Private Network (EVPN) VXLAN Network
- Identifier (VNI) configurations on HUAWEI CloudEngine switches.
-author: Zhijin Zhou (@QijunPan)
-notes:
- - Ensure that EVPN has been configured to serve as the VXLAN control plane when state is present.
- - Ensure that a bridge domain (BD) has existed when state is present.
- - Ensure that a VNI has been created and associated with a broadcast domain (BD) when state is present.
- - If you configure evpn:false to delete an EVPN instance, all configurations in the EVPN instance are deleted.
- - After an EVPN instance has been created in the BD view, you can configure an RD using route_distinguisher
- parameter in BD-EVPN instance view.
- - Before configuring VPN targets for a BD EVPN instance, ensure that an RD has been configured
- for the BD EVPN instance
- - If you unconfigure route_distinguisher, all VPN target attributes for the BD EVPN instance will be removed at the same time.
- - When using state:absent, evpn is not supported and it will be ignored.
- - When using state:absent to delete VPN target attributes, ensure the configuration of VPN target attributes has
- existed and otherwise it will report an error.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- bridge_domain_id:
- description:
- - Specify an existed bridge domain (BD).The value is an integer ranging from 1 to 16777215.
- required: true
- evpn:
- description:
- - Create or delete an EVPN instance for a VXLAN in BD view.
- choices: ['enable','disable']
- default: 'enable'
- route_distinguisher:
- description:
- - Configures a route distinguisher (RD) for a BD EVPN instance.
- The format of an RD can be as follows
- - 1) 2-byte AS number:4-byte user-defined number, for example, 1:3. An AS number is an integer ranging from
- 0 to 65535, and a user-defined number is an integer ranging from 0 to 4294967295. The AS and user-defined
- numbers cannot be both 0s. This means that an RD cannot be 0:0.
- - 2) Integral 4-byte AS number:2-byte user-defined number, for example, 65537:3. An AS number is an integer
- ranging from 65536 to 4294967295, and a user-defined number is an integer ranging from 0 to 65535.
- - 3) 4-byte AS number in dotted notation:2-byte user-defined number, for example, 0.0:3 or 0.1:0. A 4-byte
- AS number in dotted notation is in the format of x.y, where x and y are integers ranging from 0 to 65535.
- - 4) A user-defined number is an integer ranging from 0 to 65535. The AS and user-defined numbers cannot be
- both 0s. This means that an RD cannot be 0.0:0.
- - 5) 32-bit IP address:2-byte user-defined number. For example, 192.168.122.15:1. An IP address ranges from
- 0.0.0.0 to 255.255.255.255, and a user-defined number is an integer ranging from 0 to 65535.
- - 6) 'auto' specifies the RD that is automatically generated.
- vpn_target_both:
- description:
- - Add VPN targets to both the import and export VPN target lists of a BD EVPN instance.
- The format is the same as route_distinguisher.
- vpn_target_import:
- description:
- - Add VPN targets to the import VPN target list of a BD EVPN instance.
- The format is the same as route_distinguisher.
- required: true
- vpn_target_export:
- description:
- - Add VPN targets to the export VPN target list of a BD EVPN instance.
- The format is the same as route_distinguisher.
- state:
- description:
- - Manage the state of the resource.
- choices: ['present','absent']
- default: 'present'
-'''
-
-EXAMPLES = '''
-- name: EVPN BD VNI test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Configure an EVPN instance for a VXLAN in BD view"
- ce_evpn_bd_vni:
- bridge_domain_id: 20
- evpn: enable
- provider: "{{ cli }}"
-
- - name: "Configure a route distinguisher (RD) for a BD EVPN instance"
- ce_evpn_bd_vni:
- bridge_domain_id: 20
- route_distinguisher: '22:22'
- provider: "{{ cli }}"
-
- - name: "Configure VPN targets to both the import and export VPN target lists of a BD EVPN instance"
- ce_evpn_bd_vni:
- bridge_domain_id: 20
- vpn_target_both: 22:100,22:101
- provider: "{{ cli }}"
-
- - name: "Configure VPN targets to the import VPN target list of a BD EVPN instance"
- ce_evpn_bd_vni:
- bridge_domain_id: 20
- vpn_target_import: 22:22,22:23
- provider: "{{ cli }}"
-
- - name: "Configure VPN targets to the export VPN target list of a BD EVPN instance"
- ce_evpn_bd_vni:
- bridge_domain_id: 20
- vpn_target_export: 22:38,22:39
- provider: "{{ cli }}"
-
- - name: "Unconfigure VPN targets to both the import and export VPN target lists of a BD EVPN instance"
- ce_evpn_bd_vni:
- bridge_domain_id: 20
- vpn_target_both: '22:100'
- state: absent
- provider: "{{ cli }}"
-
- - name: "Unconfigure VPN targets to the import VPN target list of a BD EVPN instance"
- ce_evpn_bd_vni:
- bridge_domain_id: 20
- vpn_target_import: '22:22'
- state: absent
- provider: "{{ cli }}"
-
- - name: "Unconfigure VPN targets to the export VPN target list of a BD EVPN instance"
- ce_evpn_bd_vni:
- bridge_domain_id: 20
- vpn_target_export: '22:38'
- state: absent
- provider: "{{ cli }}"
-
- - name: "Unconfigure a route distinguisher (RD) of a BD EVPN instance"
- ce_evpn_bd_vni:
- bridge_domain_id: 20
- route_distinguisher: '22:22'
- state: absent
- provider: "{{ cli }}"
-
- - name: "Unconfigure an EVPN instance for a VXLAN in BD view"
- ce_evpn_bd_vni:
- bridge_domain_id: 20
- evpn: disable
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "bridge_domain_id": "2",
- "evpn": "enable",
- "route_distinguisher": "22:22",
- "state": "present",
- "vpn_target_both": [
- "22:100",
- "22:101"
- ],
- "vpn_target_export": [
- "22:38",
- "22:39"
- ],
- "vpn_target_import": [
- "22:22",
- "22:23"
- ]
- }
-existing:
- description: k/v pairs of existing attributes on the device
- returned: always
- type: dict
- sample: {
- "bridge_domain_id": "2",
- "evpn": "disable",
- "route_distinguisher": null,
- "vpn_target_both": [],
- "vpn_target_export": [],
- "vpn_target_import": []
- }
-end_state:
- description: k/v pairs of end attributes on the device
- returned: always
- type: dict
- sample: {
- "bridge_domain_id": "2",
- "evpn": "enable",
- "route_distinguisher": "22:22",
- "vpn_target_both": [
- "22:100",
- "22:101"
- ],
- "vpn_target_export": [
- "22:38",
- "22:39"
- ],
- "vpn_target_import": [
- "22:22",
- "22:23"
- ]
- }
-updates:
- description: command list sent to the device
- returned: always
- type: list
- sample: [
- "bridge-domain 2",
- " evpn",
- " route-distinguisher 22:22",
- " vpn-target 22:38 export-extcommunity",
- " vpn-target 22:39 export-extcommunity",
- " vpn-target 22:100 export-extcommunity",
- " vpn-target 22:101 export-extcommunity",
- " vpn-target 22:22 import-extcommunity",
- " vpn-target 22:23 import-extcommunity",
- " vpn-target 22:100 import-extcommunity",
- " vpn-target 22:101 import-extcommunity"
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import re
-import copy
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-
-CE_NC_GET_VNI_BD = """
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_GET_EVPN_CONFIG = """
-
-
-
-
- %s
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_DELETE_EVPN_CONFIG = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-CE_NC_DELETE_EVPN_CONFIG_HEAD = """
-
-
-
-
- %s
- %s
-"""
-
-CE_NC_MERGE_EVPN_CONFIG_HEAD = """
-
-
-
-
- %s
- %s
-"""
-
-CE_NC_MERGE_EVPN_AUTORTS_HEAD = """
-
-"""
-
-CE_NC_MERGE_EVPN_AUTORTS_TAIL = """
-
-"""
-
-CE_NC_DELETE_EVPN_AUTORTS_CONTEXT = """
-
- %s
-
-"""
-
-CE_NC_MERGE_EVPN_AUTORTS_CONTEXT = """
-
- %s
-
-"""
-
-CE_NC_MERGE_EVPN_RTS_HEAD = """
-
-"""
-
-CE_NC_MERGE_EVPN_RTS_TAIL = """
-
-"""
-
-CE_NC_DELETE_EVPN_RTS_CONTEXT = """
-
- %s
- %s
-
-"""
-
-CE_NC_MERGE_EVPN_RTS_CONTEXT = """
-
- %s
- %s
-
-"""
-
-CE_NC_MERGE_EVPN_CONFIG_TAIL = """
-
-
-
-
-"""
-
-
-def is_valid_value(vrf_targe_value):
- """check whether VPN target value is valid"""
-
- each_num = None
- if len(vrf_targe_value) > 21 or len(vrf_targe_value) < 3:
- return False
- if vrf_targe_value.find(':') == -1:
- return False
- elif vrf_targe_value == '0:0':
- return False
- elif vrf_targe_value == '0.0:0':
- return False
- else:
- value_list = vrf_targe_value.split(':')
- if value_list[0].find('.') != -1:
- if not value_list[1].isdigit():
- return False
- if int(value_list[1]) > 65535:
- return False
- value = value_list[0].split('.')
- if len(value) == 4:
- for each_num in value:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- return True
- elif len(value) == 2:
- for each_num in value:
- if not each_num.isdigit():
- return False
- if int(each_num) > 65535:
- return False
- return True
- else:
- return False
- elif not value_list[0].isdigit():
- return False
- elif not value_list[1].isdigit():
- return False
- elif int(value_list[0]) < 65536 and int(value_list[1]) < 4294967296:
- return True
- elif int(value_list[0]) > 65535 and int(value_list[0]) < 4294967296:
- return bool(int(value_list[1]) < 65536)
- else:
- return False
-
-
-class EvpnBd(object):
- """Manage evpn instance in BD view"""
-
- def __init__(self, argument_spec, ):
- self.spec = argument_spec
- self.module = None
- self.__init_module__()
-
- # EVPN instance info
- self.bridge_domain_id = self.module.params['bridge_domain_id']
- self.evpn = self.module.params['evpn']
- self.route_distinguisher = self.module.params['route_distinguisher']
- self.vpn_target_both = self.module.params['vpn_target_both'] or list()
- self.vpn_target_import = self.module.params[
- 'vpn_target_import'] or list()
- self.vpn_target_export = self.module.params[
- 'vpn_target_export'] or list()
- self.state = self.module.params['state']
- self.__string_to_lowercase__()
-
- self.commands = list()
- self.evpn_info = dict()
- self.conf_exist = False
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def __init_module__(self):
- """Init module"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def __check_response__(self, xml_str, xml_name):
- """Check if response message is already succeed"""
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def __string_to_lowercase__(self):
- """Convert string to lowercase"""
-
- if self.route_distinguisher:
- self.route_distinguisher = self.route_distinguisher.lower()
-
- if self.vpn_target_export:
- for index, ele in enumerate(self.vpn_target_export):
- self.vpn_target_export[index] = ele.lower()
-
- if self.vpn_target_import:
- for index, ele in enumerate(self.vpn_target_import):
- self.vpn_target_import[index] = ele.lower()
-
- if self.vpn_target_both:
- for index, ele in enumerate(self.vpn_target_both):
- self.vpn_target_both[index] = ele.lower()
-
- def get_all_evpn_rts(self, evpn_rts):
- """Get all EVPN RTS"""
-
- rts = evpn_rts.findall("evpnRT")
- if not rts:
- return
-
- for ele in rts:
- vrf_rttype = ele.find('vrfRTType')
- vrf_rtvalue = ele.find('vrfRTValue')
-
- if vrf_rttype.text == 'export_extcommunity':
- self.evpn_info['vpn_target_export'].append(vrf_rtvalue.text)
- elif vrf_rttype.text == 'import_extcommunity':
- self.evpn_info['vpn_target_import'].append(vrf_rtvalue.text)
-
- def get_all_evpn_autorts(self, evpn_autorts):
- """"Get all EVPN AUTORTS"""
-
- autorts = evpn_autorts.findall("evpnAutoRT")
- if not autorts:
- return
-
- for autort in autorts:
- vrf_rttype = autort.find('vrfRTType')
-
- if vrf_rttype.text == 'export_extcommunity':
- self.evpn_info['vpn_target_export'].append('auto')
- elif vrf_rttype.text == 'import_extcommunity':
- self.evpn_info['vpn_target_import'].append('auto')
-
- def process_rts_info(self):
- """Process RTS information"""
-
- if not self.evpn_info['vpn_target_export'] or\
- not self.evpn_info['vpn_target_import']:
- return
-
- vpn_target_export = copy.deepcopy(self.evpn_info['vpn_target_export'])
- for ele in vpn_target_export:
- if ele in self.evpn_info['vpn_target_import']:
- self.evpn_info['vpn_target_both'].append(ele)
- self.evpn_info['vpn_target_export'].remove(ele)
- self.evpn_info['vpn_target_import'].remove(ele)
-
- def get_evpn_instance_info(self):
- """Get current EVPN instance information"""
-
- if not self.bridge_domain_id:
- self.module.fail_json(msg='Error: The value of bridge_domain_id cannot be empty.')
-
- self.evpn_info['route_distinguisher'] = None
- self.evpn_info['vpn_target_import'] = list()
- self.evpn_info['vpn_target_export'] = list()
- self.evpn_info['vpn_target_both'] = list()
- self.evpn_info['evpn_inst'] = 'enable'
-
- xml_str = CE_NC_GET_EVPN_CONFIG % (
- self.bridge_domain_id, self.bridge_domain_id)
- xml_str = get_nc_config(self.module, xml_str)
- if "" in xml_str:
- self.evpn_info['evpn_inst'] = 'disable'
- return
-
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- evpn_inst = root.find("evpn/evpnInstances/evpnInstance")
- if evpn_inst:
- for eles in evpn_inst:
- if eles.tag in ["evpnAutoRD", "evpnRD", "evpnRTs", "evpnAutoRTs"]:
- if eles.tag == 'evpnAutoRD' and eles.text == 'true':
- self.evpn_info['route_distinguisher'] = 'auto'
- elif eles.tag == 'evpnRD' and self.evpn_info['route_distinguisher'] != 'auto':
- self.evpn_info['route_distinguisher'] = eles.text
- elif eles.tag == 'evpnRTs':
- self.get_all_evpn_rts(eles)
- elif eles.tag == 'evpnAutoRTs':
- self.get_all_evpn_autorts(eles)
- self.process_rts_info()
-
- def get_existing(self):
- """Get existing config"""
-
- self.existing = dict(bridge_domain_id=self.bridge_domain_id,
- evpn=self.evpn_info['evpn_inst'],
- route_distinguisher=self.evpn_info[
- 'route_distinguisher'],
- vpn_target_both=self.evpn_info['vpn_target_both'],
- vpn_target_import=self.evpn_info[
- 'vpn_target_import'],
- vpn_target_export=self.evpn_info['vpn_target_export'])
-
- def get_proposed(self):
- """Get proposed config"""
-
- self.proposed = dict(bridge_domain_id=self.bridge_domain_id,
- evpn=self.evpn,
- route_distinguisher=self.route_distinguisher,
- vpn_target_both=self.vpn_target_both,
- vpn_target_import=self.vpn_target_import,
- vpn_target_export=self.vpn_target_export,
- state=self.state)
-
- def get_end_state(self):
- """Get end config"""
-
- self.get_evpn_instance_info()
- self.end_state = dict(bridge_domain_id=self.bridge_domain_id,
- evpn=self.evpn_info['evpn_inst'],
- route_distinguisher=self.evpn_info[
- 'route_distinguisher'],
- vpn_target_both=self.evpn_info[
- 'vpn_target_both'],
- vpn_target_import=self.evpn_info[
- 'vpn_target_import'],
- vpn_target_export=self.evpn_info['vpn_target_export'])
-
- def show_result(self):
- """Show result"""
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
- def judge_if_vpn_target_exist(self, vpn_target_type):
- """Judge whether proposed vpn target has existed"""
-
- vpn_target = list()
- if vpn_target_type == 'vpn_target_import':
- vpn_target.extend(self.existing['vpn_target_both'])
- vpn_target.extend(self.existing['vpn_target_import'])
- return set(self.proposed['vpn_target_import']).issubset(vpn_target)
- elif vpn_target_type == 'vpn_target_export':
- vpn_target.extend(self.existing['vpn_target_both'])
- vpn_target.extend(self.existing['vpn_target_export'])
- return set(self.proposed['vpn_target_export']).issubset(vpn_target)
-
- return False
-
- def judge_if_config_exist(self):
- """Judge whether configuration has existed"""
-
- if self.state == 'absent':
- if self.route_distinguisher or self.vpn_target_import or self.vpn_target_export or self.vpn_target_both:
- return False
- else:
- return True
-
- if self.evpn_info['evpn_inst'] != self.evpn:
- return False
-
- if self.evpn == 'disable' and self.evpn_info['evpn_inst'] == 'disable':
- return True
-
- if self.proposed['bridge_domain_id'] != self.existing['bridge_domain_id']:
- return False
-
- if self.proposed['route_distinguisher']:
- if self.proposed['route_distinguisher'] != self.existing['route_distinguisher']:
- return False
-
- if self.proposed['vpn_target_both']:
- if not self.existing['vpn_target_both']:
- return False
- if not set(self.proposed['vpn_target_both']).issubset(self.existing['vpn_target_both']):
- return False
-
- if self.proposed['vpn_target_import']:
- if not self.judge_if_vpn_target_exist('vpn_target_import'):
- return False
-
- if self.proposed['vpn_target_export']:
- if not self.judge_if_vpn_target_exist('vpn_target_export'):
- return False
-
- return True
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def unconfig_evpn_instance(self):
- """Unconfigure EVPN instance"""
-
- self.updates_cmd.append("bridge-domain %s" % self.bridge_domain_id)
- xml_str = CE_NC_MERGE_EVPN_CONFIG_HEAD % (
- self.bridge_domain_id, self.bridge_domain_id)
- self.updates_cmd.append(" evpn")
-
- # unconfigure RD
- if self.route_distinguisher:
- if self.route_distinguisher.lower() == 'auto':
- xml_str += 'false'
- self.updates_cmd.append(" undo route-distinguisher auto")
- else:
- xml_str += ''
- self.updates_cmd.append(
- " undo route-distinguisher %s" % self.route_distinguisher)
- xml_str += CE_NC_MERGE_EVPN_CONFIG_TAIL
- recv_xml = set_nc_config(self.module, xml_str)
- self.check_response(recv_xml, "UNDO_EVPN_BD_RD")
- self.changed = True
- return
-
- # process VPN target list
- vpn_target_export = copy.deepcopy(self.vpn_target_export)
- vpn_target_import = copy.deepcopy(self.vpn_target_import)
- if self.vpn_target_both:
- for ele in self.vpn_target_both:
- if ele not in vpn_target_export:
- vpn_target_export.append(ele)
- if ele not in vpn_target_import:
- vpn_target_import.append(ele)
-
- # unconfig EVPN auto RTS
- head_flag = False
- if vpn_target_export:
- for ele in vpn_target_export:
- if ele.lower() == 'auto':
- if not head_flag:
- xml_str += CE_NC_MERGE_EVPN_AUTORTS_HEAD
- head_flag = True
- xml_str += CE_NC_DELETE_EVPN_AUTORTS_CONTEXT % (
- 'export_extcommunity')
- self.updates_cmd.append(
- " undo vpn-target auto export-extcommunity")
- if vpn_target_import:
- for ele in vpn_target_import:
- if ele.lower() == 'auto':
- if not head_flag:
- xml_str += CE_NC_MERGE_EVPN_AUTORTS_HEAD
- head_flag = True
- xml_str += CE_NC_DELETE_EVPN_AUTORTS_CONTEXT % (
- 'import_extcommunity')
- self.updates_cmd.append(
- " undo vpn-target auto import-extcommunity")
-
- if head_flag:
- xml_str += CE_NC_MERGE_EVPN_AUTORTS_TAIL
-
- # unconfig EVPN RTS
- head_flag = False
- if vpn_target_export:
- for ele in vpn_target_export:
- if ele.lower() != 'auto':
- if not head_flag:
- xml_str += CE_NC_MERGE_EVPN_RTS_HEAD
- head_flag = True
- xml_str += CE_NC_DELETE_EVPN_RTS_CONTEXT % (
- 'export_extcommunity', ele)
- self.updates_cmd.append(
- " undo vpn-target %s export-extcommunity" % ele)
-
- if vpn_target_import:
- for ele in vpn_target_import:
- if ele.lower() != 'auto':
- if not head_flag:
- xml_str += CE_NC_MERGE_EVPN_RTS_HEAD
- head_flag = True
- xml_str += CE_NC_DELETE_EVPN_RTS_CONTEXT % (
- 'import_extcommunity', ele)
- self.updates_cmd.append(
- " undo vpn-target %s import-extcommunity" % ele)
-
- if head_flag:
- xml_str += CE_NC_MERGE_EVPN_RTS_TAIL
-
- xml_str += CE_NC_MERGE_EVPN_CONFIG_TAIL
- recv_xml = set_nc_config(self.module, xml_str)
- self.check_response(recv_xml, "MERGE_EVPN_BD_VPN_TARGET_CONFIG")
- self.changed = True
-
- def config_evpn_instance(self):
- """Configure EVPN instance"""
-
- self.updates_cmd.append("bridge-domain %s" % self.bridge_domain_id)
-
- if self.evpn == 'disable':
- xml_str = CE_NC_DELETE_EVPN_CONFIG % (
- self.bridge_domain_id, self.bridge_domain_id)
- recv_xml = set_nc_config(self.module, xml_str)
- self.check_response(recv_xml, "MERGE_EVPN_BD_CONFIG")
- self.updates_cmd.append(" undo evpn")
- self.changed = True
- return
-
- xml_str = CE_NC_MERGE_EVPN_CONFIG_HEAD % (
- self.bridge_domain_id, self.bridge_domain_id)
- self.updates_cmd.append(" evpn")
-
- # configure RD
- if self.route_distinguisher:
- if not self.existing['route_distinguisher']:
- if self.route_distinguisher.lower() == 'auto':
- xml_str += 'true'
- self.updates_cmd.append(" route-distinguisher auto")
- else:
- xml_str += '%s' % self.route_distinguisher
- self.updates_cmd.append(
- " route-distinguisher %s" % self.route_distinguisher)
-
- # process VPN target list
- vpn_target_export = copy.deepcopy(self.vpn_target_export)
- vpn_target_import = copy.deepcopy(self.vpn_target_import)
- if self.vpn_target_both:
- for ele in self.vpn_target_both:
- if ele not in vpn_target_export:
- vpn_target_export.append(ele)
- if ele not in vpn_target_import:
- vpn_target_import.append(ele)
-
- # config EVPN auto RTS
- head_flag = False
- if vpn_target_export:
- for ele in vpn_target_export:
- if ele.lower() == 'auto' and \
- (not self.is_vpn_target_exist('export_extcommunity', ele.lower())):
- if not head_flag:
- xml_str += CE_NC_MERGE_EVPN_AUTORTS_HEAD
- head_flag = True
- xml_str += CE_NC_MERGE_EVPN_AUTORTS_CONTEXT % (
- 'export_extcommunity')
- self.updates_cmd.append(
- " vpn-target auto export-extcommunity")
- if vpn_target_import:
- for ele in vpn_target_import:
- if ele.lower() == 'auto' and \
- (not self.is_vpn_target_exist('import_extcommunity', ele.lower())):
- if not head_flag:
- xml_str += CE_NC_MERGE_EVPN_AUTORTS_HEAD
- head_flag = True
- xml_str += CE_NC_MERGE_EVPN_AUTORTS_CONTEXT % (
- 'import_extcommunity')
- self.updates_cmd.append(
- " vpn-target auto import-extcommunity")
-
- if head_flag:
- xml_str += CE_NC_MERGE_EVPN_AUTORTS_TAIL
-
- # config EVPN RTS
- head_flag = False
- if vpn_target_export:
- for ele in vpn_target_export:
- if ele.lower() != 'auto' and \
- (not self.is_vpn_target_exist('export_extcommunity', ele.lower())):
- if not head_flag:
- xml_str += CE_NC_MERGE_EVPN_RTS_HEAD
- head_flag = True
- xml_str += CE_NC_MERGE_EVPN_RTS_CONTEXT % (
- 'export_extcommunity', ele)
- self.updates_cmd.append(
- " vpn-target %s export-extcommunity" % ele)
-
- if vpn_target_import:
- for ele in vpn_target_import:
- if ele.lower() != 'auto' and \
- (not self.is_vpn_target_exist('import_extcommunity', ele.lower())):
- if not head_flag:
- xml_str += CE_NC_MERGE_EVPN_RTS_HEAD
- head_flag = True
- xml_str += CE_NC_MERGE_EVPN_RTS_CONTEXT % (
- 'import_extcommunity', ele)
- self.updates_cmd.append(
- " vpn-target %s import-extcommunity" % ele)
-
- if head_flag:
- xml_str += CE_NC_MERGE_EVPN_RTS_TAIL
-
- xml_str += CE_NC_MERGE_EVPN_CONFIG_TAIL
- recv_xml = set_nc_config(self.module, xml_str)
- self.check_response(recv_xml, "MERGE_EVPN_BD_CONFIG")
- self.changed = True
-
- def is_vpn_target_exist(self, target_type, value):
- """Judge whether VPN target has existed"""
-
- if target_type == 'export_extcommunity':
- if (value not in self.existing['vpn_target_export']) and\
- (value not in self.existing['vpn_target_both']):
- return False
- return True
-
- if target_type == 'import_extcommunity':
- if (value not in self.existing['vpn_target_import']) and\
- (value not in self.existing['vpn_target_both']):
- return False
- return True
-
- return False
-
- def config_evnp_bd(self):
- """Configure EVPN in BD view"""
-
- if not self.conf_exist:
- if self.state == 'present':
- self.config_evpn_instance()
- else:
- self.unconfig_evpn_instance()
-
- def process_input_params(self):
- """Process input parameters"""
-
- if self.state == 'absent':
- self.evpn = None
- else:
- if self.evpn == 'disable':
- return
-
- if self.vpn_target_both:
- for ele in self.vpn_target_both:
- if ele in self.vpn_target_export:
- self.vpn_target_export.remove(ele)
- if ele in self.vpn_target_import:
- self.vpn_target_import.remove(ele)
-
- if self.vpn_target_export and self.vpn_target_import:
- vpn_target_export = copy.deepcopy(self.vpn_target_export)
- for ele in vpn_target_export:
- if ele in self.vpn_target_import:
- self.vpn_target_both.append(ele)
- self.vpn_target_import.remove(ele)
- self.vpn_target_export.remove(ele)
-
- def check_vpn_target_para(self):
- """Check whether VPN target value is valid"""
-
- if self.route_distinguisher:
- if self.route_distinguisher.lower() != 'auto' and\
- not is_valid_value(self.route_distinguisher):
- self.module.fail_json(
- msg='Error: Route distinguisher has invalid value %s.' % self.route_distinguisher)
-
- if self.vpn_target_export:
- for ele in self.vpn_target_export:
- if ele.lower() != 'auto' and not is_valid_value(ele):
- self.module.fail_json(
- msg='Error: VPN target extended community attribute has invalid value %s.' % ele)
-
- if self.vpn_target_import:
- for ele in self.vpn_target_import:
- if ele.lower() != 'auto' and not is_valid_value(ele):
- self.module.fail_json(
- msg='Error: VPN target extended community attribute has invalid value %s.' % ele)
-
- if self.vpn_target_both:
- for ele in self.vpn_target_both:
- if ele.lower() != 'auto' and not is_valid_value(ele):
- self.module.fail_json(
- msg='Error: VPN target extended community attribute has invalid value %s.' % ele)
-
- def check_undo_params_if_exist(self):
- """Check whether all undo parameters is existed"""
-
- if self.vpn_target_import:
- for ele in self.vpn_target_import:
- if ele not in self.evpn_info['vpn_target_import'] and ele not in self.evpn_info['vpn_target_both']:
- self.module.fail_json(
- msg='Error: VPN target import attribute value %s does not exist.' % ele)
-
- if self.vpn_target_export:
- for ele in self.vpn_target_export:
- if ele not in self.evpn_info['vpn_target_export'] and ele not in self.evpn_info['vpn_target_both']:
- self.module.fail_json(
- msg='Error: VPN target export attribute value %s does not exist.' % ele)
-
- if self.vpn_target_both:
- for ele in self.vpn_target_both:
- if ele not in self.evpn_info['vpn_target_both']:
- self.module.fail_json(
- msg='Error: VPN target export and import attribute value %s does not exist.' % ele)
-
- def check_params(self):
- """Check all input params"""
-
- # bridge_domain_id check
- if self.bridge_domain_id:
- if not self.bridge_domain_id.isdigit():
- self.module.fail_json(
- msg='Error: The parameter of bridge domain id is invalid.')
- if int(self.bridge_domain_id) > 16777215 or int(self.bridge_domain_id) < 1:
- self.module.fail_json(
- msg='Error: The bridge domain id must be an integer between 1 and 16777215.')
-
- if self.state == 'absent':
- self.check_undo_params_if_exist()
-
- # check bd whether binding the vxlan vni
- self.check_vni_bd()
- self.check_vpn_target_para()
-
- if self.state == 'absent':
- if self.route_distinguisher:
- if not self.evpn_info['route_distinguisher']:
- self.module.fail_json(
- msg='Error: Route distinguisher has not been configured.')
- else:
- if self.route_distinguisher != self.evpn_info['route_distinguisher']:
- self.module.fail_json(
- msg='Error: Current route distinguisher value is %s.' %
- self.evpn_info['route_distinguisher'])
-
- if self.state == 'present':
- if self.route_distinguisher:
- if self.evpn_info['route_distinguisher'] and\
- self.route_distinguisher != self.evpn_info['route_distinguisher']:
- self.module.fail_json(
- msg='Error: Route distinguisher has already been configured.')
-
- def check_vni_bd(self):
- """Check whether vxlan vni is configured in BD view"""
-
- xml_str = CE_NC_GET_VNI_BD
- xml_str = get_nc_config(self.module, xml_str)
- if "" in xml_str or not re.findall(r'\S+\s+%s' % self.bridge_domain_id, xml_str):
- self.module.fail_json(
- msg='Error: The vxlan vni is not configured or the bridge domain id is invalid.')
-
- def work(self):
- """Execute task"""
-
- self.get_evpn_instance_info()
- self.process_input_params()
- self.check_params()
- self.get_existing()
- self.get_proposed()
- self.conf_exist = self.judge_if_config_exist()
-
- self.config_evnp_bd()
-
- self.get_end_state()
- self.show_result()
-
-
-def main():
- """Main function entry"""
-
- argument_spec = dict(
- bridge_domain_id=dict(required=True, type='str'),
- evpn=dict(required=False, type='str',
- default='enable', choices=['enable', 'disable']),
- route_distinguisher=dict(required=False, type='str'),
- vpn_target_both=dict(required=False, type='list'),
- vpn_target_import=dict(required=False, type='list'),
- vpn_target_export=dict(required=False, type='list'),
- state=dict(required=False, default='present',
- choices=['present', 'absent'])
- )
- argument_spec.update(ce_argument_spec)
- evpn_bd = EvpnBd(argument_spec)
- evpn_bd.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_evpn_bgp.py b/plugins/modules/network/cloudengine/ce_evpn_bgp.py
deleted file mode 100644
index 4789a1594b..0000000000
--- a/plugins/modules/network/cloudengine/ce_evpn_bgp.py
+++ /dev/null
@@ -1,731 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_evpn_bgp
-short_description: Manages BGP EVPN configuration on HUAWEI CloudEngine switches.
-description:
- - This module offers the ability to configure a BGP EVPN peer relationship on HUAWEI CloudEngine switches.
-author:
- - Li Yanfeng (@QijunPan)
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- bgp_instance:
- description:
- - Name of a BGP instance. The value is a string of 1 to 31 case-sensitive characters, spaces not supported.
- required: True
- as_number:
- description:
- - Specifies integral AS number. The value is an integer ranging from 1 to 4294967295.
- peer_address:
- description:
- - Specifies the IPv4 address of a BGP EVPN peer. The value is in dotted decimal notation.
- peer_group_name:
- description:
- - Specify the name of a peer group that BGP peers need to join.
- The value is a string of 1 to 47 case-sensitive characters, spaces not supported.
- peer_enable:
- description:
- - Enable or disable a BGP device to exchange routes with a specified peer or peer group in the address
- family view.
- choices: ['true','false']
- advertise_router_type:
- description:
- - Configures a device to advertise routes to its BGP EVPN peers.
- choices: ['arp','irb']
- vpn_name:
- description:
- - Associates a specified VPN instance with the IPv4 address family.
- The value is a string of 1 to 31 case-sensitive characters, spaces not supported.
- advertise_l2vpn_evpn:
- description:
- - Enable or disable a device to advertise IP routes imported to a VPN instance to its EVPN instance.
- choices: ['enable','disable']
- state:
- description:
- - Manage the state of the resource.
- default: present
- choices: ['present','absent']
-'''
-EXAMPLES = '''
-- name: evpn bgp module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Enable peer address.
- ce_evpn_bgp:
- bgp_instance: 100
- peer_address: 1.1.1.1
- as_number: 100
- peer_enable: true
- provider: "{{ cli }}"
-
- - name: Enable peer group arp.
- ce_evpn_bgp:
- bgp_instance: 100
- peer_group_name: aaa
- advertise_router_type: arp
- provider: "{{ cli }}"
-
- - name: Enable advertise l2vpn evpn.
- ce_evpn_bgp:
- bgp_instance: 100
- vpn_name: aaa
- advertise_l2vpn_evpn: enable
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"advertise_router_type": "arp", "bgp_instance": "100", "peer_group_name": "aaa", "state": "present"}
-existing:
- description: k/v pairs of existing rollback
- returned: always
- type: dict
- sample: {"bgp_instance": "100", "peer_group_advertise_type": []}
-
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["peer 1.1.1.1 enable",
- "peer aaa advertise arp"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-end_state:
- description: k/v pairs of configuration after module execution
- returned: verbose mode
- type: dict
- sample: {"advertise_l2vpn_evpn": "enable", "bgp_instance": "100", "vpn_name": "aaa"}
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import exec_command, load_config
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec
-
-
-def is_config_exist(cmp_cfg, test_cfg):
- """check configuration is exist"""
-
- if not cmp_cfg or not test_cfg:
- return False
-
- return bool(test_cfg in cmp_cfg)
-
-
-def is_valid_address(address):
- """check ip-address is valid"""
-
- if address.find('.') != -1:
- addr_list = address.split('.')
- if len(addr_list) != 4:
- return False
- for each_num in addr_list:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- return True
-
- return False
-
-
-def is_valid_as_number(as_number):
- """check as-number is valid"""
-
- if as_number.isdigit():
- if int(as_number) > 4294967295 or int(as_number) < 1:
- return False
- return True
- else:
- if as_number.find('.') != -1:
- number_list = as_number.split('.')
- if len(number_list) != 2:
- return False
- if number_list[1] == 0:
- return False
- for each_num in number_list:
- if not each_num.isdigit():
- return False
- if int(each_num) > 65535:
- return False
- return True
-
- return False
-
-
-class EvpnBgp(object):
- """
- Manages evpn bgp configuration.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.netconf = None
- self.init_module()
-
- # module input info
- self.as_number = self.module.params['as_number']
- self.bgp_instance = self.module.params['bgp_instance']
- self.peer_address = self.module.params['peer_address']
- self.peer_group_name = self.module.params['peer_group_name']
- self.peer_enable = self.module.params['peer_enable']
- self.advertise_router_type = self.module.params[
- 'advertise_router_type']
- self.vpn_name = self.module.params['vpn_name']
- self.advertise_l2vpn_evpn = self.module.params['advertise_l2vpn_evpn']
- self.state = self.module.params['state']
-
- # host info
- self.host = self.module.params['host']
- self.username = self.module.params['username']
- self.port = self.module.params['port']
-
- # state
- self.config = ""
- self.config_list = list()
- self.l2vpn_evpn_exist = False
- self.changed = False
- self.updates_cmd = list()
- self.commands = list()
- self.results = dict()
- self.existing = dict()
- self.proposed = dict()
- self.end_state = dict()
-
- def init_module(self):
- """ init module """
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def get_evpn_overlay_config(self):
- """get evpn-overlay enable configuration"""
-
- cmd = "display current-configuration | include ^evpn-overlay enable"
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- return out
-
- def get_current_config(self):
- """get current configuration"""
-
- cmd = "display current-configuration | section include bgp %s" % self.bgp_instance
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- return out
-
- def cli_add_command(self, command, undo=False):
- """add command to self.update_cmd and self.commands"""
-
- if undo and command.lower() not in ["quit", "return"]:
- cmd = "undo " + command
- else:
- cmd = command
-
- self.commands.append(cmd) # set to device
- if command.lower() not in ["quit", "return"]:
- self.updates_cmd.append(cmd) # show updates result
-
- def cli_load_config(self, commands):
- """load config by cli"""
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def check_params(self):
- """Check all input params"""
-
- # as_number check
- if not self.bgp_instance:
- self.module.fail_json(
- msg='Error: The bgp_instance can not be none.')
- if not self.peer_enable and not self.advertise_router_type and not self.advertise_l2vpn_evpn:
- self.module.fail_json(
- msg='Error: The peer_enable, advertise_router_type, advertise_l2vpn_evpn '
- 'can not be none at the same time.')
- if self.as_number:
- if not is_valid_as_number(self.as_number):
- self.module.fail_json(
- msg='Error: The parameter of as_number %s is invalid.' % self.as_number)
- # bgp_instance check
- if self.bgp_instance:
- if not is_valid_as_number(self.bgp_instance):
- self.module.fail_json(
- msg='Error: The parameter of bgp_instance %s is invalid.' % self.bgp_instance)
-
- # peer_address check
- if self.peer_address:
- if not is_valid_address(self.peer_address):
- self.module.fail_json(
- msg='Error: The %s is not a valid ip address.' % self.peer_address)
-
- # peer_group_name check
- if self.peer_group_name:
- if len(self.peer_group_name) > 47 \
- or len(self.peer_group_name.replace(' ', '')) < 1:
- self.module.fail_json(
- msg='Error: peer group name is not in the range from 1 to 47.')
-
- # vpn_name check
- if self.vpn_name:
- if len(self.vpn_name) > 31 \
- or len(self.vpn_name.replace(' ', '')) < 1:
- self.module.fail_json(
- msg='Error: peer group name is not in the range from 1 to 31.')
-
- def get_proposed(self):
- """get proposed info"""
-
- if self.as_number:
- self.proposed["as_number"] = self.as_number
- if self.bgp_instance:
- self.proposed["bgp_instance"] = self.bgp_instance
- if self.peer_address:
- self.proposed["peer_address"] = self.peer_address
- if self.peer_group_name:
- self.proposed["peer_group_name"] = self.peer_group_name
- if self.peer_enable:
- self.proposed["peer_enable"] = self.peer_enable
- if self.advertise_router_type:
- self.proposed["advertise_router_type"] = self.advertise_router_type
- if self.vpn_name:
- self.proposed["vpn_name"] = self.vpn_name
- if self.advertise_l2vpn_evpn:
- self.proposed["advertise_l2vpn_evpn"] = self.advertise_l2vpn_evpn
- if not self.peer_enable or not self.advertise_l2vpn_evpn:
- if self.state:
- self.proposed["state"] = self.state
-
- def get_peers_enable(self):
- """get evpn peer address enable list"""
-
- if len(self.config_list) != 2:
- return None
- self.config_list = self.config.split('l2vpn-family evpn')
- get = re.findall(
- r"peer ([0-9]+.[0-9]+.[0-9]+.[0-9]+)\s?as-number\s?(\S*)", self.config_list[0])
- if not get:
- return None
- else:
- peers = list()
- for item in get:
- cmd = "peer %s enable" % item[0]
- exist = is_config_exist(self.config_list[1], cmd)
- if exist:
- peers.append(
- dict(peer_address=item[0], as_number=item[1], peer_enable='true'))
- else:
- peers.append(dict(peer_address=item[0], as_number=item[1], peer_enable='false'))
- return peers
-
- def get_peers_advertise_type(self):
- """get evpn peer address advertise type list"""
-
- if len(self.config_list) != 2:
- return None
- self.config_list = self.config.split('l2vpn-family evpn')
- get = re.findall(
- r"peer ([0-9]+.[0-9]+.[0-9]+.[0-9]+)\s?as-number\s?(\S*)", self.config_list[0])
- if not get:
- return None
- else:
- peers = list()
- for item in get:
- cmd = "peer %s advertise arp" % item[0]
- exist1 = is_config_exist(self.config_list[1], cmd)
- cmd = "peer %s advertise irb" % item[0]
- exist2 = is_config_exist(self.config_list[1], cmd)
- if exist1:
- peers.append(dict(peer_address=item[0], as_number=item[1], advertise_type='arp'))
- if exist2:
- peers.append(dict(peer_address=item[0], as_number=item[1], advertise_type='irb'))
- return peers
-
- def get_peers_group_enable(self):
- """get evpn peer group name enable list"""
-
- if len(self.config_list) != 2:
- return None
- self.config_list = self.config.split('l2vpn-family evpn')
- get1 = re.findall(
- r"group (\S+) external", self.config_list[0])
-
- get2 = re.findall(
- r"group (\S+) internal", self.config_list[0])
-
- if not get1 and not get2:
- return None
- else:
- peer_groups = list()
- for item in get1:
- cmd = "peer %s enable" % item
- exist = is_config_exist(self.config_list[1], cmd)
- if exist:
- peer_groups.append(
- dict(peer_group_name=item, peer_enable='true'))
- else:
- peer_groups.append(
- dict(peer_group_name=item, peer_enable='false'))
-
- for item in get2:
- cmd = "peer %s enable" % item
- exist = is_config_exist(self.config_list[1], cmd)
- if exist:
- peer_groups.append(
- dict(peer_group_name=item, peer_enable='true'))
- else:
- peer_groups.append(
- dict(peer_group_name=item, peer_enable='false'))
- return peer_groups
-
- def get_peer_groups_advertise_type(self):
- """get evpn peer group name advertise type list"""
-
- if len(self.config_list) != 2:
- return None
- self.config_list = self.config.split('l2vpn-family evpn')
- get1 = re.findall(
- r"group (\S+) external", self.config_list[0])
-
- get2 = re.findall(
- r"group (\S+) internal", self.config_list[0])
- if not get1 and not get2:
- return None
- else:
- peer_groups = list()
- for item in get1:
- cmd = "peer %s advertise arp" % item
- exist1 = is_config_exist(self.config_list[1], cmd)
- cmd = "peer %s advertise irb" % item
- exist2 = is_config_exist(self.config_list[1], cmd)
- if exist1:
- peer_groups.append(
- dict(peer_group_name=item, advertise_type='arp'))
- if exist2:
- peer_groups.append(
- dict(peer_group_name=item, advertise_type='irb'))
-
- for item in get2:
- cmd = "peer %s advertise arp" % item
- exist1 = is_config_exist(self.config_list[1], cmd)
- cmd = "peer %s advertise irb" % item
- exist2 = is_config_exist(self.config_list[1], cmd)
- if exist1:
- peer_groups.append(
- dict(peer_group_name=item, advertise_type='arp'))
- if exist2:
- peer_groups.append(
- dict(peer_group_name=item, advertise_type='irb'))
- return peer_groups
-
- def get_existing(self):
- """get existing info"""
-
- if not self.config:
- return
- if self.bgp_instance:
- self.existing["bgp_instance"] = self.bgp_instance
-
- if self.peer_address and self.peer_enable:
- if self.l2vpn_evpn_exist:
- self.existing["peer_address_enable"] = self.get_peers_enable()
-
- if self.peer_group_name and self.peer_enable:
- if self.l2vpn_evpn_exist:
- self.existing[
- "peer_group_enable"] = self.get_peers_group_enable()
-
- if self.peer_address and self.advertise_router_type:
- if self.l2vpn_evpn_exist:
- self.existing[
- "peer_address_advertise_type"] = self.get_peers_advertise_type()
-
- if self.peer_group_name and self.advertise_router_type:
- if self.l2vpn_evpn_exist:
- self.existing[
- "peer_group_advertise_type"] = self.get_peer_groups_advertise_type()
-
- if self.advertise_l2vpn_evpn and self.vpn_name:
- cmd = " ipv4-family vpn-instance %s" % self.vpn_name
- exist = is_config_exist(self.config, cmd)
- if exist:
- self.existing["vpn_name"] = self.vpn_name
- l2vpn_cmd = "advertise l2vpn evpn"
- l2vpn_exist = is_config_exist(self.config, l2vpn_cmd)
- if l2vpn_exist:
- self.existing["advertise_l2vpn_evpn"] = 'enable'
- else:
- self.existing["advertise_l2vpn_evpn"] = 'disable'
-
- def get_end_state(self):
- """get end state info"""
-
- self.config = self.get_current_config()
- if not self.config:
- return
-
- self.config_list = self.config.split('l2vpn-family evpn')
- if len(self.config_list) == 2:
- self.l2vpn_evpn_exist = True
-
- if self.bgp_instance:
- self.end_state["bgp_instance"] = self.bgp_instance
-
- if self.peer_address and self.peer_enable:
- if self.l2vpn_evpn_exist:
- self.end_state["peer_address_enable"] = self.get_peers_enable()
-
- if self.peer_group_name and self.peer_enable:
- if self.l2vpn_evpn_exist:
- self.end_state[
- "peer_group_enable"] = self.get_peers_group_enable()
-
- if self.peer_address and self.advertise_router_type:
- if self.l2vpn_evpn_exist:
- self.end_state[
- "peer_address_advertise_type"] = self.get_peers_advertise_type()
-
- if self.peer_group_name and self.advertise_router_type:
- if self.l2vpn_evpn_exist:
- self.end_state[
- "peer_group_advertise_type"] = self.get_peer_groups_advertise_type()
-
- if self.advertise_l2vpn_evpn and self.vpn_name:
- cmd = " ipv4-family vpn-instance %s" % self.vpn_name
- exist = is_config_exist(self.config, cmd)
- if exist:
- self.end_state["vpn_name"] = self.vpn_name
- l2vpn_cmd = "advertise l2vpn evpn"
- l2vpn_exist = is_config_exist(self.config, l2vpn_cmd)
- if l2vpn_exist:
- self.end_state["advertise_l2vpn_evpn"] = 'enable'
- else:
- self.end_state["advertise_l2vpn_evpn"] = 'disable'
-
- def config_peer(self):
- """configure evpn bgp peer command"""
-
- if self.as_number and self.peer_address:
- cmd = "peer %s as-number %s" % (self.peer_address, self.as_number)
- exist = is_config_exist(self.config, cmd)
- if not exist:
- self.module.fail_json(
- msg='Error: The peer session %s does not exist or the peer already '
- 'exists in another as-number.' % self.peer_address)
- cmd = "bgp %s" % self.bgp_instance
- self.cli_add_command(cmd)
- cmd = "l2vpn-family evpn"
- self.cli_add_command(cmd)
- exist_l2vpn = is_config_exist(self.config, cmd)
- if self.peer_enable:
- cmd = "peer %s enable" % self.peer_address
- if exist_l2vpn:
- exist = is_config_exist(self.config_list[1], cmd)
- if self.peer_enable == "true" and not exist:
- self.cli_add_command(cmd)
- self.changed = True
- elif self.peer_enable == "false" and exist:
- self.cli_add_command(cmd, undo=True)
- self.changed = True
- else:
- self.cli_add_command(cmd)
- self.changed = True
-
- if self.advertise_router_type:
- cmd = "peer %s advertise %s" % (
- self.peer_address, self.advertise_router_type)
- exist = is_config_exist(self.config, cmd)
- if self.state == "present" and not exist:
- self.cli_add_command(cmd)
- self.changed = True
- elif self.state == "absent" and exist:
- self.cli_add_command(cmd, undo=True)
- self.changed = True
- elif self.peer_group_name:
- cmd_1 = "group %s external" % self.peer_group_name
- exist_1 = is_config_exist(self.config, cmd_1)
- cmd_2 = "group %s internal" % self.peer_group_name
- exist_2 = is_config_exist(self.config, cmd_2)
- exist = False
- if exist_1:
- exist = True
- if exist_2:
- exist = True
- if not exist:
- self.module.fail_json(
- msg='Error: The peer-group %s does not exist.' % self.peer_group_name)
- cmd = "bgp %s" % self.bgp_instance
- self.cli_add_command(cmd)
- cmd = "l2vpn-family evpn"
- self.cli_add_command(cmd)
- exist_l2vpn = is_config_exist(self.config, cmd)
- if self.peer_enable:
- cmd = "peer %s enable" % self.peer_group_name
- if exist_l2vpn:
- exist = is_config_exist(self.config_list[1], cmd)
- if self.peer_enable == "true" and not exist:
- self.cli_add_command(cmd)
- self.changed = True
- elif self.peer_enable == "false" and exist:
- self.cli_add_command(cmd, undo=True)
- self.changed = True
- else:
- self.cli_add_command(cmd)
- self.changed = True
-
- if self.advertise_router_type:
- cmd = "peer %s advertise %s" % (
- self.peer_group_name, self.advertise_router_type)
- exist = is_config_exist(self.config, cmd)
- if self.state == "present" and not exist:
- self.cli_add_command(cmd)
- self.changed = True
- elif self.state == "absent" and exist:
- self.cli_add_command(cmd, undo=True)
- self.changed = True
-
- def config_advertise_l2vpn_evpn(self):
- """configure advertise l2vpn evpn"""
-
- cmd = "ipv4-family vpn-instance %s" % self.vpn_name
- exist = is_config_exist(self.config, cmd)
- if not exist:
- self.module.fail_json(
- msg='Error: The VPN instance name %s does not exist.' % self.vpn_name)
- config_vpn_list = self.config.split(cmd)
- cmd = "ipv4-family vpn-instance"
- exist_vpn = is_config_exist(config_vpn_list[1], cmd)
- cmd_l2vpn = "advertise l2vpn evpn"
- if exist_vpn:
- config_vpn = config_vpn_list[1].split('ipv4-family vpn-instance')
- exist_l2vpn = is_config_exist(config_vpn[0], cmd_l2vpn)
- else:
- exist_l2vpn = is_config_exist(config_vpn_list[1], cmd_l2vpn)
- cmd = "advertise l2vpn evpn"
- if self.advertise_l2vpn_evpn == "enable" and not exist_l2vpn:
- cmd = "bgp %s" % self.bgp_instance
- self.cli_add_command(cmd)
- cmd = "ipv4-family vpn-instance %s" % self.vpn_name
- self.cli_add_command(cmd)
- cmd = "advertise l2vpn evpn"
- self.cli_add_command(cmd)
- self.changed = True
- elif self.advertise_l2vpn_evpn == "disable" and exist_l2vpn:
- cmd = "bgp %s" % self.bgp_instance
- self.cli_add_command(cmd)
- cmd = "ipv4-family vpn-instance %s" % self.vpn_name
- self.cli_add_command(cmd)
- cmd = "advertise l2vpn evpn"
- self.cli_add_command(cmd, undo=True)
- self.changed = True
-
- def work(self):
- """worker"""
-
- self.check_params()
- evpn_config = self.get_evpn_overlay_config()
- if not evpn_config:
- self.module.fail_json(
- msg="Error: evpn-overlay enable is not configured.")
- self.config = self.get_current_config()
- if not self.config:
- self.module.fail_json(
- msg="Error: Bgp instance %s does not exist." % self.bgp_instance)
-
- self.config_list = self.config.split('l2vpn-family evpn')
- if len(self.config_list) == 2:
- self.l2vpn_evpn_exist = True
- self.get_existing()
- self.get_proposed()
-
- if self.peer_enable or self.advertise_router_type:
- self.config_peer()
-
- if self.advertise_l2vpn_evpn:
- self.config_advertise_l2vpn_evpn()
- if self.commands:
- self.cli_load_config(self.commands)
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- bgp_instance=dict(required=True, type='str'),
- as_number=dict(required=False, type='str'),
- peer_address=dict(required=False, type='str'),
- peer_group_name=dict(required=False, type='str'),
- peer_enable=dict(required=False, type='str', choices=[
- 'true', 'false']),
- advertise_router_type=dict(required=False, type='str', choices=[
- 'arp', 'irb']),
-
- vpn_name=dict(required=False, type='str'),
- advertise_l2vpn_evpn=dict(required=False, type='str', choices=[
- 'enable', 'disable']),
- state=dict(required=False, default='present',
- choices=['present', 'absent'])
- )
- argument_spec.update(ce_argument_spec)
- module = EvpnBgp(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_evpn_bgp_rr.py b/plugins/modules/network/cloudengine/ce_evpn_bgp_rr.py
deleted file mode 100644
index 2e86d0f4e8..0000000000
--- a/plugins/modules/network/cloudengine/ce_evpn_bgp_rr.py
+++ /dev/null
@@ -1,531 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_evpn_bgp_rr
-short_description: Manages RR for the VXLAN Network on HUAWEI CloudEngine switches.
-description:
- - Configure an RR in BGP-EVPN address family view on HUAWEI CloudEngine switches.
-author: Zhijin Zhou (@QijunPan)
-notes:
- - Ensure that BGP view is existed.
- - The peer, peer_type, and reflect_client arguments must all exist or not exist.
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- as_number:
- description:
- - Specifies the number of the AS, in integer format.
- The value is an integer that ranges from 1 to 4294967295.
- required: true
- bgp_instance:
- description:
- - Specifies the name of a BGP instance.
- The value of instance-name can be an integer 1 or a string of 1 to 31.
- bgp_evpn_enable:
- description:
- - Enable or disable the BGP-EVPN address family.
- choices: ['enable','disable']
- default: 'enable'
- peer_type:
- description:
- - Specify the peer type.
- choices: ['group_name','ipv4_address']
- peer:
- description:
- - Specifies the IPv4 address or the group name of a peer.
- reflect_client:
- description:
- - Configure the local device as the route reflector and the peer or peer group as the client of the route reflector.
- choices: ['enable','disable']
- policy_vpn_target:
- description:
- - Enable or disable the VPN-Target filtering.
- choices: ['enable','disable']
-'''
-
-EXAMPLES = '''
-- name: BGP RR test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Configure BGP-EVPN address family view and ensure that BGP view has existed."
- ce_evpn_bgp_rr:
- as_number: 20
- bgp_evpn_enable: enable
- provider: "{{ cli }}"
-
- - name: "Configure reflect client and ensure peer has existed."
- ce_evpn_bgp_rr:
- as_number: 20
- peer_type: ipv4_address
- peer: 192.8.3.3
- reflect_client: enable
- provider: "{{ cli }}"
-
- - name: "Configure the VPN-Target filtering."
- ce_evpn_bgp_rr:
- as_number: 20
- policy_vpn_target: enable
- provider: "{{ cli }}"
-
- - name: "Configure an RR in BGP-EVPN address family view."
- ce_evpn_bgp_rr:
- as_number: 20
- bgp_evpn_enable: enable
- peer_type: ipv4_address
- peer: 192.8.3.3
- reflect_client: enable
- policy_vpn_target: disable
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "as_number": "20",
- "bgp_evpn_enable": "enable",
- "bgp_instance": null,
- "peer": "192.8.3.3",
- "peer_type": "ipv4_address",
- "policy_vpn_target": "disable",
- "reflect_client": "enable"
- }
-existing:
- description: k/v pairs of existing attributes on the device
- returned: always
- type: dict
- sample: {
- "as_number": "20",
- "bgp_evpn_enable": "disable",
- "bgp_instance": null,
- "peer": null,
- "peer_type": null,
- "policy_vpn_target": "disable",
- "reflect_client": "disable"
- }
-end_state:
- description: k/v pairs of end attributes on the device
- returned: always
- type: dict
- sample: {
- "as_number": "20",
- "bgp_evpn_enable": "enable",
- "bgp_instance": null,
- "peer": "192.8.3.3",
- "peer_type": "ipv4_address",
- "policy_vpn_target": "disable",
- "reflect_client": "enable"
- }
-updates:
- description: command list sent to the device
- returned: always
- type: list
- sample: [
- "bgp 20",
- " l2vpn-family evpn",
- " peer 192.8.3.3 enable",
- " peer 192.8.3.3 reflect-client",
- " undo policy vpn-target"
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import exec_command, load_config, ce_argument_spec
-
-
-def is_config_exist(cmp_cfg, test_cfg):
- """is configuration exist"""
-
- if not cmp_cfg or not test_cfg:
- return False
-
- return bool(test_cfg in cmp_cfg)
-
-
-class EvpnBgpRr(object):
- """Manage RR in BGP-EVPN address family view"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.__init_module__()
-
- # RR configuration parameters
- self.as_number = self.module.params['as_number']
- self.bgp_instance = self.module.params['bgp_instance']
- self.peer_type = self.module.params['peer_type']
- self.peer = self.module.params['peer']
- self.bgp_evpn_enable = self.module.params['bgp_evpn_enable']
- self.reflect_client = self.module.params['reflect_client']
- self.policy_vpn_target = self.module.params['policy_vpn_target']
-
- self.commands = list()
- self.config = None
- self.bgp_evpn_config = ""
- self.cur_config = dict()
- self.conf_exist = False
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def __init_module__(self):
- """Init module"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def cli_load_config(self, commands):
- """Load config by cli"""
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def is_bgp_view_exist(self):
- """Judge whether BGP view has existed"""
-
- if self.bgp_instance:
- view_cmd = "bgp %s instance %s" % (
- self.as_number, self.bgp_instance)
- else:
- view_cmd = "bgp %s" % self.as_number
-
- return is_config_exist(self.config, view_cmd)
-
- def is_l2vpn_family_evpn_exist(self):
- """Judge whether BGP-EVPN address family view has existed"""
-
- view_cmd = "l2vpn-family evpn"
- return is_config_exist(self.config, view_cmd)
-
- def is_reflect_client_exist(self):
- """Judge whether reflect client is configured"""
-
- view_cmd = "peer %s reflect-client" % self.peer
- return is_config_exist(self.bgp_evpn_config, view_cmd)
-
- def is_policy_vpn_target_exist(self):
- """Judge whether the VPN-Target filtering is enabled"""
-
- view_cmd = "undo policy vpn-target"
- if is_config_exist(self.bgp_evpn_config, view_cmd):
- return False
- else:
- return True
-
- def get_config_in_bgp_view(self):
- """Get configuration in BGP view"""
-
- cmd = "display current-configuration | section include"
- if self.as_number:
- if self.bgp_instance:
- cmd += " bgp %s instance %s" % (self.as_number,
- self.bgp_instance)
- else:
- cmd += " bgp %s" % self.as_number
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- config = out.strip() if out else ""
- if cmd == config:
- return ''
-
- return config
-
- def get_config_in_bgp_evpn_view(self):
- """Get configuration in BGP_EVPN view"""
-
- self.bgp_evpn_config = ""
- if not self.config:
- return ""
-
- index = self.config.find("l2vpn-family evpn")
- if index == -1:
- return ""
-
- return self.config[index:]
-
- def get_current_config(self):
- """Get current configuration"""
-
- if not self.as_number:
- self.module.fail_json(msg='Error: The value of as-number cannot be empty.')
-
- self.cur_config['bgp_exist'] = False
- self.cur_config['bgp_evpn_enable'] = 'disable'
- self.cur_config['reflect_client'] = 'disable'
- self.cur_config['policy_vpn_target'] = 'disable'
- self.cur_config['peer_type'] = None
- self.cur_config['peer'] = None
-
- self.config = self.get_config_in_bgp_view()
-
- if not self.is_bgp_view_exist():
- return
- self.cur_config['bgp_exist'] = True
-
- if not self.is_l2vpn_family_evpn_exist():
- return
- self.cur_config['bgp_evpn_enable'] = 'enable'
-
- self.bgp_evpn_config = self.get_config_in_bgp_evpn_view()
- if self.is_reflect_client_exist():
- self.cur_config['reflect_client'] = 'enable'
- self.cur_config['peer_type'] = self.peer_type
- self.cur_config['peer'] = self.peer
-
- if self.is_policy_vpn_target_exist():
- self.cur_config['policy_vpn_target'] = 'enable'
-
- def get_existing(self):
- """Get existing config"""
-
- self.existing = dict(as_number=self.as_number,
- bgp_instance=self.bgp_instance,
- peer_type=self.cur_config['peer_type'],
- peer=self.cur_config['peer'],
- bgp_evpn_enable=self.cur_config[
- 'bgp_evpn_enable'],
- reflect_client=self.cur_config['reflect_client'],
- policy_vpn_target=self.cur_config[
- 'policy_vpn_target'])
-
- def get_proposed(self):
- """Get proposed config"""
-
- self.proposed = dict(as_number=self.as_number,
- bgp_instance=self.bgp_instance,
- peer_type=self.peer_type,
- peer=self.peer,
- bgp_evpn_enable=self.bgp_evpn_enable,
- reflect_client=self.reflect_client,
- policy_vpn_target=self.policy_vpn_target)
-
- def get_end_state(self):
- """Get end config"""
-
- self.get_current_config()
- self.end_state = dict(as_number=self.as_number,
- bgp_instance=self.bgp_instance,
- peer_type=self.cur_config['peer_type'],
- peer=self.cur_config['peer'],
- bgp_evpn_enable=self.cur_config[
- 'bgp_evpn_enable'],
- reflect_client=self.cur_config['reflect_client'],
- policy_vpn_target=self.cur_config['policy_vpn_target'])
- if self.end_state == self.existing:
- self.changed = False
-
- def show_result(self):
- """Show result"""
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
- def judge_if_config_exist(self):
- """Judge whether configuration has existed"""
-
- if self.bgp_evpn_enable and self.bgp_evpn_enable != self.cur_config['bgp_evpn_enable']:
- return False
-
- if self.bgp_evpn_enable == 'disable' and self.cur_config['bgp_evpn_enable'] == 'disable':
- return True
-
- if self.reflect_client and self.reflect_client == 'enable':
- if self.peer_type and self.peer_type != self.cur_config['peer_type']:
- return False
- if self.peer and self.peer != self.cur_config['peer']:
- return False
- if self.reflect_client and self.reflect_client != self.cur_config['reflect_client']:
- return False
-
- if self.policy_vpn_target and self.policy_vpn_target != self.cur_config['policy_vpn_target']:
- return False
-
- return True
-
- def cli_add_command(self, command, undo=False):
- """Add command to self.update_cmd and self.commands"""
-
- if undo and command.lower() not in ["quit", "return"]:
- cmd = "undo " + command
- else:
- cmd = command
-
- self.commands.append(cmd) # set to device
- if command.lower() not in ["quit", "return"]:
- self.updates_cmd.append(cmd) # show updates result
-
- def config_rr(self):
- """Configure RR"""
-
- if self.conf_exist:
- return
-
- if self.bgp_instance:
- view_cmd = "bgp %s instance %s" % (
- self.as_number, self.bgp_instance)
- else:
- view_cmd = "bgp %s" % self.as_number
- self.cli_add_command(view_cmd)
-
- if self.bgp_evpn_enable == 'disable':
- self.cli_add_command("undo l2vpn-family evpn")
- else:
- self.cli_add_command("l2vpn-family evpn")
- if self.reflect_client and self.reflect_client != self.cur_config['reflect_client']:
- if self.reflect_client == 'enable':
- self.cli_add_command("peer %s enable" % self.peer)
- self.cli_add_command(
- "peer %s reflect-client" % self.peer)
- else:
- self.cli_add_command(
- "undo peer %s reflect-client" % self.peer)
- self.cli_add_command("undo peer %s enable" % self.peer)
- if self.cur_config['bgp_evpn_enable'] == 'enable':
- if self.policy_vpn_target and self.policy_vpn_target != self.cur_config['policy_vpn_target']:
- if self.policy_vpn_target == 'enable':
- self.cli_add_command("policy vpn-target")
- else:
- self.cli_add_command("undo policy vpn-target")
- else:
- if self.policy_vpn_target and self.policy_vpn_target == 'disable':
- self.cli_add_command("undo policy vpn-target")
-
- if self.commands:
- self.cli_load_config(self.commands)
- self.changed = True
-
- def check_is_ipv4_addr(self):
- """Check ipaddress validate"""
-
- rule1 = r'(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.'
- rule2 = r'(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])'
- ipv4_regex = '%s%s%s%s%s%s' % ('^', rule1, rule1, rule1, rule2, '$')
-
- return bool(re.match(ipv4_regex, self.peer))
-
- def check_params(self):
- """Check all input params"""
-
- if self.cur_config['bgp_exist'] == 'false':
- self.module.fail_json(msg="Error: BGP view does not exist.")
-
- if self.bgp_instance:
- if len(self.bgp_instance) < 1 or len(self.bgp_instance) > 31:
- self.module.fail_json(
- msg="Error: The length of BGP instance-name must be between 1 or a string of 1 to and 31.")
-
- if self.as_number:
- if len(self.as_number) > 11 or len(self.as_number) == 0:
- self.module.fail_json(
- msg='Error: The len of as_number %s is out of [1 - 11].' % self.as_number)
-
- tmp_dict1 = dict(peer_type=self.peer_type,
- peer=self.peer,
- reflect_client=self.reflect_client)
- tmp_dict2 = dict((k, v)
- for k, v in tmp_dict1.items() if v is not None)
- if len(tmp_dict2) != 0 and len(tmp_dict2) != 3:
- self.module.fail_json(
- msg='Error: The peer, peer_type, and reflect_client arguments must all exist or not exist.')
-
- if self.peer_type:
- if self.peer_type == 'ipv4_address' and not self.check_is_ipv4_addr():
- self.module.fail_json(msg='Error: Illegal IPv4 address.')
- elif self.peer_type == 'group_name' and self.check_is_ipv4_addr():
- self.module.fail_json(
- msg='Error: Ip address cannot be configured as group-name.')
-
- def work(self):
- """Execute task"""
-
- self.get_current_config()
- self.check_params()
- self.get_existing()
- self.get_proposed()
- self.conf_exist = self.judge_if_config_exist()
-
- self.config_rr()
-
- self.get_end_state()
- self.show_result()
-
-
-def main():
- """Main function entry"""
-
- argument_spec = dict(
- as_number=dict(required=True, type='str'),
- bgp_instance=dict(required=False, type='str'),
- bgp_evpn_enable=dict(required=False, type='str',
- default='enable', choices=['enable', 'disable']),
- peer_type=dict(required=False, type='str', choices=[
- 'group_name', 'ipv4_address']),
- peer=dict(required=False, type='str'),
- reflect_client=dict(required=False, type='str',
- choices=['enable', 'disable']),
- policy_vpn_target=dict(required=False, choices=['enable', 'disable']),
- )
- argument_spec.update(ce_argument_spec)
- evpn_bgp_rr = EvpnBgpRr(argument_spec)
- evpn_bgp_rr.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_evpn_global.py b/plugins/modules/network/cloudengine/ce_evpn_global.py
deleted file mode 100644
index 8f17b2139a..0000000000
--- a/plugins/modules/network/cloudengine/ce_evpn_global.py
+++ /dev/null
@@ -1,240 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_evpn_global
-short_description: Manages global configuration of EVPN on HUAWEI CloudEngine switches.
-description:
- - Manages global configuration of EVPN on HUAWEI CloudEngine switches.
-author: Zhijin Zhou (@QijunPan)
-notes:
- - Before configuring evpn_overlay_enable=disable, delete other EVPN configurations.
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- evpn_overlay_enable:
- description:
- - Configure EVPN as the VXLAN control plane.
- required: true
- choices: ['enable','disable']
-'''
-
-EXAMPLES = '''
-- name: evpn global module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Configure EVPN as the VXLAN control plan
- ce_evpn_global:
- evpn_overlay_enable: enable
- provider: "{{ cli }}"
-
- - name: Undo EVPN as the VXLAN control plan
- ce_evpn_global:
- evpn_overlay_enable: disable
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "evpn_overlay_enable": "enable"
- }
-existing:
- description: k/v pairs of existing attributes on the device
- returned: always
- type: dict
- sample: {
- "evpn_overlay_enable": "disable"
- }
-end_state:
- description: k/v pairs of end attributes on the interface
- returned: always
- type: dict
- sample: {
- "evpn_overlay_enable": "enable"
- }
-updates:
- description: command list sent to the device
- returned: always
- type: list
- sample: [
- "evpn-overlay enable",
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import exec_command, load_config
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec
-
-
-class EvpnGlobal(object):
- """Manage global configuration of EVPN"""
-
- def __init__(self, argument_spec, ):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # EVPN global configuration parameters
- self.overlay_enable = self.module.params['evpn_overlay_enable']
-
- self.commands = list()
- self.global_info = dict()
- self.conf_exist = False
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def init_module(self):
- """init_module"""
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def cli_load_config(self, commands):
- """load config by cli"""
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def cli_add_command(self, command, undo=False):
- """add command to self.update_cmd and self.commands"""
- if undo and command.lower() not in ["quit", "return"]:
- cmd = "undo " + command
- else:
- cmd = command
-
- self.commands.append(cmd) # set to device
- if command.lower() not in ["quit", "return"]:
- self.updates_cmd.append(cmd) # show updates result
-
- def get_evpn_global_info(self):
- """ get current EVPN global configuration"""
-
- self.global_info['evpnOverLay'] = 'disable'
- cmd = "display current-configuration | include ^evpn-overlay enable"
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- if out:
- self.global_info['evpnOverLay'] = 'enable'
-
- def get_existing(self):
- """get existing config"""
- self.existing = dict(
- evpn_overlay_enable=self.global_info['evpnOverLay'])
-
- def get_proposed(self):
- """get proposed config"""
- self.proposed = dict(evpn_overlay_enable=self.overlay_enable)
-
- def get_end_state(self):
- """get end config"""
- self.get_evpn_global_info()
- self.end_state = dict(
- evpn_overlay_enable=self.global_info['evpnOverLay'])
-
- def show_result(self):
- """ show result"""
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
- def judge_if_config_exist(self):
- """ judge whether configuration has existed"""
- if self.overlay_enable == self.global_info['evpnOverLay']:
- return True
-
- return False
-
- def config_evnp_global(self):
- """ set global EVPN configuration"""
- if not self.conf_exist:
- if self.overlay_enable == 'enable':
- self.cli_add_command('evpn-overlay enable')
- else:
- self.cli_add_command('evpn-overlay enable', True)
-
- if self.commands:
- self.cli_load_config(self.commands)
- self.changed = True
-
- def work(self):
- """execute task"""
- self.get_evpn_global_info()
- self.get_existing()
- self.get_proposed()
- self.conf_exist = self.judge_if_config_exist()
-
- self.config_evnp_global()
-
- self.get_end_state()
- self.show_result()
-
-
-def main():
- """main function entry"""
-
- argument_spec = dict(
- evpn_overlay_enable=dict(
- required=True, type='str', choices=['enable', 'disable']),
- )
- argument_spec.update(ce_argument_spec)
- evpn_global = EvpnGlobal(argument_spec)
- evpn_global.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_facts.py b/plugins/modules/network/cloudengine/ce_facts.py
deleted file mode 100644
index 004bbce294..0000000000
--- a/plugins/modules/network/cloudengine/ce_facts.py
+++ /dev/null
@@ -1,418 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_facts
-author: "wangdezhuang (@QijunPan)"
-short_description: Gets facts about HUAWEI CloudEngine switches.
-description:
- - Collects facts from CloudEngine devices running the CloudEngine
- operating system. Fact collection is supported over Cli
- transport. This module prepends all of the base network fact keys
- with C(ansible_net_). The facts module will always collect a
- base set of facts from the device and can enable or disable
- collection of additional facts.
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- gather_subset:
- description:
- - When supplied, this argument will restrict the facts collected
- to a given subset. Possible values for this argument include
- all, hardware, config, and interfaces. Can specify a
- list of values to include a larger subset. Values can also be used
- with an initial C(M(!)) to specify that a specific subset should
- not be collected.
- required: false
- default: '!config'
-'''
-
-EXAMPLES = """
-# Note: examples below use the following provider dict to handle
-# transport and authentication to the node.
-
-- name: CloudEngine facts test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Gather_subset is all"
- ce_facts:
- gather_subset: all
- provider: "{{ cli }}"
-
- - name: "Collect only the config facts"
- ce_facts:
- gather_subset: config
- provider: "{{ cli }}"
-
- - name: "Do not collect hardware facts"
- ce_facts:
- gather_subset: "!hardware"
- provider: "{{ cli }}"
-"""
-
-RETURN = """
-gather_subset:
- description: The list of fact subsets collected from the device
- returned: always
- type: list
-
-# default
-BIOS Version:
- description: The BIOS version running on the remote device
- returned: always
- type: str
-Board Type:
- description: The board type of the remote device
- returned: always
- type: str
-CPLD1 Version:
- description: The CPLD1 Version running the remote device
- returned: always
- type: str
-CPLD2 Version:
- description: The CPLD2 Version running the remote device
- returned: always
- type: str
-MAB Version:
- description: The MAB Version running the remote device
- returned: always
- type: str
-PCB Version:
- description: The PCB Version running the remote device
- returned: always
- type: str
-hostname:
- description: The hostname of the remote device
- returned: always
- type: str
-
-# hardware
-FAN:
- description: The fan state on the device
- returned: when hardware is configured
- type: str
-PWR:
- description: The power state on the device
- returned: when hardware is configured
- type: str
-filesystems:
- description: The filesystems on the device
- returned: when hardware is configured
- type: str
-flash_free:
- description: The flash free space on the device
- returned: when hardware is configured
- type: str
-flash_total:
- description: The flash total space on the device
- returned: when hardware is configured
- type: str
-memory_free:
- description: The memory free space on the remote device
- returned: when hardware is configured
- type: str
-memory_total:
- description: The memory total space on the remote device
- returned: when hardware is configured
- type: str
-
-# config
-config:
- description: The current system configuration on the device
- returned: when config is configured
- type: str
-
-# interfaces
-all_ipv4_addresses:
- description: All IPv4 addresses configured on the device
- returned: when interfaces is configured
- type: list
-interfaces:
- description: A hash of all interfaces running on the system
- returned: when interfaces is configured
- type: dict
-neighbors:
- description: The list of LLDP neighbors from the remote device
- returned: when interfaces is configured
- type: dict
-"""
-
-import re
-
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import run_commands
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec, check_args
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.six import iteritems
-
-
-class FactsBase(object):
-
- COMMANDS = frozenset()
-
- def __init__(self, module):
- self.module = module
- self.facts = dict()
- self.responses = None
-
- def populate(self):
- self.responses = run_commands(self.module, list(self.COMMANDS))
-
-
-class Default(FactsBase):
- """ Class default """
-
- COMMANDS = [
- 'display version',
- 'display current-configuration | include sysname'
- ]
-
- def populate(self):
- """ Populate method """
-
- super(Default, self).populate()
-
- data = self.responses[0]
- if data:
- version = data.split("\n")
- for item in version:
- if re.findall(r"^\d+\S\s+", item.strip()):
- tmp_item = item.split()
- tmp_key = tmp_item[1] + " " + tmp_item[2]
- if len(tmp_item) > 5:
- self.facts[tmp_key] = " ".join(tmp_item[4:])
- else:
- self.facts[tmp_key] = tmp_item[4]
-
- data = self.responses[1]
- if data:
- tmp_value = re.findall(r'sysname (.*)', data)
- self.facts['hostname'] = tmp_value[0]
-
-
-class Config(FactsBase):
- """ Class config """
-
- COMMANDS = [
- 'display current-configuration configuration system'
- ]
-
- def populate(self):
- """ Populate method """
-
- super(Config, self).populate()
-
- data = self.responses[0]
- if data:
- self.facts['config'] = data.split("\n")
-
-
-class Hardware(FactsBase):
- """ Class hardware """
-
- COMMANDS = [
- 'dir',
- 'display memory',
- 'display device'
- ]
-
- def populate(self):
- """ Populate method """
-
- super(Hardware, self).populate()
-
- data = self.responses[0]
- if data:
- self.facts['filesystems'] = re.findall(r'Directory of (.*)/', data)[0]
- self.facts['flash_total'] = re.findall(r'(.*) total', data)[0].replace(",", "")
- self.facts['flash_free'] = re.findall(r'total \((.*) free\)', data)[0].replace(",", "")
-
- data = self.responses[1]
- if data:
- memory_total = re.findall(r'Total Memory Used: (.*) Kbytes', data)[0]
- use_percent = re.findall(r'Memory Using Percentage: (.*)%', data)[0]
- memory_free = str(int(memory_total) - int(memory_total) * int(use_percent) / 100)
- self.facts['memory_total'] = memory_total + " Kb"
- self.facts['memory_free'] = memory_free + " Kb"
-
- data = self.responses[2]
- if data:
- device_info = data.split("\n")
- tmp_device_info = device_info[4:-1]
- for item in tmp_device_info:
- tmp_item = item.split()
- if len(tmp_item) == 8:
- self.facts[tmp_item[2]] = tmp_item[6]
- elif len(tmp_item) == 7:
- self.facts[tmp_item[0]] = tmp_item[5]
-
-
-class Interfaces(FactsBase):
- """ Class interfaces """
-
- COMMANDS = [
- 'display interface brief',
- 'display ip interface brief',
- 'display lldp neighbor brief'
- ]
-
- def populate(self):
- """ Populate method"""
-
- interface_dict = dict()
- ipv4_addr_dict = dict()
- neighbors_dict = dict()
-
- super(Interfaces, self).populate()
-
- data = self.responses[0]
- begin = False
- if data:
- interface_info = data.split("\n")
- for item in interface_info:
- if begin:
- tmp_item = item.split()
- interface_dict[tmp_item[0]] = tmp_item[1]
-
- if re.findall(r"^Interface", item.strip()):
- begin = True
-
- self.facts['interfaces'] = interface_dict
-
- data = self.responses[1]
- if data:
- ipv4_addr = data.split("\n")
- tmp_ipv4 = ipv4_addr[11:]
- for item in tmp_ipv4:
- tmp_item = item.split()
- ipv4_addr_dict[tmp_item[0]] = tmp_item[1]
- self.facts['all_ipv4_addresses'] = ipv4_addr_dict
-
- data = self.responses[2]
- if data:
- neighbors = data.split("\n")
- tmp_neighbors = neighbors[2:]
- for item in tmp_neighbors:
- tmp_item = item.split()
- if len(tmp_item) > 3:
- neighbors_dict[tmp_item[0]] = tmp_item[3]
- else:
- neighbors_dict[tmp_item[0]] = None
- self.facts['neighbors'] = neighbors_dict
-
-
-FACT_SUBSETS = dict(
- default=Default,
- hardware=Hardware,
- interfaces=Interfaces,
- config=Config,
-)
-
-VALID_SUBSETS = frozenset(FACT_SUBSETS.keys())
-
-
-def main():
- """ Module main """
-
- spec = dict(
- gather_subset=dict(default=['!config'], type='list')
- )
-
- spec.update(ce_argument_spec)
-
- module = AnsibleModule(argument_spec=spec, supports_check_mode=True)
-
- warnings = list()
- check_args(module, warnings)
-
- gather_subset = module.params['gather_subset']
-
- runable_subsets = set()
- exclude_subsets = set()
-
- for subset in gather_subset:
- if subset == 'all':
- runable_subsets.update(VALID_SUBSETS)
- continue
-
- if subset.startswith('!'):
- subset = subset[1:]
- if subset == 'all':
- exclude_subsets.update(VALID_SUBSETS)
- continue
- exclude = True
- else:
- exclude = False
-
- if subset not in VALID_SUBSETS:
- module.fail_json(msg='Bad subset')
-
- if exclude:
- exclude_subsets.add(subset)
- else:
- runable_subsets.add(subset)
-
- if not runable_subsets:
- runable_subsets.update(VALID_SUBSETS)
-
- runable_subsets.difference_update(exclude_subsets)
- runable_subsets.add('default')
-
- facts = dict()
- facts['gather_subset'] = list(runable_subsets)
-
- instances = list()
- for key in runable_subsets:
- instances.append(FACT_SUBSETS[key](module))
-
- for inst in instances:
- inst.populate()
- facts.update(inst.facts)
-
- ansible_facts = dict()
- for key, value in iteritems(facts):
- # this is to maintain capability with nxos_facts 2.1
- if key.startswith('_'):
- ansible_facts[key[1:]] = value
- else:
- ansible_facts[key] = value
-
- module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_file_copy.py b/plugins/modules/network/cloudengine/ce_file_copy.py
deleted file mode 100644
index 70e1ae74c0..0000000000
--- a/plugins/modules/network/cloudengine/ce_file_copy.py
+++ /dev/null
@@ -1,416 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_file_copy
-short_description: Copy a file to a remote cloudengine device over SCP on HUAWEI CloudEngine switches.
-description:
- - Copy a file to a remote cloudengine device over SCP on HUAWEI CloudEngine switches.
-author:
- - Zhou Zhijin (@QijunPan)
-notes:
- - The feature must be enabled with feature scp-server.
- - If the file is already present, no transfer will take place.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-requirements:
- - paramiko
-options:
- local_file:
- description:
- - Path to local file. Local directory must exist.
- The maximum length of I(local_file) is C(4096).
- required: true
- remote_file:
- description:
- - Remote file path of the copy. Remote directories must exist.
- If omitted, the name of the local file will be used.
- The maximum length of I(remote_file) is C(4096).
- file_system:
- description:
- - The remote file system of the device. If omitted,
- devices that support a I(file_system) parameter will use
- their default values.
- File system indicates the storage medium and can be set to as follows,
- 1) C(flash) is root directory of the flash memory on the master MPU.
- 2) C(slave#flash) is root directory of the flash memory on the slave MPU.
- If no slave MPU exists, this drive is unavailable.
- 3) C(chassis ID/slot number#flash) is root directory of the flash memory on
- a device in a stack. For example, C(1/5#flash) indicates the flash memory
- whose chassis ID is 1 and slot number is 5.
- default: 'flash:'
-'''
-
-EXAMPLES = '''
-- name: File copy test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Copy a local file to remote device"
- ce_file_copy:
- local_file: /usr/vrpcfg.cfg
- remote_file: /vrpcfg.cfg
- file_system: 'flash:'
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-transfer_result:
- description: information about transfer result.
- returned: always
- type: str
- sample: 'The local file has been successfully transferred to the device.'
-local_file:
- description: The path of the local file.
- returned: always
- type: str
- sample: '/usr/work/vrpcfg.zip'
-remote_file:
- description: The path of the remote file.
- returned: always
- type: str
- sample: '/vrpcfg.zip'
-'''
-
-import re
-import os
-import sys
-import time
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec, get_nc_config
-from ansible.module_utils.connection import ConnectionError
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import validate_ip_v6_address
-
-try:
- import paramiko
- HAS_PARAMIKO = True
-except ImportError:
- HAS_PARAMIKO = False
-
-try:
- from scp import SCPClient
- HAS_SCP = True
-except ImportError:
- HAS_SCP = False
-
-CE_NC_GET_DISK_INFO = """
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_GET_FILE_INFO = """
-
-
-
-
- %s
- %s
-
-
-
-
-
-"""
-
-CE_NC_GET_SCP_ENABLE = """
-
-
-
-
-"""
-
-
-def get_cli_exception(exc=None):
- """Get cli exception message"""
-
- msg = list()
- if not exc:
- exc = sys.exc_info[1]
- if exc:
- errs = str(exc).split("\r\n")
- for err in errs:
- if not err:
- continue
- if "matched error in response:" in err:
- continue
- if " at '^' position" in err:
- err = err.replace(" at '^' position", "")
- if err.replace(" ", "") == "^":
- continue
- if len(err) > 2 and err[0] in ["<", "["] and err[-1] in [">", "]"]:
- continue
- if err[-1] == ".":
- err = err[:-1]
- if err.replace(" ", "") == "":
- continue
- msg.append(err)
- else:
- msg = ["Error: Fail to get cli exception message."]
-
- while msg[-1][-1] == ' ':
- msg[-1] = msg[-1][:-1]
-
- if msg[-1][-1] != ".":
- msg[-1] += "."
-
- return ", ".join(msg).capitalize()
-
-
-class FileCopy(object):
- """File copy function class"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # file copy parameters
- self.local_file = self.module.params['local_file']
- self.remote_file = self.module.params['remote_file']
- self.file_system = self.module.params['file_system']
- self.host_is_ipv6 = validate_ip_v6_address(self.module.params['provider']['host'])
-
- # state
- self.transfer_result = None
- self.changed = False
-
- def init_module(self):
- """Init module"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def remote_file_exists(self, dst, file_system='flash:'):
- """Remote file whether exists"""
-
- full_path = file_system + dst
- file_name = os.path.basename(full_path)
- file_path = os.path.dirname(full_path)
- file_path = file_path + '/'
- xml_str = CE_NC_GET_FILE_INFO % (file_name, file_path)
- ret_xml = get_nc_config(self.module, xml_str)
- if "" in ret_xml:
- return False, 0
-
- xml_str = ret_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get file info
- root = ElementTree.fromstring(xml_str)
- topo = root.find("vfm/dirs/dir")
- if topo is None:
- return False, 0
-
- for eles in topo:
- if eles.tag in ["DirSize"]:
- return True, int(eles.text.replace(',', ''))
-
- return False, 0
-
- def local_file_exists(self):
- """Local file whether exists"""
-
- return os.path.isfile(self.local_file)
-
- def enough_space(self):
- """Whether device has enough space"""
-
- xml_str = CE_NC_GET_DISK_INFO
- ret_xml = get_nc_config(self.module, xml_str)
- if "" in ret_xml:
- return
-
- xml_str = ret_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- topo = root.find("vfm/dfs/df/freeSize")
- kbytes_free = topo.text
-
- file_size = os.path.getsize(self.local_file)
- if int(kbytes_free) * 1024 > file_size:
- return True
-
- return False
-
- def transfer_file(self, dest):
- """Begin to transfer file by scp"""
-
- if not self.local_file_exists():
- self.module.fail_json(
- msg='Could not transfer file. Local file doesn\'t exist.')
-
- if not self.enough_space():
- self.module.fail_json(
- msg='Could not transfer file. Not enough space on device.')
-
- hostname = self.module.params['provider']['host']
- username = self.module.params['provider']['username']
- password = self.module.params['provider']['password']
- port = self.module.params['provider']['port']
-
- ssh = paramiko.SSHClient()
- ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- ssh.connect(hostname=hostname, username=username, password=password, port=port)
- full_remote_path = '{0}{1}'.format(self.file_system, dest)
- scp = SCPClient(ssh.get_transport())
- try:
- scp.put(self.local_file, full_remote_path)
- except Exception:
- time.sleep(10)
- file_exists, temp_size = self.remote_file_exists(
- dest, self.file_system)
- file_size = os.path.getsize(self.local_file)
- if file_exists and int(temp_size) == int(file_size):
- pass
- else:
- scp.close()
- self.module.fail_json(msg='Could not transfer file. There was an error '
- 'during transfer. Please make sure the format of '
- 'input parameters is right.')
- scp.close()
- return True
-
- def get_scp_enable(self):
- """Get scp enable state"""
-
- ret_xml = ''
- try:
- ret_xml = get_nc_config(self.module, CE_NC_GET_SCP_ENABLE)
- except ConnectionError:
- self.module.fail_json(msg='Error: The NETCONF API of scp_enable is not supported.')
-
- if "" in ret_xml:
- return False
-
- xml_str = ret_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get file info
- root = ElementTree.fromstring(xml_str)
- topo1 = root.find("sshs/sshServer/scpEnable")
- topo2 = root.find("sshs/sshServerEnable/scpIpv4Enable")
- topo3 = root.find("sshs/sshServerEnable/scpIpv6Enable")
- if topo1 is not None:
- return str(topo1.text).strip().lower() == 'enable'
- elif self.host_is_ipv6 and topo3 is not None:
- return str(topo3.text).strip().lower() == 'enable'
- elif topo2 is not None:
- return str(topo2.text).strip().lower() == 'enable'
- return False
-
- def work(self):
- """Execute task """
-
- if not HAS_SCP:
- self.module.fail_json(
- msg="'Error: No scp package, please install it.'")
-
- if not HAS_PARAMIKO:
- self.module.fail_json(
- msg="'Error: No paramiko package, please install it.'")
-
- if self.local_file and len(self.local_file) > 4096:
- self.module.fail_json(
- msg="'Error: The maximum length of local_file is 4096.'")
-
- if self.remote_file and len(self.remote_file) > 4096:
- self.module.fail_json(
- msg="'Error: The maximum length of remote_file is 4096.'")
-
- scp_enable = self.get_scp_enable()
- if not scp_enable:
- if self.host_is_ipv6:
- self.module.fail_json(
- msg="'Error: Please ensure ipv6 SCP server are enabled.'")
- else:
- self.module.fail_json(
- msg="'Error: Please ensure ipv4 SCP server are enabled.'")
-
- if not os.path.isfile(self.local_file):
- self.module.fail_json(
- msg="Local file {0} not found".format(self.local_file))
-
- dest = self.remote_file or ('/' + os.path.basename(self.local_file))
- remote_exists, file_size = self.remote_file_exists(
- dest, file_system=self.file_system)
- if remote_exists and (os.path.getsize(self.local_file) != file_size):
- remote_exists = False
-
- if not remote_exists:
- self.changed = True
- file_exists = False
- else:
- file_exists = True
- self.transfer_result = 'The local file already exists on the device.'
-
- if not file_exists:
- self.transfer_file(dest)
- self.transfer_result = 'The local file has been successfully transferred to the device.'
-
- if self.remote_file is None:
- self.remote_file = '/' + os.path.basename(self.local_file)
-
- self.module.exit_json(
- changed=self.changed,
- transfer_result=self.transfer_result,
- local_file=self.local_file,
- remote_file=self.remote_file,
- file_system=self.file_system)
-
-
-def main():
- """Main function entry"""
-
- argument_spec = dict(
- local_file=dict(required=True),
- remote_file=dict(required=False),
- file_system=dict(required=False, default='flash:')
- )
- argument_spec.update(ce_argument_spec)
- filecopy_obj = FileCopy(argument_spec)
- filecopy_obj.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_info_center_debug.py b/plugins/modules/network/cloudengine/ce_info_center_debug.py
deleted file mode 100644
index 57487c3d70..0000000000
--- a/plugins/modules/network/cloudengine/ce_info_center_debug.py
+++ /dev/null
@@ -1,617 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_info_center_debug
-short_description: Manages information center debug configuration on HUAWEI CloudEngine switches.
-description:
- - Manages information center debug configurations on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- state:
- description:
- - Specify desired state of the resource.
- default: present
- choices: ['present','absent']
- debug_time_stamp:
- description:
- - Timestamp type of debugging information.
- choices: ['date_boot', 'date_second', 'date_tenthsecond', 'date_millisecond', 'shortdate_second',
- 'shortdate_tenthsecond', 'shortdate_millisecond', 'formatdate_second', 'formatdate_tenthsecond',
- 'formatdate_millisecond']
- module_name:
- description:
- - Module name of the rule.
- The value is a string of 1 to 31 case-insensitive characters. The default value is default.
- Please use lower-case letter, such as [aaa, acl, arp, bfd].
- channel_id:
- description:
- - Number of a channel.
- The value is an integer ranging from 0 to 9. The default value is 0.
- debug_enable:
- description:
- - Whether a device is enabled to output debugging information.
- default: no_use
- choices: ['no_use','true','false']
- debug_level:
- description:
- - Debug level permitted to output.
- choices: ['emergencies', 'alert', 'critical', 'error', 'warning', 'notification',
- 'informational', 'debugging']
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine info center debug test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Config debug time stamp"
- ce_info_center_debug:
- state: present
- debug_time_stamp: date_boot
- provider: "{{ cli }}"
-
- - name: "Undo debug time stamp"
- ce_info_center_debug:
- state: absent
- debug_time_stamp: date_boot
- provider: "{{ cli }}"
-
- - name: "Config debug module log level"
- ce_info_center_debug:
- state: present
- module_name: aaa
- channel_id: 1
- debug_enable: true
- debug_level: error
- provider: "{{ cli }}"
-
- - name: "Undo debug module log level"
- ce_info_center_debug:
- state: absent
- module_name: aaa
- channel_id: 1
- debug_enable: true
- debug_level: error
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"state": "present", "debug_time_stamp": "date_boot"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {"debugTimeStamp": "DATE_MILLISECOND"}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"debugTimeStamp": "DATE_BOOT"}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["info-center timestamp debugging boot"]
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-
-# get info center debug global
-CE_GET_DEBUG_GLOBAL_HEADER = """
-
-
-
-"""
-CE_GET_DEBUG_GLOBAL_TAIL = """
-
-
-
-"""
-# merge info center debug global
-CE_MERGE_DEBUG_GLOBAL_HEADER = """
-
-
-
-"""
-CE_MERGE_DEBUG_GLOBAL_TAIL = """
-
-
-
-"""
-
-# get info center debug source
-CE_GET_DEBUG_SOURCE_HEADER = """
-
-
-
-
-"""
-CE_GET_DEBUG_SOURCE_TAIL = """
-
-
-
-
-"""
-# merge info center debug source
-CE_MERGE_DEBUG_SOURCE_HEADER = """
-
-
-
-
-"""
-CE_MERGE_DEBUG_SOURCE_TAIL = """
-
-
-
-
-"""
-# delete info center debug source
-CE_DELETE_DEBUG_SOURCE_HEADER = """
-
-
-
-
-"""
-CE_DELETE_DEBUG_SOURCE_TAIL = """
-
-
-
-
-"""
-
-TIME_STAMP_DICT = {"date_boot": "boot",
- "date_second": "date precision-time second",
- "date_tenthsecond": "date precision-time tenth-second",
- "date_millisecond": "date precision-time millisecond",
- "shortdate_second": "short-date precision-time second",
- "shortdate_tenthsecond": "short-date precision-time tenth-second",
- "shortdate_millisecond": "short-date precision-time millisecond",
- "formatdate_second": "format-date precision-time second",
- "formatdate_tenthsecond": "format-date precision-time tenth-second",
- "formatdate_millisecond": "format-date precision-time millisecond"}
-
-CHANNEL_DEFAULT_DBG_STATE = {"0": "true",
- "1": "true",
- "2": "false",
- "3": "false",
- "4": "false",
- "5": "false",
- "6": "false",
- "7": "false",
- "8": "false",
- "9": "false"}
-
-CHANNEL_DEFAULT_DBG_LEVEL = {"0": "debugging",
- "1": "debugging",
- "2": "debugging",
- "3": "debugging",
- "4": "debugging",
- "5": "debugging",
- "6": "debugging",
- "7": "debugging",
- "8": "debugging",
- "9": "debugging"}
-
-
-class InfoCenterDebug(object):
- """ Manages info center debug configuration """
-
- def __init__(self, **kwargs):
- """ Init function """
-
- # argument spec
- argument_spec = kwargs["argument_spec"]
- self.spec = argument_spec
- self.module = AnsibleModule(argument_spec=self.spec, supports_check_mode=True)
-
- # module args
- self.state = self.module.params['state']
- self.debug_time_stamp = self.module.params['debug_time_stamp'] or None
- self.module_name = self.module.params['module_name'] or None
- self.channel_id = self.module.params['channel_id'] or None
- self.debug_enable = self.module.params['debug_enable']
- self.debug_level = self.module.params['debug_level'] or None
-
- # cur config
- self.cur_global_cfg = dict()
- self.cur_source_cfg = dict()
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def check_global_args(self):
- """ Check global args """
-
- need_cfg = False
- find_flag = False
- self.cur_global_cfg["global_cfg"] = []
-
- if self.debug_time_stamp:
-
- conf_str = CE_GET_DEBUG_GLOBAL_HEADER
- conf_str += ""
- conf_str += CE_GET_DEBUG_GLOBAL_TAIL
-
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- find_flag = False
- else:
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- global_cfg = root.findall("syslog/globalParam")
- if global_cfg:
- for tmp in global_cfg:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["debugTimeStamp"]:
- tmp_dict[site.tag] = site.text
-
- self.cur_global_cfg["global_cfg"].append(tmp_dict)
-
- if self.cur_global_cfg["global_cfg"]:
- for tmp in self.cur_global_cfg["global_cfg"]:
- find_flag = True
-
- if tmp.get("debugTimeStamp").lower() != self.debug_time_stamp:
- find_flag = False
-
- if find_flag:
- break
- else:
- find_flag = False
-
- if self.state == "present":
- need_cfg = bool(not find_flag)
- else:
- need_cfg = bool(find_flag)
-
- self.cur_global_cfg["need_cfg"] = need_cfg
-
- def check_source_args(self):
- """ Check source args """
-
- need_cfg = False
- find_flag = False
- self.cur_source_cfg["source_cfg"] = []
-
- if self.module_name:
- if len(self.module_name) < 1 or len(self.module_name) > 31:
- self.module.fail_json(
- msg='Error: The module_name is out of [1 - 31].')
-
- if not self.channel_id:
- self.module.fail_json(
- msg='Error: Please input channel_id at the same time.')
-
- if self.channel_id:
- if self.channel_id.isdigit():
- if int(self.channel_id) < 0 or int(self.channel_id) > 9:
- self.module.fail_json(
- msg='Error: The value of channel_id is out of [0 - 9].')
- else:
- self.module.fail_json(
- msg='Error: The channel_id is not digit.')
-
- conf_str = CE_GET_DEBUG_SOURCE_HEADER
-
- if self.module_name != "default":
- conf_str += "%s" % self.module_name.upper()
- else:
- conf_str += "default"
-
- if self.channel_id:
- conf_str += ""
- if self.debug_enable != 'no_use':
- conf_str += ""
- if self.debug_level:
- conf_str += ""
-
- conf_str += CE_GET_DEBUG_SOURCE_TAIL
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- find_flag = False
- else:
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- source_cfg = root.findall("syslog/icSources/icSource")
- if source_cfg:
- for tmp in source_cfg:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["moduleName", "icChannelId", "dbgEnFlg", "dbgEnLevel"]:
- tmp_dict[site.tag] = site.text
-
- self.cur_source_cfg["source_cfg"].append(tmp_dict)
-
- if self.cur_source_cfg["source_cfg"]:
- for tmp in self.cur_source_cfg["source_cfg"]:
- find_flag = True
-
- if self.module_name and tmp.get("moduleName").lower() != self.module_name.lower():
- find_flag = False
- if self.channel_id and tmp.get("icChannelId") != self.channel_id:
- find_flag = False
- if self.debug_enable != 'no_use' and tmp.get("dbgEnFlg") != self.debug_enable:
- find_flag = False
- if self.debug_level and tmp.get("dbgEnLevel") != self.debug_level:
- find_flag = False
-
- if find_flag:
- break
- else:
- find_flag = False
-
- if self.state == "present":
- need_cfg = bool(not find_flag)
- else:
- need_cfg = bool(find_flag)
-
- self.cur_source_cfg["need_cfg"] = need_cfg
-
- def get_proposed(self):
- """ Get proposed """
-
- self.proposed["state"] = self.state
-
- if self.debug_time_stamp:
- self.proposed["debug_time_stamp"] = self.debug_time_stamp
- if self.module_name:
- self.proposed["module_name"] = self.module_name
- if self.channel_id:
- self.proposed["channel_id"] = self.channel_id
- if self.debug_enable != 'no_use':
- self.proposed["debug_enable"] = self.debug_enable
- if self.debug_level:
- self.proposed["debug_level"] = self.debug_level
-
- def get_existing(self):
- """ Get existing """
-
- if self.cur_global_cfg["global_cfg"]:
- self.existing["global_cfg"] = self.cur_global_cfg["global_cfg"]
- if self.cur_source_cfg["source_cfg"]:
- self.existing["source_cfg"] = self.cur_source_cfg["source_cfg"]
-
- def get_end_state(self):
- """ Get end state """
-
- self.check_global_args()
- if self.cur_global_cfg["global_cfg"]:
- self.end_state["global_cfg"] = self.cur_global_cfg["global_cfg"]
-
- self.check_source_args()
- if self.cur_source_cfg["source_cfg"]:
- self.end_state["source_cfg"] = self.cur_source_cfg["source_cfg"]
-
- def merge_debug_global(self):
- """ Merge debug global """
-
- conf_str = CE_MERGE_DEBUG_GLOBAL_HEADER
-
- if self.debug_time_stamp:
- conf_str += "%s" % self.debug_time_stamp.upper()
-
- conf_str += CE_MERGE_DEBUG_GLOBAL_TAIL
-
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Merge debug global failed.')
-
- if self.debug_time_stamp:
- cmd = "info-center timestamp debugging " + TIME_STAMP_DICT.get(self.debug_time_stamp)
- self.updates_cmd.append(cmd)
-
- self.changed = True
-
- def delete_debug_global(self):
- """ Delete debug global """
-
- conf_str = CE_MERGE_DEBUG_GLOBAL_HEADER
-
- if self.debug_time_stamp:
- conf_str += "DATE_MILLISECOND"
-
- conf_str += CE_MERGE_DEBUG_GLOBAL_TAIL
-
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: delete debug global failed.')
-
- if self.debug_time_stamp:
- cmd = "undo info-center timestamp debugging"
- self.updates_cmd.append(cmd)
-
- self.changed = True
-
- def merge_debug_source(self):
- """ Merge debug source """
-
- conf_str = CE_MERGE_DEBUG_SOURCE_HEADER
-
- if self.module_name:
- conf_str += "%s" % self.module_name
- if self.channel_id:
- conf_str += "%s" % self.channel_id
- if self.debug_enable != 'no_use':
- conf_str += "%s" % self.debug_enable
- if self.debug_level:
- conf_str += "%s" % self.debug_level
-
- conf_str += CE_MERGE_DEBUG_SOURCE_TAIL
-
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Merge debug source failed.')
-
- cmd = "info-center source"
- if self.module_name:
- cmd += " %s" % self.module_name
- if self.channel_id:
- cmd += " channel %s" % self.channel_id
- if self.debug_enable != 'no_use':
- if self.debug_enable == "true":
- cmd += " debug state on"
- else:
- cmd += " debug state off"
- if self.debug_level:
- cmd += " level %s" % self.debug_level
-
- self.updates_cmd.append(cmd)
- self.changed = True
-
- def delete_debug_source(self):
- """ Delete debug source """
-
- if self.debug_enable == 'no_use' and not self.debug_level:
- conf_str = CE_DELETE_DEBUG_SOURCE_HEADER
- if self.module_name:
- conf_str += "%s" % self.module_name
- if self.channel_id:
- conf_str += "%s" % self.channel_id
- conf_str += CE_DELETE_DEBUG_SOURCE_TAIL
- else:
- conf_str = CE_MERGE_DEBUG_SOURCE_HEADER
- if self.module_name:
- conf_str += "%s" % self.module_name
- if self.channel_id:
- conf_str += "%s" % self.channel_id
- if self.debug_enable != 'no_use':
- conf_str += "%s" % CHANNEL_DEFAULT_DBG_STATE.get(self.channel_id)
- if self.debug_level:
- conf_str += "%s" % CHANNEL_DEFAULT_DBG_LEVEL.get(self.channel_id)
- conf_str += CE_MERGE_DEBUG_SOURCE_TAIL
-
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Delete debug source failed.')
-
- cmd = "undo info-center source"
- if self.module_name:
- cmd += " %s" % self.module_name
- if self.channel_id:
- cmd += " channel %s" % self.channel_id
- if self.debug_enable != 'no_use':
- cmd += " debug state"
- if self.debug_level:
- cmd += " level"
-
- self.updates_cmd.append(cmd)
- self.changed = True
-
- def work(self):
- """ work function """
-
- self.check_global_args()
- self.check_source_args()
- self.get_proposed()
- self.get_existing()
-
- if self.state == "present":
- if self.cur_global_cfg["need_cfg"]:
- self.merge_debug_global()
- if self.cur_source_cfg["need_cfg"]:
- self.merge_debug_source()
-
- else:
- if self.cur_global_cfg["need_cfg"]:
- self.delete_debug_global()
- if self.cur_source_cfg["need_cfg"]:
- self.delete_debug_source()
-
- self.get_end_state()
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- self.results['updates'] = self.updates_cmd
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- debug_time_stamp=dict(choices=['date_boot', 'date_second', 'date_tenthsecond',
- 'date_millisecond', 'shortdate_second', 'shortdate_tenthsecond',
- 'shortdate_millisecond', 'formatdate_second', 'formatdate_tenthsecond',
- 'formatdate_millisecond']),
- module_name=dict(type='str'),
- channel_id=dict(type='str'),
- debug_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- debug_level=dict(choices=['emergencies', 'alert', 'critical', 'error', 'warning', 'notification',
- 'informational', 'debugging'])
- )
-
- argument_spec.update(ce_argument_spec)
- module = InfoCenterDebug(argument_spec=argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_info_center_global.py b/plugins/modules/network/cloudengine/ce_info_center_global.py
deleted file mode 100644
index 96355e99ca..0000000000
--- a/plugins/modules/network/cloudengine/ce_info_center_global.py
+++ /dev/null
@@ -1,1725 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_info_center_global
-short_description: Manages outputting logs on HUAWEI CloudEngine switches.
-description:
- - This module offers the ability to be output to the log buffer, log file, console, terminal, or log host on HUAWEI CloudEngine switches.
-author:
- - Li Yanfeng (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- info_center_enable:
- description:
- - Whether the info-center function is enabled. The value is of the Boolean type.
- choices: ['true','false']
- packet_priority:
- description:
- - Set the priority of the syslog packet.The value is an integer ranging from 0 to 7. The default value is 0.
- suppress_enable:
- description:
- - Whether a device is enabled to suppress duplicate statistics. The value is of the Boolean type.
- choices: [ 'false', 'true' ]
- logfile_max_num:
- description:
- - Maximum number of log files of the same type. The default value is 200.
- - The value range for log files is[3, 500], for security files is [1, 3],and for operation files is [1, 7].
- logfile_max_size:
- description:
- - Maximum size (in MB) of a log file. The default value is 32.
- - The value range for log files is [4, 8, 16, 32], for security files is [1, 4],
- - and for operation files is [1, 4].
- default: 32
- choices: ['4', '8', '16', '32']
- channel_id:
- description:
- - Number for channel. The value is an integer ranging from 0 to 9. The default value is 0.
- channel_cfg_name:
- description:
- - Channel name.The value is a string of 1 to 30 case-sensitive characters. The default value is console.
- default: console
- channel_out_direct:
- description:
- - Direction of information output.
- choices: ['console','monitor','trapbuffer','logbuffer','snmp','logfile']
- filter_feature_name:
- description:
- - Feature name of the filtered log. The value is a string of 1 to 31 case-insensitive characters.
- filter_log_name:
- description:
- - Name of the filtered log. The value is a string of 1 to 63 case-sensitive characters.
- ip_type:
- description:
- - Log server address type, IPv4 or IPv6.
- choices: ['ipv4','ipv6']
- server_ip:
- description:
- - Log server address, IPv4 or IPv6 type. The value is a string of 0 to 255 characters.
- The value can be an valid IPv4 or IPv6 address.
- server_domain:
- description:
- - Server name. The value is a string of 1 to 255 case-sensitive characters.
- is_default_vpn:
- description:
- - Use the default VPN or not.
- type: bool
- default: 'no'
- vrf_name:
- description:
- - VPN name on a log server. The value is a string of 1 to 31 case-sensitive characters.
- The default value is _public_.
- level:
- description:
- - Level of logs saved on a log server.
- choices: ['emergencies','alert','critical','error','warning','notification','informational','debugging']
- server_port:
- description:
- - Number of a port sending logs.The value is an integer ranging from 1 to 65535.
- For UDP, the default value is 514. For TCP, the default value is 601. For TSL, the default value is 6514.
- facility:
- description:
- - Log record tool.
- choices: ['local0','local1','local2','local3','local4','local5','local6','local7']
- channel_name:
- description:
- - Channel name. The value is a string of 1 to 30 case-sensitive characters.
- timestamp:
- description:
- - Log server timestamp. The value is of the enumerated type and case-sensitive.
- choices: ['UTC', 'localtime']
- transport_mode:
- description:
- - Transport mode. The value is of the enumerated type and case-sensitive.
- choices: ['tcp','udp']
- ssl_policy_name:
- description:
- - SSL policy name. The value is a string of 1 to 23 case-sensitive characters.
- source_ip:
- description:
- - Log source ip address, IPv4 or IPv6 type. The value is a string of 0 to 255.
- The value can be an valid IPv4 or IPv6 address.
- state:
- description:
- - Specify desired state of the resource.
- default: present
- choices: ['present','absent']
-'''
-EXAMPLES = '''
-- name: info center global module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Config info-center enable
- ce_info_center_global:
- info_center_enable: true
- state: present
- provider: "{{ cli }}"
-
- - name: Config statistic-suppress enable
- ce_info_center_global:
- suppress_enable: true
- state: present
- provider: "{{ cli }}"
-
- - name: Config info-center syslog packet-priority 1
- ce_info_center_global:
- packet_priority: 2
- state: present
- provider: "{{ cli }}"
-
- - name: Config info-center channel 1 name aaa
- ce_info_center_global:
- channel_id: 1
- channel_cfg_name: aaa
- state: present
- provider: "{{ cli }}"
-
- - name: Config info-center logfile size 10
- ce_info_center_global:
- logfile_max_num: 10
- state: present
- provider: "{{ cli }}"
-
- - name: Config info-center console channel 1
- ce_info_center_global:
- channel_out_direct: console
- channel_id: 1
- state: present
- provider: "{{ cli }}"
-
- - name: Config info-center filter-id bymodule-alias snmp snmp_ipunlock
- ce_info_center_global:
- filter_feature_name: SNMP
- filter_log_name: SNMP_IPLOCK
- state: present
- provider: "{{ cli }}"
-
-
- - name: Config info-center max-logfile-number 16
- ce_info_center_global:
- logfile_max_size: 16
- state: present
- provider: "{{ cli }}"
-
- - name: Config syslog loghost domain.
- ce_info_center_global:
- server_domain: aaa
- vrf_name: aaa
- channel_id: 1
- transport_mode: tcp
- facility: local4
- server_port: 100
- level: alert
- timestamp: UTC
- state: present
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"channel_id": "1", "facility": "local4", "is_default_vpn": True, "level": "alert", "server_domain": "aaa",
- "server_port": "100", "state": "present", "timestamp": "localtime", "transport_mode": "tcp"}
-existing:
- description: k/v pairs of existing rollback
- returned: always
- type: dict
- sample:
- "server_domain_info": [
- {
- "chnlId": "1",
- "chnlName": "monitor",
- "facility": "local4",
- "isBriefFmt": "false",
- "isDefaultVpn": "false",
- "level": "alert",
- "serverDomain": "aaa",
- "serverPort": "100",
- "sourceIP": "0.0.0.0",
- "sslPolicyName": "gmc",
- "timestamp": "UTC",
- "transportMode": "tcp",
- "vrfName": "aaa"
- }
- ]
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample:
- "server_domain_info": [
- {
- "chnlId": "1",
- "chnlName": "monitor",
- "facility": "local4",
- "isBriefFmt": "false",
- "isDefaultVpn": "true",
- "level": "alert",
- "serverDomain": "aaa",
- "serverPort": "100",
- "sourceIP": "0.0.0.0",
- "sslPolicyName": null,
- "timestamp": "localtime",
- "transportMode": "tcp",
- "vrfName": "_public_"
- },
- {
- "chnlId": "1",
- "chnlName": "monitor",
- "facility": "local4",
- "isBriefFmt": "false",
- "isDefaultVpn": "false",
- "level": "alert",
- "serverDomain": "aaa",
- "serverPort": "100",
- "sourceIP": "0.0.0.0",
- "sslPolicyName": "gmc",
- "timestamp": "UTC",
- "transportMode": "tcp",
- "vrfName": "aaa"
- }
- ]
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["info-center loghost domain aaa level alert port 100 facility local4 channel 1 localtime transport tcp"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec, get_nc_config, set_nc_config, check_ip_addr
-
-
-CE_NC_GET_CENTER_GLOBAL_INFO_HEADER = """
-
-
-
-"""
-CE_NC_GET_CENTER_GLOBAL_INFO_TAIL = """
-
-
-
-"""
-
-CE_NC_MERGE_CENTER_GLOBAL_INFO_HEADER = """
-
-
-
-"""
-
-CE_NC_MERGE_CENTER_GLOBAL_INFO_TAIL = """
-
-
-
-"""
-
-CE_NC_GET_LOG_FILE_INFO_HEADER = """
-
-
-
-
-"""
-CE_NC_GET_LOG_FILE_INFO_TAIL = """
-
-
-
-
-"""
-
-CE_NC_MERGE_LOG_FILE_INFO_HEADER = """
-
-
-
-
-"""
-
-CE_NC_MERGE_LOG_FILE_INFO_TAIL = """
-
-
-
-
-"""
-
-
-CE_NC_GET_CHANNEL_INFO = """
-
-
-
-
- %s
-
-
-
-
-
-"""
-
-CE_NC_MERGE_CHANNEL_INFO_HEADER = """
-
-
-
-
-"""
-CE_NC_MERGE_CHANNEL_INFO_TAIL = """
-
-
-
-
-"""
-
-CE_NC_GET_CHANNEL_DIRECT_INFO = """
-
-
-
-
- %s
-
-
-
-
-
-"""
-CE_NC_MERGE_CHANNEL_DIRECT_HEADER = """
-
-
-
-
-"""
-
-CE_NC_MERGE_CHANNEL_DIRECT_TAIL = """
-
-
-
-
-"""
-
-CE_NC_GET_FILTER_INFO = """
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_CREATE_CHANNEL_FILTER_HEADER = """
-
-
-
-
-
-"""
-CE_NC_CREATE_CHANNEL_FILTER_TAIL = """
-
-
-
-
-"""
-CE_NC_DELETE_CHANNEL_FILTER_HEADER = """
-
-
-
-
-
-"""
-CE_NC_DELETE_CHANNEL_FILTER_TAIL = """
-
-
-
-
-"""
-
-CE_NC_GET_SERVER_IP_INFO_HEADER = """
-
-
-
-
- %s
- %s
- %s
- %s
-"""
-CE_NC_GET_SERVER_IP_INFO_TAIL = """
-
-
-
-
-"""
-CE_NC_MERGE_SERVER_IP_INFO_HEADER = """
-
-
-
-
- %s
- %s
- %s
- %s
-"""
-CE_NC_MERGE_SERVER_IP_INFO_TAIL = """
-
-
-
-
-"""
-CE_NC_DELETE_SERVER_IP_INFO_HEADER = """
-
-
-
-
- %s
- %s
- %s
- %s
-"""
-CE_NC_DELETE_SERVER_IP_INFO_TAIL = """
-
-
-
-
-"""
-CE_NC_GET_SERVER_DNS_INFO_HEADER = """
-
-
-
-
-"""
-
-CE_NC_GET_SERVER_DNS_INFO_TAIL = """
-
-
-
-
-"""
-
-CE_NC_MERGE_SERVER_DNS_INFO_HEADER = """
-
-
-
-
- %s
- %s
- %s
-"""
-CE_NC_MERGE_SERVER_DNS_INFO_TAIL = """
-
-
-
-
-"""
-
-CE_NC_DELETE_SERVER_DNS_INFO_HEADER = """
-
-
-
-
- %s
- %s
- %s
-"""
-CE_NC_DELETE_SERVER_DNS_INFO_TAIL = """
-
-
-
-
-"""
-
-
-def get_out_direct_default(out_direct):
- """get default out direct"""
-
- outdict = {"console": "1", "monitor": "2", "trapbuffer": "3",
- "logbuffer": "4", "snmp": "5", "logfile": "6"}
- channel_id_default = outdict.get(out_direct)
- return channel_id_default
-
-
-def get_channel_name_default(channel_id):
- """get default out direct"""
-
- channel_dict = {"0": "console", "1": "monitor", "2": "loghost", "3": "trapbuffer", "4": "logbuffer",
- "5": "snmpagent", "6": "channel6", "7": "channel7", "8": "channel8", "9": "channel9"}
- channel_name_default = channel_dict.get(channel_id)
- return channel_name_default
-
-
-class InfoCenterGlobal(object):
- """
- Manages info center global configuration.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.info_center_enable = self.module.params['info_center_enable'] or None
- self.packet_priority = self.module.params['packet_priority'] or None
- self.suppress_enable = self.module.params['suppress_enable'] or None
- self.logfile_max_num = self.module.params['logfile_max_num'] or None
- self.logfile_max_size = self.module.params['logfile_max_size'] or None
- self.channel_id = self.module.params['channel_id'] or None
- self.channel_cfg_name = self.module.params['channel_cfg_name'] or None
- self.channel_out_direct = self.module.params['channel_out_direct'] or None
- self.filter_feature_name = self.module.params['filter_feature_name'] or None
- self.filter_log_name = self.module.params['filter_log_name'] or None
- self.ip_type = self.module.params['ip_type'] or None
- self.server_ip = self.module.params['server_ip'] or None
- self.server_domain = self.module.params['server_domain'] or None
- self.is_default_vpn = self.module.params['is_default_vpn'] or None
- self.vrf_name = self.module.params['vrf_name'] or None
- self.level = self.module.params['level'] or None
- self.server_port = self.module.params['server_port'] or None
- self.facility = self.module.params['facility'] or None
- self.channel_name = self.module.params['channel_name'] or None
- self.timestamp = self.module.params['timestamp'] or None
- self.transport_mode = self.module.params['transport_mode'] or None
- self.ssl_policy_name = self.module.params['ssl_policy_name'] or None
- self.source_ip = self.module.params['source_ip'] or None
- self.state = self.module.params['state'] or None
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.existing = dict()
- self.proposed = dict()
- self.end_state = dict()
-
- # syslog info
- self.cur_global_info = None
- self.cur_logfile_info = None
- self.channel_info = None
- self.channel_direct_info = None
- self.filter_info = None
- self.server_ip_info = None
- self.server_domain_info = None
-
- def init_module(self):
- """ init module """
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def check_response(self, con_obj, xml_name):
- """Check if response message is already succeed."""
-
- xml_str = con_obj.xml
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_channel_dict(self):
- """ get channel attributes dict."""
-
- channel_info = dict()
- # get channel info
- conf_str = CE_NC_GET_CHANNEL_INFO % self.channel_id
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return channel_info
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
- channel_info["channelInfos"] = list()
- channels = root.findall("syslog/icChannels/icChannel")
- if channels:
- for channel in channels:
- channel_dict = dict()
- for ele in channel:
- if ele.tag in ["icChnlId", "icChnlCfgName"]:
- channel_dict[ele.tag] = ele.text
- channel_info["channelInfos"].append(channel_dict)
- return channel_info
-
- def is_exist_channel_id_name(self, channel_id, channel_name):
- """if channel id exist"""
-
- if not self.channel_info:
- return False
-
- for id2name in self.channel_info["channelInfos"]:
- if id2name["icChnlId"] == channel_id and id2name["icChnlCfgName"] == channel_name:
- return True
- return False
-
- def config_merge_syslog_channel(self, channel_id, channel_name):
- """config channel id"""
-
- if not self.is_exist_channel_id_name(channel_id, channel_name):
- conf_str = CE_NC_MERGE_CHANNEL_INFO_HEADER
- if channel_id:
- conf_str += "%s" % channel_id
- if channel_name:
- conf_str += "%s" % channel_name
-
- conf_str += CE_NC_MERGE_CHANNEL_INFO_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: Merge syslog channel id failed.')
-
- self.updates_cmd.append(
- "info-center channel %s name %s" % (channel_id, channel_name))
- self.changed = True
-
- def delete_merge_syslog_channel(self, channel_id, channel_name):
- """delete channel id"""
-
- change_flag = False
-
- if channel_name:
- for id2name in self.channel_info["channelInfos"]:
- channel_default_name = get_channel_name_default(
- id2name["icChnlId"])
- if id2name["icChnlId"] == channel_id and id2name["icChnlCfgName"] == channel_name:
- channel_name = channel_default_name
- change_flag = True
-
- if not channel_name:
- for id2name in self.channel_info["channelInfos"]:
- channel_default_name = get_channel_name_default(
- id2name["icChnlId"])
- if id2name["icChnlId"] == channel_id and id2name["icChnlCfgName"] != channel_default_name:
- channel_name = channel_default_name
- change_flag = True
- if change_flag:
- conf_str = CE_NC_MERGE_CHANNEL_INFO_HEADER
- if channel_id:
- conf_str += "%s" % channel_id
- if channel_name:
- conf_str += "%s" % channel_name
-
- conf_str += CE_NC_MERGE_CHANNEL_INFO_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: Merge syslog channel id failed.')
-
- self.updates_cmd.append("undo info-center channel %s" % channel_id)
- self.changed = True
-
- def get_channel_direct_dict(self):
- """ get channel direct attributes dict."""
-
- channel_direct_info = dict()
- # get channel direct info
- conf_str = CE_NC_GET_CHANNEL_DIRECT_INFO % self.channel_out_direct
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return channel_direct_info
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
- channel_direct_info["channelDirectInfos"] = list()
- dir_channels = root.findall("syslog/icDirChannels/icDirChannel")
- if dir_channels:
- for ic_dir_channel in dir_channels:
- channel_direct_dict = dict()
- for ele in ic_dir_channel:
- if ele.tag in ["icOutDirect", "icCfgChnlId"]:
- channel_direct_dict[ele.tag] = ele.text
- channel_direct_info["channelDirectInfos"].append(
- channel_direct_dict)
- return channel_direct_info
-
- def is_exist_out_direct(self, out_direct, channel_id):
- """if channel out direct exist"""
-
- if not self.channel_direct_info:
- return False
-
- for id2name in self.channel_direct_info["channelDirectInfos"]:
- if id2name["icOutDirect"] == out_direct and id2name["icCfgChnlId"] == channel_id:
- return True
- return False
-
- def config_merge_out_direct(self, out_direct, channel_id):
- """config out direct"""
-
- if not self.is_exist_out_direct(out_direct, channel_id):
- conf_str = CE_NC_MERGE_CHANNEL_DIRECT_HEADER
- if out_direct:
- conf_str += "%s" % out_direct
- if channel_id:
- conf_str += "%s" % channel_id
-
- conf_str += CE_NC_MERGE_CHANNEL_DIRECT_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: Merge syslog channel out direct failed.')
-
- self.updates_cmd.append(
- "info-center %s channel %s" % (out_direct, channel_id))
- self.changed = True
-
- def delete_merge_out_direct(self, out_direct, channel_id):
- """delete out direct"""
-
- change_flag = False
- channel_id_default = get_out_direct_default(out_direct)
- if channel_id:
- for id2name in self.channel_direct_info["channelDirectInfos"]:
- if id2name["icOutDirect"] == out_direct and id2name["icCfgChnlId"] == channel_id:
- if channel_id != channel_id_default:
- channel_id = channel_id_default
- change_flag = True
-
- if not channel_id:
- for id2name in self.channel_direct_info["channelDirectInfos"]:
- if id2name["icOutDirect"] == out_direct and id2name["icCfgChnlId"] != channel_id_default:
- channel_id = channel_id_default
- change_flag = True
-
- if change_flag:
- conf_str = CE_NC_MERGE_CHANNEL_DIRECT_HEADER
- if out_direct:
- conf_str += "%s" % out_direct
- if channel_id:
- conf_str += "%s" % channel_id
-
- conf_str += CE_NC_MERGE_CHANNEL_DIRECT_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: Merge syslog channel out direct failed.')
-
- self.updates_cmd.append("undo info-center logfile channel")
- self.changed = True
-
- def get_filter_dict(self):
- """ get syslog filter attributes dict."""
-
- filter_info = dict()
- # get filter info
- conf_str = CE_NC_GET_FILTER_INFO
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return filter_info
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
- filter_info["filterInfos"] = list()
- ic_filters = root.findall("syslog/icFilters/icFilter")
- if ic_filters:
- for ic_filter in ic_filters:
- filter_dict = dict()
- for ele in ic_filter:
- if ele.tag in ["icFeatureName", "icFilterLogName"]:
- filter_dict[ele.tag] = ele.text
- filter_info["filterInfos"].append(filter_dict)
- return filter_info
-
- def is_exist_filter(self, filter_feature_name, filter_log_name):
- """if filter info exist"""
-
- if not self.filter_info:
- return False
- for id2name in self.filter_info["filterInfos"]:
- if id2name["icFeatureName"] == filter_feature_name and id2name["icFilterLogName"] == filter_log_name:
- return True
- return False
-
- def config_merge_filter(self, filter_feature_name, filter_log_name):
- """config filter"""
-
- if not self.is_exist_filter(filter_feature_name, filter_log_name):
- conf_str = CE_NC_CREATE_CHANNEL_FILTER_HEADER
- conf_str += "true"
- if filter_feature_name:
- conf_str += "%s" % filter_feature_name
- if filter_log_name:
- conf_str += "%s" % filter_log_name
-
- conf_str += CE_NC_CREATE_CHANNEL_FILTER_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Merge syslog filter failed.')
-
- self.updates_cmd.append("info-center filter-id bymodule-alias %s %s"
- % (filter_feature_name, filter_log_name))
- self.changed = True
-
- def delete_merge_filter(self, filter_feature_name, filter_log_name):
- """delete filter"""
-
- change_flag = False
- if self.is_exist_filter(filter_feature_name, filter_log_name):
- for id2name in self.filter_info["filterInfos"]:
- if id2name["icFeatureName"] == filter_feature_name and id2name["icFilterLogName"] == filter_log_name:
- change_flag = True
- if change_flag:
- conf_str = CE_NC_DELETE_CHANNEL_FILTER_HEADER
- conf_str += "true"
- if filter_feature_name:
- conf_str += "%s" % filter_feature_name
- if filter_log_name:
- conf_str += "%s" % filter_log_name
-
- conf_str += CE_NC_DELETE_CHANNEL_FILTER_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: Merge syslog channel out direct failed.')
- self.updates_cmd.append("undo info-center filter-id bymodule-alias %s %s"
- % (filter_feature_name, filter_log_name))
- self.changed = True
-
- def get_server_ip_dict(self):
- """ get server ip attributes dict."""
-
- server_ip_info = dict()
- # get server ip info
- is_default_vpn = "false"
- if not self.is_default_vpn:
- self.is_default_vpn = False
- if self.is_default_vpn is True:
- is_default_vpn = "true"
- if not self.vrf_name:
- self.vrf_name = "_public_"
- conf_str = CE_NC_GET_SERVER_IP_INFO_HEADER % (
- self.ip_type, self.server_ip, self.vrf_name, is_default_vpn)
- conf_str += CE_NC_GET_SERVER_IP_INFO_TAIL
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return server_ip_info
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
- server_ip_info["serverIpInfos"] = list()
- syslog_servers = root.findall("syslog/syslogServers/syslogServer")
- if syslog_servers:
- for syslog_server in syslog_servers:
- server_dict = dict()
- for ele in syslog_server:
- if ele.tag in ["ipType", "serverIp", "vrfName", "level", "serverPort", "facility", "chnlId",
- "chnlName", "timestamp", "transportMode", "sslPolicyName", "isDefaultVpn",
- "sourceIP", "isBriefFmt"]:
- server_dict[ele.tag] = ele.text
- server_ip_info["serverIpInfos"].append(server_dict)
- return server_ip_info
-
- def config_merge_loghost(self):
- """config loghost ip or dns"""
-
- conf_str = ""
- is_default_vpn = "false"
- if self.is_default_vpn is True:
- is_default_vpn = "true"
- if self.ip_type:
- conf_str = CE_NC_MERGE_SERVER_IP_INFO_HEADER % (self.ip_type, self.server_ip, self.vrf_name,
- is_default_vpn)
- elif self.server_domain:
- conf_str = CE_NC_MERGE_SERVER_DNS_INFO_HEADER % (
- self.server_domain, self.vrf_name, is_default_vpn)
- if self.level:
- conf_str += "%s" % self.level
- if self.server_port:
- conf_str += "%s" % self.server_port
- if self.facility:
- conf_str += "%s" % self.facility
- if self.channel_id:
- conf_str += "%s" % self.channel_id
- if self.channel_name:
- conf_str += "%s" % self.channel_name
- if self.timestamp:
- conf_str += "%s" % self.timestamp
- if self.transport_mode:
- conf_str += "%s" % self.transport_mode
- if self.ssl_policy_name:
- conf_str += "%s" % self.ssl_policy_name
- if self.source_ip:
- conf_str += "%s" % self.source_ip
- if self.ip_type:
- conf_str += CE_NC_MERGE_SERVER_IP_INFO_TAIL
- elif self.server_domain:
- conf_str += CE_NC_MERGE_SERVER_DNS_INFO_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Merge server loghost failed.')
-
- cmd = "info-center loghost"
- if self.ip_type == "ipv4" and self.server_ip:
- cmd += " %s" % self.server_ip
- if self.ip_type == "ipv6" and self.server_ip:
- cmd += " ipv6 %s" % self.server_ip
- if self.server_domain:
- cmd += " domain %s" % self.server_domain
- if self.channel_id:
- cmd += " channel %s" % self.channel_id
- if self.channel_name:
- cmd += " channel %s" % self.channel_name
- if self.vrf_name:
- if self.vrf_name != "_public_":
- cmd += " vpn-instance %s" % self.vrf_name
- if self.source_ip:
- cmd += " source-ip %s" % self.source_ip
- if self.facility:
- cmd += " facility %s" % self.facility
- if self.server_port:
- cmd += " port %s" % self.server_port
- if self.level:
- cmd += " level %s" % self.level
- if self.timestamp:
- if self.timestamp == "localtime":
- cmd += " local-time"
- else:
- cmd += " utc"
- if self.transport_mode:
- cmd += " transport %s" % self.transport_mode
- if self.ssl_policy_name:
- cmd += " ssl-policy %s" % self.ssl_policy_name
- self.updates_cmd.append(cmd)
- self.changed = True
-
- def delete_merge_loghost(self):
- """delete loghost ip or dns"""
-
- conf_str = ""
- is_default_vpn = "false"
- if self.is_default_vpn is True:
- is_default_vpn = "true"
- if self.ip_type:
- conf_str = CE_NC_DELETE_SERVER_IP_INFO_HEADER % (self.ip_type, self.server_ip, self.vrf_name,
- is_default_vpn)
- elif self.server_domain:
- conf_str = CE_NC_DELETE_SERVER_DNS_INFO_HEADER % (
- self.server_domain, self.vrf_name, is_default_vpn)
- if self.level:
- conf_str += "%s" % self.level
- if self.server_port:
- conf_str += "%s" % self.server_port
- if self.facility:
- conf_str += "%s" % self.facility
- if self.channel_id:
- conf_str += "%s" % self.channel_id
- if self.channel_name:
- conf_str += "%s" % self.channel_name
- if self.timestamp:
- conf_str += "%s" % self.timestamp
- if self.transport_mode:
- conf_str += "%s" % self.transport_mode
- if self.ssl_policy_name:
- conf_str += "%s" % self.ssl_policy_name
- if self.source_ip:
- conf_str += "%s" % self.source_ip
- if self.ip_type:
- conf_str += CE_NC_DELETE_SERVER_IP_INFO_TAIL
- elif self.server_domain:
- conf_str += CE_NC_DELETE_SERVER_DNS_INFO_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Merge server loghost failed.')
-
- cmd = "undo info-center loghost"
- if self.ip_type == "ipv4" and self.server_ip:
- cmd += " %s" % self.server_ip
- if self.ip_type == "ipv6" and self.server_ip:
- cmd += " ipv6 %s" % self.server_ip
- if self.server_domain:
- cmd += " domain %s" % self.server_domain
- if self.vrf_name:
- if self.vrf_name != "_public_":
- cmd += " vpn-instance %s" % self.vrf_name
- self.updates_cmd.append(cmd)
- self.changed = True
-
- def get_server_domain_dict(self):
- """ get server domain attributes dict"""
-
- server_domain_info = dict()
- # get server domain info
- if not self.is_default_vpn:
- self.is_default_vpn = False
- if not self.vrf_name:
- self.vrf_name = "_public_"
- conf_str = CE_NC_GET_SERVER_DNS_INFO_HEADER
- conf_str += CE_NC_GET_SERVER_DNS_INFO_TAIL
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return server_domain_info
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
- server_domain_info["serverAddressInfos"] = list()
- syslog_dnss = root.findall("syslog/syslogDNSs/syslogDNS")
- if syslog_dnss:
- for syslog_dns in syslog_dnss:
- dns_dict = dict()
- for ele in syslog_dns:
- if ele.tag in ["serverDomain", "vrfName", "level", "serverPort", "facility", "chnlId",
- "chnlName", "timestamp", "transportMode", "sslPolicyName", "isDefaultVpn",
- "sourceIP", "isBriefFmt"]:
- dns_dict[ele.tag] = ele.text
- server_domain_info["serverAddressInfos"].append(dns_dict)
-
- return server_domain_info
-
- def check_need_loghost_cfg(self):
- """ check need cfg"""
-
- need_cfg = False
- find_flag = False
- if self.ip_type and self.server_ip:
- if self.server_ip_info:
- for tmp in self.server_ip_info["serverIpInfos"]:
- find_flag = True
- if self.ip_type and tmp.get("ipType") != self.ip_type:
- find_flag = False
- if self.server_ip and tmp.get("serverIp") != self.server_ip:
- find_flag = False
- if self.vrf_name and tmp.get("vrfName") != self.vrf_name:
- find_flag = False
- if self.level and tmp.get("level") != self.level:
- find_flag = False
- if self.server_port and tmp.get("serverPort") != self.server_port:
- find_flag = False
- if self.facility and tmp.get("facility") != self.facility:
- find_flag = False
- if self.channel_id and tmp.get("chnlId") != self.channel_id:
- find_flag = False
- if self.channel_name and tmp.get("chnlName") != self.channel_name:
- find_flag = False
- if self.timestamp and tmp.get("timestamp") != self.timestamp:
- find_flag = False
- if self.transport_mode and tmp.get("transportMode") != self.transport_mode:
- find_flag = False
- if self.ssl_policy_name and tmp.get("sslPolicyName") != self.ssl_policy_name:
- find_flag = False
- if self.source_ip and tmp.get("sourceIP") != self.source_ip:
- find_flag = False
- if find_flag:
- break
- elif self.server_domain:
- if self.server_domain_info:
- for tmp in self.server_domain_info["serverAddressInfos"]:
- find_flag = True
- if self.server_domain and tmp.get("serverDomain") != self.server_domain:
- find_flag = False
- if self.vrf_name and tmp.get("vrfName") != self.vrf_name:
- find_flag = False
- if self.level and tmp.get("level") != self.level:
- find_flag = False
- if self.server_port and tmp.get("serverPort") != self.server_port:
- find_flag = False
- if self.facility and tmp.get("facility") != self.facility:
- find_flag = False
- if self.channel_id and tmp.get("chnlId") != self.channel_id:
- find_flag = False
- if self.channel_name and tmp.get("chnlName") != self.channel_name:
- find_flag = False
- if self.timestamp and tmp.get("timestamp") != self.timestamp:
- find_flag = False
- if self.transport_mode and tmp.get("transportMode") != self.transport_mode:
- find_flag = False
- if self.ssl_policy_name and tmp.get("sslPolicyName") != self.ssl_policy_name:
- find_flag = False
- if self.source_ip and tmp.get("sourceIP") != self.source_ip:
- find_flag = False
- if find_flag:
- break
- else:
- find_flag = False
-
- if self.state == "present":
- need_cfg = bool(not find_flag)
- elif self.state == "absent":
- need_cfg = bool(find_flag)
- return need_cfg
-
- def get_syslog_global(self):
- """get syslog global attributes"""
-
- cur_global_info = dict()
- conf_str = CE_NC_GET_CENTER_GLOBAL_INFO_HEADER
- if self.info_center_enable:
- conf_str += ""
- if self.packet_priority:
- conf_str += ""
- if self.suppress_enable:
- conf_str += ""
- conf_str += CE_NC_GET_CENTER_GLOBAL_INFO_TAIL
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return cur_global_info
- else:
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- global_info = root.findall(
- "syslog/globalParam")
-
- if global_info:
- for tmp in global_info:
- for site in tmp:
- if site.tag in ["icEnable", "packetPriority", "suppressEnable"]:
- cur_global_info[site.tag] = site.text
- return cur_global_info
-
- def merge_syslog_global(self):
- """config global"""
-
- conf_str = CE_NC_MERGE_CENTER_GLOBAL_INFO_HEADER
- if self.info_center_enable:
- conf_str += "%s" % self.info_center_enable
- if self.packet_priority:
- if self.state == "present":
- packet_priority = self.packet_priority
- else:
- packet_priority = 0
- conf_str += "%s" % packet_priority
- if self.suppress_enable:
- conf_str += "%s" % self.suppress_enable
-
- conf_str += CE_NC_MERGE_CENTER_GLOBAL_INFO_TAIL
-
- if self.info_center_enable == "true" and self.cur_global_info["icEnable"] != self.info_center_enable:
- cmd = "info-center enable"
- self.updates_cmd.append(cmd)
- self.changed = True
- if self.suppress_enable == "true" and self.cur_global_info["suppressEnable"] != self.suppress_enable:
- cmd = "info-center statistic-suppress enable"
- self.updates_cmd.append(cmd)
- self.changed = True
- if self.info_center_enable == "false" and self.cur_global_info["icEnable"] != self.info_center_enable:
- cmd = "undo info-center enable"
- self.updates_cmd.append(cmd)
- self.changed = True
- if self.suppress_enable == "false" and self.cur_global_info["suppressEnable"] != self.suppress_enable:
- cmd = "undo info-center statistic-suppress enable"
- self.updates_cmd.append(cmd)
- self.changed = True
-
- if self.state == "present":
- if self.packet_priority:
- if self.cur_global_info["packetPriority"] != self.packet_priority:
- cmd = "info-center syslog packet-priority %s" % self.packet_priority
- self.updates_cmd.append(cmd)
- self.changed = True
- if self.state == "absent":
- if self.packet_priority:
- if self.cur_global_info["packetPriority"] == self.packet_priority:
- cmd = "undo info-center syslog packet-priority %s" % self.packet_priority
- self.updates_cmd.append(cmd)
- self.changed = True
- if self.changed:
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Merge syslog global failed.')
-
- def get_syslog_logfile(self):
- """get syslog logfile"""
-
- cur_logfile_info = dict()
- conf_str = CE_NC_GET_LOG_FILE_INFO_HEADER
- conf_str += "log"
- if self.logfile_max_num:
- conf_str += ""
- if self.logfile_max_size:
- conf_str += ""
- conf_str += CE_NC_GET_LOG_FILE_INFO_TAIL
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return cur_logfile_info
- else:
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- logfile_info = root.findall(
- "syslog/icLogFileInfos/icLogFileInfo")
- if logfile_info:
- for tmp in logfile_info:
- for site in tmp:
- if site.tag in ["maxFileNum", "maxFileSize"]:
- cur_logfile_info[site.tag] = site.text
- return cur_logfile_info
-
- def merge_syslog_logfile(self):
- """config logfile"""
-
- logfile_max_num = "200"
- conf_str = CE_NC_MERGE_LOG_FILE_INFO_HEADER
- if self.logfile_max_num:
- if self.state == "present":
- logfile_max_num = self.logfile_max_num
- else:
- if self.logfile_max_num != "200" and self.cur_logfile_info["maxFileNum"] == self.logfile_max_num:
- logfile_max_num = "200"
- conf_str += "%s" % logfile_max_num
-
- if self.logfile_max_size:
- logfile_max_size = "32"
- if self.state == "present":
- logfile_max_size = self.logfile_max_size
- else:
- if self.logfile_max_size != "32" and self.cur_logfile_info["maxFileSize"] == self.logfile_max_size:
- logfile_max_size = "32"
- conf_str += "%s" % logfile_max_size
-
- conf_str += "log"
- conf_str += CE_NC_MERGE_LOG_FILE_INFO_TAIL
-
- if self.state == "present":
- if self.logfile_max_num:
- if self.cur_logfile_info["maxFileNum"] != self.logfile_max_num:
- cmd = "info-center max-logfile-number %s" % self.logfile_max_num
- self.updates_cmd.append(cmd)
- self.changed = True
- if self.logfile_max_size:
- if self.cur_logfile_info["maxFileSize"] != self.logfile_max_size:
- cmd = "info-center logfile size %s" % self.logfile_max_size
- self.updates_cmd.append(cmd)
- self.changed = True
- if self.state == "absent":
- if self.logfile_max_num and self.logfile_max_num != "200":
- if self.cur_logfile_info["maxFileNum"] == self.logfile_max_num:
- cmd = "undo info-center max-logfile-number"
- self.updates_cmd.append(cmd)
- self.changed = True
- if self.logfile_max_size and self.logfile_max_size != "32":
- if self.cur_logfile_info["maxFileSize"] == self.logfile_max_size:
- cmd = "undo info-center logfile size"
- self.updates_cmd.append(cmd)
- self.changed = True
-
- if self.changed:
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: Merge syslog logfile failed.')
-
- def check_params(self):
- """Check all input params"""
-
- # packet_priority check
- if self.packet_priority:
- if not self.packet_priority.isdigit():
- self.module.fail_json(
- msg='Error: The parameter of packet priority is invalid.')
- if int(self.packet_priority) > 7 or int(self.packet_priority) < 0:
- self.module.fail_json(
- msg='Error: The packet priority must be an integer between 0 and 7.')
-
- # logfile_max_num check
- if self.logfile_max_num:
- if not self.logfile_max_num.isdigit():
- self.module.fail_json(
- msg='Error: The parameter of logfile_max_num is invalid.')
- if int(self.logfile_max_num) > 500 or int(self.logfile_max_num) < 3:
- self.module.fail_json(
- msg='Error: The logfile_max_num must be an integer between 3 and 500.')
-
- # channel_id check
- if self.channel_id:
- if not self.channel_id.isdigit():
- self.module.fail_json(
- msg='Error: The parameter of channel_id is invalid.')
- if int(self.channel_id) > 9 or int(self.channel_id) < 0:
- self.module.fail_json(
- msg='Error: The channel_id must be an integer between 0 and 9.')
-
- # channel_cfg_name check
- if self.channel_cfg_name:
- if len(self.channel_cfg_name) > 30 \
- or len(self.channel_cfg_name.replace(' ', '')) < 1:
- self.module.fail_json(
- msg='Error: channel_cfg_name is not in the range from 1 to 30.')
-
- # filter_feature_name check
- if self.filter_feature_name:
- if len(self.filter_feature_name) > 31 \
- or len(self.filter_feature_name.replace(' ', '')) < 1:
- self.module.fail_json(
- msg='Error: filter_feature_name is not in the range from 1 to 31.')
-
- # filter_log_name check
- if self.filter_log_name:
- if len(self.filter_log_name) > 63 \
- or len(self.filter_log_name.replace(' ', '')) < 1:
- self.module.fail_json(
- msg='Error: filter_log_name is not in the range from 1 to 63.')
-
- # server_ip check
- if self.server_ip:
- if not check_ip_addr(self.server_ip):
- self.module.fail_json(
- msg='Error: The %s is not a valid ip address' % self.server_ip)
- # source_ip check
- if self.source_ip:
- if not check_ip_addr(self.source_ip):
- self.module.fail_json(
- msg='Error: The %s is not a valid ip address' % self.source_ip)
-
- # server_domain check
- if self.server_domain:
- if len(self.server_domain) > 255 \
- or len(self.server_domain.replace(' ', '')) < 1:
- self.module.fail_json(
- msg='Error: server_domain is not in the range from 1 to 255.')
-
- # vrf_name check
- if self.vrf_name:
- if len(self.vrf_name) > 31 \
- or len(self.vrf_name.replace(' ', '')) < 1:
- self.module.fail_json(
- msg='Error: vrf_name is not in the range from 1 to 31.')
-
- # server_port check
- if self.server_port:
- if not self.server_port.isdigit():
- self.module.fail_json(
- msg='Error: The parameter of server_port is invalid.')
- if int(self.server_port) > 65535 or int(self.server_port) < 1:
- self.module.fail_json(
- msg='Error: The server_port must be an integer between 1 and 65535.')
-
- # channel_name check
- if self.channel_name:
- if len(self.channel_name) > 31 \
- or len(self.channel_name.replace(' ', '')) < 1:
- self.module.fail_json(
- msg='Error: channel_name is not in the range from 1 to 30.')
-
- # ssl_policy_name check
- if self.ssl_policy_name:
- if len(self.ssl_policy_name) > 23 \
- or len(self.ssl_policy_name.replace(' ', '')) < 1:
- self.module.fail_json(
- msg='Error: ssl_policy_name is not in the range from 1 to 23.')
-
- def get_proposed(self):
- """get proposed info"""
-
- if self.info_center_enable:
- self.proposed["info_center_enable"] = self.info_center_enable
- if self.packet_priority:
- self.proposed["packet_priority"] = self.packet_priority
- if self.suppress_enable:
- self.proposed["suppress_enable"] = self.suppress_enable
- if self.logfile_max_num:
- self.proposed["logfile_max_num"] = self.logfile_max_num
- if self.logfile_max_size:
- self.proposed["logfile_max_size"] = self.logfile_max_size
- if self.channel_id:
- self.proposed["channel_id"] = self.channel_id
- if self.channel_cfg_name:
- self.proposed["channel_cfg_name"] = self.channel_cfg_name
- if self.channel_out_direct:
- self.proposed["channel_out_direct"] = self.channel_out_direct
- if self.filter_feature_name:
- self.proposed["filter_feature_name"] = self.filter_feature_name
- if self.filter_log_name:
- self.proposed["filter_log_name"] = self.filter_log_name
- if self.ip_type:
- self.proposed["ip_type"] = self.ip_type
- if self.server_ip:
- self.proposed["server_ip"] = self.server_ip
- if self.server_domain:
- self.proposed["server_domain"] = self.server_domain
- if self.vrf_name:
- self.proposed["vrf_name"] = self.vrf_name
- if self.level:
- self.proposed["level"] = self.level
- if self.server_port:
- self.proposed["server_port"] = self.server_port
- if self.facility:
- self.proposed["facility"] = self.facility
- if self.channel_name:
- self.proposed["channel_name"] = self.channel_name
- if self.timestamp:
- self.proposed["timestamp"] = self.timestamp
- if self.ssl_policy_name:
- self.proposed["ssl_policy_name"] = self.ssl_policy_name
- if self.transport_mode:
- self.proposed["transport_mode"] = self.transport_mode
- if self.is_default_vpn:
- self.proposed["is_default_vpn"] = self.is_default_vpn
- if self.source_ip:
- self.proposed["source_ip"] = self.source_ip
- if self.state:
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- if self.info_center_enable:
- self.existing["info_center_enable"] = self.cur_global_info[
- "icEnable"]
- if self.packet_priority:
- self.existing["packet_priority"] = self.cur_global_info[
- "packetPriority"]
- if self.suppress_enable:
- self.existing["suppress_enable"] = self.cur_global_info[
- "suppressEnable"]
- if self.logfile_max_num:
- self.existing["logfile_max_num"] = self.cur_logfile_info[
- "maxFileNum"]
- if self.logfile_max_size:
- self.existing["logfile_max_size"] = self.cur_logfile_info[
- "maxFileSize"]
-
- if self.channel_id and self.channel_cfg_name:
- if self.channel_info:
- self.existing["channel_id_info"] = self.channel_info[
- "channelInfos"]
- if self.channel_out_direct and self.channel_id:
- if self.channel_direct_info:
- self.existing["channel_out_direct_info"] = self.channel_direct_info[
- "channelDirectInfos"]
- if self.filter_feature_name and self.filter_log_name:
- if self.filter_info:
- self.existing["filter_id_info"] = self.filter_info[
- "filterInfos"]
- if self.ip_type:
- if self.server_ip_info:
- self.existing["server_ip_info"] = self.server_ip_info[
- "serverIpInfos"]
-
- if self.server_domain:
- if self.server_domain_info:
- self.existing["server_domain_info"] = self.server_domain_info[
- "serverAddressInfos"]
-
- def get_end_state(self):
- """get end state info"""
-
- if self.info_center_enable or self.packet_priority or self.suppress_enable:
- self.cur_global_info = self.get_syslog_global()
- if self.logfile_max_num or self.logfile_max_size:
- self.cur_logfile_info = self.get_syslog_logfile()
- if self.channel_id and self.channel_cfg_name:
- self.channel_info = self.get_channel_dict()
- if self.channel_out_direct and self.channel_id:
- self.channel_direct_info = self.get_channel_direct_dict()
- if self.filter_feature_name and self.filter_log_name:
- self.filter_info = self.get_filter_dict()
- if self.ip_type:
- self.server_ip_info = self.get_server_ip_dict()
- if self.server_domain:
- self.server_domain_info = self.get_server_domain_dict()
-
- if self.info_center_enable:
- self.end_state[
- "info_center_enable"] = self.cur_global_info["icEnable"]
- if self.packet_priority:
- self.end_state["packet_priority"] = self.cur_global_info[
- "packetPriority"]
- if self.suppress_enable:
- self.end_state["suppress_enable"] = self.cur_global_info[
- "suppressEnable"]
- if self.logfile_max_num:
- self.end_state["logfile_max_num"] = self.cur_logfile_info[
- "maxFileNum"]
- if self.logfile_max_size:
- self.end_state["logfile_max_size"] = self.cur_logfile_info[
- "maxFileSize"]
-
- if self.channel_id and self.channel_cfg_name:
- if self.channel_info:
- self.end_state["channel_id_info"] = self.channel_info[
- "channelInfos"]
-
- if self.channel_out_direct and self.channel_id:
- if self.channel_direct_info:
- self.end_state["channel_out_direct_info"] = self.channel_direct_info[
- "channelDirectInfos"]
-
- if self.filter_feature_name and self.filter_log_name:
- if self.filter_info:
- self.end_state["filter_id_info"] = self.filter_info[
- "filterInfos"]
-
- if self.ip_type:
- if self.server_ip_info:
- self.end_state["server_ip_info"] = self.server_ip_info[
- "serverIpInfos"]
-
- if self.server_domain:
- if self.server_domain_info:
- self.end_state["server_domain_info"] = self.server_domain_info[
- "serverAddressInfos"]
- if self.end_state == self.existing:
- self.changed = False
-
- def work(self):
- """worker"""
-
- self.check_params()
- if self.info_center_enable or self.packet_priority or self.suppress_enable:
- self.cur_global_info = self.get_syslog_global()
- if self.logfile_max_num or self.logfile_max_size:
- self.cur_logfile_info = self.get_syslog_logfile()
- if self.channel_id:
- self.channel_info = self.get_channel_dict()
- if self.channel_out_direct:
- self.channel_direct_info = self.get_channel_direct_dict()
- if self.filter_feature_name and self.filter_log_name:
- self.filter_info = self.get_filter_dict()
- if self.ip_type:
- self.server_ip_info = self.get_server_ip_dict()
- if self.server_domain:
- self.server_domain_info = self.get_server_domain_dict()
- self.get_existing()
- self.get_proposed()
- if self.info_center_enable or self.packet_priority or self.suppress_enable:
- self.merge_syslog_global()
-
- if self.logfile_max_num or self.logfile_max_size:
- self.merge_syslog_logfile()
-
- if self.server_ip:
- if not self.ip_type:
- self.module.fail_json(
- msg='Error: ip_type and server_ip must be exist at the same time.')
- if self.ip_type:
- if not self.server_ip:
- self.module.fail_json(
- msg='Error: ip_type and server_ip must be exist at the same time.')
-
- if self.ip_type or self.server_domain or self.channel_id or self.filter_feature_name:
- if self.ip_type and self.server_domain:
- self.module.fail_json(
- msg='Error: ip_type and server_domain can not be exist at the same time.')
- if self.channel_id and self.channel_name:
- self.module.fail_json(
- msg='Error: channel_id and channel_name can not be exist at the same time.')
- if self.ssl_policy_name:
- if self.transport_mode == "udp":
- self.module.fail_json(
- msg='Error: transport_mode: udp does not support ssl_policy.')
- if not self.transport_mode:
- self.module.fail_json(
- msg='Error: transport_mode, ssl_policy_name must be exist at the same time.')
- if self.ip_type == "ipv6":
- if self.vrf_name and self.vrf_name != "_public_":
- self.module.fail_json(
- msg='Error: ipType:ipv6 only support default vpn:_public_.')
- if self.is_default_vpn is True:
- if self.vrf_name:
- if self.vrf_name != "_public_":
- self.module.fail_json(
- msg='Error: vrf_name should be _public_ when is_default_vpn is True.')
- else:
- self.vrf_name = "_public_"
- else:
- if self.vrf_name == "_public_":
- self.module.fail_json(
- msg='Error: The default vpn value is _public_, but is_default_vpn is False.')
- if self.state == "present":
- # info-center channel channel-number name channel-name
- if self.channel_id and self.channel_cfg_name:
- self.config_merge_syslog_channel(
- self.channel_id, self.channel_cfg_name)
- # info-center { console | logfile | monitor | snmp | logbuffer
- # | trapbuffer } channel channel-number
- if self.channel_out_direct and self.channel_id:
- self.config_merge_out_direct(
- self.channel_out_direct, self.channel_id)
- # info-center filter-id bymodule-alias modname alias
- if self.filter_feature_name and self.filter_log_name:
- self.config_merge_filter(
- self.filter_feature_name, self.filter_log_name)
- if self.ip_type and self.server_ip:
- if not self.vrf_name:
- self.vrf_name = "_public_"
- if self.check_need_loghost_cfg():
- self.config_merge_loghost()
- if self.server_domain:
- if not self.vrf_name:
- self.vrf_name = "_public_"
- if self.check_need_loghost_cfg():
- self.config_merge_loghost()
-
- elif self.state == "absent":
- if self.channel_id:
- self.delete_merge_syslog_channel(
- self.channel_id, self.channel_cfg_name)
- if self.channel_out_direct:
- self.delete_merge_out_direct(
- self.channel_out_direct, self.channel_id)
- if self.filter_feature_name and self.filter_log_name:
- self.delete_merge_filter(
- self.filter_feature_name, self.filter_log_name)
- if self.ip_type and self.server_ip:
- if not self.vrf_name:
- self.vrf_name = "_public_"
- if self.check_need_loghost_cfg():
- self.delete_merge_loghost()
- if self.server_domain:
- if not self.vrf_name:
- self.vrf_name = "_public_"
- if self.check_need_loghost_cfg():
- self.delete_merge_loghost()
-
- self.get_end_state()
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- info_center_enable=dict(choices=['true', 'false']),
- packet_priority=dict(type='str'),
- suppress_enable=dict(choices=['true', 'false']),
- logfile_max_num=dict(type='str'),
- logfile_max_size=dict(choices=['4', '8', '16', '32']),
- channel_id=dict(type='str'),
- channel_cfg_name=dict(type='str'),
- channel_out_direct=dict(choices=['console', 'monitor',
- 'trapbuffer', 'logbuffer', 'snmp', 'logfile']),
- filter_feature_name=dict(type='str'),
- filter_log_name=dict(type='str'),
- ip_type=dict(choices=['ipv4', 'ipv6']),
- server_ip=dict(type='str'),
- server_domain=dict(type='str'),
- is_default_vpn=dict(default=False, type='bool'),
- vrf_name=dict(type='str'),
- level=dict(choices=['emergencies', 'alert', 'critical', 'error', 'warning', 'notification',
- 'informational', 'debugging']),
- server_port=dict(type='str'),
- facility=dict(choices=['local0', 'local1', 'local2',
- 'local3', 'local4', 'local5', 'local6', 'local7']),
- channel_name=dict(type='str'),
- timestamp=dict(choices=['UTC', 'localtime']),
- transport_mode=dict(choices=['tcp', 'udp']),
- ssl_policy_name=dict(type='str'),
- source_ip=dict(type='str'),
- state=dict(choices=['present', 'absent'], default='present')
-
- )
- argument_spec.update(ce_argument_spec)
- module = InfoCenterGlobal(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_info_center_log.py b/plugins/modules/network/cloudengine/ce_info_center_log.py
deleted file mode 100644
index fc04cffdfb..0000000000
--- a/plugins/modules/network/cloudengine/ce_info_center_log.py
+++ /dev/null
@@ -1,548 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_info_center_log
-short_description: Manages information center log configuration on HUAWEI CloudEngine switches.
-description:
- - Setting the Timestamp Format of Logs.
- Configuring the Device to Output Logs to the Log Buffer.
-author: QijunPan (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- log_time_stamp:
- description:
- - Sets the timestamp format of logs.
- choices: ['date_boot', 'date_second', 'date_tenthsecond', 'date_millisecond',
- 'shortdate_second', 'shortdate_tenthsecond', 'shortdate_millisecond',
- 'formatdate_second', 'formatdate_tenthsecond', 'formatdate_millisecond']
- log_buff_enable:
- description:
- - Enables the Switch to send logs to the log buffer.
- default: no_use
- choices: ['no_use','true', 'false']
- log_buff_size:
- description:
- - Specifies the maximum number of logs in the log buffer.
- The value is an integer that ranges from 0 to 10240. If logbuffer-size is 0, logs are not displayed.
- module_name:
- description:
- - Specifies the name of a module.
- The value is a module name in registration logs.
- channel_id:
- description:
- - Specifies a channel ID.
- The value is an integer ranging from 0 to 9.
- log_enable:
- description:
- - Indicates whether log filtering is enabled.
- default: no_use
- choices: ['no_use','true', 'false']
- log_level:
- description:
- - Specifies a log severity.
- choices: ['emergencies', 'alert', 'critical', 'error',
- 'warning', 'notification', 'informational', 'debugging']
- state:
- description:
- - Determines whether the config should be present or not
- on the device.
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine info center log test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Setting the timestamp format of logs"
- ce_info_center_log:
- log_time_stamp: date_tenthsecond
- provider: "{{ cli }}"
-
- - name: "Enabled to output information to the log buffer"
- ce_info_center_log:
- log_buff_enable: true
- provider: "{{ cli }}"
-
- - name: "Set the maximum number of logs in the log buffer"
- ce_info_center_log:
- log_buff_size: 100
- provider: "{{ cli }}"
-
- - name: "Set a rule for outputting logs to a channel"
- ce_info_center_log:
- module_name: aaa
- channel_id: 1
- log_enable: true
- log_level: critical
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: verbose mode
- type: dict
- sample: {"log_time_stamp": "date_tenthsecond", "state": "present"}
-existing:
- description: k/v pairs of existing configuration
- returned: verbose mode
- type: dict
- sample: {"log_time_stamp": "date_second"}
-end_state:
- description: k/v pairs of configuration after module execution
- returned: verbose mode
- type: dict
- sample: {"log_time_stamp": "date_tenthsecond"}
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: ["info-center timestamp log date precision-time tenth-second"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-
-CE_NC_GET_LOG = """
-
-
-
-
-
-
-
-
-
- %s
- %s
-
-
-
-
-
-
-
-"""
-
-CE_NC_GET_LOG_GLOBAL = """
-
-
-
-
-
-
-
-
-
-"""
-
-TIME_STAMP_DICT = {"date_boot": "boot",
- "date_second": "date precision-time second",
- "date_tenthsecond": "date precision-time tenth-second",
- "date_millisecond": "date precision-time millisecond",
- "shortdate_second": "short-date precision-time second",
- "shortdate_tenthsecond": "short-date precision-time tenth-second",
- "shortdate_millisecond": "short-date precision-time millisecond",
- "formatdate_second": "format-date precision-time second",
- "formatdate_tenthsecond": "format-date precision-time tenth-second",
- "formatdate_millisecond": "format-date precision-time millisecond"}
-
-CHANNEL_DEFAULT_LOG_STATE = {"0": "true",
- "1": "true",
- "2": "true",
- "3": "false",
- "4": "true",
- "5": "false",
- "6": "true",
- "7": "true",
- "8": "true",
- "9": "true"}
-
-CHANNEL_DEFAULT_LOG_LEVEL = {"0": "warning",
- "1": "warning",
- "2": "informational",
- "3": "informational",
- "4": "warning",
- "5": "debugging",
- "6": "debugging",
- "7": "warning",
- "8": "debugging",
- "9": "debugging"}
-
-
-class InfoCenterLog(object):
- """
- Manages information center log configuration
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.log_time_stamp = self.module.params['log_time_stamp']
- self.log_buff_enable = self.module.params['log_buff_enable']
- self.log_buff_size = self.module.params['log_buff_size']
- self.module_name = self.module.params['module_name']
- self.channel_id = self.module.params['channel_id']
- self.log_enable = self.module.params['log_enable']
- self.log_level = self.module.params['log_level']
- self.state = self.module.params['state']
-
- # state
- self.log_dict = dict()
- self.changed = False
- self.updates_cmd = list()
- self.commands = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def init_module(self):
- """init module"""
-
- self.module = AnsibleModule(argument_spec=self.spec, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed"""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_log_dict(self):
- """ log config dict"""
-
- log_dict = dict()
- if self.module_name:
- if self.module_name.lower() == "default":
- conf_str = CE_NC_GET_LOG % (self.module_name.lower(), self.channel_id)
- else:
- conf_str = CE_NC_GET_LOG % (self.module_name.upper(), self.channel_id)
- else:
- conf_str = CE_NC_GET_LOG_GLOBAL
-
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return log_dict
-
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
-
- # get global param info
- glb = root.find("syslog/globalParam")
- if glb:
- for attr in glb:
- if attr.tag in ["bufferSize", "logTimeStamp", "icLogBuffEn"]:
- log_dict[attr.tag] = attr.text
-
- # get info-center source info
- log_dict["source"] = dict()
- src = root.find("syslog/icSources/icSource")
- if src:
- for attr in src:
- if attr.tag in ["moduleName", "icChannelId", "icChannelName", "logEnFlg", "logEnLevel"]:
- log_dict["source"][attr.tag] = attr.text
-
- return log_dict
-
- def config_log_global(self):
- """config log global param"""
-
- xml_str = ''
- if self.log_time_stamp:
- if self.state == "present" and self.log_time_stamp.upper() != self.log_dict.get("logTimeStamp"):
- xml_str += '%s' % self.log_time_stamp.upper()
- self.updates_cmd.append(
- "info-center timestamp log %s" % TIME_STAMP_DICT.get(self.log_time_stamp))
- elif self.state == "absent" and self.log_time_stamp.upper() == self.log_dict.get("logTimeStamp"):
- xml_str += 'DATE_SECOND' # set default
- self.updates_cmd.append("undo info-center timestamp log")
- else:
- pass
-
- if self.log_buff_enable != 'no_use':
- if self.log_dict.get("icLogBuffEn") != self.log_buff_enable:
- xml_str += '%s' % self.log_buff_enable
- if self.log_buff_enable == "true":
- self.updates_cmd.append("info-center logbuffer")
- else:
- self.updates_cmd.append("undo info-center logbuffer")
-
- if self.log_buff_size:
- if self.state == "present" and self.log_dict.get("bufferSize") != self.log_buff_size:
- xml_str += '%s' % self.log_buff_size
- self.updates_cmd.append(
- "info-center logbuffer size %s" % self.log_buff_size)
- elif self.state == "absent" and self.log_dict.get("bufferSize") == self.log_buff_size:
- xml_str += '512'
- self.updates_cmd.append("undo info-center logbuffer size")
-
- if xml_str == '':
- return ""
- else:
- xml_str += ''
- return xml_str
-
- def config_log_soruce(self):
- """config info-center sources"""
-
- xml_str = ''
- if not self.module_name or not self.channel_id:
- return xml_str
-
- source = self.log_dict["source"]
- if self.state == "present":
- xml_str = ''
- cmd = 'info-center source %s channel %s log' % (
- self.module_name, self.channel_id)
- else:
- if not source or self.module_name != source.get("moduleName").lower() or \
- self.channel_id != source.get("icChannelId"):
- return ''
-
- if self.log_enable == 'no_use' and not self.log_level:
- xml_str = ''
- else:
- xml_str = ''
- cmd = 'undo info-center source %s channel %s log' % (
- self.module_name, self.channel_id)
-
- xml_str += '%s%s' % (
- self.module_name, self.channel_id)
-
- # log_enable
- if self.log_enable != 'no_use':
- if self.state == "present" and (not source or self.log_enable != source.get("logEnFlg")):
- xml_str += '%s' % self.log_enable
- if self.log_enable == "true":
- cmd += ' state on'
- else:
- cmd += ' state off'
- elif self.state == "absent" and source and self.log_level == source.get("logEnLevel"):
- xml_str += '%s' % CHANNEL_DEFAULT_LOG_STATE.get(self.channel_id)
- cmd += ' state'
-
- # log_level
- if self.log_level:
- if self.state == "present" and (not source or self.log_level != source.get("logEnLevel")):
- xml_str += '%s' % self.log_level
- cmd += ' level %s' % self.log_level
- elif self.state == "absent" and source and self.log_level == source.get("logEnLevel"):
- xml_str += '%s' % CHANNEL_DEFAULT_LOG_LEVEL.get(self.channel_id)
- cmd += ' level'
-
- if xml_str.endswith(""):
- if self.log_enable == 'no_use' and not self.log_level and self.state == "absent":
- xml_str += ''
- self.updates_cmd.append(cmd)
- return xml_str
- else:
- return ''
- else:
- xml_str += ''
- self.updates_cmd.append(cmd)
- return xml_str
-
- def netconf_load_config(self, xml_str):
- """load log config by netconf"""
-
- if not xml_str:
- return
-
- xml_cfg = """
-
-
- %s
-
- """ % xml_str
-
- recv_xml = set_nc_config(self.module, xml_cfg)
- self.check_response(recv_xml, "SET_LOG")
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- # check log_buff_size ranges from 0 to 10240
- if self.log_buff_size:
- if not self.log_buff_size.isdigit():
- self.module.fail_json(
- msg="Error: log_buff_size is not digit.")
- if int(self.log_buff_size) < 0 or int(self.log_buff_size) > 10240:
- self.module.fail_json(
- msg="Error: log_buff_size is not ranges from 0 to 10240.")
-
- # check channel_id ranging from 0 to 9
- if self.channel_id:
- if not self.channel_id.isdigit():
- self.module.fail_json(msg="Error: channel_id is not digit.")
- if int(self.channel_id) < 0 or int(self.channel_id) > 9:
- self.module.fail_json(
- msg="Error: channel_id is not ranges from 0 to 9.")
-
- # module_name and channel_id must be set at the same time
- if bool(self.module_name) != bool(self.channel_id):
- self.module.fail_json(
- msg="Error: module_name and channel_id must be set at the same time.")
-
- def get_proposed(self):
- """get proposed info"""
-
- if self.log_time_stamp:
- self.proposed["log_time_stamp"] = self.log_time_stamp
- if self.log_buff_enable != 'no_use':
- self.proposed["log_buff_enable"] = self.log_buff_enable
- if self.log_buff_size:
- self.proposed["log_buff_size"] = self.log_buff_size
- if self.module_name:
- self.proposed["module_name"] = self.module_name
- if self.channel_id:
- self.proposed["channel_id"] = self.channel_id
- if self.log_enable != 'no_use':
- self.proposed["log_enable"] = self.log_enable
- if self.log_level:
- self.proposed["log_level"] = self.log_level
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- if not self.log_dict:
- return
-
- if self.log_time_stamp:
- self.existing["log_time_stamp"] = self.log_dict.get("logTimeStamp").lower()
- if self.log_buff_enable != 'no_use':
- self.existing["log_buff_enable"] = self.log_dict.get("icLogBuffEn")
- if self.log_buff_size:
- self.existing["log_buff_size"] = self.log_dict.get("bufferSize")
- if self.module_name:
- self.existing["source"] = self.log_dict.get("source")
-
- def get_end_state(self):
- """get end state info"""
-
- log_dict = self.get_log_dict()
- if not log_dict:
- return
-
- if self.log_time_stamp:
- self.end_state["log_time_stamp"] = log_dict.get("logTimeStamp").lower()
- if self.log_buff_enable != 'no_use':
- self.end_state["log_buff_enable"] = log_dict.get("icLogBuffEn")
- if self.log_buff_size:
- self.end_state["log_buff_size"] = log_dict.get("bufferSize")
- if self.module_name:
- self.end_state["source"] = log_dict.get("source")
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.log_dict = self.get_log_dict()
- self.get_existing()
- self.get_proposed()
-
- # deal present or absent
- xml_str = ''
- if self.log_time_stamp or self.log_buff_enable != 'no_use' or self.log_buff_size:
- xml_str += self.config_log_global()
-
- if self.module_name:
- xml_str += self.config_log_soruce()
-
- if xml_str:
- self.netconf_load_config(xml_str)
- self.changed = True
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- log_time_stamp=dict(required=False, type='str',
- choices=['date_boot', 'date_second', 'date_tenthsecond', 'date_millisecond',
- 'shortdate_second', 'shortdate_tenthsecond', 'shortdate_millisecond',
- 'formatdate_second', 'formatdate_tenthsecond', 'formatdate_millisecond']),
- log_buff_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- log_buff_size=dict(required=False, type='str'),
- module_name=dict(required=False, type='str'),
- channel_id=dict(required=False, type='str'),
- log_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- log_level=dict(required=False, type='str',
- choices=['emergencies', 'alert', 'critical', 'error',
- 'warning', 'notification', 'informational', 'debugging']),
- state=dict(required=False, default='present',
- choices=['present', 'absent'])
- )
-
- argument_spec.update(ce_argument_spec)
- module = InfoCenterLog(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_info_center_trap.py b/plugins/modules/network/cloudengine/ce_info_center_trap.py
deleted file mode 100644
index 31d5276e69..0000000000
--- a/plugins/modules/network/cloudengine/ce_info_center_trap.py
+++ /dev/null
@@ -1,697 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_info_center_trap
-short_description: Manages information center trap configuration on HUAWEI CloudEngine switches.
-description:
- - Manages information center trap configurations on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- state:
- description:
- - Specify desired state of the resource.
- default: present
- choices: ['present','absent']
- trap_time_stamp:
- description:
- - Timestamp format of alarm information.
- choices: ['date_boot', 'date_second', 'date_tenthsecond', 'date_millisecond', 'shortdate_second',
- 'shortdate_tenthsecond', 'shortdate_millisecond', 'formatdate_second', 'formatdate_tenthsecond',
- 'formatdate_millisecond']
- trap_buff_enable:
- description:
- - Whether a trap buffer is enabled to output information.
- default: no_use
- choices: ['no_use','true','false']
- trap_buff_size:
- description:
- - Size of a trap buffer.
- The value is an integer ranging from 0 to 1024. The default value is 256.
- module_name:
- description:
- - Module name of the rule.
- The value is a string of 1 to 31 case-insensitive characters. The default value is default.
- Please use lower-case letter, such as [aaa, acl, arp, bfd].
- channel_id:
- description:
- - Number of a channel.
- The value is an integer ranging from 0 to 9. The default value is 0.
- trap_enable:
- description:
- - Whether a device is enabled to output alarms.
- default: no_use
- choices: ['no_use','true','false']
- trap_level:
- description:
- - Trap level permitted to output.
- choices: ['emergencies', 'alert', 'critical', 'error', 'warning', 'notification',
- 'informational', 'debugging']
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine info center trap test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Config trap buffer"
- ce_info_center_trap:
- state: present
- trap_buff_enable: true
- trap_buff_size: 768
- provider: "{{ cli }}"
-
- - name: "Undo trap buffer"
- ce_info_center_trap:
- state: absent
- trap_buff_enable: true
- trap_buff_size: 768
- provider: "{{ cli }}"
-
- - name: "Config trap module log level"
- ce_info_center_trap:
- state: present
- module_name: aaa
- channel_id: 1
- trap_enable: true
- trap_level: error
- provider: "{{ cli }}"
-
- - name: "Undo trap module log level"
- ce_info_center_trap:
- state: absent
- module_name: aaa
- channel_id: 1
- trap_enable: true
- trap_level: error
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"state": "present", "trap_buff_enable": "true", "trap_buff_size": "768"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {"icTrapBuffEn": "false", "trapBuffSize": "256"}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"icTrapBuffEn": "true", "trapBuffSize": "768"}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["info-center trapbuffer", "info-center trapbuffer size 768"]
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-
-# get info center trap global
-CE_GET_TRAP_GLOBAL_HEADER = """
-
-
-
-"""
-CE_GET_TRAP_GLOBAL_TAIL = """
-
-
-
-"""
-# merge info center trap global
-CE_MERGE_TRAP_GLOBAL_HEADER = """
-
-
-
-"""
-CE_MERGE_TRAP_GLOBAL_TAIL = """
-
-
-
-"""
-
-# get info center trap source
-CE_GET_TRAP_SOURCE_HEADER = """
-
-
-
-
-"""
-CE_GET_TRAP_SOURCE_TAIL = """
-
-
-
-
-"""
-# merge info center trap source
-CE_MERGE_TRAP_SOURCE_HEADER = """
-
-
-
-
-"""
-CE_MERGE_TRAP_SOURCE_TAIL = """
-
-
-
-
-"""
-# delete info center trap source
-CE_DELETE_TRAP_SOURCE_HEADER = """
-
-
-
-
-"""
-CE_DELETE_TRAP_SOURCE_TAIL = """
-
-
-
-
-"""
-
-TIME_STAMP_DICT = {"date_boot": "boot",
- "date_second": "date precision-time second",
- "date_tenthsecond": "date precision-time tenth-second",
- "date_millisecond": "date precision-time millisecond",
- "shortdate_second": "short-date precision-time second",
- "shortdate_tenthsecond": "short-date precision-time tenth-second",
- "shortdate_millisecond": "short-date precision-time millisecond",
- "formatdate_second": "format-date precision-time second",
- "formatdate_tenthsecond": "format-date precision-time tenth-second",
- "formatdate_millisecond": "format-date precision-time millisecond"}
-
-CHANNEL_DEFAULT_TRAP_STATE = {"0": "true",
- "1": "true",
- "2": "true",
- "3": "true",
- "4": "false",
- "5": "true",
- "6": "true",
- "7": "true",
- "8": "true",
- "9": "true"}
-
-CHANNEL_DEFAULT_TRAP_LEVEL = {"0": "debugging",
- "1": "debugging",
- "2": "debugging",
- "3": "debugging",
- "4": "debugging",
- "5": "debugging",
- "6": "debugging",
- "7": "debugging",
- "8": "debugging",
- "9": "debugging"}
-
-
-class InfoCenterTrap(object):
- """ Manages info center trap configuration """
-
- def __init__(self, **kwargs):
- """ Init function """
-
- # argument spec
- argument_spec = kwargs["argument_spec"]
- self.spec = argument_spec
- self.module = AnsibleModule(argument_spec=self.spec, supports_check_mode=True)
-
- # module args
- self.state = self.module.params['state']
- self.trap_time_stamp = self.module.params['trap_time_stamp'] or None
- self.trap_buff_enable = self.module.params['trap_buff_enable']
- self.trap_buff_size = self.module.params['trap_buff_size'] or None
- self.module_name = self.module.params['module_name'] or None
- self.channel_id = self.module.params['channel_id'] or None
- self.trap_enable = self.module.params['trap_enable']
- self.trap_level = self.module.params['trap_level'] or None
-
- # cur config
- self.cur_global_cfg = dict()
- self.cur_source_cfg = dict()
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def netconf_get_config(self, conf_str):
- """ Netconf get config """
-
- xml_str = get_nc_config(self.module, conf_str)
-
- return xml_str
-
- def netconf_set_config(self, conf_str):
- """ Netconf set config """
-
- xml_str = set_nc_config(self.module, conf_str)
-
- return xml_str
-
- def check_global_args(self):
- """ Check global args """
-
- need_cfg = False
- find_flag = False
- self.cur_global_cfg["global_cfg"] = []
-
- if self.trap_time_stamp or self.trap_buff_enable != 'no_use' or self.trap_buff_size:
- if self.trap_buff_size:
- if self.trap_buff_size.isdigit():
- if int(self.trap_buff_size) < 0 or int(self.trap_buff_size) > 1024:
- self.module.fail_json(
- msg='Error: The value of trap_buff_size is out of [0 - 1024].')
- else:
- self.module.fail_json(
- msg='Error: The trap_buff_size is not digit.')
-
- conf_str = CE_GET_TRAP_GLOBAL_HEADER
-
- if self.trap_time_stamp:
- conf_str += ""
- if self.trap_buff_enable != 'no_use':
- conf_str += ""
- if self.trap_buff_size:
- conf_str += ""
-
- conf_str += CE_GET_TRAP_GLOBAL_TAIL
- recv_xml = self.netconf_get_config(conf_str=conf_str)
-
- if "" in recv_xml:
- find_flag = False
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- global_cfg = root.findall("syslog/globalParam")
- if global_cfg:
- for tmp in global_cfg:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["trapTimeStamp", "icTrapBuffEn", "trapBuffSize"]:
- tmp_dict[site.tag] = site.text
-
- self.cur_global_cfg["global_cfg"].append(tmp_dict)
-
- if self.cur_global_cfg["global_cfg"]:
- for tmp in self.cur_global_cfg["global_cfg"]:
- find_flag = True
-
- if self.trap_time_stamp and tmp.get("trapTimeStamp").lower() != self.trap_time_stamp:
- find_flag = False
- if self.trap_buff_enable != 'no_use' and tmp.get("icTrapBuffEn") != self.trap_buff_enable:
- find_flag = False
- if self.trap_buff_size and tmp.get("trapBuffSize") != self.trap_buff_size:
- find_flag = False
-
- if find_flag:
- break
- else:
- find_flag = False
-
- if self.state == "present":
- need_cfg = bool(not find_flag)
- else:
- need_cfg = bool(find_flag)
-
- self.cur_global_cfg["need_cfg"] = need_cfg
-
- def check_source_args(self):
- """ Check source args """
-
- need_cfg = False
- find_flag = False
- self.cur_source_cfg["source_cfg"] = list()
-
- if self.module_name:
- if len(self.module_name) < 1 or len(self.module_name) > 31:
- self.module.fail_json(
- msg='Error: The module_name is out of [1 - 31].')
-
- if not self.channel_id:
- self.module.fail_json(
- msg='Error: Please input channel_id at the same time.')
-
- if self.channel_id:
- if self.channel_id.isdigit():
- if int(self.channel_id) < 0 or int(self.channel_id) > 9:
- self.module.fail_json(
- msg='Error: The value of channel_id is out of [0 - 9].')
- else:
- self.module.fail_json(
- msg='Error: The channel_id is not digit.')
-
- conf_str = CE_GET_TRAP_SOURCE_HEADER
-
- if self.module_name != "default":
- conf_str += "%s" % self.module_name.upper()
- else:
- conf_str += "default"
-
- if self.channel_id:
- conf_str += ""
- if self.trap_enable != 'no_use':
- conf_str += ""
- if self.trap_level:
- conf_str += ""
-
- conf_str += CE_GET_TRAP_SOURCE_TAIL
- recv_xml = self.netconf_get_config(conf_str=conf_str)
-
- if "" in recv_xml:
- find_flag = False
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- source_cfg = root.findall("syslog/icSources/icSource")
- if source_cfg:
- for tmp in source_cfg:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["moduleName", "icChannelId", "trapEnFlg", "trapEnLevel"]:
- tmp_dict[site.tag] = site.text
-
- self.cur_source_cfg["source_cfg"].append(tmp_dict)
-
- if self.cur_source_cfg["source_cfg"]:
- for tmp in self.cur_source_cfg["source_cfg"]:
- find_flag = True
-
- if self.module_name and tmp.get("moduleName").lower() != self.module_name.lower():
- find_flag = False
- if self.channel_id and tmp.get("icChannelId") != self.channel_id:
- find_flag = False
- if self.trap_enable != 'no_use' and tmp.get("trapEnFlg") != self.trap_enable:
- find_flag = False
- if self.trap_level and tmp.get("trapEnLevel") != self.trap_level:
- find_flag = False
-
- if find_flag:
- break
- else:
- find_flag = False
-
- if self.state == "present":
- need_cfg = bool(not find_flag)
- else:
- need_cfg = bool(find_flag)
-
- self.cur_source_cfg["need_cfg"] = need_cfg
-
- def get_proposed(self):
- """ Get proposed """
-
- self.proposed["state"] = self.state
-
- if self.trap_time_stamp:
- self.proposed["trap_time_stamp"] = self.trap_time_stamp
- if self.trap_buff_enable != 'no_use':
- self.proposed["trap_buff_enable"] = self.trap_buff_enable
- if self.trap_buff_size:
- self.proposed["trap_buff_size"] = self.trap_buff_size
- if self.module_name:
- self.proposed["module_name"] = self.module_name
- if self.channel_id:
- self.proposed["channel_id"] = self.channel_id
- if self.trap_enable != 'no_use':
- self.proposed["trap_enable"] = self.trap_enable
- if self.trap_level:
- self.proposed["trap_level"] = self.trap_level
-
- def get_existing(self):
- """ Get existing """
-
- if self.cur_global_cfg["global_cfg"]:
- self.existing["global_cfg"] = self.cur_global_cfg["global_cfg"]
- if self.cur_source_cfg["source_cfg"]:
- self.existing["source_cfg"] = self.cur_source_cfg["source_cfg"]
-
- def get_end_state(self):
- """ Get end state """
-
- self.check_global_args()
- if self.cur_global_cfg["global_cfg"]:
- self.end_state["global_cfg"] = self.cur_global_cfg["global_cfg"]
-
- self.check_source_args()
- if self.cur_source_cfg["source_cfg"]:
- self.end_state["source_cfg"] = self.cur_source_cfg["source_cfg"]
-
- def merge_trap_global(self):
- """ Merge trap global """
-
- conf_str = CE_MERGE_TRAP_GLOBAL_HEADER
-
- if self.trap_time_stamp:
- conf_str += "%s" % self.trap_time_stamp.upper()
- if self.trap_buff_enable != 'no_use':
- conf_str += "%s" % self.trap_buff_enable
- if self.trap_buff_size:
- conf_str += "%s" % self.trap_buff_size
-
- conf_str += CE_MERGE_TRAP_GLOBAL_TAIL
-
- recv_xml = self.netconf_set_config(conf_str=conf_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Merge trap global failed.')
-
- if self.trap_time_stamp:
- cmd = "info-center timestamp trap " + TIME_STAMP_DICT.get(self.trap_time_stamp)
- self.updates_cmd.append(cmd)
- if self.trap_buff_enable != 'no_use':
- if self.trap_buff_enable == "true":
- cmd = "info-center trapbuffer"
- else:
- cmd = "undo info-center trapbuffer"
- self.updates_cmd.append(cmd)
- if self.trap_buff_size:
- cmd = "info-center trapbuffer size %s" % self.trap_buff_size
- self.updates_cmd.append(cmd)
-
- self.changed = True
-
- def delete_trap_global(self):
- """ Delete trap global """
-
- conf_str = CE_MERGE_TRAP_GLOBAL_HEADER
-
- if self.trap_time_stamp:
- conf_str += "DATE_SECOND"
- if self.trap_buff_enable != 'no_use':
- conf_str += "false"
- if self.trap_buff_size:
- conf_str += "256"
-
- conf_str += CE_MERGE_TRAP_GLOBAL_TAIL
-
- recv_xml = self.netconf_set_config(conf_str=conf_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: delete trap global failed.')
-
- if self.trap_time_stamp:
- cmd = "undo info-center timestamp trap"
- self.updates_cmd.append(cmd)
- if self.trap_buff_enable != 'no_use':
- cmd = "undo info-center trapbuffer"
- self.updates_cmd.append(cmd)
- if self.trap_buff_size:
- cmd = "undo info-center trapbuffer size"
- self.updates_cmd.append(cmd)
-
- self.changed = True
-
- def merge_trap_source(self):
- """ Merge trap source """
-
- conf_str = CE_MERGE_TRAP_SOURCE_HEADER
-
- if self.module_name:
- conf_str += "%s" % self.module_name
- if self.channel_id:
- conf_str += "%s" % self.channel_id
- if self.trap_enable != 'no_use':
- conf_str += "%s" % self.trap_enable
- if self.trap_level:
- conf_str += "%s" % self.trap_level
-
- conf_str += CE_MERGE_TRAP_SOURCE_TAIL
-
- recv_xml = self.netconf_set_config(conf_str=conf_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Merge trap source failed.')
-
- cmd = "info-center source"
- if self.module_name:
- cmd += " %s" % self.module_name
- if self.channel_id:
- cmd += " channel %s" % self.channel_id
- if self.trap_enable != 'no_use':
- if self.trap_enable == "true":
- cmd += " trap state on"
- else:
- cmd += " trap state off"
- if self.trap_level:
- cmd += " level %s" % self.trap_level
-
- self.updates_cmd.append(cmd)
- self.changed = True
-
- def delete_trap_source(self):
- """ Delete trap source """
-
- if self.trap_enable == 'no_use' and not self.trap_level:
- conf_str = CE_DELETE_TRAP_SOURCE_HEADER
- if self.module_name:
- conf_str += "%s" % self.module_name
- if self.channel_id:
- conf_str += "%s" % self.channel_id
- conf_str += CE_DELETE_TRAP_SOURCE_TAIL
- else:
- conf_str = CE_MERGE_TRAP_SOURCE_HEADER
- if self.module_name:
- conf_str += "%s" % self.module_name
- if self.channel_id:
- conf_str += "%s" % self.channel_id
- if self.trap_enable != 'no_use':
- conf_str += "%s" % CHANNEL_DEFAULT_TRAP_STATE.get(self.channel_id)
- if self.trap_level:
- conf_str += "%s" % CHANNEL_DEFAULT_TRAP_LEVEL.get(self.channel_id)
- conf_str += CE_MERGE_TRAP_SOURCE_TAIL
-
- recv_xml = self.netconf_set_config(conf_str=conf_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Delete trap source failed.')
-
- cmd = "undo info-center source"
- if self.module_name:
- cmd += " %s" % self.module_name
- if self.channel_id:
- cmd += " channel %s" % self.channel_id
- if self.trap_enable != 'no_use':
- cmd += " trap state"
- if self.trap_level:
- cmd += " level"
-
- self.updates_cmd.append(cmd)
- self.changed = True
-
- def work(self):
- """ work function """
-
- self.check_global_args()
- self.check_source_args()
- self.get_proposed()
- self.get_existing()
-
- if self.state == "present":
- if self.cur_global_cfg["need_cfg"]:
- self.merge_trap_global()
- if self.cur_source_cfg["need_cfg"]:
- self.merge_trap_source()
-
- else:
- if self.cur_global_cfg["need_cfg"]:
- self.delete_trap_global()
- if self.cur_source_cfg["need_cfg"]:
- self.delete_trap_source()
-
- self.get_end_state()
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- self.results['updates'] = self.updates_cmd
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- trap_time_stamp=dict(choices=['date_boot', 'date_second', 'date_tenthsecond',
- 'date_millisecond', 'shortdate_second', 'shortdate_tenthsecond',
- 'shortdate_millisecond', 'formatdate_second', 'formatdate_tenthsecond',
- 'formatdate_millisecond']),
- trap_buff_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- trap_buff_size=dict(type='str'),
- module_name=dict(type='str'),
- channel_id=dict(type='str'),
- trap_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- trap_level=dict(choices=['emergencies', 'alert', 'critical', 'error', 'warning', 'notification',
- 'informational', 'debugging'])
- )
-
- argument_spec.update(ce_argument_spec)
- module = InfoCenterTrap(argument_spec=argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_interface.py b/plugins/modules/network/cloudengine/ce_interface.py
deleted file mode 100644
index 930a27fd0b..0000000000
--- a/plugins/modules/network/cloudengine/ce_interface.py
+++ /dev/null
@@ -1,895 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_interface
-short_description: Manages physical attributes of interfaces on HUAWEI CloudEngine switches.
-description:
- - Manages physical attributes of interfaces on HUAWEI CloudEngine switches.
-author: QijunPan (@QijunPan)
-notes:
- - This module is also used to create logical interfaces such as
- vlanif and loopbacks.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- interface:
- description:
- - Full name of interface, i.e. 40GE1/0/10, Tunnel1.
- interface_type:
- description:
- - Interface type to be configured from the device.
- choices: ['ge', '10ge', '25ge', '4x10ge', '40ge', '100ge', 'vlanif', 'loopback', 'meth',
- 'eth-trunk', 'nve', 'tunnel', 'ethernet', 'fcoe-port', 'fabric-port', 'stack-port', 'null']
- admin_state:
- description:
- - Specifies the interface management status.
- The value is an enumerated type.
- up, An interface is in the administrative Up state.
- down, An interface is in the administrative Down state.
- choices: ['up', 'down']
- description:
- description:
- - Specifies an interface description.
- The value is a string of 1 to 242 case-sensitive characters,
- spaces supported but question marks (?) not supported.
- mode:
- description:
- - Manage Layer 2 or Layer 3 state of the interface.
- choices: ['layer2', 'layer3']
- l2sub:
- description:
- - Specifies whether the interface is a Layer 2 sub-interface.
- type: bool
- default: 'no'
- state:
- description:
- - Specify desired state of the resource.
- default: present
- choices: ['present', 'absent', 'default']
-'''
-
-EXAMPLES = '''
-- name: interface module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
- - name: Ensure an interface is a Layer 3 port and that it has the proper description
- ce_interface:
- interface: 10GE1/0/22
- description: 'Configured by Ansible'
- mode: layer3
- provider: '{{ cli }}'
-
- - name: Admin down an interface
- ce_interface:
- interface: 10GE1/0/22
- admin_state: down
- provider: '{{ cli }}'
-
- - name: Remove all tunnel interfaces
- ce_interface:
- interface_type: tunnel
- state: absent
- provider: '{{ cli }}'
-
- - name: Remove all logical interfaces
- ce_interface:
- interface_type: '{{ item }}'
- state: absent
- provider: '{{ cli }}'
- with_items:
- - loopback
- - eth-trunk
- - nve
-
- - name: Admin up all 10GE interfaces
- ce_interface:
- interface_type: 10GE
- admin_state: up
- provider: '{{ cli }}'
-'''
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"interface": "10GE1/0/10", "admin_state": "down"}
-existing:
- description: k/v pairs of existing switchport
- returned: always
- type: dict
- sample: {"admin_state": "up", "description": "None",
- "interface": "10GE1/0/10", "mode": "layer2"}
-end_state:
- description: k/v pairs of switchport after module execution
- returned: always
- type: dict
- sample: {"admin_state": "down", "description": "None",
- "interface": "10GE1/0/10", "mode": "layer2"}
-updates:
- description: command list sent to the device
- returned: always
- type: list
- sample: ["interface 10GE1/0/10", "shutdown"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-
-import re
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-
-CE_NC_GET_INTFS = """
-
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-"""
-
-
-CE_NC_GET_INTF = """
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_XML_CREATE_INTF = """
-
-
-
- %s
- %s
-
-
-
-"""
-
-CE_NC_XML_CREATE_INTF_L2SUB = """
-
-
-
- %s
- %s
- true
-
-
-
-"""
-
-CE_NC_XML_DELETE_INTF = """
-
-
-
- %s
-
-
-
-"""
-
-
-CE_NC_XML_MERGE_INTF_DES = """
-
-
-
- %s
- %s
-
-
-
-"""
-CE_NC_XML_MERGE_INTF_STATUS = """
-
-
-
- %s
- %s
-
-
-
-"""
-
-CE_NC_XML_MERGE_INTF_L2ENABLE = """
-
-
-
- %s
- %s
-
-
-
-"""
-
-ADMIN_STATE_TYPE = ('ge', '10ge', '25ge', '4x10ge', '40ge', '100ge',
- 'vlanif', 'meth', 'eth-trunk', 'vbdif', 'tunnel',
- 'ethernet', 'stack-port')
-
-SWITCH_PORT_TYPE = ('ge', '10ge', '25ge',
- '4x10ge', '40ge', '100ge', 'eth-trunk')
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- if interface.upper().startswith('GE'):
- return 'ge'
- elif interface.upper().startswith('10GE'):
- return '10ge'
- elif interface.upper().startswith('25GE'):
- return '25ge'
- elif interface.upper().startswith('4X10GE'):
- return '4x10ge'
- elif interface.upper().startswith('40GE'):
- return '40ge'
- elif interface.upper().startswith('100GE'):
- return '100ge'
- elif interface.upper().startswith('VLANIF'):
- return 'vlanif'
- elif interface.upper().startswith('LOOPBACK'):
- return 'loopback'
- elif interface.upper().startswith('METH'):
- return 'meth'
- elif interface.upper().startswith('ETH-TRUNK'):
- return 'eth-trunk'
- elif interface.upper().startswith('VBDIF'):
- return 'vbdif'
- elif interface.upper().startswith('NVE'):
- return 'nve'
- elif interface.upper().startswith('TUNNEL'):
- return 'tunnel'
- elif interface.upper().startswith('ETHERNET'):
- return 'ethernet'
- elif interface.upper().startswith('FCOE-PORT'):
- return 'fcoe-port'
- elif interface.upper().startswith('FABRIC-PORT'):
- return 'fabric-port'
- elif interface.upper().startswith('STACK-PORT'):
- return 'stack-port'
- elif interface.upper().startswith('NULL'):
- return 'null'
- else:
- return None
-
-
-def is_admin_state_enable(iftype):
- """admin state disable: loopback nve"""
-
- return bool(iftype in ADMIN_STATE_TYPE)
-
-
-def is_portswitch_enalbe(iftype):
- """"is portswitch? """
-
- return bool(iftype in SWITCH_PORT_TYPE)
-
-
-class Interface(object):
- """Manages physical attributes of interfaces."""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # interface info
- self.interface = self.module.params['interface']
- self.interface_type = self.module.params['interface_type']
- self.admin_state = self.module.params['admin_state']
- self.description = self.module.params['description']
- self.mode = self.module.params['mode']
- self.l2sub = self.module.params['l2sub']
- self.state = self.module.params['state']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
- self.intfs_info = dict() # all type interface info
- self.intf_info = dict() # one interface info
- self.intf_type = None # loopback tunnel ...
-
- def init_module(self):
- """init_module"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_interfaces_dict(self):
- """ get interfaces attributes dict."""
-
- intfs_info = dict()
- conf_str = CE_NC_GET_INTFS % self.interface_type
- recv_xml = get_nc_config(self.module, conf_str)
-
- if "" in recv_xml:
- return intfs_info
-
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- intfs = root.findall("ifm/interfaces/")
- if intfs:
- for intf in intfs:
- intf_type = intf.find("ifPhyType").text.lower()
- if intf_type:
- if not intfs_info.get(intf_type):
- intfs_info[intf_type] = list()
- intf_info = dict()
- for tmp in intf:
- intf_info[tmp.tag] = tmp.text
- intfs_info[intf_type].append(intf_info)
- return intfs_info
-
- def get_interface_dict(self, ifname):
- """ get one interface attributes dict."""
-
- intf_info = dict()
- conf_str = CE_NC_GET_INTF % ifname
- recv_xml = get_nc_config(self.module, conf_str)
-
- if "" in recv_xml:
- return intf_info
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- intfs = root.findall("ifm/interfaces/interface/")
- if intfs:
- for intf in intfs:
- intf_info[intf.tag] = intf.text
- return intf_info
-
- def create_interface(self, ifname, description, admin_state, mode, l2sub):
- """Create interface."""
-
- if l2sub:
- self.updates_cmd.append("interface %s mode l2" % ifname)
- else:
- self.updates_cmd.append("interface %s" % ifname)
-
- if not description:
- description = ''
- else:
- self.updates_cmd.append("description %s" % description)
-
- if l2sub:
- xmlstr = CE_NC_XML_CREATE_INTF_L2SUB % (ifname, description)
- else:
- xmlstr = CE_NC_XML_CREATE_INTF % (ifname, description)
- if admin_state and is_admin_state_enable(self.intf_type):
- xmlstr += CE_NC_XML_MERGE_INTF_STATUS % (ifname, admin_state)
- if admin_state == 'up':
- self.updates_cmd.append("undo shutdown")
- else:
- self.updates_cmd.append("shutdown")
- if mode and is_portswitch_enalbe(self.intf_type):
- if mode == "layer2":
- xmlstr += CE_NC_XML_MERGE_INTF_L2ENABLE % (ifname, 'enable')
- self.updates_cmd.append('portswitch')
- elif mode == "layer3":
- xmlstr += CE_NC_XML_MERGE_INTF_L2ENABLE % (ifname, 'disable')
- self.updates_cmd.append('undo portswitch')
-
- conf_str = ' ' + xmlstr + ' '
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "CREATE_INTF")
- self.changed = True
-
- def delete_interface(self, ifname):
- """ Delete interface."""
-
- xmlstr = CE_NC_XML_DELETE_INTF % ifname
- conf_str = ' ' + xmlstr + ' '
- self.updates_cmd.append('undo interface %s' % ifname)
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "DELETE_INTF")
- self.changed = True
-
- def delete_interfaces(self, iftype):
- """ Delete interfaces with type."""
-
- xmlstr = ''
- intfs_list = self.intfs_info.get(iftype.lower())
- if not intfs_list:
- return
-
- for intf in intfs_list:
- xmlstr += CE_NC_XML_DELETE_INTF % intf['ifName']
- self.updates_cmd.append('undo interface %s' % intf['ifName'])
-
- conf_str = ' ' + xmlstr + ' '
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "DELETE_INTFS")
- self.changed = True
-
- def merge_interface(self, ifname, description, admin_state, mode):
- """ Merge interface attributes."""
-
- xmlstr = ''
- change = False
- self.updates_cmd.append("interface %s" % ifname)
- if description and self.intf_info["ifDescr"] != description:
- xmlstr += CE_NC_XML_MERGE_INTF_DES % (ifname, description)
- self.updates_cmd.append("description %s" % description)
- change = True
-
- if admin_state and is_admin_state_enable(self.intf_type) \
- and self.intf_info["ifAdminStatus"] != admin_state:
- xmlstr += CE_NC_XML_MERGE_INTF_STATUS % (ifname, admin_state)
- change = True
- if admin_state == "up":
- self.updates_cmd.append("undo shutdown")
- else:
- self.updates_cmd.append("shutdown")
-
- if is_portswitch_enalbe(self.intf_type):
- if mode == "layer2" and self.intf_info["isL2SwitchPort"] != "true":
- xmlstr += CE_NC_XML_MERGE_INTF_L2ENABLE % (ifname, 'enable')
- self.updates_cmd.append("portswitch")
- change = True
- elif mode == "layer3" \
- and self.intf_info["isL2SwitchPort"] != "false":
- xmlstr += CE_NC_XML_MERGE_INTF_L2ENABLE % (ifname, 'disable')
- self.updates_cmd.append("undo portswitch")
- change = True
-
- if not change:
- return
-
- conf_str = ' ' + xmlstr + ' '
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "MERGE_INTF_ATTR")
- self.changed = True
-
- def merge_interfaces(self, iftype, description, admin_state, mode):
- """ Merge interface attributes by type."""
-
- xmlstr = ''
- change = False
- intfs_list = self.intfs_info.get(iftype.lower())
- if not intfs_list:
- return
-
- for intf in intfs_list:
- if_change = False
- self.updates_cmd.append("interface %s" % intf['ifName'])
- if description and intf["ifDescr"] != description:
- xmlstr += CE_NC_XML_MERGE_INTF_DES % (
- intf['ifName'], description)
- self.updates_cmd.append("description %s" % description)
- if_change = True
- if admin_state and is_admin_state_enable(self.intf_type)\
- and intf["ifAdminStatus"] != admin_state:
- xmlstr += CE_NC_XML_MERGE_INTF_STATUS % (
- intf['ifName'], admin_state)
- if_change = True
- if admin_state == "up":
- self.updates_cmd.append("undo shutdown")
- else:
- self.updates_cmd.append("shutdown")
-
- if is_portswitch_enalbe(self.intf_type):
- if mode == "layer2" \
- and intf["isL2SwitchPort"] != "true":
- xmlstr += CE_NC_XML_MERGE_INTF_L2ENABLE % (
- intf['ifName'], 'enable')
- self.updates_cmd.append("portswitch")
- if_change = True
- elif mode == "layer3" \
- and intf["isL2SwitchPort"] != "false":
- xmlstr += CE_NC_XML_MERGE_INTF_L2ENABLE % (
- intf['ifName'], 'disable')
- self.updates_cmd.append("undo portswitch")
- if_change = True
-
- if if_change:
- change = True
- else:
- self.updates_cmd.pop()
-
- if not change:
- return
-
- conf_str = ' ' + xmlstr + ' '
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "MERGE_INTFS_ATTR")
- self.changed = True
-
- def default_interface(self, ifname):
- """default_interface"""
-
- change = False
- xmlstr = ""
- self.updates_cmd.append("interface %s" % ifname)
- # set description default
- if self.intf_info["ifDescr"]:
- xmlstr += CE_NC_XML_MERGE_INTF_DES % (ifname, '')
- self.updates_cmd.append("undo description")
- change = True
-
- # set admin_status default
- if is_admin_state_enable(self.intf_type) \
- and self.intf_info["ifAdminStatus"] != 'up':
- xmlstr += CE_NC_XML_MERGE_INTF_STATUS % (ifname, 'up')
- self.updates_cmd.append("undo shutdown")
- change = True
-
- # set portswitch default
- if is_portswitch_enalbe(self.intf_type) \
- and self.intf_info["isL2SwitchPort"] != "true":
- xmlstr += CE_NC_XML_MERGE_INTF_L2ENABLE % (ifname, 'enable')
- self.updates_cmd.append("portswitch")
- change = True
-
- if not change:
- return
-
- conf_str = ' ' + xmlstr + ' '
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "SET_INTF_DEFAULT")
- self.changed = True
-
- def default_interfaces(self, iftype):
- """ Set interface config to default by type."""
-
- change = False
- xmlstr = ''
- intfs_list = self.intfs_info.get(iftype.lower())
- if not intfs_list:
- return
-
- for intf in intfs_list:
- if_change = False
- self.updates_cmd.append("interface %s" % intf['ifName'])
-
- # set description default
- if intf['ifDescr']:
- xmlstr += CE_NC_XML_MERGE_INTF_DES % (intf['ifName'], '')
- self.updates_cmd.append("undo description")
- if_change = True
-
- # set admin_status default
- if is_admin_state_enable(self.intf_type) and intf["ifAdminStatus"] != 'up':
- xmlstr += CE_NC_XML_MERGE_INTF_STATUS % (intf['ifName'], 'up')
- self.updates_cmd.append("undo shutdown")
- if_change = True
-
- # set portswitch default
- if is_portswitch_enalbe(self.intf_type) and intf["isL2SwitchPort"] != "true":
- xmlstr += CE_NC_XML_MERGE_INTF_L2ENABLE % (intf['ifName'], 'enable')
- self.updates_cmd.append("portswitch")
- if_change = True
-
- if if_change:
- change = True
- else:
- self.updates_cmd.pop()
-
- if not change:
- return
-
- conf_str = ' ' + xmlstr + ' '
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "SET_INTFS_DEFAULT")
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- if not self.interface and not self.interface_type:
- self.module.fail_json(
- msg='Error: Interface or interface_type must be set.')
- if self.interface and self.interface_type:
- self.module.fail_json(
- msg='Error: Interface or interface_type'
- ' can not be set at the same time.')
-
- # interface type check
- if self.interface:
- self.intf_type = get_interface_type(self.interface)
- if not self.intf_type:
- self.module.fail_json(
- msg='Error: interface name of %s'
- ' is error.' % self.interface)
-
- elif self.interface_type:
- self.intf_type = get_interface_type(self.interface_type)
- if not self.intf_type or self.intf_type != self.interface_type.replace(" ", "").lower():
- self.module.fail_json(
- msg='Error: interface type of %s'
- ' is error.' % self.interface_type)
-
- if not self.intf_type:
- self.module.fail_json(
- msg='Error: interface or interface type %s is error.')
-
- # shutdown check
- if not is_admin_state_enable(self.intf_type) \
- and self.state == "present" and self.admin_state == "down":
- self.module.fail_json(
- msg='Error: The %s interface can not'
- ' be shutdown.' % self.intf_type)
-
- # port switch mode check
- if not is_portswitch_enalbe(self.intf_type)\
- and self.mode and self.state == "present":
- self.module.fail_json(
- msg='Error: The %s interface can not manage'
- ' Layer 2 or Layer 3 state.' % self.intf_type)
-
- # check description len
- if self.description:
- if len(self.description) > 242 \
- or len(self.description.replace(' ', '')) < 1:
- self.module.fail_json(
- msg='Error: interface description '
- 'is not in the range from 1 to 242.')
- # check l2sub flag
- if self.l2sub:
- if not self.interface:
- self.module.fail_json(msg='Error: L2sub flag can not be set when there no interface set with.')
- if self.interface.count(".") != 1:
- self.module.fail_json(msg='Error: Interface name is invalid, it is not sub-interface.')
-
- def get_proposed(self):
- """get_proposed"""
-
- self.proposed['state'] = self.state
- if self.interface:
- self.proposed["interface"] = self.interface
- if self.interface_type:
- self.proposed["interface_type"] = self.interface_type
-
- if self.state == 'present':
- if self.description:
- self.proposed["description"] = self.description
- if self.mode:
- self.proposed["mode"] = self.mode
- if self.admin_state:
- self.proposed["admin_state"] = self.admin_state
- self.proposed["l2sub"] = self.l2sub
-
- elif self.state == 'default':
- if self.description:
- self.proposed["description"] = ""
- if is_admin_state_enable(self.intf_type) and self.admin_state:
- self.proposed["admin_state"] = self.admin_state
- if is_portswitch_enalbe(self.intf_type) and self.mode:
- self.proposed["mode"] = self.mode
-
- def get_existing(self):
- """get_existing"""
-
- if self.intf_info:
- self.existing["interface"] = self.intf_info["ifName"]
- if is_admin_state_enable(self.intf_type):
- self.existing["admin_state"] = self.intf_info["ifAdminStatus"]
- self.existing["description"] = self.intf_info["ifDescr"]
- if is_portswitch_enalbe(self.intf_type):
- if self.intf_info["isL2SwitchPort"] == "true":
- self.existing["mode"] = "layer2"
- else:
- self.existing["mode"] = "layer3"
-
- if self.intfs_info:
- intfs = self.intfs_info.get(self.intf_type.lower())
- for intf in intfs:
- intf_para = dict()
- if intf["ifAdminStatus"]:
- intf_para["admin_state"] = intf["ifAdminStatus"]
- intf_para["description"] = intf["ifDescr"]
-
- if intf["isL2SwitchPort"] == "true":
- intf_para["mode"] = "layer2"
- else:
- intf_para["mode"] = "layer3"
- self.existing[intf["ifName"]] = intf_para
-
- def get_end_state(self):
- """get_end_state"""
- if self.interface:
- end_info = self.get_interface_dict(self.interface)
- if end_info:
- self.end_state["interface"] = end_info["ifName"]
- if is_admin_state_enable(self.intf_type):
- self.end_state["admin_state"] = end_info["ifAdminStatus"]
- self.end_state["description"] = end_info["ifDescr"]
- if is_portswitch_enalbe(self.intf_type):
- if end_info["isL2SwitchPort"] == "true":
- self.end_state["mode"] = "layer2"
- else:
- self.end_state["mode"] = "layer3"
-
- if self.interface_type:
- end_info = self.get_interfaces_dict()
- intfs = end_info.get(self.intf_type.lower())
- for intf in intfs:
- intf_para = dict()
- if intf["ifAdminStatus"]:
- intf_para["admin_state"] = intf["ifAdminStatus"]
- intf_para["description"] = intf["ifDescr"]
-
- if intf["isL2SwitchPort"] == "true":
- intf_para["mode"] = "layer2"
- else:
- intf_para["mode"] = "layer3"
- self.end_state[intf["ifName"]] = intf_para
-
- def work(self):
- """worker"""
-
- self.check_params()
-
- # single interface config
- if self.interface:
- self.intf_info = self.get_interface_dict(self.interface)
- self.get_existing()
- if self.state == 'present':
- if not self.intf_info:
- # create interface
- self.create_interface(self.interface,
- self.description,
- self.admin_state,
- self.mode,
- self.l2sub)
- else:
- # merge interface
- if self.description or self.admin_state or self.mode:
- self.merge_interface(self.interface,
- self.description,
- self.admin_state,
- self.mode)
-
- elif self.state == 'absent':
- if self.intf_info:
- # delete interface
- self.delete_interface(self.interface)
- else:
- # interface does not exist
- self.module.fail_json(
- msg='Error: interface does not exist.')
-
- else: # default
- if not self.intf_info:
- # error, interface does not exist
- self.module.fail_json(
- msg='Error: interface does not exist.')
- else:
- self.default_interface(self.interface)
-
- # interface type config
- else:
- self.intfs_info = self.get_interfaces_dict()
- self.get_existing()
- if self.state == 'present':
- if self.intfs_info.get(self.intf_type.lower()):
- if self.description or self.admin_state or self.mode:
- self.merge_interfaces(self.intf_type,
- self.description,
- self.admin_state,
- self.mode)
- elif self.state == 'absent':
- # delete all interface of this type
- if self.intfs_info.get(self.intf_type.lower()):
- self.delete_interfaces(self.intf_type)
-
- else:
- # set interfaces config to default
- if self.intfs_info.get(self.intf_type.lower()):
- self.default_interfaces(self.intf_type)
- else:
- self.module.fail_json(
- msg='Error: no interface in this type.')
-
- self.get_proposed()
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """main"""
-
- argument_spec = dict(
- interface=dict(required=False, type='str'),
- admin_state=dict(choices=['up', 'down'], required=False),
- description=dict(required=False, default=None),
- mode=dict(choices=['layer2', 'layer3'], required=False),
- interface_type=dict(required=False),
- l2sub=dict(required=False, default=False, type='bool'),
- state=dict(choices=['absent', 'present', 'default'],
- default='present', required=False),
- )
-
- argument_spec.update(ce_argument_spec)
- interface = Interface(argument_spec)
- interface.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_interface_ospf.py b/plugins/modules/network/cloudengine/ce_interface_ospf.py
deleted file mode 100644
index 7e7e4f92a5..0000000000
--- a/plugins/modules/network/cloudengine/ce_interface_ospf.py
+++ /dev/null
@@ -1,797 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_interface_ospf
-short_description: Manages configuration of an OSPF interface instanceon HUAWEI CloudEngine switches.
-description:
- - Manages configuration of an OSPF interface instanceon HUAWEI CloudEngine switches.
-author: QijunPan (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- interface:
- description:
- - Full name of interface, i.e. 40GE1/0/10.
- required: true
- process_id:
- description:
- - Specifies a process ID.
- The value is an integer ranging from 1 to 4294967295.
- required: true
- area:
- description:
- - Ospf area associated with this ospf process.
- Valid values are a string, formatted as an IP address
- (i.e. "0.0.0.0") or as an integer between 1 and 4294967295.
- required: true
- cost:
- description:
- - The cost associated with this interface.
- Valid values are an integer in the range from 1 to 65535.
- hello_interval:
- description:
- - Time between sending successive hello packets.
- Valid values are an integer in the range from 1 to 65535.
- dead_interval:
- description:
- - Time interval an ospf neighbor waits for a hello
- packet before tearing down adjacencies. Valid values are an
- integer in the range from 1 to 235926000.
- silent_interface:
- description:
- - Setting to true will prevent this interface from receiving
- HELLO packets. Valid values are 'true' and 'false'.
- type: bool
- default: 'no'
- auth_mode:
- description:
- - Specifies the authentication type.
- choices: ['none', 'null', 'hmac-sha256', 'md5', 'hmac-md5', 'simple']
- auth_text_simple:
- description:
- - Specifies a password for simple authentication.
- The value is a string of 1 to 8 characters.
- auth_key_id:
- description:
- - Authentication key id when C(auth_mode) is 'hmac-sha256', 'md5' or 'hmac-md5.
- Valid value is an integer is in the range from 1 to 255.
- auth_text_md5:
- description:
- - Specifies a password for MD5, HMAC-MD5, or HMAC-SHA256 authentication.
- The value is a string of 1 to 255 case-sensitive characters, spaces not supported.
- state:
- description:
- - Determines whether the config should be present or not
- on the device.
- default: present
- choices: ['present','absent']
-'''
-
-EXAMPLES = '''
-- name: eth_trunk module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
- - name: Enables OSPF and sets the cost on an interface
- ce_interface_ospf:
- interface: 10GE1/0/30
- process_id: 1
- area: 100
- cost: 100
- provider: '{{ cli }}'
-
- - name: Sets the dead interval of the OSPF neighbor
- ce_interface_ospf:
- interface: 10GE1/0/30
- process_id: 1
- area: 100
- dead_interval: 100
- provider: '{{ cli }}'
-
- - name: Sets the interval for sending Hello packets on an interface
- ce_interface_ospf:
- interface: 10GE1/0/30
- process_id: 1
- area: 100
- hello_interval: 2
- provider: '{{ cli }}'
-
- - name: Disables an interface from receiving and sending OSPF packets
- ce_interface_ospf:
- interface: 10GE1/0/30
- process_id: 1
- area: 100
- silent_interface: true
- provider: '{{ cli }}'
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: verbose mode
- type: dict
- sample: {"process_id": "1", "area": "0.0.0.100", "interface": "10GE1/0/30", "cost": "100"}
-existing:
- description: k/v pairs of existing configuration
- returned: verbose mode
- type: dict
- sample: {"process_id": "1", "area": "0.0.0.100"}
-end_state:
- description: k/v pairs of configuration after module execution
- returned: verbose mode
- type: dict
- sample: {"process_id": "1", "area": "0.0.0.100", "interface": "10GE1/0/30",
- "cost": "100", "dead_interval": "40", "hello_interval": "10",
- "silent_interface": "false", "auth_mode": "none"}
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: ["interface 10GE1/0/30",
- "ospf enable 1 area 0.0.0.100",
- "ospf cost 100"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-CE_NC_GET_OSPF = """
-
-
-
-
-
- %s
-
-
-
-
- %s
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_XML_BUILD_PROCESS = """
-
-
-
-
-
- %s
-
-
- %s
- %s
-
-
-
-
-
-
-
-"""
-
-CE_NC_XML_BUILD_MERGE_INTF = """
-
-
- %s
-
-
-"""
-
-CE_NC_XML_BUILD_DELETE_INTF = """
-
-
- %s
-
-
-"""
-CE_NC_XML_SET_IF_NAME = """
- %s
-"""
-
-CE_NC_XML_SET_HELLO = """
- %s
-"""
-
-CE_NC_XML_SET_DEAD = """
- %s
-"""
-
-CE_NC_XML_SET_SILENT = """
- %s
-"""
-
-CE_NC_XML_SET_COST = """
- %s
-"""
-
-CE_NC_XML_SET_AUTH_MODE = """
- %s
-"""
-
-
-CE_NC_XML_SET_AUTH_TEXT_SIMPLE = """
- %s
-"""
-
-CE_NC_XML_SET_AUTH_MD5 = """
- %s
- %s
-"""
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- if interface.upper().startswith('GE'):
- return 'ge'
- elif interface.upper().startswith('10GE'):
- return '10ge'
- elif interface.upper().startswith('25GE'):
- return '25ge'
- elif interface.upper().startswith('4X10GE'):
- return '4x10ge'
- elif interface.upper().startswith('40GE'):
- return '40ge'
- elif interface.upper().startswith('100GE'):
- return '100ge'
- elif interface.upper().startswith('VLANIF'):
- return 'vlanif'
- elif interface.upper().startswith('LOOPBACK'):
- return 'loopback'
- elif interface.upper().startswith('METH'):
- return 'meth'
- elif interface.upper().startswith('ETH-TRUNK'):
- return 'eth-trunk'
- elif interface.upper().startswith('VBDIF'):
- return 'vbdif'
- elif interface.upper().startswith('NVE'):
- return 'nve'
- elif interface.upper().startswith('TUNNEL'):
- return 'tunnel'
- elif interface.upper().startswith('ETHERNET'):
- return 'ethernet'
- elif interface.upper().startswith('FCOE-PORT'):
- return 'fcoe-port'
- elif interface.upper().startswith('FABRIC-PORT'):
- return 'fabric-port'
- elif interface.upper().startswith('STACK-PORT'):
- return 'stack-port'
- elif interface.upper().startswith('NULL'):
- return 'null'
- else:
- return None
-
-
-def is_valid_v4addr(addr):
- """check is ipv4 addr is valid"""
-
- if not addr:
- return False
-
- if addr.find('.') != -1:
- addr_list = addr.split('.')
- if len(addr_list) != 4:
- return False
- for each_num in addr_list:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- return True
-
- return False
-
-
-class InterfaceOSPF(object):
- """
- Manages configuration of an OSPF interface instance.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.interface = self.module.params['interface']
- self.process_id = self.module.params['process_id']
- self.area = self.module.params['area']
- self.cost = self.module.params['cost']
- self.hello_interval = self.module.params['hello_interval']
- self.dead_interval = self.module.params['dead_interval']
- self.silent_interface = self.module.params['silent_interface']
- self.auth_mode = self.module.params['auth_mode']
- self.auth_text_simple = self.module.params['auth_text_simple']
- self.auth_key_id = self.module.params['auth_key_id']
- self.auth_text_md5 = self.module.params['auth_text_md5']
- self.state = self.module.params['state']
-
- # ospf info
- self.ospf_info = dict()
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def init_module(self):
- """init module"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def netconf_set_config(self, xml_str, xml_name):
- """netconf set config"""
-
- rcv_xml = set_nc_config(self.module, xml_str)
- if "" not in rcv_xml:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_area_ip(self):
- """convert integer to ip address"""
-
- if not self.area.isdigit():
- return self.area
-
- addr_int = ['0'] * 4
- addr_int[0] = str(((int(self.area) & 0xFF000000) >> 24) & 0xFF)
- addr_int[1] = str(((int(self.area) & 0x00FF0000) >> 16) & 0xFF)
- addr_int[2] = str(((int(self.area) & 0x0000FF00) >> 8) & 0XFF)
- addr_int[3] = str(int(self.area) & 0xFF)
-
- return '.'.join(addr_int)
-
- def get_ospf_dict(self):
- """ get one ospf attributes dict."""
-
- ospf_info = dict()
- conf_str = CE_NC_GET_OSPF % (
- self.process_id, self.get_area_ip(), self.interface)
- rcv_xml = get_nc_config(self.module, conf_str)
-
- if "" in rcv_xml:
- return ospf_info
-
- xml_str = rcv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get process base info
- root = ElementTree.fromstring(xml_str)
- ospfsite = root.find("ospfv2/ospfv2comm/ospfSites/ospfSite")
- if not ospfsite:
- self.module.fail_json(msg="Error: ospf process does not exist.")
-
- for site in ospfsite:
- if site.tag in ["processId", "routerId", "vrfName"]:
- ospf_info[site.tag] = site.text
-
- # get areas info
- ospf_info["areaId"] = ""
- areas = root.find(
- "ospfv2/ospfv2comm/ospfSites/ospfSite/areas/area")
- if areas:
- for area in areas:
- if area.tag == "areaId":
- ospf_info["areaId"] = area.text
- break
-
- # get interface info
- ospf_info["interface"] = dict()
- intf = root.find(
- "ospfv2/ospfv2comm/ospfSites/ospfSite/areas/area/interfaces/interface")
- if intf:
- for attr in intf:
- if attr.tag in ["ifName", "networkType",
- "helloInterval", "deadInterval",
- "silentEnable", "configCost",
- "authenticationMode", "authTextSimple",
- "keyId", "authTextMd5"]:
- ospf_info["interface"][attr.tag] = attr.text
-
- return ospf_info
-
- def set_ospf_interface(self):
- """set interface ospf enable, and set its ospf attributes"""
-
- xml_intf = CE_NC_XML_SET_IF_NAME % self.interface
-
- # ospf view
- self.updates_cmd.append("ospf %s" % self.process_id)
- self.updates_cmd.append("area %s" % self.get_area_ip())
- if self.silent_interface:
- xml_intf += CE_NC_XML_SET_SILENT % str(self.silent_interface).lower()
- if self.silent_interface:
- self.updates_cmd.append("silent-interface %s" % self.interface)
- else:
- self.updates_cmd.append("undo silent-interface %s" % self.interface)
-
- # interface view
- self.updates_cmd.append("interface %s" % self.interface)
- self.updates_cmd.append("ospf enable %s area %s" % (
- self.process_id, self.get_area_ip()))
- if self.cost:
- xml_intf += CE_NC_XML_SET_COST % self.cost
- self.updates_cmd.append("ospf cost %s" % self.cost)
- if self.hello_interval:
- xml_intf += CE_NC_XML_SET_HELLO % self.hello_interval
- self.updates_cmd.append("ospf timer hello %s" %
- self.hello_interval)
- if self.dead_interval:
- xml_intf += CE_NC_XML_SET_DEAD % self.dead_interval
- self.updates_cmd.append("ospf timer dead %s" % self.dead_interval)
- if self.auth_mode:
- xml_intf += CE_NC_XML_SET_AUTH_MODE % self.auth_mode
- if self.auth_mode == "none":
- self.updates_cmd.append("undo ospf authentication-mode")
- else:
- self.updates_cmd.append("ospf authentication-mode %s" % self.auth_mode)
- if self.auth_mode == "simple" and self.auth_text_simple:
- xml_intf += CE_NC_XML_SET_AUTH_TEXT_SIMPLE % self.auth_text_simple
- self.updates_cmd.pop()
- self.updates_cmd.append("ospf authentication-mode %s %s"
- % (self.auth_mode, self.auth_text_simple))
- elif self.auth_mode in ["hmac-sha256", "md5", "hmac-md5"] and self.auth_key_id:
- xml_intf += CE_NC_XML_SET_AUTH_MD5 % (
- self.auth_key_id, self.auth_text_md5)
- self.updates_cmd.pop()
- self.updates_cmd.append("ospf authentication-mode %s %s %s"
- % (self.auth_mode, self.auth_key_id, self.auth_text_md5))
- else:
- pass
-
- xml_str = CE_NC_XML_BUILD_PROCESS % (self.process_id,
- self.get_area_ip(),
- (CE_NC_XML_BUILD_MERGE_INTF % xml_intf))
- self.netconf_set_config(xml_str, "SET_INTERFACE_OSPF")
- self.changed = True
-
- def merge_ospf_interface(self):
- """merge interface ospf attributes"""
-
- intf_dict = self.ospf_info["interface"]
-
- # ospf view
- xml_ospf = ""
- if intf_dict.get("silentEnable") != str(self.silent_interface).lower():
- xml_ospf += CE_NC_XML_SET_SILENT % str(self.silent_interface).lower()
- self.updates_cmd.append("ospf %s" % self.process_id)
- self.updates_cmd.append("area %s" % self.get_area_ip())
- if self.silent_interface:
- self.updates_cmd.append("silent-interface %s" % self.interface)
- else:
- self.updates_cmd.append("undo silent-interface %s" % self.interface)
-
- # interface view
- xml_intf = ""
- self.updates_cmd.append("interface %s" % self.interface)
- if self.cost and intf_dict.get("configCost") != self.cost:
- xml_intf += CE_NC_XML_SET_COST % self.cost
- self.updates_cmd.append("ospf cost %s" % self.cost)
- if self.hello_interval and intf_dict.get("helloInterval") != self.hello_interval:
- xml_intf += CE_NC_XML_SET_HELLO % self.hello_interval
- self.updates_cmd.append("ospf timer hello %s" %
- self.hello_interval)
- if self.dead_interval and intf_dict.get("deadInterval") != self.dead_interval:
- xml_intf += CE_NC_XML_SET_DEAD % self.dead_interval
- self.updates_cmd.append("ospf timer dead %s" % self.dead_interval)
- if self.auth_mode:
- # NOTE: for security, authentication config will always be update
- xml_intf += CE_NC_XML_SET_AUTH_MODE % self.auth_mode
- if self.auth_mode == "none":
- self.updates_cmd.append("undo ospf authentication-mode")
- else:
- self.updates_cmd.append("ospf authentication-mode %s" % self.auth_mode)
- if self.auth_mode == "simple" and self.auth_text_simple:
- xml_intf += CE_NC_XML_SET_AUTH_TEXT_SIMPLE % self.auth_text_simple
- self.updates_cmd.pop()
- self.updates_cmd.append("ospf authentication-mode %s %s"
- % (self.auth_mode, self.auth_text_simple))
- elif self.auth_mode in ["hmac-sha256", "md5", "hmac-md5"] and self.auth_key_id:
- xml_intf += CE_NC_XML_SET_AUTH_MD5 % (
- self.auth_key_id, self.auth_text_md5)
- self.updates_cmd.pop()
- self.updates_cmd.append("ospf authentication-mode %s %s %s"
- % (self.auth_mode, self.auth_key_id, self.auth_text_md5))
- else:
- pass
- if not xml_intf:
- self.updates_cmd.pop() # remove command: interface
-
- if not xml_ospf and not xml_intf:
- return
-
- xml_sum = CE_NC_XML_SET_IF_NAME % self.interface
- xml_sum += xml_ospf + xml_intf
- xml_str = CE_NC_XML_BUILD_PROCESS % (self.process_id,
- self.get_area_ip(),
- (CE_NC_XML_BUILD_MERGE_INTF % xml_sum))
- self.netconf_set_config(xml_str, "MERGE_INTERFACE_OSPF")
- self.changed = True
-
- def unset_ospf_interface(self):
- """set interface ospf disable, and all its ospf attributes will be removed"""
-
- intf_dict = self.ospf_info["interface"]
- xml_sum = ""
- xml_intf = CE_NC_XML_SET_IF_NAME % self.interface
- if intf_dict.get("silentEnable") == "true":
- xml_sum += CE_NC_XML_BUILD_MERGE_INTF % (
- xml_intf + (CE_NC_XML_SET_SILENT % "false"))
- self.updates_cmd.append("ospf %s" % self.process_id)
- self.updates_cmd.append("area %s" % self.get_area_ip())
- self.updates_cmd.append(
- "undo silent-interface %s" % self.interface)
-
- xml_sum += CE_NC_XML_BUILD_DELETE_INTF % xml_intf
- xml_str = CE_NC_XML_BUILD_PROCESS % (self.process_id,
- self.get_area_ip(),
- xml_sum)
- self.netconf_set_config(xml_str, "DELETE_INTERFACE_OSPF")
- self.updates_cmd.append("undo ospf cost")
- self.updates_cmd.append("undo ospf timer hello")
- self.updates_cmd.append("undo ospf timer dead")
- self.updates_cmd.append("undo ospf authentication-mode")
- self.updates_cmd.append("undo ospf enable %s area %s" % (
- self.process_id, self.get_area_ip()))
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- self.interface = self.interface.replace(" ", "").upper()
-
- # interface check
- if not get_interface_type(self.interface):
- self.module.fail_json(msg="Error: interface is invalid.")
-
- # process_id check
- if not self.process_id.isdigit():
- self.module.fail_json(msg="Error: process_id is not digit.")
- if int(self.process_id) < 1 or int(self.process_id) > 4294967295:
- self.module.fail_json(msg="Error: process_id must be an integer between 1 and 4294967295.")
-
- # area check
- if self.area.isdigit():
- if int(self.area) < 0 or int(self.area) > 4294967295:
- self.module.fail_json(msg="Error: area id (Integer) must be between 0 and 4294967295.")
- else:
- if not is_valid_v4addr(self.area):
- self.module.fail_json(msg="Error: area id is invalid.")
-
- # area authentication check
- if self.state == "present":
- if self.auth_mode:
- if self.auth_mode == "simple":
- if self.auth_text_simple and len(self.auth_text_simple) > 8:
- self.module.fail_json(
- msg="Error: auth_text_simple is not in the range from 1 to 8.")
- if self.auth_mode in ["hmac-sha256", "hmac-sha256", "md5"]:
- if self.auth_key_id and not self.auth_text_md5:
- self.module.fail_json(
- msg='Error: auth_key_id and auth_text_md5 should be set at the same time.')
- if not self.auth_key_id and self.auth_text_md5:
- self.module.fail_json(
- msg='Error: auth_key_id and auth_text_md5 should be set at the same time.')
- if self.auth_key_id:
- if not self.auth_key_id.isdigit():
- self.module.fail_json(
- msg="Error: auth_key_id is not digit.")
- if int(self.auth_key_id) < 1 or int(self.auth_key_id) > 255:
- self.module.fail_json(
- msg="Error: auth_key_id is not in the range from 1 to 255.")
- if self.auth_text_md5 and len(self.auth_text_md5) > 255:
- self.module.fail_json(
- msg="Error: auth_text_md5 is not in the range from 1 to 255.")
- # cost check
- if self.cost:
- if not self.cost.isdigit():
- self.module.fail_json(msg="Error: cost is not digit.")
- if int(self.cost) < 1 or int(self.cost) > 65535:
- self.module.fail_json(
- msg="Error: cost is not in the range from 1 to 65535")
-
- # hello_interval check
- if self.hello_interval:
- if not self.hello_interval.isdigit():
- self.module.fail_json(
- msg="Error: hello_interval is not digit.")
- if int(self.hello_interval) < 1 or int(self.hello_interval) > 65535:
- self.module.fail_json(
- msg="Error: hello_interval is not in the range from 1 to 65535")
-
- # dead_interval check
- if self.dead_interval:
- if not self.dead_interval.isdigit():
- self.module.fail_json(msg="Error: dead_interval is not digit.")
- if int(self.dead_interval) < 1 or int(self.dead_interval) > 235926000:
- self.module.fail_json(
- msg="Error: dead_interval is not in the range from 1 to 235926000")
-
- def get_proposed(self):
- """get proposed info"""
-
- self.proposed["interface"] = self.interface
- self.proposed["process_id"] = self.process_id
- self.proposed["area"] = self.get_area_ip()
- self.proposed["cost"] = self.cost
- self.proposed["hello_interval"] = self.hello_interval
- self.proposed["dead_interval"] = self.dead_interval
- self.proposed["silent_interface"] = self.silent_interface
- if self.auth_mode:
- self.proposed["auth_mode"] = self.auth_mode
- if self.auth_mode == "simple":
- self.proposed["auth_text_simple"] = self.auth_text_simple
- if self.auth_mode in ["hmac-sha256", "hmac-sha256", "md5"]:
- self.proposed["auth_key_id"] = self.auth_key_id
- self.proposed["auth_text_md5"] = self.auth_text_md5
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- if not self.ospf_info:
- return
-
- if self.ospf_info["interface"]:
- self.existing["interface"] = self.interface
- self.existing["cost"] = self.ospf_info["interface"].get("configCost")
- self.existing["hello_interval"] = self.ospf_info["interface"].get("helloInterval")
- self.existing["dead_interval"] = self.ospf_info["interface"].get("deadInterval")
- self.existing["silent_interface"] = self.ospf_info["interface"].get("silentEnable")
- self.existing["auth_mode"] = self.ospf_info["interface"].get("authenticationMode")
- self.existing["auth_text_simple"] = self.ospf_info["interface"].get("authTextSimple")
- self.existing["auth_key_id"] = self.ospf_info["interface"].get("keyId")
- self.existing["auth_text_md5"] = self.ospf_info["interface"].get("authTextMd5")
- self.existing["process_id"] = self.ospf_info["processId"]
- self.existing["area"] = self.ospf_info["areaId"]
-
- def get_end_state(self):
- """get end state info"""
-
- ospf_info = self.get_ospf_dict()
- if not ospf_info:
- return
-
- if ospf_info["interface"]:
- self.end_state["interface"] = self.interface
- self.end_state["cost"] = ospf_info["interface"].get("configCost")
- self.end_state["hello_interval"] = ospf_info["interface"].get("helloInterval")
- self.end_state["dead_interval"] = ospf_info["interface"].get("deadInterval")
- self.end_state["silent_interface"] = ospf_info["interface"].get("silentEnable")
- self.end_state["auth_mode"] = ospf_info["interface"].get("authenticationMode")
- self.end_state["auth_text_simple"] = ospf_info["interface"].get("authTextSimple")
- self.end_state["auth_key_id"] = ospf_info["interface"].get("keyId")
- self.end_state["auth_text_md5"] = ospf_info["interface"].get("authTextMd5")
- self.end_state["process_id"] = ospf_info["processId"]
- self.end_state["area"] = ospf_info["areaId"]
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.ospf_info = self.get_ospf_dict()
- self.get_existing()
- self.get_proposed()
-
- # deal present or absent
- if self.state == "present":
- if not self.ospf_info or not self.ospf_info["interface"]:
- # create ospf area and set interface config
- self.set_ospf_interface()
- else:
- # merge interface ospf area config
- self.merge_ospf_interface()
- else:
- if self.ospf_info and self.ospf_info["interface"]:
- # delete interface ospf area config
- self.unset_ospf_interface()
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- interface=dict(required=True, type='str'),
- process_id=dict(required=True, type='str'),
- area=dict(required=True, type='str'),
- cost=dict(required=False, type='str'),
- hello_interval=dict(required=False, type='str'),
- dead_interval=dict(required=False, type='str'),
- silent_interface=dict(required=False, default=False, type='bool'),
- auth_mode=dict(required=False,
- choices=['none', 'null', 'hmac-sha256', 'md5', 'hmac-md5', 'simple'], type='str'),
- auth_text_simple=dict(required=False, type='str', no_log=True),
- auth_key_id=dict(required=False, type='str'),
- auth_text_md5=dict(required=False, type='str', no_log=True),
- state=dict(required=False, default='present',
- choices=['present', 'absent'])
- )
-
- argument_spec.update(ce_argument_spec)
- module = InterfaceOSPF(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_ip_interface.py b/plugins/modules/network/cloudengine/ce_ip_interface.py
deleted file mode 100644
index b1a9539c8f..0000000000
--- a/plugins/modules/network/cloudengine/ce_ip_interface.py
+++ /dev/null
@@ -1,739 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_ip_interface
-short_description: Manages L3 attributes for IPv4 and IPv6 interfaces on HUAWEI CloudEngine switches.
-description:
- - Manages Layer 3 attributes for IPv4 and IPv6 interfaces on HUAWEI CloudEngine switches.
-author: QijunPan (@QijunPan)
-notes:
- - Interface must already be a L3 port when using this module.
- - Logical interfaces (loopback, vlanif) must be created first.
- - C(mask) must be inserted in decimal format (i.e. 24) for
- both IPv6 and IPv4.
- - A single interface can have multiple IPv6 configured.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- interface:
- description:
- - Full name of interface, i.e. 40GE1/0/22, vlanif10.
- required: true
- addr:
- description:
- - IPv4 or IPv6 Address.
- mask:
- description:
- - Subnet mask for IPv4 or IPv6 Address in decimal format.
- version:
- description:
- - IP address version.
- default: v4
- choices: ['v4','v6']
- ipv4_type:
- description:
- - Specifies an address type.
- The value is an enumerated type.
- main, primary IP address.
- sub, secondary IP address.
- default: main
- choices: ['main','sub']
- state:
- description:
- - Specify desired state of the resource.
- default: present
- choices: ['present','absent']
-'''
-
-EXAMPLES = '''
-- name: ip_interface module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
- - name: Ensure ipv4 address is configured on 10GE1/0/22
- ce_ip_interface:
- interface: 10GE1/0/22
- version: v4
- state: present
- addr: 20.20.20.20
- mask: 24
- provider: '{{ cli }}'
-
- - name: Ensure ipv4 secondary address is configured on 10GE1/0/22
- ce_ip_interface:
- interface: 10GE1/0/22
- version: v4
- state: present
- addr: 30.30.30.30
- mask: 24
- ipv4_type: sub
- provider: '{{ cli }}'
-
- - name: Ensure ipv6 is enabled on 10GE1/0/22
- ce_ip_interface:
- interface: 10GE1/0/22
- version: v6
- state: present
- provider: '{{ cli }}'
-
- - name: Ensure ipv6 address is configured on 10GE1/0/22
- ce_ip_interface:
- interface: 10GE1/0/22
- version: v6
- state: present
- addr: 2001::db8:800:200c:cccb
- mask: 64
- provider: '{{ cli }}'
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"addr": "20.20.20.20", "interface": "10GE1/0/22", "mask": "24"}
-existing:
- description: k/v pairs of existing IP attributes on the interface
- returned: always
- type: dict
- sample: {"ipv4": [{"ifIpAddr": "11.11.11.11", "subnetMask": "255.255.0.0", "addrType": "main"}],
- "interface": "10GE1/0/22"}
-end_state:
- description: k/v pairs of IP attributes after module execution
- returned: always
- type: dict
- sample: {"ipv4": [{"ifIpAddr": "20.20.20.20", "subnetMask": "255.255.255.0", "addrType": "main"}],
- "interface": "10GE1/0/22"}
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: ["interface 10GE1/0/22", "ip address 20.20.20.20 24"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-
-CE_NC_GET_INTF = """
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_ADD_IPV4 = """
-
-
-
-
- %s
-
-
-
- %s
- %s
- %s
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_IPV4 = """
-
-
-
-
- %s
-
-
-
- %s
- %s
- main
-
-
- %s
- %s
- main
-
-
-
-
-
-
-
-"""
-
-
-CE_NC_DEL_IPV4 = """
-
-
-
-
- %s
-
-
-
- %s
- %s
- %s
-
-
-
-
-
-
-
-"""
-
-CE_NC_ADD_IPV6 = """
-
-
-
-
- %s
-
-
-
- %s
- %s
- global
-
-
-
-
-
-
-
-"""
-
-CE_NC_DEL_IPV6 = """
-
-
-
-
- %s
-
-
-
- %s
- %s
- global
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_IPV6_ENABLE = """
-
-
-
-
- %s
-
- %s
-
-
-
-
-
-"""
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- if interface.upper().startswith('GE'):
- return 'ge'
- elif interface.upper().startswith('10GE'):
- return '10ge'
- elif interface.upper().startswith('25GE'):
- return '25ge'
- elif interface.upper().startswith('4X10GE'):
- return '4x10ge'
- elif interface.upper().startswith('40GE'):
- return '40ge'
- elif interface.upper().startswith('100GE'):
- return '100ge'
- elif interface.upper().startswith('VLANIF'):
- return 'vlanif'
- elif interface.upper().startswith('LOOPBACK'):
- return 'loopback'
- elif interface.upper().startswith('METH'):
- return 'meth'
- elif interface.upper().startswith('ETH-TRUNK'):
- return 'eth-trunk'
- elif interface.upper().startswith('VBDIF'):
- return 'vbdif'
- elif interface.upper().startswith('NVE'):
- return 'nve'
- elif interface.upper().startswith('TUNNEL'):
- return 'tunnel'
- elif interface.upper().startswith('ETHERNET'):
- return 'ethernet'
- elif interface.upper().startswith('FCOE-PORT'):
- return 'fcoe-port'
- elif interface.upper().startswith('FABRIC-PORT'):
- return 'fabric-port'
- elif interface.upper().startswith('STACK-PORT'):
- return 'stack-port'
- elif interface.upper().startswith('NULL'):
- return 'null'
- else:
- return None
-
-
-def is_valid_v4addr(addr):
- """check is ipv4 addr is valid"""
-
- if not addr:
- return False
-
- if addr.find('.') != -1:
- addr_list = addr.split('.')
- if len(addr_list) != 4:
- return False
- for each_num in addr_list:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- return True
-
- return False
-
-
-class IpInterface(object):
- """
- Manages L3 attributes for IPv4 and IPv6 interfaces.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.__init_module__()
-
- # module input info]
- self.interface = self.module.params['interface']
- self.addr = self.module.params['addr']
- self.mask = self.module.params['mask']
- self.version = self.module.params['version']
- self.ipv4_type = self.module.params['ipv4_type']
- self.state = self.module.params['state']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
- # interface info
- self.intf_info = dict()
- self.intf_type = None
-
- def __init_module__(self):
- """ init module """
-
- required_if = [("version", "v4", ("addr", "mask"))]
- required_together = [("addr", "mask")]
- self.module = AnsibleModule(
- argument_spec=self.spec,
- required_if=required_if,
- required_together=required_together,
- supports_check_mode=True
- )
-
- def netconf_set_config(self, xml_str, xml_name):
- """ netconf set config """
-
- rcv_xml = set_nc_config(self.module, xml_str)
- if "" not in rcv_xml:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_interface_dict(self, ifname):
- """ get one interface attributes dict."""
-
- intf_info = dict()
- conf_str = CE_NC_GET_INTF % ifname
- rcv_xml = get_nc_config(self.module, conf_str)
-
- if "" in rcv_xml:
- return intf_info
-
- # get interface base info
- intf = re.findall(
- r'.*(.*).*\s*'
- r'(.*).*', rcv_xml)
-
- if intf:
- intf_info = dict(ifName=intf[0][0],
- isL2SwitchPort=intf[0][1])
-
- # get interface ipv4 address info
- ipv4_info = re.findall(
- r'.*(.*).*\s*(.*)'
- r'.*\s*(.*).*', rcv_xml)
- intf_info["am4CfgAddr"] = list()
- for info in ipv4_info:
- intf_info["am4CfgAddr"].append(
- dict(ifIpAddr=info[0], subnetMask=info[1], addrType=info[2]))
-
- # get interface ipv6 address info
- ipv6_info = re.findall(
- r'.*.*\s*(.*).*', rcv_xml)
- if not ipv6_info:
- self.module.fail_json(msg='Error: Fail to get interface %s IPv6 state.' % self.interface)
- else:
- intf_info["enableFlag"] = ipv6_info[0]
-
- # get interface ipv6 enable info
- ipv6_info = re.findall(
- r'.*(.*).*\s*(.*)'
- r'.*\s*(.*).*', rcv_xml)
-
- intf_info["am6CfgAddr"] = list()
- for info in ipv6_info:
- intf_info["am6CfgAddr"].append(
- dict(ifIp6Addr=info[0], addrPrefixLen=info[1], addrType6=info[2]))
-
- return intf_info
-
- def convert_len_to_mask(self, masklen):
- """convert mask length to ip address mask, i.e. 24 to 255.255.255.0"""
-
- mask_int = ["0"] * 4
- length = int(masklen)
-
- if length > 32:
- self.module.fail_json(msg='Error: IPv4 ipaddress mask length is invalid.')
- if length < 8:
- mask_int[0] = str(int((0xFF << (8 - length % 8)) & 0xFF))
- if length >= 8:
- mask_int[0] = '255'
- mask_int[1] = str(int((0xFF << (16 - (length % 16))) & 0xFF))
- if length >= 16:
- mask_int[1] = '255'
- mask_int[2] = str(int((0xFF << (24 - (length % 24))) & 0xFF))
- if length >= 24:
- mask_int[2] = '255'
- mask_int[3] = str(int((0xFF << (32 - (length % 32))) & 0xFF))
- if length == 32:
- mask_int[3] = '255'
-
- return '.'.join(mask_int)
-
- def is_ipv4_exist(self, addr, maskstr, ipv4_type):
- """"Check IPv4 address exist"""
-
- addrs = self.intf_info["am4CfgAddr"]
- if not addrs:
- return False
-
- for address in addrs:
- if address["ifIpAddr"] == addr:
- return address["subnetMask"] == maskstr and address["addrType"] == ipv4_type
- return False
-
- def get_ipv4_main_addr(self):
- """get IPv4 main address"""
-
- addrs = self.intf_info["am4CfgAddr"]
- if not addrs:
- return None
-
- for address in addrs:
- if address["addrType"] == "main":
- return address
-
- return None
-
- def is_ipv6_exist(self, addr, masklen):
- """Check IPv6 address exist"""
-
- addrs = self.intf_info["am6CfgAddr"]
- if not addrs:
- return False
-
- for address in addrs:
- if address["ifIp6Addr"] == addr.upper():
- if address["addrPrefixLen"] == masklen and address["addrType6"] == "global":
- return True
- else:
- self.module.fail_json(
- msg="Error: Input IPv6 address or mask is invalid.")
-
- return False
-
- def set_ipv4_addr(self, ifname, addr, mask, ipv4_type):
- """Set interface IPv4 address"""
-
- if not addr or not mask or not type:
- return
-
- maskstr = self.convert_len_to_mask(mask)
- if self.state == "present":
- if not self.is_ipv4_exist(addr, maskstr, ipv4_type):
- # primary IP address
- if ipv4_type == "main":
- main_addr = self.get_ipv4_main_addr()
- if not main_addr:
- # no ipv4 main address in this interface
- xml_str = CE_NC_ADD_IPV4 % (ifname, addr, maskstr, ipv4_type)
- self.netconf_set_config(xml_str, "ADD_IPV4_ADDR")
- else:
- # remove old address and set new
- xml_str = CE_NC_MERGE_IPV4 % (ifname, main_addr["ifIpAddr"],
- main_addr["subnetMask"],
- addr, maskstr)
- self.netconf_set_config(xml_str, "MERGE_IPV4_ADDR")
- # secondary IP address
- else:
- xml_str = CE_NC_ADD_IPV4 % (ifname, addr, maskstr, ipv4_type)
- self.netconf_set_config(xml_str, "ADD_IPV4_ADDR")
-
- self.updates_cmd.append("interface %s" % ifname)
- if ipv4_type == "main":
- self.updates_cmd.append("ip address %s %s" % (addr, maskstr))
- else:
- self.updates_cmd.append("ip address %s %s sub" % (addr, maskstr))
- self.changed = True
- else:
- if self.is_ipv4_exist(addr, maskstr, ipv4_type):
- xml_str = CE_NC_DEL_IPV4 % (ifname, addr, maskstr, ipv4_type)
- self.netconf_set_config(xml_str, "DEL_IPV4_ADDR")
- self.updates_cmd.append("interface %s" % ifname)
- if ipv4_type == "main":
- self.updates_cmd.append("undo ip address %s %s" % (addr, maskstr))
- else:
- self.updates_cmd.append("undo ip address %s %s sub" % (addr, maskstr))
- self.changed = True
-
- def set_ipv6_addr(self, ifname, addr, mask):
- """Set interface IPv6 address"""
-
- if not addr or not mask:
- return
-
- if self.state == "present":
- self.updates_cmd.append("interface %s" % ifname)
- if self.intf_info["enableFlag"] == "false":
- xml_str = CE_NC_MERGE_IPV6_ENABLE % (ifname, "true")
- self.netconf_set_config(xml_str, "SET_IPV6_ENABLE")
- self.updates_cmd.append("ipv6 enable")
- self.changed = True
-
- if not self.is_ipv6_exist(addr, mask):
- xml_str = CE_NC_ADD_IPV6 % (ifname, addr, mask)
- self.netconf_set_config(xml_str, "ADD_IPV6_ADDR")
-
- self.updates_cmd.append("ipv6 address %s %s" % (addr, mask))
- self.changed = True
-
- if not self.changed:
- self.updates_cmd.pop()
- else:
- if self.is_ipv6_exist(addr, mask):
- xml_str = CE_NC_DEL_IPV6 % (ifname, addr, mask)
- self.netconf_set_config(xml_str, "DEL_IPV6_ADDR")
- self.updates_cmd.append("interface %s" % ifname)
- self.updates_cmd.append(
- "undo ipv6 address %s %s" % (addr, mask))
- self.changed = True
-
- def set_ipv6_enable(self, ifname):
- """Set interface IPv6 enable"""
-
- if self.state == "present":
- if self.intf_info["enableFlag"] == "false":
- xml_str = CE_NC_MERGE_IPV6_ENABLE % (ifname, "true")
- self.netconf_set_config(xml_str, "SET_IPV6_ENABLE")
- self.updates_cmd.append("interface %s" % ifname)
- self.updates_cmd.append("ipv6 enable")
- self.changed = True
- else:
- if self.intf_info["enableFlag"] == "true":
- xml_str = CE_NC_MERGE_IPV6_ENABLE % (ifname, "false")
- self.netconf_set_config(xml_str, "SET_IPV6_DISABLE")
- self.updates_cmd.append("interface %s" % ifname)
- self.updates_cmd.append("undo ipv6 enable")
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- # check interface type
- if self.interface:
- self.intf_type = get_interface_type(self.interface)
- if not self.intf_type:
- self.module.fail_json(
- msg='Error: Interface name of %s '
- 'is error.' % self.interface)
-
- # ipv4 addr and mask check
- if self.version == "v4":
- if not is_valid_v4addr(self.addr):
- self.module.fail_json(
- msg='Error: The %s is not a valid address.' % self.addr)
- if not self.mask.isdigit():
- self.module.fail_json(msg='Error: mask is invalid.')
- if int(self.mask) > 32 or int(self.mask) < 1:
- self.module.fail_json(
- msg='Error: mask must be an integer between 1 and 32.')
-
- # ipv6 mask check
- if self.version == "v6":
- if self.addr:
- if not self.mask.isdigit():
- self.module.fail_json(msg='Error: mask is invalid.')
- if int(self.mask) > 128 or int(self.mask) < 1:
- self.module.fail_json(
- msg='Error: mask must be an integer between 1 and 128.')
-
- # interface and layer3 check
- self.intf_info = self.get_interface_dict(self.interface)
- if not self.intf_info:
- self.module.fail_json(msg='Error: interface %s does not exist.' % self.interface)
-
- if self.intf_info["isL2SwitchPort"] == "true":
- self.module.fail_json(msg='Error: interface %s is layer2.' % self.interface)
-
- def get_proposed(self):
- """get proposed info"""
-
- self.proposed["state"] = self.state
- self.proposed["addr"] = self.addr
- self.proposed["mask"] = self.mask
- self.proposed["ipv4_type"] = self.ipv4_type
- self.proposed["version"] = self.version
- self.proposed["interface"] = self.interface
-
- def get_existing(self):
- """get existing info"""
-
- self.existing["interface"] = self.interface
- self.existing["ipv4addr"] = self.intf_info["am4CfgAddr"]
- self.existing["ipv6addr"] = self.intf_info["am6CfgAddr"]
- self.existing["ipv6enalbe"] = self.intf_info["enableFlag"]
-
- def get_end_state(self):
- """get end state info"""
-
- intf_info = self.get_interface_dict(self.interface)
- self.end_state["interface"] = self.interface
- self.end_state["ipv4addr"] = intf_info["am4CfgAddr"]
- self.end_state["ipv6addr"] = intf_info["am6CfgAddr"]
- self.end_state["ipv6enalbe"] = intf_info["enableFlag"]
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.get_existing()
- self.get_proposed()
-
- # deal present or absent
- if self.version == "v4":
- self.set_ipv4_addr(self.interface, self.addr, self.mask, self.ipv4_type)
- else:
- if not self.addr and not self.mask:
- self.set_ipv6_enable(self.interface)
- else:
- self.set_ipv6_addr(self.interface, self.addr, self.mask)
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- interface=dict(required=True),
- addr=dict(required=False),
- version=dict(required=False, choices=['v4', 'v6'],
- default='v4'),
- mask=dict(type='str', required=False),
- ipv4_type=dict(required=False, choices=['main', 'sub'], default='main'),
- state=dict(required=False, default='present',
- choices=['present', 'absent'])
- )
-
- argument_spec.update(ce_argument_spec)
- module = IpInterface(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_is_is_instance.py b/plugins/modules/network/cloudengine/ce_is_is_instance.py
deleted file mode 100644
index 555c5ba778..0000000000
--- a/plugins/modules/network/cloudengine/ce_is_is_instance.py
+++ /dev/null
@@ -1,330 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: ce_is_is_instance
-author: xuxiaowei0512 (@CloudEngine-Ansible)
-short_description: Manages isis process id configuration on HUAWEI CloudEngine devices.
-description:
- - Manages isis process id, creates a isis instance id or deletes a process id on HUAWEI CloudEngine devices.
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - This module works with connection C(netconf).
-options:
- instance_id:
- description:
- - Specifies the id of a isis process.The value is a number of 1 to 4294967295.
- required: true
- type: int
- vpn_name:
- description:
- - VPN Instance, associate the VPN instance with the corresponding IS-IS process.
- type: str
- state:
- description:
- - Determines whether the config should be present or not on the device.
- default: present
- type: str
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = r'''
- - name: Set isis process
- ce_is_is_instance:
- instance_id: 3
- state: present
-
- - name: Unset isis process
- ce_is_is_instance:
- instance_id: 3
- state: absent
-
- - name: check isis process
- ce_is_is_instance:
- instance_id: 4294967296
- state: present
-
- - name: Set vpn name
- ce_is_is_instance:
- instance_id: 22
- vpn_name: vpn1
- state: present
-
- - name: check vpn name
- ce_is_is_instance:
- instance_id: 22
- vpn_name: vpn1234567896321452212221556asdasdasdasdsadvdv
- state: present
-'''
-
-RETURN = r'''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "instance_id": 1,
- "vpn_name": null
- }
-existing:
- description: k/v pairs of existing configuration
- returned: always
- type: dict
- sample: {
- "session": {}
- }
-end_state:
- description: k/v pairs of configuration after module execution
- returned: always
- type: dict
- sample: {
- "session": {
- "instance_id": 1,
- "vpn_name": null
- }
- }
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: [
- "isis 1"
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config
-
-CE_NC_GET_ISIS = """
-
-
- %s
-
-
-"""
-
-CE_NC_GET_ISIS_INSTANCE = """
-
-
- %s
-
-
-
-"""
-
-
-def is_valid_ip_vpn(vpname):
- """check ip vpn"""
-
- if not vpname:
- return False
-
- if vpname == "_public_":
- return False
-
- if len(vpname) < 1 or len(vpname) > 31:
- return False
-
- return True
-
-
-class ISIS_Instance(object):
- """Manages ISIS Instance"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.__init_module__()
-
- # module input info
- self.instance_id = self.module.params['instance_id']
- self.vpn_name = self.module.params['vpn_name']
- self.state = self.module.params['state']
-
- # state
- self.changed = False
- self.isis_dict = dict()
- self.updates_cmd = list()
- self.commands = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def __init_module__(self):
- """init module"""
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def get_isis_dict(self):
- """isis config dict"""
- isis_dict = dict()
- isis_dict["instance"] = dict()
- conf_str = CE_NC_GET_ISIS % (
- (CE_NC_GET_ISIS_INSTANCE % self.instance_id))
-
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return isis_dict
-
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
-
- # get isis info
- glb = root.find("isiscomm/isSites/isSite")
- if glb:
- for attr in glb:
- isis_dict["instance"][attr.tag] = attr.text
-
- return isis_dict
-
- def config_session(self):
- """configures isis"""
- xml_str = ""
- instance = self.isis_dict["instance"]
- if not self.instance_id:
- return xml_str
-
- if self.state == "present":
- xml_str = "%s" % self.instance_id
- self.updates_cmd.append("isis %s" % self.instance_id)
-
- if self.vpn_name:
- xml_str += "%s" % self.vpn_name
- self.updates_cmd.append("vpn-instance %s" % self.vpn_name)
- else:
- # absent
- if self.instance_id and str(self.instance_id) == instance.get("instanceId"):
- xml_str = "%s" % self.instance_id
- self.updates_cmd.append("undo isis %s" % self.instance_id)
-
- if self.state == "present":
- return '' + xml_str + ''
- else:
- if xml_str:
- return '' + xml_str + ''
-
- def netconf_load_config(self, xml_str):
- """load isis config by netconf"""
-
- if not xml_str:
- return
-
- xml_cfg = """
-
-
- %s
-
- """ % xml_str
- set_nc_config(self.module, xml_cfg)
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- # check instance id
- if not self.instance_id:
- self.module.fail_json(msg="Error: Missing required arguments: instance_id.")
-
- if self.instance_id:
- if self.instance_id < 1 or self.instance_id > 4294967295:
- self.module.fail_json(msg="Error: Instance id is not ranges from 1 to 4294967295.")
-
- # check vpn_name
- if self.vpn_name:
- if not is_valid_ip_vpn(self.vpn_name):
- self.module.fail_json(msg="Error: Session vpn_name is invalid.")
-
- def get_proposed(self):
- """get proposed info"""
- # base config
- self.proposed["instance_id"] = self.instance_id
- self.proposed["vpn_name"] = self.vpn_name
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- if not self.isis_dict:
- self.existing["instance"] = None
-
- self.existing["instance"] = self.isis_dict.get("instance")
-
- def get_end_state(self):
- """get end state info"""
-
- isis_dict = self.get_isis_dict()
- if not isis_dict:
- self.end_state["instance"] = None
-
- self.end_state["instance"] = isis_dict.get("instance")
-
- if self.end_state == self.existing:
- self.changed = False
-
- def work(self):
- """worker"""
- self.check_params()
- self.isis_dict = self.get_isis_dict()
- self.get_existing()
- self.get_proposed()
-
- # deal present or absent
- xml_str = ''
- if self.instance_id:
- cfg_str = self.config_session()
- if cfg_str:
- xml_str += cfg_str
-
- # update to device
- if xml_str:
- self.netconf_load_config(xml_str)
- self.changed = True
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
- argument_spec = dict(
- instance_id=dict(required=True, type='int'),
- vpn_name=dict(required=False, type='str'),
- state=dict(required=False, default='present', choices=['present', 'absent'])
- )
-
- module = ISIS_Instance(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_is_is_interface.py b/plugins/modules/network/cloudengine/ce_is_is_interface.py
deleted file mode 100644
index 41e47d0243..0000000000
--- a/plugins/modules/network/cloudengine/ce_is_is_interface.py
+++ /dev/null
@@ -1,788 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_is_is_interface
-author: xuxiaowei0512 (@CloudEngine-Ansible)
-short_description: Manages isis interface configuration on HUAWEI CloudEngine devices.
-description:
- - Manages isis process id, creates a isis instance id or deletes a process id on HUAWEI CloudEngine devices.
-notes:
- - Interface must already be a L3 port when using this module.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - This module works with connection C(netconf).
-options:
- instance_id:
- description:
- - Specifies the id of a isis process.
- The value is a number of 1 to 4294967295.
- required: true
- type: int
- ifname:
- description:
- - A L3 interface.
- required: true
- type: str
- leveltype:
- description:
- - level type for three types.
- type: str
- choices: ['level_1', 'level_2', 'level_1_2']
- level1dispriority:
- description:
- - the dispriority of the level1.
- The value is a number of 1 to 127.
- type: int
- level2dispriority:
- description:
- - the dispriority of the level1.
- The value is a number of 1 to 127.
- type: int
- silentenable:
- description:
- - enable the interface can send isis message.
- The value is a bool type.
- type: bool
- silentcost:
- description:
- - Specifies whether the routing cost of the silent interface is 0.
- The value is a bool type.
- type: bool
- typep2penable:
- description:
- - Simulate the network type of the interface as P2P.
- The value is a bool type.
- type: bool
- snpacheck:
- description:
- - Enable SNPA check for LSPs and SNPs.
- The value is a bool type.
- type: bool
- p2pnegotiationmode:
- description:
- - Set the P2P neighbor negotiation type.
- type: str
- choices: ['2_way', '3_way', '3_wayonly']
- p2ppeeripignore:
- description:
- - When the P2P hello packet is received, no IP address check is performed.
- The value is a bool type.
- type: bool
- ppposicpcheckenable:
- description:
- - Interface for setting PPP link protocol to check OSICP negotiation status.
- The value is a bool type.
- type: bool
- level1cost:
- description:
- - Specifies the link cost of the interface when performing Level-1 SPF calculation.
- The value is a number of 0 to 16777215.
- type: int
- level2cost:
- description:
- - Specifies the link cost of the interface when performing Level-2 SPF calculation.
- The value is a number of 0 to 16777215.
- type: int
- bfdstaticen:
- description:
- - Configure static BFD on a specific interface enabled with ISIS.
- The value is a bool type.
- type: bool
- bfdblocken:
- description:
- - Blocking interfaces to dynamically create BFD features.
- The value is a bool type.
- type: bool
- state:
- description:
- - Determines whether the config should be present or not on the device.
- type: str
- default: 'present'
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = '''
- - name: "create vlan and config vlanif"
- ce_config:
- lines: 'vlan {{ test_vlan_id }},quit,interface {{test_intf_vlanif}},ip address {{test_vlanif_ip}} 24'
- match: none
-
- - name: "create eth-trunk and config eth-trunk"
- ce_config:
- lines: 'interface {{test_intf_trunk}},undo portswitch,ip address {{test_trunk_ip}} 24'
- match: none
-
- - name: "create vpn instance"
- ce_config:
- lines: 'ip vpn-instance {{test_vpn}},ipv4-family'
- match: none
-
- - name: Set isis circuit-level
- ce_is_is_interface:
- instance_id: 3
- ifname: Eth-Trunk10
- leveltype: level_1_2
- state: present
-
- - name: Set isis level1dispriority
- ce_is_is_interface:
- instance_id: 3
- ifname: Eth-Trunk10
- level1dispriority: 0
- state: present
-
- - name: Set isis level2dispriority
- ce_is_is_interface:
- instance_id: 3
- ifname: Eth-Trunk10
- level2dispriority: 0
- state: present
-
- - name: Set isis silentenable
- ce_is_is_interface:
- instance_id: 3
- ifname: Eth-Trunk10
- silentenable: true
- state: present
-
- - name: Set vpn name
- ce_is_is_instance:
- instance_id: 22
- vpn_name: vpn1
- state: present
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "addr_type": null,
- "create_type": null,
- "dest_addr": null,
- "out_if_name": "10GE1/0/1",
- "session_name": "bfd_l2link",
- "src_addr": null,
- "state": "present",
- "use_default_ip": true,
- "vrf_name": null
- }
-existing:
- description: k/v pairs of existing configuration
- returned: always
- type: dict
- sample: {
- "session": {}
- }
-end_state:
- description: k/v pairs of configuration after module execution
- returned: always
- type: dict
- sample: {
- "session": {
- "addrType": "IPV4",
- "createType": "SESS_STATIC",
- "destAddr": null,
- "outIfName": "10GE1/0/1",
- "sessName": "bfd_l2link",
- "srcAddr": null,
- "useDefaultIp": "true",
- "vrfName": null
- }
- }
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: [
- "bfd bfd_l2link bind peer-ip default-ip interface 10ge1/0/1"
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import sys
-import socket
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config
-
-CE_NC_GET_ISIS = """
-
-
- %s
-
-
-"""
-
-CE_NC_GET_ISIS_INTERFACE = """
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_ISIS_INTERFACE = """
-
-
- %s
-
-
- %s
-
-
-
-
-"""
-
-CE_NC_DELETE_ISIS_INTERFACE = """
-
-
- %s
-
-
- %s
-
-
-
-
-"""
-
-CE_NC_GET_ISIS_BFDINTERFACE = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_ISIS_BFDINTERFACE = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_DELETE_ISIS_BFDINTERFACE = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
- %s
-
-
-
-
-
-
-"""
-
-
-def is_valid_ip_vpn(vpname):
- """check ip vpn"""
-
- if not vpname:
- return False
-
- if vpname == "_public_":
- return False
-
- if len(vpname) < 1 or len(vpname) > 31:
- return False
-
- return True
-
-
-def check_ip_addr(ipaddr):
- """check ip address, Supports IPv4 and IPv6"""
-
- if not ipaddr or '\x00' in ipaddr:
- return False
-
- try:
- res = socket.getaddrinfo(ipaddr, 0, socket.AF_UNSPEC,
- socket.SOCK_STREAM,
- 0, socket.AI_NUMERICHOST)
- return bool(res)
- except socket.gaierror:
- err = sys.exc_info()[1]
- if err.args[0] == socket.EAI_NONAME:
- return False
- raise
-
- return True
-
-
-def check_default_ip(ipaddr):
- """check the default multicast IP address"""
-
- # The value ranges from 224.0.0.107 to 224.0.0.250
- if not check_ip_addr(ipaddr):
- return False
-
- if ipaddr.count(".") != 3:
- return False
-
- ips = ipaddr.split(".")
- if ips[0] != "224" or ips[1] != "0" or ips[2] != "0":
- return False
-
- if not ips[3].isdigit() or int(ips[3]) < 107 or int(ips[3]) > 250:
- return False
-
- return True
-
-
-def get_interface_type(interface):
- """get the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface.upper().startswith('GE'):
- return 'ge'
- elif interface.upper().startswith('10GE'):
- return '10ge'
- elif interface.upper().startswith('25GE'):
- return '25ge'
- elif interface.upper().startswith('4X10GE'):
- return '4x10ge'
- elif interface.upper().startswith('40GE'):
- return '40ge'
- elif interface.upper().startswith('100GE'):
- return '100ge'
- elif interface.upper().startswith('VLANIF'):
- return 'vlanif'
- elif interface.upper().startswith('LOOPBACK'):
- return 'loopback'
- elif interface.upper().startswith('METH'):
- return 'meth'
- elif interface.upper().startswith('ETH-TRUNK'):
- return 'eth-trunk'
- elif interface.upper().startswith('VBDIF'):
- return 'vbdif'
- elif interface.upper().startswith('NVE'):
- return 'nve'
- elif interface.upper().startswith('TUNNEL'):
- return 'tunnel'
- elif interface.upper().startswith('ETHERNET'):
- return 'ethernet'
- elif interface.upper().startswith('FCOE-PORT'):
- return 'fcoe-port'
- elif interface.upper().startswith('FABRIC-PORT'):
- return 'fabric-port'
- elif interface.upper().startswith('STACK-PORT'):
- return 'stack-port'
- elif interface.upper().startswith('NULL'):
- return'null'
- else:
- return None
-
-
-class ISIS_Instance(object):
- """Manages ISIS Instance"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.__init_module__()
-
- # module input info
- self.instance_id = self.module.params['instance_id']
- self.ifname = self.module.params['ifname']
- self.leveltype = self.module.params['leveltype']
- self.level1dispriority = self.module.params['level1dispriority']
- self.level2dispriority = self.module.params['level2dispriority']
- self.silentenable = self.module.params['silentenable']
- self.silentcost = self.module.params['silentcost']
- self.typep2penable = self.module.params['typep2penable']
- self.snpacheck = self.module.params['snpacheck']
- self.p2pnegotiationmode = self.module.params['p2pnegotiationmode']
- self.p2ppeeripignore = self.module.params['p2ppeeripignore']
- self.ppposicpcheckenable = self.module.params['ppposicpcheckenable']
- self.level1cost = self.module.params['level1cost']
- self.level2cost = self.module.params['level2cost']
- self.bfdstaticen = self.module.params['bfdstaticen']
- self.bfdblocken = self.module.params['bfdblocken']
- self.state = self.module.params['state']
-
- # state
- self.changed = False
- self.isis_dict = dict()
- self.updates_cmd = list()
- self.commands = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def __init_module__(self):
- """init module"""
- mutually_exclusive = [["level1dispriority", "level2dispriority"],
- ["level1cost", "level2cost"]]
- self.module = AnsibleModule(
- argument_spec=self.spec,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
-
- def get_isis_dict(self):
- """bfd config dict"""
-
- isis_dict = dict()
- isis_dict["instance"] = dict()
- conf_str = CE_NC_GET_ISIS % (
- (CE_NC_GET_ISIS_INTERFACE % self.instance_id))
- if self.bfdstaticen or self.bfdblocken:
- conf_str = CE_NC_GET_ISIS % (
- (CE_NC_GET_ISIS_BFDINTERFACE % self.instance_id))
-
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return isis_dict
-
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
-
- #
- glb = root.find("isiscomm/isSites/isSite/isCircuits/isCircuit")
- if self.bfdstaticen or self.bfdblocken:
- glb = root.find("isiscomm/isSites/isSite/isSiteMTs/isSiteMT/isCircMts/isCircMt")
- if glb:
- for attr in glb:
- isis_dict["instance"][attr.tag] = attr.text
-
- return isis_dict
-
- def config_session(self):
- """configures bfd session"""
-
- xml_str = ""
- instance = self.isis_dict["instance"]
- if not self.instance_id:
- return xml_str
- if self.ifname:
- xml_str = "%s" % self.ifname
- self.updates_cmd.append("interface %s" % self.ifname)
- if self.state == "present":
- self.updates_cmd.append("isis enable %s" % self.instance_id)
-
- if self.leveltype:
- if self.leveltype == "level_1":
- xml_str += "level_1"
- self.updates_cmd.append("isis circuit-level level-1")
- elif self.leveltype == "level_2":
- xml_str += "level_2"
- self.updates_cmd.append("isis circuit-level level-2")
- elif self.leveltype == "level_1_2":
- xml_str += "level_1_2"
- self.updates_cmd.append("isis circuit-level level-1-2")
- if self.level1dispriority is not None:
- xml_str += "%s" % self.level1dispriority
- self.updates_cmd.append("isis dis-priority %s level-1" % self.level1dispriority)
- if self.level2dispriority is not None:
- xml_str += "%s" % self.level2dispriority
- self.updates_cmd.append("isis dis-priority %s level-2" % self.level2dispriority)
- if self.p2pnegotiationmode:
- if self.p2pnegotiationmode == "2_way":
- xml_str += "2_way"
- self.updates_cmd.append("isis ppp-negotiation 2-way")
- elif self.p2pnegotiationmode == "3_way":
- xml_str += "3_way"
- self.updates_cmd.append("isis ppp-negotiation 3-way")
- elif self.p2pnegotiationmode == "3_wayonly":
- xml_str += "3_wayonly"
- self.updates_cmd.append("isis ppp-negotiation only")
- if self.level1cost is not None:
- xml_str += "%s" % self.level1cost
- self.updates_cmd.append("isis cost %s level-1" % self.level1cost)
- if self.level2cost is not None:
- xml_str += "%s" % self.level2cost
- self.updates_cmd.append("isis cost %s level-2" % self.level2cost)
-
- else:
- # absent
- self.updates_cmd.append("undo isis enable")
- if self.leveltype and self.leveltype == instance.get("circuitLevelType"):
- xml_str += "level_1_2"
- self.updates_cmd.append("undo isis circuit-level")
- if self.level1dispriority is not None and self.level1dispriority == instance.get("level1DisPriority"):
- xml_str += "64"
- self.updates_cmd.append("undo isis dis-priority %s level-1" % self.level1dispriority)
- if self.level2dispriority is not None and self.level2dispriority == instance.get("level2dispriority"):
- xml_str += "64"
- self.updates_cmd.append("undo isis dis-priority %s level-2" % self.level2dispriority)
- if self.p2pnegotiationmode and self.p2pnegotiationmode == instance.get("p2pNegotiationMode"):
- xml_str += ""
- self.updates_cmd.append("undo isis ppp-negotiation")
- if self.level1cost is not None and self.level1cost == instance.get("level1Cost"):
- xml_str += ""
- self.updates_cmd.append("undo isis cost %s level-1" % self.level1cost)
- if self.level2cost is not None and self.level2cost == instance.get("level2Cost"):
- xml_str += ""
- self.updates_cmd.append("undo isis cost %s level-2" % self.level2cost)
-
- if self.silentenable and instance.get("silentEnable", "false") == "false":
- xml_str += "true"
- self.updates_cmd.append("isis silent")
- elif not self.silentenable and instance.get("silentEnable", "false") == "true":
- xml_str += "false"
- self.updates_cmd.append("undo isis silent")
-
- if self.silentcost and instance.get("silentCost", "false") == "false":
- xml_str += "true"
- self.updates_cmd.append("isis silent advertise-zero-cost")
- elif not self.silentcost and instance.get("silentCost", "false") == "true":
- xml_str += "false"
-
- if self.typep2penable and instance.get("typeP2pEnable", "false") == "false":
- xml_str += "true"
- self.updates_cmd.append("isis circuit-type p2p")
- elif not self.typep2penable and instance.get("typeP2pEnable", "false") == "true":
- xml_str += "false"
- self.updates_cmd.append("undo isis circuit-type")
-
- if self.snpacheck and instance.get("snpaCheck", "false") == "false":
- xml_str += "true"
- self.updates_cmd.append("isis circuit-type p2p strict-snpa-check")
- elif not self.snpacheck and instance.get("snpaCheck", "false") == "true":
- xml_str += "false"
-
- if self.p2ppeeripignore and instance.get("p2pPeerIPIgnore", "false") == "false":
- xml_str += "true"
- self.updates_cmd.append("isis peer-ip-ignore")
- elif not self.p2ppeeripignore and instance.get("p2pPeerIPIgnore", "false") == "true":
- xml_str += "false"
- self.updates_cmd.append("undo isis peer-ip-ignore")
-
- if self.ppposicpcheckenable and instance.get("pPPOsicpCheckEnable", "false") == "false":
- xml_str += "true"
- self.updates_cmd.append("isis ppp-osicp-check")
- elif not self.ppposicpcheckenable and instance.get("pPPOsicpCheckEnable", "false") == "true":
- xml_str += "false"
- self.updates_cmd.append("undo isis ppp-osicp-check")
- if self.bfdstaticen and instance.get("bfdStaticEn", "false") == "false":
- xml_str += "true"
- self.updates_cmd.append("isis bfd static")
- elif not self.bfdstaticen and instance.get("bfdStaticEn", "false") == "true":
- xml_str += "false"
- self.updates_cmd.append("undo isis bfd static")
- if self.bfdblocken and instance.get("bfdBlockEn", "false") == "false":
- xml_str += "true"
- self.updates_cmd.append("isis bfd block")
- elif not self.bfdblocken and instance.get("bfdBlockEn", "false") == "true":
- xml_str += "false"
- self.updates_cmd.append("undo isis bfd block")
-
- if self.state == "present":
- if self.bfdstaticen is not None or self.bfdblocken is not None:
- return CE_NC_MERGE_ISIS_BFDINTERFACE % (self.instance_id, xml_str)
- return CE_NC_MERGE_ISIS_INTERFACE % (self.instance_id, xml_str)
- else:
- if self.bfdstaticen is not None or self.bfdblocken is not None:
- return CE_NC_DELETE_ISIS_BFDINTERFACE % (self.instance_id, xml_str)
- return CE_NC_DELETE_ISIS_INTERFACE % (self.instance_id, xml_str)
-
- def netconf_load_config(self, xml_str):
- """load bfd config by netconf"""
-
- if not xml_str:
- return
-
- xml_cfg = """
-
-
- %s
-
- """ % xml_str
- set_nc_config(self.module, xml_cfg)
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- # check instance id
- if not self.instance_id:
- self.module.fail_json(msg="Error: Missing required arguments: instance_id.")
-
- if self.instance_id:
- if self.instance_id < 1 or self.instance_id > 4294967295:
- self.module.fail_json(msg="Error: Instance id is not ranges from 1 to 4294967295.")
-
- # check level1dispriority
- if self.level1dispriority is not None:
- if self.level1dispriority < 0 or self.level1dispriority > 127:
- self.module.fail_json(msg="Error: level1dispriority is not ranges from 0 to 127.")
-
- if self.level2dispriority is not None:
- if self.level2dispriority < 0 or self.level2dispriority > 127:
- self.module.fail_json(msg="Error: level2dispriority is not ranges from 0 to 127.")
-
- if self.level1cost is not None:
- if self.level1cost < 0 or self.level1cost > 16777215:
- self.module.fail_json(msg="Error: level1cost is not ranges from 0 to 16777215.")
-
- if self.level2cost is not None:
- if self.level2cost < 0 or self.level2cost > 16777215:
- self.module.fail_json(msg="Error: level2cost is not ranges from 0 to 16777215.")
-
- def get_proposed(self):
- """get proposed info"""
- self.proposed["instance_id"] = self.instance_id
- self.proposed["ifname"] = self.ifname
- self.proposed["leveltype"] = self.leveltype
- self.proposed["level1dispriority"] = self.level1dispriority
- self.proposed["level2dispriority"] = self.level2dispriority
- self.proposed["silentenable"] = self.silentenable
- self.proposed["silentcost"] = self.silentcost
- self.proposed["typep2penable"] = self.typep2penable
- self.proposed["snpacheck"] = self.snpacheck
- self.proposed["p2pnegotiationmode"] = self.p2pnegotiationmode
- self.proposed["p2ppeeripignore"] = self.p2ppeeripignore
- self.proposed["ppposicpcheckenable"] = self.ppposicpcheckenable
- self.proposed["level1cost"] = self.level1cost
- self.proposed["level2cost"] = self.level2cost
- self.proposed["bfdstaticen"] = self.bfdstaticen
- self.proposed["bfdblocken"] = self.bfdblocken
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- if not self.isis_dict:
- self.existing["instance"] = None
- else:
- self.existing["instance"] = self.isis_dict.get("instance")
-
- def get_end_state(self):
- """get end state info"""
-
- isis_dict = self.get_isis_dict()
- if not isis_dict:
- self.end_state["instance"] = None
- else:
- self.end_state["instance"] = isis_dict.get("instance")
- if self.existing == self.end_state:
- self.changed = False
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.isis_dict = self.get_isis_dict()
- self.get_existing()
- self.get_proposed()
-
- # deal present or absent
- xml_str = ''
- if self.instance_id:
- xml_str += self.config_session()
-
- # update to device
- if xml_str:
- self.netconf_load_config(xml_str)
- self.changed = True
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- instance_id=dict(required=True, type='int'),
- ifname=dict(required=True, type='str'),
- leveltype=dict(required=False, type='str', choices=['level_1', 'level_2', 'level_1_2']),
- level1dispriority=dict(required=False, type='int'),
- level2dispriority=dict(required=False, type='int'),
- silentenable=dict(required=False, type='bool'),
- silentcost=dict(required=False, type='bool'),
- typep2penable=dict(required=False, type='bool'),
- snpacheck=dict(required=False, type='bool'),
- p2pnegotiationmode=dict(required=False, type='str', choices=['2_way', '3_way', '3_wayonly']),
- p2ppeeripignore=dict(required=False, type='bool'),
- ppposicpcheckenable=dict(required=False, type='bool'),
- level1cost=dict(required=False, type='int'),
- level2cost=dict(required=False, type='int'),
- bfdstaticen=dict(required=False, type='bool'),
- bfdblocken=dict(required=False, type='bool'),
- state=dict(required=False, default='present', choices=['present', 'absent'])
- )
-
- module = ISIS_Instance(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_is_is_view.py b/plugins/modules/network/cloudengine/ce_is_is_view.py
deleted file mode 100644
index 7a8b279ae9..0000000000
--- a/plugins/modules/network/cloudengine/ce_is_is_view.py
+++ /dev/null
@@ -1,1955 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_is_is_view
-author: xuxiaowei0512 (@CloudEngine-Ansible)
-short_description: Manages isis view configuration on HUAWEI CloudEngine devices.
-description:
- - Manages isis process id, creates a isis instance id or deletes a process id
- on HUAWEI CloudEngine devices.
-options:
- coststyle:
- description:
- - Specifies the cost style.
- type: str
- choices: ['narrow', 'wide', 'transition', 'ntransition', 'wtransition']
- cost_type:
- description:
- - Specifies the cost type.
- type: str
- choices: ['external', 'internal']
- defaultmode:
- description:
- - Specifies the default mode.
- type: str
- choices: ['always', 'matchDefault', 'matchAny']
- export_policytype:
- description:
- - Specifies the default mode.
- type: str
- choices: ['aclNumOrName', 'ipPrefix', 'routePolicy']
- export_protocol:
- description:
- - Specifies the export router protocol.
- type: str
- choices: ['direct', 'ospf', 'isis', 'static', 'rip', 'bgp', 'ospfv3', 'all']
- impotr_leveltype:
- description:
- - Specifies the export router protocol.
- type: str
- choices: ['level_1', 'level_2', 'level_1_2']
- islevel:
- description:
- - Specifies the isis level.
- type: str
- choices: ['level_1', 'level_2', 'level_1_2']
- level_type:
- description:
- - Specifies the isis level type.
- type: str
- choices: ['level_1', 'level_2', 'level_1_2']
- penetration_direct:
- description:
- - Specifies the penetration direct.
- type: str
- choices: ['level2-level1', 'level1-level2']
- protocol:
- description:
- - Specifies the protocol.
- type: str
- choices: ['direct', 'ospf', 'isis', 'static', 'rip', 'bgp', 'ospfv3', 'all']
- aclnum_or_name:
- description:
- - Specifies the acl number or name for isis.
- type: str
- allow_filter:
- description:
- - Specifies the alow filter or not.
- type: bool
- allow_up_down:
- description:
- - Specifies the alow up or down.
- type: bool
- autocostenable:
- description:
- - Specifies the alow auto cost enable.
- type: bool
- autocostenablecompatible:
- description:
- - Specifies the alow auto cost enable compatible.
- type: bool
- avoid_learning:
- description:
- - Specifies the alow avoid learning.
- type: bool
- bfd_min_tx:
- description:
- - Specifies the bfd min sent package.
- type: int
- bfd_min_rx:
- description:
- - Specifies the bfd min received package.
- type: int
- bfd_multiplier_num:
- description:
- - Specifies the bfd multiplier number.
- type: int
- cost:
- description:
- - Specifies the bfd cost.
- type: int
- description:
- description:
- - Specifies description of isis.
- type: str
- enablelevel1tolevel2:
- description:
- - Enable level1 to level2.
- type: bool
- export_aclnumorname:
- description:
- - Specifies export acl number or name.
- type: str
- export_ipprefix:
- description:
- - Specifies export ip prefix.
- type: str
- export_processid:
- description:
- - Specifies export process id.
- type: int
- export_routepolicyname:
- description:
- - Specifies export route policy name.
- type: str
- import_aclnumorname:
- description:
- - Specifies import acl number or name.
- type: str
- import_cost:
- description:
- - Specifies import cost.
- type: int
- import_ipprefix:
- description:
- - Specifies import ip prefix.
- type: str
- import_route_policy:
- description:
- - Specifies import route policy.
- type: str
- import_routepolicy_name:
- description:
- - Specifies import route policy name.
- type: str
- import_routepolicyname:
- description:
- - Specifies import route policy name.
- type: str
- import_tag:
- description:
- - Specifies import tag.
- type: int
- inheritcost:
- description:
- - Enable inherit cost.
- type: bool
- instance_id:
- description:
- - Specifies instance id.
- type: int
- ip_address:
- description:
- - Specifies ip address.
- type: str
- ip_prefix_name:
- description:
- - Specifies ip prefix name.
- type: str
- max_load:
- description:
- - Specifies route max load.
- type: int
- mode_routepolicyname:
- description:
- - Specifies the mode of route polic yname.
- type: str
- mode_tag:
- description:
- - Specifies the tag of mode.
- type: int
- netentity:
- description:
- - Specifies the netentity.
- type: str
- permitibgp:
- description:
- - Specifies the permitibgp.
- type: bool
- processid:
- description:
- - Specifies the process id.
- type: int
- relaxspfLimit:
- description:
- - Specifies enable the relax spf limit.
- type: bool
- route_policy_name:
- description:
- - Specifies the route policy name.
- type: str
- stdbandwidth:
- description:
- - Specifies the std band width.
- type: int
- stdlevel1cost:
- description:
- - Specifies the std level1 cost.
- type: int
- stdlevel2cost:
- description:
- - Specifies the std level2 cost.
- type: int
- tag:
- description:
- - Specifies the isis tag.
- type: int
- weight:
- description:
- - Specifies the isis weight.
- type: int
- preference_value:
- description:
- - Specifies the preference value.
- type: int
- state:
- description:
- - Determines whether the config should be present or not on the device.
- default: present
- type: str
- choices: ['present', 'absent']
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - This module works with connection C(netconf).
-'''
-
-EXAMPLES = '''
- - name: Set isis description
- ce_is_is_view:
- instance_id: 3
- description: abcdeggfs
- state: present
-
- - name: Set isis islevel
- ce_is_is_view:
- instance_id: 3
- islevel: level_1
- state: present
- - name: Set isis coststyle
- ce_is_is_view:
- instance_id: 3
- coststyle: narrow
- state: present
-
- - name: Set isis stdlevel1cost
- ce_is_is_view:
- instance_id: 3
- stdlevel1cost: 63
- state: present
-
- - name: set isis stdlevel2cost
- ce_is_is_view:
- instance_id: 3
- stdlevel2cost: 63
- state: present
-
- - name: set isis stdbandwidth
- ce_is_is_view:
- instance_id: 3
- stdbandwidth: 1
- state: present
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "state": "present"
- }
-existing:
- description: k/v pairs of existing configuration
- returned: always
- type: dict
- sample: {
- "session": {}
- }
-end_state:
- description: k/v pairs of configuration after module execution
- returned: always
- type: dict
- sample: {
- "session": {
- "addrType": "IPV4",
- "createType": "SESS_STATIC",
- "destAddr": null,
- "outIfName": "10GE1/0/1",
- "sessName": "bfd_l2link",
- "srcAddr": null,
- "useDefaultIp": "true",
- "vrfName": null
- }
- }
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: [
- "bfd bfd_l2link bind peer-ip default-ip interface 10ge1/0/1"
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import sys
-import socket
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config
-
-CE_NC_GET_ISIS = """
-
-
- %s
-
-
-"""
-
-CE_NC_GET_ISIS_INSTANCE = """
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_GET_ISIS_ENTITY = """
-
-
- %s
-
-
-
-
-
-
-
-"""
-
-CE_NC_CREAT_ISIS_ENTITY = """
-
-
- %s
-
-
- %s
-
-
-
-
-"""
-
-CE_NC_DELATE_ISIS_ENTITY = """
-
-
- %s
-
-
- %s
-
-
-
-
-"""
-
-CE_NC_GET_ISIS_PREFERENCE = """
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MREGE_ISIS_PREFERENCE = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_DELETE_ISIS_PREFERENCE = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_GET_ISIS_MAXLOAD = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
-
-
-
-"""
-
-CE_NC_MERGE_ISIS_MAXLOAD = """
-
-
- %s
-
-
- afIpv4
- 0
- %s
-
-
-
-
-"""
-
-CE_NC_DELETE_ISIS_MAXLOAD = """
-
-
- %s
-
-
- afIpv4
- 0
- 32
-
-
-
-
-"""
-
-CE_NC_GET_ISIS_NEXTHOP = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_ISIS_NEXTHOP = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
- %s
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_DELETE_ISIS_NEXTHOP = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
- %s
- 1
-
-
-
-
-
-
-"""
-
-CE_NC_GET_ISIS_LEAKROUTELEVEL2 = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_ISIS_LEAKROUTELEVEL2 = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_DELETE_ISIS_LEAKROUTELEVEL2 = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
- 0
-
-
-
- false
-
-
-
-
-
-
-"""
-
-CE_NC_GET_ISIS_LEAKROUTELEVEL1 = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_ISIS_LEAKROUTELEVEL1 = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_DELETE_ISIS_LEAKROUTELEVEL1 = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
- 0
-
-
-
- false
- false
-
-
-
-
-
-
-"""
-
-CE_NC_GET_ISIS_DEFAULTROUTE = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_ISIS_DEFAULTROUTE = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_DELETE_ISIS_DEFAULTROUTE = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
- always
- 0
- 0
- level_2
- false
-
-
-
-
-
-
-"""
-
-CE_NC_GET_ISIS_IMPORTROUTE = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_ISIS_IMPORTROUTE = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_GET_ISIS_EXPORTROUTE = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_ISIS_EXPORTROUTE = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_GET_ISIS_IMPORTIPROUTE = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_ISIS_IMPORTIPROUTE = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_GET_ISIS_BFDLINK = """
-
-
- %s
-
-
- afIpv4
- 0
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_ISIS_BFDLINK = """
-
-
- %s
-
-
- afIpv4
- 0
- %s
-
-
-
-
-"""
-
-CE_NC_DELETE_ISIS_BFDLINK = """
-
-
- %s
-
-
- afIpv4
- 0
- 3
- 3
- 3
-
-
-
-
-"""
-
-
-def is_valid_ip_vpn(vpname):
- """check ip vpn"""
-
- if not vpname:
- return False
-
- if vpname == "_public_":
- return False
-
- if len(vpname) < 1 or len(vpname) > 31:
- return False
-
- return True
-
-
-def check_ip_addr(ipaddr):
- """check ip address, Supports IPv4 and IPv6"""
-
- if not ipaddr or '\x00' in ipaddr:
- return False
-
- try:
- res = socket.getaddrinfo(ipaddr, 0, socket.AF_UNSPEC,
- socket.SOCK_STREAM,
- 0, socket.AI_NUMERICHOST)
- return bool(res)
- except socket.gaierror:
- err = sys.exc_info()[1]
- if err.args[0] == socket.EAI_NONAME:
- return False
- raise
-
- return True
-
-
-def check_default_ip(ipaddr):
- """check the default multicast IP address"""
-
- # The value ranges from 224.0.0.107 to 224.0.0.250
- if not check_ip_addr(ipaddr):
- return False
-
- if ipaddr.count(".") != 3:
- return False
-
- ips = ipaddr.split(".")
- if ips[0] != "224" or ips[1] != "0" or ips[2] != "0":
- return False
-
- if not ips[3].isdigit() or int(ips[3]) < 107 or int(ips[3]) > 250:
- return False
-
- return True
-
-
-def get_interface_type(interface):
- """get the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- if interface.upper().startswith('GE'):
- iftype = 'ge'
- elif interface.upper().startswith('10GE'):
- iftype = '10ge'
- elif interface.upper().startswith('25GE'):
- iftype = '25ge'
- elif interface.upper().startswith('4X10GE'):
- iftype = '4x10ge'
- elif interface.upper().startswith('40GE'):
- iftype = '40ge'
- elif interface.upper().startswith('100GE'):
- iftype = '100ge'
- elif interface.upper().startswith('VLANIF'):
- iftype = 'vlanif'
- elif interface.upper().startswith('LOOPBACK'):
- iftype = 'loopback'
- elif interface.upper().startswith('METH'):
- iftype = 'meth'
- elif interface.upper().startswith('ETH-TRUNK'):
- iftype = 'eth-trunk'
- elif interface.upper().startswith('VBDIF'):
- iftype = 'vbdif'
- elif interface.upper().startswith('NVE'):
- iftype = 'nve'
- elif interface.upper().startswith('TUNNEL'):
- iftype = 'tunnel'
- elif interface.upper().startswith('ETHERNET'):
- iftype = 'ethernet'
- elif interface.upper().startswith('FCOE-PORT'):
- iftype = 'fcoe-port'
- elif interface.upper().startswith('FABRIC-PORT'):
- iftype = 'fabric-port'
- elif interface.upper().startswith('STACK-PORT'):
- iftype = 'stack-port'
- elif interface.upper().startswith('NULL'):
- iftype = 'null'
- else:
- return None
-
- return iftype.lower()
-
-
-class ISIS_View(object):
- """Manages ISIS Instance"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.__init_module__()
-
- # module input info
- self.instance_id = self.module.params['instance_id']
- self.description = self.module.params['description']
- self.islevel = self.module.params['islevel']
- self.coststyle = self.module.params['coststyle']
- self.relaxspfLimit = self.module.params['relaxspfLimit']
- self.stdlevel1cost = self.module.params['stdlevel1cost']
- self.stdlevel2cost = self.module.params['stdlevel2cost']
- self.stdbandwidth = self.module.params['stdbandwidth']
- self.autocostenable = self.module.params['autocostenable']
- self.autocostenablecompatible = self.module.params['autocostenablecompatible']
- self.netentity = self.module.params['netentity']
- self.preference_value = self.module.params['preference_value']
- self.route_policy_name = self.module.params['route_policy_name']
- self.max_load = self.module.params['max_load']
- self.ip_address = self.module.params['ip_address']
- self.weight = self.module.params['weight']
- self.aclnum_or_name = self.module.params['aclnum_or_name']
- self.ip_prefix_name = self.module.params['ip_prefix_name']
- self.import_routepolicy_name = self.module.params['import_routepolicy_name']
- self.tag = self.module.params['tag']
- self.allow_filter = self.module.params['allow_filter']
- self.allow_up_down = self.module.params['allow_up_down']
- self.penetration_direct = self.module.params['penetration_direct']
- self.enablelevel1tolevel2 = self.module.params['enablelevel1tolevel2']
- self.defaultmode = self.module.params['defaultmode']
- self.mode_routepolicyname = self.module.params['mode_routepolicyname']
- self.cost = self.module.params['cost']
- self.mode_tag = self.module.params['mode_tag']
- self.level_type = self.module.params['level_type']
- self.avoid_learning = self.module.params['avoid_learning']
- self.protocol = self.module.params['protocol']
- self.processid = self.module.params['processid']
- self.cost_type = self.module.params['cost_type']
- self.import_cost = self.module.params['import_cost']
- self.import_tag = self.module.params['import_tag']
- self.impotr_leveltype = self.module.params['impotr_leveltype']
- self.import_route_policy = self.module.params['import_route_policy']
- self.inheritcost = self.module.params['inheritcost']
- self.permitibgp = self.module.params['permitibgp']
- self.avoid_learning = self.module.params['avoid_learning']
- self.export_protocol = self.module.params['export_protocol']
- self.export_policytype = self.module.params['export_policytype']
- self.export_processid = self.module.params['export_processid']
- self.export_aclnumorname = self.module.params['export_aclnumorname']
- self.export_ipprefix = self.module.params['export_ipprefix']
- self.export_routepolicyname = self.module.params['export_routepolicyname']
- self.import_aclnumorname = self.module.params['import_aclnumorname']
- self.import_ipprefix = self.module.params['import_ipprefix']
- self.import_routepolicyname = self.module.params['import_routepolicyname']
- self.bfd_min_rx = self.module.params['bfd_min_rx']
- self.bfd_min_tx = self.module.params['bfd_min_tx']
- self.bfd_multiplier_num = self.module.params['bfd_multiplier_num']
- self.state = self.module.params['state']
-
- # state
- self.changed = False
- self.isis_dict = dict()
- self.updates_cmd = list()
- self.commands = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def __init_module__(self):
- """init module"""
-
- mutually_exclusive = [["stdlevel1cost", "stdlevel2cost"],
- ["aclnum_or_name", "ip_prefix_name", "import_routepolicy_name"],
- ["export_aclnumorname", "import_ipprefix", "import_routepolicyname"]]
- required_together = [('ip_address', 'weight')]
- self.module = AnsibleModule(
- argument_spec=self.spec,
- mutually_exclusive=mutually_exclusive,
- required_together=required_together,
- supports_check_mode=True)
-
- def get_isis_dict(self):
- """bfd config dict"""
-
- isis_dict = dict()
- isis_dict["instance"] = dict()
- conf_str = CE_NC_GET_ISIS % (
- (CE_NC_GET_ISIS_INSTANCE % self.instance_id))
-
- if self.netentity:
- conf_str = CE_NC_GET_ISIS % (
- (CE_NC_GET_ISIS_ENTITY % self.instance_id))
-
- if self.route_policy_name or self.preference_value:
- conf_str = CE_NC_GET_ISIS % (
- (CE_NC_GET_ISIS_PREFERENCE % self.instance_id))
- if self.max_load:
- conf_str = CE_NC_GET_ISIS % (
- (CE_NC_GET_ISIS_MAXLOAD % self.instance_id))
- if self.ip_address:
- conf_str = CE_NC_GET_ISIS % (
- (CE_NC_GET_ISIS_NEXTHOP % self.instance_id))
- if self.penetration_direct and self.penetration_direct == "level2-level1":
- conf_str = CE_NC_GET_ISIS % (
- (CE_NC_GET_ISIS_LEAKROUTELEVEL2 % self.instance_id))
- elif self.penetration_direct and self.penetration_direct == "level1-level2":
- conf_str = CE_NC_GET_ISIS % (
- (CE_NC_GET_ISIS_LEAKROUTELEVEL1 % self.instance_id))
- elif self.defaultmode:
- conf_str = CE_NC_GET_ISIS % (
- (CE_NC_GET_ISIS_DEFAULTROUTE % self.instance_id))
- elif self.protocol:
- conf_str = CE_NC_GET_ISIS % (
- (CE_NC_GET_ISIS_IMPORTROUTE % self.instance_id))
- elif self.export_protocol:
- conf_str = CE_NC_GET_ISIS % (
- (CE_NC_GET_ISIS_EXPORTROUTE % self.instance_id))
- elif self.bfd_min_rx or self.bfd_min_tx or self.bfd_multiplier_num:
- conf_str = CE_NC_GET_ISIS % (
- (CE_NC_GET_ISIS_BFDLINK % self.instance_id))
- elif self.import_aclnumorname or self.import_ipprefix or self.import_ipprefix:
- conf_str = CE_NC_GET_ISIS % (
- (CE_NC_GET_ISIS_IMPORTIPROUTE % self.instance_id))
- xml_str = get_nc_config(self.module, conf_str)
-
- if "" in xml_str:
- return isis_dict
-
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
-
- # get bfd global info
- if self.netentity:
- glb = root.find("isiscomm/isSites/isSite/isNetEntitys/isNetEntity")
- elif self.route_policy_name or self.preference_value:
- glb = root.find("isiscomm/isSites/isSite//isSiteMTs/isSiteMT/isPreferences/isPreference")
- elif self.max_load:
- glb = root.find("isiscomm/isSites/isSite/isSiteMTs/isSiteMT")
- elif self.ip_address:
- glb = root.find("isiscomm/isSites/isSite/isSiteMTs/isSiteMT/isNextHopWeights/isNextHopWeight")
- elif self.penetration_direct and self.penetration_direct == "level2-level1":
- glb = root.find("isiscomm/isSites/isSite/isSiteMTs/isSiteMT/isLeakRouteLevel2ToLevel1s/isLeakRouteLevel2ToLevel1")
- elif self.penetration_direct and self.penetration_direct == "level1-level2":
- glb = root.find(
- "isiscomm/isSites/isSite/isSiteMTs/isSiteMT/isLeakRouteLevel1ToLevel2s/isLeakRouteLevel1ToLevel2")
- elif self.defaultmode:
- glb = root.find(
- "isiscomm/isSites/isSite/isSiteMTs/isSiteMT/isDefaultRoutes/isDefaultRoute")
- elif self.protocol:
- glb = root.find(
- "isiscomm/isSites/isSite/isSiteMTs/isSiteMT/isImportRoutes/isImportRoute")
- elif self.export_protocol:
- glb = root.find(
- "isiscomm/isSites/isSite/isSiteMTs/isSiteMT/isFilterExports/isFilterExport")
- elif self.bfd_min_rx or self.bfd_min_tx or self.bfd_multiplier_num:
- glb = root.find(
- "isiscomm/isSites/isSite/isSiteMTs/isSiteMT")
- elif self.import_aclnumorname or self.import_ipprefix or self.import_ipprefix:
- glb = root.find(
- "isiscomm/isSites/isSite/isSiteMTs/isSiteMT/isFilterImports/isFilterImport")
- else:
- glb = root.find("isiscomm/isSites/isSite")
-
- if glb is not None:
- for attr in glb:
- isis_dict["instance"][attr.tag] = attr.text
-
- return isis_dict
-
- def config_session(self):
- """configures bfd session"""
-
- xml_str = ""
- instance = self.isis_dict["instance"]
- if not self.instance_id:
- return xml_str
- xml_str = "%s" % self.instance_id
- self.updates_cmd.append("isis %s" % self.instance_id)
- cmd_list = list()
-
- if self.state == "present":
- if self.description and self.description != instance.get("description"):
- xml_str += "%s" % self.description
- self.updates_cmd.append("description %s" % self.description)
-
- if self.islevel and self.islevel != instance.get("isLevel"):
- xml_str += "%s" % self.islevel
- self.updates_cmd.append("is-level %s" % self.islevel)
-
- if self.coststyle:
- if self.coststyle != instance.get("costStyle"):
- xml_str += "%s" % self.coststyle
- self.updates_cmd.append("cost-style %s" % self.coststyle)
- if self.relaxspfLimit and instance.get("relaxSpfLimit", "false") == "false":
- xml_str += "true"
- self.updates_cmd.append("cost-style %s relax-spf-limit" % self.coststyle)
- elif not self.relaxspfLimit and instance.get("relaxSpfLimit", "false") == "true":
- xml_str += "false"
- self.updates_cmd.append("cost-style %s" % self.coststyle)
-
- if self.stdlevel1cost and str(self.stdlevel1cost) != instance.get("stdLevel1Cost"):
- xml_str += "%s" % self.stdlevel1cost
- self.updates_cmd.append("circuit-cost %s level-1" % self.stdlevel1cost)
-
- if self.stdlevel2cost and str(self.stdlevel2cost) != instance.get("stdLevel2Cost"):
- xml_str += "%s" % self.stdlevel2cost
- self.updates_cmd.append("circuit-cost %s level-2" % self.stdlevel2cost)
-
- if self.stdbandwidth and str(self.stdbandwidth) != instance.get("stdbandwidth"):
- xml_str += "%s" % self.stdbandwidth
- self.updates_cmd.append("bandwidth-reference %s" % self.stdbandwidth)
-
- if self.netentity and self.netentity != instance.get("netEntity"):
- xml_str = CE_NC_CREAT_ISIS_ENTITY % (self.instance_id, self.netentity)
- self.updates_cmd.append("network-entity %s" % self.netentity)
-
- if self.preference_value or self.route_policy_name:
- xml_str = ""
- cmd_session = "preference"
- if self.preference_value and str(self.preference_value) != instance.get("preferenceValue"):
- xml_str = "%s" % self.preference_value
- cmd_session += " %s" % self.preference_value
- if self.route_policy_name and self.route_policy_name != instance.get("routePolicyName"):
- xml_str += "%s" % self.route_policy_name
- cmd_session += " route-policy %s" % self.route_policy_name
- cmd_list.insert(0, cmd_session)
- self.updates_cmd.extend(cmd_list)
- xml_str = CE_NC_MREGE_ISIS_PREFERENCE % (self.instance_id, xml_str)
-
- if self.max_load and str(self.max_load) != instance.get("maxLoadBalancing"):
- xml_str = CE_NC_MERGE_ISIS_MAXLOAD % (self.instance_id, self.max_load)
- self.updates_cmd.append("maximum load-balancing %s" % self.max_load)
-
- if self.ip_address:
- xml_str = CE_NC_MERGE_ISIS_NEXTHOP % (self.instance_id, self.ip_address, self.weight)
- self.updates_cmd.append("nexthop %s weight %s" % (self.ip_address, self.weight))
-
- if self.penetration_direct:
- xml_str = ""
- if self.penetration_direct == "level2-level1":
- cmd_session = "import-route isis level-2 into level-1"
- elif self.penetration_direct == "level1-level2":
- cmd_session = "import-route isis level-1 into level-2"
- if self.aclnum_or_name:
- xml_str = "%s" % self.aclnum_or_name
- xml_str += "aclNumOrName"
- if isinstance(self.aclnum_or_name, int):
- cmd_session += " filter-policy %s" % self.aclnum_or_name
- elif isinstance(self.aclnum_or_name, str):
- cmd_session += " filter-policy acl-name %s" % self.aclnum_or_name
- if self.ip_prefix_name:
- xml_str = "%s" % self.ip_prefix_name
- xml_str += "ipPrefix"
- cmd_session += " filter-policy ip-prefix %s" % self.ip_prefix_name
- if self.import_routepolicy_name:
- xml_str = "%s" % self.import_routepolicy_name
- xml_str += "routePolicy"
- cmd_session += " filter-policy route-policy %s" % self.import_routepolicy_name
- if self.tag:
- xml_str += "%s" % self.tag
- cmd_session += " tag %s" % self.tag
- if self.allow_filter or self.allow_up_down:
- cmd_session += " direct"
- if self.allow_filter:
- xml_str += "true"
- cmd_session += " allow-filter-policy"
- if self.allow_up_down:
- xml_str += "true"
- cmd_session += " allow-up-down-bit"
- cmd_list.insert(0, cmd_session)
- self.updates_cmd.extend(cmd_list)
- if self.enablelevel1tolevel2:
- xml_str += "true"
- self.updates_cmd.append("undo import-route isis level-1 into level-2 disable")
-
- if self.defaultmode:
- cmd_session = "default-route-advertise"
- if self.defaultmode == "always":
- xml_str = "always"
- cmd_session += " always"
- elif self.defaultmode == "matchDefault":
- xml_str = "matchDefault"
- cmd_session += " match default"
- elif self.defaultmode == "matchAny":
- xml_str = "matchAny"
- xml_str += "routePolicy"
- xml_str += "%s" % self.mode_routepolicyname
- cmd_session += " route-policy %s" % self.mode_routepolicyname
- if self.cost is not None:
- xml_str += "%s" % self.cost
- cmd_session += " cost %s" % self.cost
- if self.mode_tag:
- xml_str += "%s" % self.mode_tag
- cmd_session += " tag %s" % self.mode_tag
- if self.level_type:
- if self.level_type == "level_1":
- xml_str += "level_1"
- cmd_session += " level-1"
- elif self.level_type == "level_2":
- xml_str += "level_2"
- cmd_session += " level-2"
- elif self.level_type == "level_1_2":
- xml_str += "level_1_2"
- cmd_session += " level-1-2"
- if self.avoid_learning:
- xml_str += "true"
- cmd_session += " avoid-learning"
- elif not self.avoid_learning:
- xml_str += "false"
- cmd_list.insert(0, cmd_session)
- self.updates_cmd.extend(cmd_list)
-
- if self.protocol:
- cmd_session = "import-route"
- if self.protocol == "rip":
- xml_str = "rip"
- cmd_session += " rip"
- elif self.protocol == "isis":
- xml_str = "isis"
- cmd_session += " isis"
- elif self.protocol == "ospf":
- xml_str = "ospf"
- cmd_session += " ospf"
- elif self.protocol == "static":
- xml_str = "static"
- cmd_session += " static"
- elif self.protocol == "direct":
- xml_str = "direct"
- cmd_session += " direct"
- elif self.protocol == "bgp":
- xml_str = "bgp"
- cmd_session += " bgp"
- if self.permitibgp:
- xml_str += "true"
- cmd_session += " permit-ibgp"
- if self.protocol == "rip" or self.protocol == "isis" or self.protocol == "ospf":
- xml_str += "%s" % self.processid
- cmd_session += " %s" % self.processid
- if self.inheritcost:
- xml_str += "%s" % self.inheritcost
- cmd_session += " inherit-cost"
- if self.cost_type:
- if self.cost_type == "external":
- xml_str += "external"
- cmd_session += " cost-type external"
- elif self.cost_type == "internal":
- xml_str += "internal"
- cmd_session += " cost-type internal"
- if self.import_cost:
- xml_str += "%s" % self.import_cost
- cmd_session += " cost %s" % self.import_cost
- if self.import_tag:
- xml_str += "%s" % self.import_tag
- cmd_session += " tag %s" % self.import_tag
- if self.import_route_policy:
- xml_str += "routePolicy"
- xml_str += "%s" % self.import_route_policy
- cmd_session += " route-policy %s" % self.import_route_policy
- if self.impotr_leveltype:
- if self.impotr_leveltype == "level_1":
- cmd_session += " level-1"
- elif self.impotr_leveltype == "level_2":
- cmd_session += " level-2"
- elif self.impotr_leveltype == "level_1_2":
- cmd_session += " level-1-2"
- cmd_list.insert(0, cmd_session)
- self.updates_cmd.extend(cmd_list)
-
- if self.bfd_min_rx or self.bfd_min_tx or self.bfd_multiplier_num:
- xml_str = ""
- self.updates_cmd.append("bfd all-interfaces enable")
- cmd_session = "bfd all-interfaces"
- if self.bfd_min_rx:
- xml_str += "%s" % self.bfd_min_rx
- cmd_session += " min-rx-interval %s" % self.bfd_min_rx
- if self.bfd_min_tx:
- xml_str += "%s" % self.bfd_min_tx
- cmd_session += " min-tx-interval %s" % self.bfd_min_tx
- if self.bfd_multiplier_num:
- xml_str += "%s" % self.bfd_multiplier_num
- cmd_session += " detect-multiplier %s" % self.bfd_multiplier_num
- cmd_list.insert(0, cmd_session)
- self.updates_cmd.extend(cmd_list)
-
- if self.export_protocol:
- cmd_session = "filter-policy"
- if self.export_aclnumorname:
- xml_str = "aclNumOrName"
- xml_str += "%s" % self.export_aclnumorname
- if isinstance(self.export_aclnumorname, int):
- cmd_session += " %s" % self.export_aclnumorname
- elif isinstance(self.export_aclnumorname, str):
- cmd_session += " acl-name %s" % self.export_aclnumorname
- if self.export_ipprefix:
- xml_str = "ipPrefix"
- xml_str += "%s" % self.export_ipprefix
- cmd_session += " ip-prefix %s" % self.export_ipprefix
- if self.export_routepolicyname:
- xml_str = "routePolicy"
- xml_str += "%s" % self.export_routepolicyname
- cmd_session += " route-policy %s" % self.export_routepolicyname
- xml_str += "%s" % self.export_protocol
- cmd_session += " export %s" % self.export_protocol
- if self.export_processid is not None:
- xml_str += "%s" % self.export_processid
- cmd_session += " %s" % self.export_processid
- cmd_list.insert(0, cmd_session)
- self.updates_cmd.extend(cmd_list)
-
- if self.import_ipprefix or self.import_aclnumorname or self.import_routepolicyname:
- cmd_session = "filter-policy"
- if self.import_aclnumorname:
- xml_str = "aclNumOrName"
- xml_str += "%s" % self.import_aclnumorname
- if isinstance(self.import_aclnumorname, int):
- cmd_session += " %s" % self.import_aclnumorname
- elif isinstance(self.import_aclnumorname, str):
- cmd_session += " acl-name %s" % self.import_aclnumorname
- if self.import_ipprefix:
- xml_str = "ipPrefix"
- xml_str += "%s" % self.import_ipprefix
- cmd_session += " ip-prefix %s" % self.import_ipprefix
- if self.import_routepolicyname:
- xml_str = "routePolicy"
- xml_str += "%s" % self.import_routepolicyname
- cmd_session += " route-policy %s" % self.import_routepolicyname
- cmd_session += "import"
- cmd_list.insert(0, cmd_session)
- self.updates_cmd.extend(cmd_list)
- else:
- # absent
- if self.description and self.description == instance.get("description"):
- xml_str += "%s" % self.description
- self.updates_cmd.append("undo description")
-
- if self.islevel and self.islevel == instance.get("isLevel"):
- xml_str += "level_1_2"
- self.updates_cmd.append("undo is-level")
-
- if self.coststyle and self.coststyle == instance.get("costStyle"):
- xml_str += "%s" % ("narrow")
- xml_str += "false"
- self.updates_cmd.append("undo cost-style")
-
- if self.stdlevel1cost and str(self.stdlevel1cost) == instance.get("stdLevel1Cost"):
- xml_str += "%s" % self.stdlevel1cost
- self.updates_cmd.append("undo circuit-cost %s level-1" % self.stdlevel1cost)
-
- if self.stdlevel2cost and str(self.stdlevel2cost) == instance.get("stdLevel2Cost"):
- xml_str += "%s" % self.stdlevel2cost
- self.updates_cmd.append("undo circuit-cost %s level-2" % self.stdlevel2cost)
-
- if self.stdbandwidth and str(self.stdbandwidth) == instance.get("stdbandwidth"):
- xml_str += "100"
- self.updates_cmd.append("undo bandwidth-reference")
-
- if self.netentity and self.netentity == instance.get("netEntity"):
- xml_str = CE_NC_DELATE_ISIS_ENTITY % (self.instance_id, self.netentity)
- self.updates_cmd.append("undo network-entity %s" % self.netentity)
-
- if self.preference_value or self.route_policy_name:
- xml_str = ""
- if self.preference_value and str(self.preference_value) == instance.get("preferenceValue"):
- xml_str = "%s" % self.preference_value
- if self.route_policy_name and self.route_policy_name == instance.get("routePolicyName"):
- xml_str += "%s" % self.route_policy_name
- self.updates_cmd.append("undo preference")
- elif not self.preference_value and self.route_policy_name and self.route_policy_name == instance.get("routePolicyName"):
- xml_str = "%s" % self.route_policy_name
- self.updates_cmd.append("undo preference")
- xml_str = CE_NC_DELETE_ISIS_PREFERENCE % (self.instance_id, xml_str)
-
- if self.max_load and str(self.max_load) == instance.get("maxLoadBalancing"):
- xml_str = CE_NC_DELETE_ISIS_MAXLOAD % self.instance_id
- self.updates_cmd.append("undo maximum load-balancing")
-
- if self.ip_address:
- xml_str = CE_NC_DELETE_ISIS_NEXTHOP % (self.instance_id, self.ip_address)
- self.updates_cmd.append("undo nexthop %s" % self.ip_address)
-
- if self.penetration_direct:
- if self.penetration_direct == "level2-level1":
- self.updates_cmd.append("undo import-route isis level-2 into level-1")
- elif self.penetration_direct == "level1-level2":
- self.updates_cmd.append("undo import-route isis level-1 into level-2")
- self.updates_cmd.append("import-route isis level-1 into level-2 disable")
-
- if self.bfd_min_rx or self.bfd_min_tx or self.bfd_multiplier_num is not None:
- xml_str = CE_NC_DELETE_ISIS_BFDLINK % self.instance_id
- self.updates_cmd.append("undo bfd all-interfaces enable")
- cmd_session = "undo bfd all-interfaces"
- if self.bfd_min_rx:
- cmd_session += " min-rx-interval %s" % self.bfd_min_rx
- if self.bfd_min_tx:
- cmd_session += " min-tx-interval %s" % self.bfd_min_tx
- if self.bfd_multiplier_num:
- cmd_session += " detect-multiplier %s" % self.bfd_multiplier_num
- cmd_list.insert(0, cmd_session)
- self.updates_cmd.extend(cmd_list)
-
- if self.defaultmode:
- xml_str = CE_NC_DELETE_ISIS_DEFAULTROUTE % self.instance_id
- self.updates_cmd.append("undo default-route-advertise")
-
- if self.protocol:
- if self.protocol == "rip" or self.protocol == "isis" or self.protocol == "ospf":
- self.updates_cmd.append("undo import-route %s %s" % (self.protocol, self.processid))
- else:
- self.updates_cmd.append("undo import-route %s" % self.protocol)
-
- if self.export_protocol:
- cmd_session = "undo filter-policy"
- if self.export_aclnumorname:
- if isinstance(self.export_aclnumorname, int):
- cmd_session += " %s" % self.export_aclnumorname
- elif isinstance(self.export_aclnumorname, str):
- cmd_session += " acl-name %s" % self.export_aclnumorname
- if self.export_ipprefix:
- cmd_session += " ip-prefix %s" % self.export_ipprefix
- if self.export_routepolicyname:
- cmd_session += " route-policy %s" % self.export_routepolicyname
- cmd_session += " export %s" % self.export_protocol
- if self.export_processid is not None:
- cmd_session += " %s" % self.export_processid
- cmd_list.insert(0, cmd_session)
- self.updates_cmd.extend(cmd_list)
- if self.import_ipprefix or self.import_aclnumorname or self.import_routepolicyname:
- cmd_session = "undo filter-policy"
- if self.import_aclnumorname:
- if isinstance(self.import_aclnumorname, int):
- cmd_session += " %s" % self.import_aclnumorname
- elif isinstance(self.import_aclnumorname, str):
- cmd_session += " acl-name %s" % self.import_aclnumorname
- if self.import_ipprefix:
- cmd_session += " ip-prefix %s" % self.import_ipprefix
- if self.import_routepolicyname:
- cmd_session += " route-policy %s" % self.import_routepolicyname
- cmd_session += " import"
- cmd_list.insert(0, cmd_session)
- self.updates_cmd.extend(cmd_list)
-
- if self.autocostenable and instance.get("stdAutoCostEnable", "false") == "false":
- xml_str += "true"
- self.updates_cmd.append("auto-cost enable")
- elif not self.autocostenable and instance.get("stdAutoCostEnable", "false") == "true":
- xml_str += "false"
- xml_str += "false"
- self.updates_cmd.append("undo auto-cost enable")
-
- if self.autocostenable:
- if self.autocostenablecompatible and instance.get("stdAutoCostEnableCompatible", "false") == "false":
- xml_str += "true"
- self.updates_cmd.append("auto-cost enable compatible")
- elif not self.autocostenablecompatible and instance.get("stdAutoCostEnableCompatible", "false") == "true":
- xml_str += "false"
- self.updates_cmd.append("auto-cost enable")
-
- if self.state == "present":
- if self.netentity or self.preference_value or self.route_policy_name or self.max_load or self.ip_address:
- return xml_str
- elif self.penetration_direct:
- if self.penetration_direct == "level2-level1":
- return CE_NC_MERGE_ISIS_LEAKROUTELEVEL2 % (self.instance_id, xml_str)
- elif self.penetration_direct == "level1-level2":
- return CE_NC_MERGE_ISIS_LEAKROUTELEVEL1 % (self.instance_id, xml_str)
- elif self.defaultmode:
- return CE_NC_MERGE_ISIS_DEFAULTROUTE % (self.instance_id, xml_str)
- elif self.protocol:
- return CE_NC_MERGE_ISIS_IMPORTROUTE % (self.instance_id, xml_str)
- elif self.export_protocol:
- return CE_NC_MERGE_ISIS_EXPORTROUTE % (self.instance_id, xml_str)
- elif self.import_routepolicyname or self.import_aclnumorname or self.import_ipprefix:
- return CE_NC_MERGE_ISIS_IMPORTIPROUTE % (self.instance_id, xml_str)
- elif self.bfd_min_rx or self.bfd_min_tx or self.bfd_multiplier_num:
- return CE_NC_MERGE_ISIS_BFDLINK % (self.instance_id, xml_str)
- else:
- return '' + xml_str + ''
- else:
- if self.netentity or self.preference_value or self.route_policy_name or self.max_load \
- or self.ip_address or self.defaultmode or self.bfd_min_rx or self.bfd_min_tx or self.bfd_multiplier_num is not None:
- return xml_str
- else:
- return '' + xml_str + ''
-
- def netconf_load_config(self, xml_str):
- """load bfd config by netconf"""
-
- if not xml_str:
- return
- if xml_str == "%s" % self.instance_id:
- pass
- else:
- xml_cfg = """
-
-
- %s
-
- """ % xml_str
- set_nc_config(self.module, xml_cfg)
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
- levelcost = 16777215
- if not self.instance_id:
- self.module.fail_json(msg="Error: Missing required arguments: instance_id.")
-
- if self.instance_id:
- if self.instance_id < 1 or self.instance_id > 4294967295:
- self.module.fail_json(msg="Error: Instance id is not ranges from 1 to 4294967295.")
-
- # check description
- if self.description:
- if len(self.description) < 1 or len(self.description) > 80:
- self.module.fail_json(msg="Error: description is invalid.")
-
- #
- if self.stdbandwidth:
- if self.stdbandwidth < 1 or self.stdbandwidth > 2147483648:
- self.module.fail_json(msg="Error: stdbandwidth is not ranges from 1 to 2147483648.")
-
- if self.relaxspfLimit is not None and not self.coststyle:
- self.module.fail_json(msg="Error: relaxspfLimit must set after coststyle.")
-
- if self.coststyle:
- if self.coststyle != "wide" and self.coststyle != "wtransition":
- levelcost = 63
- else:
- levelcost = 16777215
- if self.stdlevel1cost:
- if self.stdlevel1cost < 1 or self.stdlevel1cost > levelcost:
- self.module.fail_json(msg="Error: stdlevel1cost is not ranges from 1 to %s." % levelcost)
-
- if self.stdlevel2cost:
- if self.stdlevel2cost < 1 or self.stdlevel2cost > levelcost:
- self.module.fail_json(msg="Error: stdlevel2cost is not ranges from 1 to %s." % levelcost)
-
- if self.coststyle:
- if self.coststyle != "ntransition" and self.coststyle != "transition":
- if self.relaxspfLimit:
- self.module.fail_json(msg="Error: relaxspfLimit can not be set while the coststyle is not ntransition or transition")
-
- if self.autocostenablecompatible:
- if not self.autocostenable:
- self.module.fail_json(msg="Error: you shoule enable the autocostenable first.")
-
- if self.preference_value:
- if self.preference_value < 1 or self.preference_value > 255:
- self.module.fail_json(msg="Error: preference_value is not ranges from 1 to 255.")
-
- if self.route_policy_name:
- if len(self.route_policy_name) < 1 or len(self.route_policy_name) > 200:
- self.module.fail_json(msg="Error: route_policy_name is invalid.")
-
- if self.max_load:
- if self.max_load < 1 or self.max_load > 32:
- self.module.fail_json(msg="Error: max_load is not ranges from 1 to 32.")
-
- if self.weight:
- if self.weight < 1 or self.weight > 254:
- self.module.fail_json(msg="Error: weight is not ranges from 1 to 254.")
-
- if self.aclnum_or_name:
- if isinstance(self.aclnum_or_name, int):
- if self.aclnum_or_name < 2000 or self.aclnum_or_name > 2999:
- self.module.fail_json(msg="Error: acl_num is not ranges from 2000 to 2999.")
- elif isinstance(self.aclnum_or_name, str):
- if len(self.aclnum_or_name) < 1 or len(self.aclnum_or_name) > 32:
- self.module.fail_json(msg="Error: acl_name is invalid.")
- if self.ip_prefix_name:
- if len(self.ip_prefix_name) < 1 or len(self.ip_prefix_name) > 169:
- self.module.fail_json(msg="Error: ip_prefix_name is invalid.")
- if self.import_routepolicy_name:
- if len(self.import_routepolicy_name) < 1 or len(self.import_routepolicy_name) > 200:
- self.module.fail_json(msg="Error: import_routepolicy_name is invalid.")
- if self.tag:
- if self.tag < 1 or self.tag > 4294967295:
- self.module.fail_json(msg="Error: tag is not ranges from 1 to 4294967295.")
-
- if self.mode_routepolicyname:
- if len(self.mode_routepolicyname) < 1 or len(self.mode_routepolicyname) > 200:
- self.module.fail_json(msg="Error: mode_routepolicyname is invalid.")
- if self.cost is not None:
- if self.cost < 0 or self.cost > 4261412864:
- self.module.fail_json(msg="Error: cost is not ranges from 0 to 4261412864.")
- if self.mode_tag:
- if self.mode_tag < 1 or self.mode_tag > 4294967295:
- self.module.fail_json(msg="Error: mode_tag is not ranges from 1 to 4294967295.")
-
- if self.processid is not None:
- if self.processid < 0 or self.processid > 4294967295:
- self.module.fail_json(msg="Error: processid is not ranges from 0 to 4294967295.")
-
- if self.import_cost is not None:
- if self.import_cost < 0 or self.import_cost > 4261412864:
- self.module.fail_json(msg="Error: import_cost is not ranges from 0 to 4261412864.")
-
- if self.import_tag:
- if self.import_tag < 1 or self.import_tag > 4294967295:
- self.module.fail_json(msg="Error: import_tag is not ranges from 1 to 4294967295.")
-
- if self.export_aclnumorname:
- if isinstance(self.export_aclnumorname, int):
- if self.export_aclnumorname < 2000 or self.export_aclnumorname > 2999:
- self.module.fail_json(msg="Error: acl_num is not ranges from 2000 to 2999.")
- elif isinstance(self.export_aclnumorname, str):
- if len(self.export_aclnumorname) < 1 or len(self.export_aclnumorname) > 32:
- self.module.fail_json(msg="Error: acl_name is invalid.")
-
- if self.export_processid:
- if self.export_processid < 1 or self.export_processid > 4294967295:
- self.module.fail_json(msg="Error: export_processid is not ranges from 1 to 4294967295.")
-
- if self.export_ipprefix:
- if len(self.export_ipprefix) < 1 or len(self.export_ipprefix) > 169:
- self.module.fail_json(msg="Error: export_ipprefix is invalid.")
-
- if self.export_routepolicyname:
- if len(self.export_routepolicyname) < 1 or len(self.export_routepolicyname) > 200:
- self.module.fail_json(msg="Error: export_routepolicyname is invalid.")
-
- if self.bfd_min_rx:
- if self.bfd_min_rx < 50 or self.bfd_min_rx > 1000:
- self.module.fail_json(msg="Error: bfd_min_rx is not ranges from 50 to 1000.")
-
- if self.bfd_min_tx:
- if self.bfd_min_tx < 50 or self.bfd_min_tx > 1000:
- self.module.fail_json(msg="Error: bfd_min_tx is not ranges from 50 to 1000.")
-
- if self.bfd_multiplier_num:
- if self.bfd_multiplier_num < 3 or self.bfd_multiplier_num > 50:
- self.module.fail_json(msg="Error: bfd_multiplier_num is not ranges from 3 to 50.")
-
- if self.import_routepolicyname:
- if len(self.import_routepolicyname) < 1 or len(self.import_routepolicyname) > 200:
- self.module.fail_json(msg="Error: import_routepolicyname is invalid.")
-
- if self.import_aclnumorname:
- if isinstance(self.import_aclnumorname, int):
- if self.import_aclnumorname < 2000 or self.import_aclnumorname > 2999:
- self.module.fail_json(msg="Error: acl_num is not ranges from 2000 to 2999.")
- elif isinstance(self.import_aclnumorname, str):
- if len(self.import_aclnumorname) < 1 or len(self.import_aclnumorname) > 32:
- self.module.fail_json(msg="Error: acl_name is invalid.")
-
- def get_proposed(self):
- """get proposed info"""
- # base config
- self.proposed["instance_id"] = self.instance_id
- self.proposed["description"] = self.description
- self.proposed["islevel"] = self.islevel
- self.proposed["coststyle"] = self.coststyle
- self.proposed["relaxspfLimit"] = self.relaxspfLimit
- self.proposed["stdlevel1cost"] = self.stdlevel1cost
- self.proposed["stdlevel2cost"] = self.stdlevel2cost
- self.proposed["stdbandwidth"] = self.stdbandwidth
- self.proposed["autocostenable"] = self.autocostenable
- self.proposed["autocostenablecompatible"] = self.autocostenablecompatible
- self.proposed["netentity"] = self.netentity
- self.proposed["preference_value"] = self.preference_value
- self.proposed["route_policy_name"] = self.route_policy_name
- self.proposed["max_load"] = self.max_load
- self.proposed["ip_address"] = self.ip_address
- self.proposed["weight"] = self.weight
- self.proposed["penetration_direct"] = self.penetration_direct
- self.proposed["aclnum_or_name"] = self.aclnum_or_name
- self.proposed["ip_prefix_name"] = self.ip_prefix_name
- self.proposed["import_routepolicy_name"] = self.import_routepolicy_name
- self.proposed["tag"] = self.tag
- self.proposed["allow_filter"] = self.allow_filter
- self.proposed["allow_up_down"] = self.allow_up_down
- self.proposed["enablelevel1tolevel2"] = self.enablelevel1tolevel2
- self.proposed["protocol"] = self.protocol
- self.proposed["processid"] = self.processid
- self.proposed["cost_type"] = self.cost_type
- self.proposed["import_cost"] = self.import_cost
- self.proposed["import_tag"] = self.import_tag
- self.proposed["import_route_policy"] = self.import_route_policy
- self.proposed["impotr_leveltype"] = self.impotr_leveltype
- self.proposed["inheritcost"] = self.inheritcost
- self.proposed["permitibgp"] = self.permitibgp
- self.proposed["export_protocol"] = self.export_protocol
- self.proposed["export_policytype"] = self.export_policytype
- self.proposed["export_processid"] = self.export_processid
- self.proposed["export_aclnumorname"] = self.export_aclnumorname
- self.proposed["export_ipprefix"] = self.export_ipprefix
- self.proposed["export_routepolicyname"] = self.export_routepolicyname
- self.proposed["import_aclnumorname"] = self.import_aclnumorname
- self.proposed["import_ipprefix"] = self.import_ipprefix
- self.proposed["import_routepolicyname"] = self.import_routepolicyname
- self.proposed["bfd_min_rx"] = self.bfd_min_rx
- self.proposed["bfd_min_tx"] = self.bfd_min_tx
- self.proposed["bfd_multiplier_num"] = self.bfd_multiplier_num
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- if not self.isis_dict:
- self.existing["instance"] = None
- else:
- self.existing["instance"] = self.isis_dict.get("instance")
-
- def get_end_state(self):
- """get end state info"""
-
- isis_dict = self.get_isis_dict()
- if not isis_dict:
- self.end_state["instance"] = None
- else:
- self.end_state["instance"] = isis_dict.get("instance")
- if self.end_state == self.existing:
- self.changed = False
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.isis_dict = self.get_isis_dict()
- self.get_existing()
- self.get_proposed()
-
- # deal present or absent
- xml_str = ''
- if self.instance_id:
- xml_str += self.config_session()
- # update to device
- if xml_str:
- self.netconf_load_config(xml_str)
- self.changed = True
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- instance_id=dict(required=True, type='int'),
- description=dict(required=False, type='str'),
- islevel=dict(required=False, type='str', choices=['level_1', 'level_2', 'level_1_2']),
- coststyle=dict(required=False, type='str', choices=['narrow', 'wide', 'transition', 'ntransition', 'wtransition']),
- relaxspfLimit=dict(required=False, type='bool'),
- stdlevel1cost=dict(required=False, type='int'),
- stdlevel2cost=dict(required=False, type='int'),
- stdbandwidth=dict(required=False, type='int'),
- autocostenable=dict(required=False, type='bool'),
- autocostenablecompatible=dict(required=False, type='bool'),
- netentity=dict(required=False, type='str'),
- preference_value=dict(required=False, type='int'),
- route_policy_name=dict(required=False, type='str'),
- max_load=dict(required=False, type='int'),
- ip_address=dict(required=False, type='str'),
- weight=dict(required=False, type='int'),
- penetration_direct=dict(required=False, type='str', choices=['level2-level1', 'level1-level2']),
- aclnum_or_name=dict(required=False, type='str'),
- ip_prefix_name=dict(required=False, type='str'),
- import_routepolicy_name=dict(required=False, type='str'),
- tag=dict(required=False, type='int'),
- allow_filter=dict(required=False, type='bool'),
- allow_up_down=dict(required=False, type='bool'),
- enablelevel1tolevel2=dict(required=False, type='bool'),
- defaultmode=dict(required=False, type='str', choices=['always', 'matchDefault', 'matchAny']),
- mode_routepolicyname=dict(required=False, type='str'),
- cost=dict(required=False, type='int'),
- mode_tag=dict(required=False, type='int'),
- level_type=dict(required=False, type='str', choices=['level_1', 'level_2', 'level_1_2']),
- avoid_learning=dict(required=False, type='bool'),
- protocol=dict(required=False, type='str', choices=['direct', 'ospf', 'isis', 'static', 'rip', 'bgp', 'ospfv3', 'all']),
- processid=dict(required=False, type='int'),
- cost_type=dict(required=False, type='str', choices=['external', 'internal']),
- import_cost=dict(required=False, type='int'),
- import_tag=dict(required=False, type='int'),
- import_route_policy=dict(required=False, type='str'),
- impotr_leveltype=dict(required=False, type='str', choices=['level_1', 'level_2', 'level_1_2']),
- inheritcost=dict(required=False, type='bool'),
- permitibgp=dict(required=False, type='bool'),
- export_protocol=dict(required=False, type='str', choices=['direct', 'ospf', 'isis', 'static', 'rip', 'bgp', 'ospfv3', 'all']),
- export_policytype=dict(required=False, type='str', choices=['aclNumOrName', 'ipPrefix', 'routePolicy']),
- export_processid=dict(required=False, type='int'),
- export_aclnumorname=dict(required=False, type='str'),
- export_ipprefix=dict(required=False, type='str'),
- export_routepolicyname=dict(required=False, type='str'),
- import_aclnumorname=dict(required=False, type='str'),
- import_ipprefix=dict(required=False, type='str'),
- import_routepolicyname=dict(required=False, type='str'),
- bfd_min_rx=dict(required=False, type='int'),
- bfd_min_tx=dict(required=False, type='int'),
- bfd_multiplier_num=dict(required=False, type='int'),
- state=dict(required=False, default='present', choices=['present', 'absent'])
- )
-
- module = ISIS_View(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_lacp.py b/plugins/modules/network/cloudengine/ce_lacp.py
deleted file mode 100644
index 769499a8ad..0000000000
--- a/plugins/modules/network/cloudengine/ce_lacp.py
+++ /dev/null
@@ -1,492 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: ce_lacp
-short_description: Manages Eth-Trunk interfaces on HUAWEI CloudEngine switches
-description:
- - Manages Eth-Trunk specific configuration parameters on HUAWEI CloudEngine switches.
-author: xuxiaowei0512 (@CloudEngine-Ansible)
-notes:
- - C(state=absent) removes the Eth-Trunk config and interface if it already exists. If members to be removed are not explicitly
- passed, all existing members (if any), are removed, and Eth-Trunk removed.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- trunk_id:
- description:
- - Eth-Trunk interface number.
- The value is an integer.
- The value range depends on the assign forward eth-trunk mode command.
- When 256 is specified, the value ranges from 0 to 255.
- When 512 is specified, the value ranges from 0 to 511.
- When 1024 is specified, the value ranges from 0 to 1023.
- type: int
- mode:
- description:
- - Specifies the working mode of an Eth-Trunk interface.
- default: null
- choices: ['Manual','Dynamic','Static']
- type: str
- preempt_enable:
- description:
- - Specifies lacp preempt enable of Eth-Trunk lacp.
- The value is an boolean 'true' or 'false'.
- type: bool
- state_flapping:
- description:
- - Lacp dampening state-flapping.
- type: bool
- port_id_extension_enable:
- description:
- - Enable the function of extending the LACP negotiation port number.
- type: bool
- unexpected_mac_disable:
- description:
- - Lacp dampening unexpected-mac disable.
- type: bool
- system_id:
- description:
- - Link Aggregation Control Protocol System ID,interface Eth-Trunk View.
- - Formate 'X-X-X',X is hex(a,aa,aaa, or aaaa)
- type: str
- timeout_type:
- description:
- - Lacp timeout type,that may be 'Fast' or 'Slow'.
- choices: ['Slow', 'Fast']
- type: str
- fast_timeout:
- description:
- - When lacp timeout type is 'Fast', user-defined time can be a number(3~90).
- type: int
- mixed_rate_link_enable:
- description:
- - Value of max active linknumber.
- type: bool
- preempt_delay:
- description:
- - Value of preemption delay time.
- type: int
- collector_delay:
- description:
- - Value of delay time in units of 10 microseconds.
- type: int
- max_active_linknumber:
- description:
- - Max active linknumber in link aggregation group.
- type: int
- select:
- description:
- - Select priority or speed to preempt.
- choices: ['Speed', 'Prority']
- type: str
- priority:
- description:
- - The priority of eth-trunk member interface.
- type: int
- global_priority:
- description:
- - Configure lacp priority on system-view.
- type: int
- state:
- description:
- - Manage the state of the resource.
- default: present
- choices: ['present','absent']
- type: str
-'''
-EXAMPLES = r'''
- - name: Ensure Eth-Trunk100 is created, and set to mode lacp-static
- ce_lacp:
- trunk_id: 100
- mode: 'lacp-static'
- state: present
- - name: Ensure Eth-Trunk100 is created, add two members, and set global priority to 1231
- ce_lacp:
- trunk_id: 100
- global_priority: 1231
- state: present
- - name: Ensure Eth-Trunk100 is created, and set mode to Dynamic and configure other options
- ce_lacp:
- trunk_id: 100
- mode: Dynamic
- preempt_enable: True,
- state_flapping: True,
- port_id_extension_enable: True,
- unexpected_mac_disable: True,
- timeout_type: Fast,
- fast_timeout: 123,
- mixed_rate_link_enable: True,
- preempt_delay: 23,
- collector_delay: 33,
- state: present
-'''
-
-RETURN = r'''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"trunk_id": "100", "members": ['10GE1/0/24','10GE1/0/25'], "mode": "lacp-static"}
-existing:
- description: k/v pairs of existing Eth-Trunk
- returned: always
- type: dict
- sample: {"trunk_id": "100", "hash_type": "mac", "members_detail": [
- {"memberIfName": "10GE1/0/25", "memberIfState": "Down"}],
- "min_links": "1", "mode": "manual"}
-end_state:
- description: k/v pairs of Eth-Trunk info after module execution
- returned: always
- type: dict
- sample: {"trunk_id": "100", "hash_type": "mac", "members_detail": [
- {"memberIfName": "10GE1/0/24", "memberIfState": "Down"},
- {"memberIfName": "10GE1/0/25", "memberIfState": "Down"}],
- "min_links": "1", "mode": "lacp-static"}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["interface Eth-Trunk 100",
- "mode lacp-static",
- "interface 10GE1/0/25",
- "eth-trunk 100"]
-'''
-
-import xml.etree.ElementTree as ET
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils._text import to_native
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config
-
-LACP = {'trunk_id': 'ifName',
- 'mode': 'workMode',
- 'preempt_enable': 'isSupportPrmpt',
- 'state_flapping': 'dampStaFlapEn',
- 'port_id_extension_enable': 'trunkPortIdExt',
- 'unexpected_mac_disable': 'dampUnexpMacEn',
- 'system_id': 'trunkSysMac',
- 'timeout_type': 'rcvTimeoutType',
- 'fast_timeout': 'fastTimeoutUserDefinedValue',
- 'mixed_rate_link_enable': 'mixRateEnable',
- 'preempt_delay': 'promptDelay',
- 'collector_delay': 'collectMaxDelay',
- 'max_active_linknumber': 'maxActiveNum',
- 'select': 'selectPortStd',
- 'weight': 'weight',
- 'priority': 'portPriority',
- 'global_priority': 'priority'
- }
-
-
-def has_element(parent, xpath):
- """get or create a element by xpath"""
- ele = parent.find('./' + xpath)
- if ele is not None:
- return ele
- ele = parent
- lpath = xpath.split('/')
- for p in lpath:
- e = parent.find('.//' + p)
- if e is None:
- e = ET.SubElement(ele, p)
- ele = e
- return ele
-
-
-def bulid_xml(kwargs, operation='get'):
- """create a xml tree by dictionary with operation,get,merge and delete"""
- attrib = {'xmlns': "http://www.huawei.com/netconf/vrp",
- 'content-version': "1.0", 'format-version': "1.0"}
-
- root = ET.Element('ifmtrunk')
- for key in kwargs.keys():
- if key in ('global_priority',):
- xpath = 'lacpSysInfo'
- elif key in ('priority',):
- xpath = 'TrunkIfs/TrunkIf/TrunkMemberIfs/TrunkMemberIf/lacpPortInfo/lacpPort'
- elif key in ['preempt_enable', 'timeout_type', 'fast_timeout', 'select', 'preempt_delay',
- 'max_active_linknumber', 'collector_delay', 'mixed_rate_link_enable',
- 'state_flapping', 'unexpected_mac_disable', 'system_id',
- 'port_id_extension_enable']:
- xpath = 'TrunkIfs/TrunkIf/lacpTrunk'
- elif key in ('trunk_id', 'mode'):
- xpath = 'TrunkIfs/TrunkIf'
- if xpath != '':
- parent = has_element(root, xpath)
- element = ET.SubElement(parent, LACP[key])
- if operation == 'merge':
- parent.attrib = dict(operation=operation)
- element.text = str(kwargs[key])
- if key == 'mode':
- element.text = str(kwargs[key])
- if key == 'trunk_id':
- element.text = 'Eth-Trunk' + str(kwargs[key])
- root.attrib = attrib
- config = ET.tostring(root)
- if operation == 'merge' or operation == 'delete':
- return '%s' % to_native(config)
- return '%s' % to_native(config)
-
-
-def check_param(kwargs):
- """check args list,the boolean or list values cloud not be checked,because they are limit by args list in main"""
-
- for key in kwargs:
- if kwargs[key] is None:
- continue
- if key == 'trunk_id':
- value = int(kwargs[key])
- # maximal value is 1024,although the value is limit by command 'assign forward eth-trunk mode '
- if value < 0 or value > 1024:
- return 'Error: Wrong Value of Eth-Trunk interface number'
- elif key == 'system_id':
- # X-X-X ,X is hex(4 bit)
- if not re.match(r'[0-9a-f]{1,4}\-[0-9a-f]{1,4}\-[0-9a-f]{1,4}', kwargs[key], re.IGNORECASE):
- return 'Error: The system-id is invalid.'
- values = kwargs[key].split('-')
- flag = 0
- # all 'X' is 0,that is invalid value
- for v in values:
- if len(v.strip('0')) < 1:
- flag += 1
- if flag == 3:
- return 'Error: The system-id is invalid.'
- elif key == 'timeout_type':
- # select a value from choices, choices=['Slow','Fast'],it's checked by AnsibleModule
- pass
- elif key == 'fast_timeout':
- value = int(kwargs[key])
- if value < 3 or value > 90:
- return 'Error: Wrong Value of timeout,fast user-defined value<3-90>'
- rtype = str(kwargs.get('timeout_type'))
- if rtype == 'Slow':
- return 'Error: Short timeout period for receiving packets is need,when user define the time.'
- elif key == 'preempt_delay':
- value = int(kwargs[key])
- if value < 0 or value > 180:
- return 'Error: Value of preemption delay time is from 0 to 180'
- elif key == 'collector_delay':
- value = int(kwargs[key])
- if value < 0 or value > 65535:
- return 'Error: Value of collector delay time is from 0 to 65535'
- elif key == 'max_active_linknumber':
- value = int(kwargs[key])
- if value < 0 or value > 64:
- return 'Error: Value of collector delay time is from 0 to 64'
- elif key == 'priority' or key == 'global_priority':
- value = int(kwargs[key])
- if value < 0 or value > 65535:
- return 'Error: Value of priority is from 0 to 65535'
- return 'ok'
-
-
-def xml_to_dict(args):
- """transfer xml string into dict """
- rdict = dict()
- args = re.sub(r'xmlns=\".+?\"', '', args)
- root = ET.fromstring(args)
- ifmtrunk = root.find('.//ifmtrunk')
- if ifmtrunk is not None:
- try:
- ifmtrunk_iter = ET.Element.iter(ifmtrunk)
- except AttributeError:
- ifmtrunk_iter = ifmtrunk.getiterator()
-
- for ele in ifmtrunk_iter:
- if ele.text is not None and len(ele.text.strip()) > 0:
- rdict[ele.tag] = ele.text
- return rdict
-
-
-def compare_config(module, kwarg_exist, kwarg_end):
- """compare config between exist and end"""
- dic_command = {'isSupportPrmpt': 'lacp preempt enable',
- 'rcvTimeoutType': 'lacp timeout', # lacp timeout fast user-defined 23
- 'fastTimeoutUserDefinedValue': 'lacp timeout user-defined',
- 'selectPortStd': 'lacp select',
- 'promptDelay': 'lacp preempt delay',
- 'maxActiveNum': 'lacp max active-linknumber',
- 'collectMaxDelay': 'lacp collector delay',
- 'mixRateEnable': 'lacp mixed-rate link enable',
- 'dampStaFlapEn': 'lacp dampening state-flapping',
- 'dampUnexpMacEn': 'lacp dampening unexpected-mac disable',
- 'trunkSysMac': 'lacp system-id',
- 'trunkPortIdExt': 'lacp port-id-extension enable',
- 'portPriority': 'lacp priority', # interface 10GE1/0/1
- 'lacpMlagPriority': 'lacp m-lag priority',
- 'lacpMlagSysId': 'lacp m-lag system-id',
- 'priority': 'lacp priority'
- }
- rlist = list()
- exist = set(kwarg_exist.keys())
- end = set(kwarg_end.keys())
- undo = exist - end
- add = end - exist
- update = end & exist
-
- for key in undo:
- if key in dic_command:
- rlist.append('undo ' + dic_command[key])
- for key in add:
- if key in dic_command:
- rlist.append(dic_command[key] + ' ' + kwarg_end[key])
- for key in update:
- if kwarg_exist[key] != kwarg_end[key] and key in dic_command:
- if kwarg_exist[key] == 'true' and kwarg_end[key] == 'false':
- rlist.append('undo ' + dic_command[key])
- elif kwarg_exist[key] == 'false' and kwarg_end[key] == 'true':
- rlist.append(dic_command[key])
- else:
- rlist.append(dic_command[key] + ' ' + kwarg_end[key].lower())
- return rlist
-
-
-class Lacp(object):
- """
- Manages Eth-Trunk interfaces LACP.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.trunk_id = self.module.params['trunk_id']
- self.mode = self.module.params['mode']
- self.param = dict()
-
- self.state = self.module.params['state']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def init_module(self):
- """ init AnsibleModule """
-
- self.module = AnsibleModule(
- argument_spec=self.spec,
- mutually_exclusive=[['trunk_id', 'global_priority']],
- required_one_of=[['trunk_id', 'global_priority']],
- supports_check_mode=True)
-
- def check_params(self):
- """check module params """
- for key in self.module.params.keys():
- if key in LACP.keys() and self.module.params[key] is not None:
- self.param[key] = self.module.params[key]
- if isinstance(self.module.params[key], bool):
- self.param[key] = str(self.module.params[key]).lower()
- msg = check_param(self.param)
- if msg != 'ok':
- self.module.fail_json(msg=msg)
-
- def get_existing(self):
- """get existing"""
- xml_str = bulid_xml(self.param)
- xml = get_nc_config(self.module, xml_str)
- return xml_to_dict(xml)
-
- def get_proposed(self):
- """get proposed"""
- proposed = dict(state=self.state)
- proposed.update(self.param)
- return proposed
-
- def get_end_state(self):
- """ get end_state"""
- xml_str = bulid_xml(self.param)
- xml = get_nc_config(self.module, xml_str)
- return xml_to_dict(xml)
-
- def work(self):
- """worker"""
-
- self.check_params()
- existing = self.get_existing()
- proposed = self.get_proposed()
-
- # deal present or absent
- if self.state == "present":
- operation = 'merge'
- else:
- operation = 'delete'
-
- xml_str = bulid_xml(self.param, operation=operation)
- set_nc_config(self.module, xml_str)
- end_state = self.get_end_state()
-
- self.results['proposed'] = proposed
- self.results['existing'] = existing
- self.results['end_state'] = end_state
- updates_cmd = compare_config(self.module, existing, end_state)
- self.results['updates'] = updates_cmd
- if updates_cmd:
- self.results['changed'] = True
- else:
- self.results['changed'] = False
-
- self.module.exit_json(**self.results)
-
-
-def main():
-
- argument_spec = dict(
- mode=dict(required=False,
- choices=['Manual', 'Dynamic', 'Static'],
- type='str'),
- trunk_id=dict(required=False, type='int'),
- preempt_enable=dict(required=False, type='bool'),
- state_flapping=dict(required=False, type='bool'),
- port_id_extension_enable=dict(required=False, type='bool'),
- unexpected_mac_disable=dict(required=False, type='bool'),
- system_id=dict(required=False, type='str'),
- timeout_type=dict(required=False, type='str', choices=['Slow', 'Fast']),
- fast_timeout=dict(required=False, type='int'),
- mixed_rate_link_enable=dict(required=False, type='bool'),
- preempt_delay=dict(required=False, type='int'),
- collector_delay=dict(required=False, type='int'),
- max_active_linknumber=dict(required=False, type='int'),
- select=dict(required=False, type='str', choices=['Speed', 'Prority']),
- priority=dict(required=False, type='int'),
- global_priority=dict(required=False, type='int'),
- state=dict(required=False, default='present',
- choices=['present', 'absent'])
- )
-
- module = Lacp(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_link_status.py b/plugins/modules/network/cloudengine/ce_link_status.py
deleted file mode 100644
index c1c58e8a93..0000000000
--- a/plugins/modules/network/cloudengine/ce_link_status.py
+++ /dev/null
@@ -1,568 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-
-module: ce_link_status
-short_description: Get interface link status on HUAWEI CloudEngine switches.
-description:
- - Get interface link status on HUAWEI CloudEngine switches.
-author:
- - Zhijin Zhou (@QijunPan)
-notes:
- - Current physical state shows an interface's physical status.
- - Current link state shows an interface's link layer protocol status.
- - Current IPv4 state shows an interface's IPv4 protocol status.
- - Current IPv6 state shows an interface's IPv6 protocol status.
- - Inbound octets(bytes) shows the number of bytes that an interface received.
- - Inbound unicast(pkts) shows the number of unicast packets that an interface received.
- - Inbound multicast(pkts) shows the number of multicast packets that an interface received.
- - Inbound broadcast(pkts) shows the number of broadcast packets that an interface received.
- - Inbound error(pkts) shows the number of error packets that an interface received.
- - Inbound drop(pkts) shows the total number of packets that were sent to the interface but dropped by an interface.
- - Inbound rate(byte/sec) shows the rate at which an interface receives bytes within an interval.
- - Inbound rate(pkts/sec) shows the rate at which an interface receives packets within an interval.
- - Outbound octets(bytes) shows the number of the bytes that an interface sent.
- - Outbound unicast(pkts) shows the number of unicast packets that an interface sent.
- - Outbound multicast(pkts) shows the number of multicast packets that an interface sent.
- - Outbound broadcast(pkts) shows the number of broadcast packets that an interface sent.
- - Outbound error(pkts) shows the total number of packets that an interface sent but dropped by the remote interface.
- - Outbound drop(pkts) shows the number of dropped packets that an interface sent.
- - Outbound rate(byte/sec) shows the rate at which an interface sends bytes within an interval.
- - Outbound rate(pkts/sec) shows the rate at which an interface sends packets within an interval.
- - Speed shows the rate for an Ethernet interface.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- interface:
- description:
- - For the interface parameter, you can enter C(all) to display information about all interfaces,
- an interface type such as C(40GE) to display information about interfaces of the specified type,
- or full name of an interface such as C(40GE1/0/22) or C(vlanif10)
- to display information about the specific interface.
- required: true
-'''
-
-EXAMPLES = '''
-
-- name: Link status test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Get specified interface link status information
- ce_link_status:
- interface: 40GE1/0/1
- provider: "{{ cli }}"
-
- - name: Get specified interface type link status information
- ce_link_status:
- interface: 40GE
- provider: "{{ cli }}"
-
- - name: Get all interfaces link status information
- ce_link_status:
- interface: all
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-result:
- description: Interface link status information
- returned: always
- type: dict
- sample: {
- "40ge2/0/8": {
- "Current IPv4 state": "down",
- "Current IPv6 state": "down",
- "Current link state": "up",
- "Current physical state": "up",
- "Inbound broadcast(pkts)": "0",
- "Inbound drop(pkts)": "0",
- "Inbound error(pkts)": "0",
- "Inbound multicast(pkts)": "20151",
- "Inbound octets(bytes)": "7314813",
- "Inbound rate(byte/sec)": "11",
- "Inbound rate(pkts/sec)": "0",
- "Inbound unicast(pkts)": "0",
- "Outbound broadcast(pkts)": "1",
- "Outbound drop(pkts)": "0",
- "Outbound error(pkts)": "0",
- "Outbound multicast(pkts)": "20152",
- "Outbound octets(bytes)": "7235021",
- "Outbound rate(byte/sec)": "11",
- "Outbound rate(pkts/sec)": "0",
- "Outbound unicast(pkts)": "0",
- "Speed": "40GE"
- }
- }
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec, get_nc_config, get_nc_next
-
-CE_NC_GET_PORT_SPEED = """
-
-
-
-
- %s
-
-
-
-
-
-
-
-"""
-
-CE_NC_GET_INT_STATISTICS = """
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-INTERFACE_ALL = 1
-INTERFACE_TYPE = 2
-INTERFACE_FULL_NAME = 3
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- if interface.upper().startswith('GE'):
- return 'ge'
- elif interface.upper().startswith('10GE'):
- return '10ge'
- elif interface.upper().startswith('25GE'):
- return '25ge'
- elif interface.upper().startswith('4X10GE'):
- return '4x10ge'
- elif interface.upper().startswith('40GE'):
- return '40ge'
- elif interface.upper().startswith('100GE'):
- return '100ge'
- elif interface.upper().startswith('VLANIF'):
- return 'vlanif'
- elif interface.upper().startswith('LOOPBACK'):
- return 'loopback'
- elif interface.upper().startswith('METH'):
- return 'meth'
- elif interface.upper().startswith('ETH-TRUNK'):
- return 'eth-trunk'
- elif interface.upper().startswith('VBDIF'):
- return 'vbdif'
- elif interface.upper().startswith('NVE'):
- return 'nve'
- elif interface.upper().startswith('TUNNEL'):
- return 'tunnel'
- elif interface.upper().startswith('ETHERNET'):
- return 'ethernet'
- elif interface.upper().startswith('FCOE-PORT'):
- return 'fcoe-port'
- elif interface.upper().startswith('FABRIC-PORT'):
- return 'fabric-port'
- elif interface.upper().startswith('STACK-PORT'):
- return 'stack-Port'
- elif interface.upper().startswith('NULL'):
- return 'null'
- else:
- return None
-
-
-def is_ethernet_port(interface):
- """Judge whether it is ethernet port"""
-
- ethernet_port = ['ge', '10ge', '25ge', '4x10ge', '40ge', '100ge', 'meth']
- if_type = get_interface_type(interface)
- if if_type in ethernet_port:
- return True
- return False
-
-
-class LinkStatus(object):
- """Get interface link status information"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # interface name
- self.interface = self.module.params['interface']
- self.interface = self.interface.replace(' ', '').lower()
- self.param_type = None
- self.if_type = None
-
- # state
- self.results = dict()
- self.result = dict()
-
- def check_params(self):
- """Check all input params"""
-
- if not self.interface:
- self.module.fail_json(msg='Error: Interface name cannot be empty.')
-
- if self.interface and self.interface != 'all':
- if not self.if_type:
- self.module.fail_json(
- msg='Error: Interface name of %s is error.' % self.interface)
-
- def init_module(self):
- """Init module object"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def show_result(self):
- """Show result"""
-
- self.results['result'] = self.result
-
- self.module.exit_json(**self.results)
-
- def get_intf_dynamic_info(self, dyn_info, intf_name):
- """Get interface dynamic information"""
-
- if not intf_name:
- return
-
- if dyn_info:
- for eles in dyn_info:
- if eles.tag in ["ifPhyStatus", "ifV4State", "ifV6State", "ifLinkStatus"]:
- if eles.tag == "ifPhyStatus":
- self.result[intf_name][
- 'Current physical state'] = eles.text
- elif eles.tag == "ifLinkStatus":
- self.result[intf_name][
- 'Current link state'] = eles.text
- elif eles.tag == "ifV4State":
- self.result[intf_name][
- 'Current IPv4 state'] = eles.text
- elif eles.tag == "ifV6State":
- self.result[intf_name][
- 'Current IPv6 state'] = eles.text
-
- def get_intf_statistics_info(self, stat_info, intf_name):
- """Get interface statistics information"""
-
- if not intf_name:
- return
-
- if_type = get_interface_type(intf_name)
- if if_type == 'fcoe-port' or if_type == 'nve' or if_type == 'tunnel' or \
- if_type == 'vbdif' or if_type == 'vlanif':
- return
-
- if stat_info:
- for eles in stat_info:
- if eles.tag in ["receiveByte", "sendByte", "rcvUniPacket", "rcvMutiPacket", "rcvBroadPacket",
- "sendUniPacket", "sendMutiPacket", "sendBroadPacket", "rcvErrorPacket",
- "rcvDropPacket", "sendErrorPacket", "sendDropPacket"]:
- if eles.tag == "receiveByte":
- self.result[intf_name][
- 'Inbound octets(bytes)'] = eles.text
- elif eles.tag == "rcvUniPacket":
- self.result[intf_name][
- 'Inbound unicast(pkts)'] = eles.text
- elif eles.tag == "rcvMutiPacket":
- self.result[intf_name][
- 'Inbound multicast(pkts)'] = eles.text
- elif eles.tag == "rcvBroadPacket":
- self.result[intf_name][
- 'Inbound broadcast(pkts)'] = eles.text
- elif eles.tag == "rcvErrorPacket":
- self.result[intf_name][
- 'Inbound error(pkts)'] = eles.text
- elif eles.tag == "rcvDropPacket":
- self.result[intf_name][
- 'Inbound drop(pkts)'] = eles.text
- elif eles.tag == "sendByte":
- self.result[intf_name][
- 'Outbound octets(bytes)'] = eles.text
- elif eles.tag == "sendUniPacket":
- self.result[intf_name][
- 'Outbound unicast(pkts)'] = eles.text
- elif eles.tag == "sendMutiPacket":
- self.result[intf_name][
- 'Outbound multicast(pkts)'] = eles.text
- elif eles.tag == "sendBroadPacket":
- self.result[intf_name][
- 'Outbound broadcast(pkts)'] = eles.text
- elif eles.tag == "sendErrorPacket":
- self.result[intf_name][
- 'Outbound error(pkts)'] = eles.text
- elif eles.tag == "sendDropPacket":
- self.result[intf_name][
- 'Outbound drop(pkts)'] = eles.text
-
- def get_intf_cleared_stat(self, clr_stat, intf_name):
- """Get interface cleared state information"""
-
- if not intf_name:
- return
-
- if_type = get_interface_type(intf_name)
- if if_type == 'fcoe-port' or if_type == 'nve' or if_type == 'tunnel' or \
- if_type == 'vbdif' or if_type == 'vlanif':
- return
-
- if clr_stat:
- for eles in clr_stat:
- if eles.tag in ["inByteRate", "inPacketRate", "outByteRate", "outPacketRate"]:
- if eles.tag == "inByteRate":
- self.result[intf_name][
- 'Inbound rate(byte/sec)'] = eles.text
- elif eles.tag == "inPacketRate":
- self.result[intf_name][
- 'Inbound rate(pkts/sec)'] = eles.text
- elif eles.tag == "outByteRate":
- self.result[intf_name][
- 'Outbound rate(byte/sec)'] = eles.text
- elif eles.tag == "outPacketRate":
- self.result[intf_name][
- 'Outbound rate(pkts/sec)'] = eles.text
-
- def get_all_interface_info(self, intf_type=None):
- """Get interface information by all or by interface type"""
-
- xml_str = CE_NC_GET_INT_STATISTICS % ''
- con_obj = get_nc_next(self.module, xml_str)
- if "" in con_obj:
- return
-
- xml_str = con_obj.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get link status information
- root = ElementTree.fromstring(xml_str)
- intfs_info = root.findall("ifm/interfaces/interface")
- if not intfs_info:
- return
-
- intf_name = ''
- flag = False
- for eles in intfs_info:
- if eles.tag == "interface":
- for ele in eles:
- if ele.tag in ["ifName", "ifDynamicInfo", "ifStatistics", "ifClearedStat"]:
- if ele.tag == "ifName":
- intf_name = ele.text.lower()
- if intf_type:
- if get_interface_type(intf_name) != intf_type.lower():
- break
- else:
- flag = True
- self.init_interface_data(intf_name)
- if is_ethernet_port(intf_name):
- self.get_port_info(intf_name)
- if ele.tag == "ifDynamicInfo":
- self.get_intf_dynamic_info(ele, intf_name)
- elif ele.tag == "ifStatistics":
- self.get_intf_statistics_info(ele, intf_name)
- elif ele.tag == "ifClearedStat":
- self.get_intf_cleared_stat(ele, intf_name)
- if intf_type and not flag:
- self.module.fail_json(
- msg='Error: %s interface type does not exist.' % intf_type.upper())
-
- def get_interface_info(self):
- """Get interface information"""
-
- xml_str = CE_NC_GET_INT_STATISTICS % self.interface.upper()
- con_obj = get_nc_config(self.module, xml_str)
- if "" in con_obj:
- self.module.fail_json(
- msg='Error: %s interface does not exist.' % self.interface.upper())
- return
-
- xml_str = con_obj.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get link status information
- root = ElementTree.fromstring(xml_str)
- intf_info = root.find("ifm/interfaces/interface")
- if intf_info:
- for eles in intf_info:
- if eles.tag in ["ifDynamicInfo", "ifStatistics", "ifClearedStat"]:
- if eles.tag == "ifDynamicInfo":
- self.get_intf_dynamic_info(eles, self.interface)
- elif eles.tag == "ifStatistics":
- self.get_intf_statistics_info(eles, self.interface)
- elif eles.tag == "ifClearedStat":
- self.get_intf_cleared_stat(eles, self.interface)
-
- def init_interface_data(self, intf_name):
- """Init interface data"""
-
- # init link status data
- self.result[intf_name] = dict()
- self.result[intf_name]['Current physical state'] = 'down'
- self.result[intf_name]['Current link state'] = 'down'
- self.result[intf_name]['Current IPv4 state'] = 'down'
- self.result[intf_name]['Current IPv6 state'] = 'down'
- self.result[intf_name]['Inbound octets(bytes)'] = '--'
- self.result[intf_name]['Inbound unicast(pkts)'] = '--'
- self.result[intf_name]['Inbound multicast(pkts)'] = '--'
- self.result[intf_name]['Inbound broadcast(pkts)'] = '--'
- self.result[intf_name]['Inbound error(pkts)'] = '--'
- self.result[intf_name]['Inbound drop(pkts)'] = '--'
- self.result[intf_name]['Inbound rate(byte/sec)'] = '--'
- self.result[intf_name]['Inbound rate(pkts/sec)'] = '--'
- self.result[intf_name]['Outbound octets(bytes)'] = '--'
- self.result[intf_name]['Outbound unicast(pkts)'] = '--'
- self.result[intf_name]['Outbound multicast(pkts)'] = '--'
- self.result[intf_name]['Outbound broadcast(pkts)'] = '--'
- self.result[intf_name]['Outbound error(pkts)'] = '--'
- self.result[intf_name]['Outbound drop(pkts)'] = '--'
- self.result[intf_name]['Outbound rate(byte/sec)'] = '--'
- self.result[intf_name]['Outbound rate(pkts/sec)'] = '--'
- self.result[intf_name]['Speed'] = '--'
-
- def get_port_info(self, interface):
- """Get port information"""
-
- if_type = get_interface_type(interface)
- if if_type == 'meth':
- xml_str = CE_NC_GET_PORT_SPEED % interface.lower().replace('meth', 'MEth')
- else:
- xml_str = CE_NC_GET_PORT_SPEED % interface.upper()
- con_obj = get_nc_config(self.module, xml_str)
- if "" in con_obj:
- return
-
- xml_str = con_obj.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get link status information
- root = ElementTree.fromstring(xml_str)
- port_info = root.find("devm/ports/port")
- if port_info:
- for eles in port_info:
- if eles.tag == "ethernetPort":
- for ele in eles:
- if ele.tag == 'speed':
- self.result[interface]['Speed'] = ele.text
-
- def get_link_status(self):
- """Get link status information"""
-
- if self.param_type == INTERFACE_FULL_NAME:
- self.init_interface_data(self.interface)
- self.get_interface_info()
- if is_ethernet_port(self.interface):
- self.get_port_info(self.interface)
- elif self.param_type == INTERFACE_TYPE:
- self.get_all_interface_info(self.interface)
- else:
- self.get_all_interface_info()
-
- def get_intf_param_type(self):
- """Get the type of input interface parameter"""
-
- if self.interface == 'all':
- self.param_type = INTERFACE_ALL
- return
-
- if self.if_type == self.interface:
- self.param_type = INTERFACE_TYPE
- return
-
- self.param_type = INTERFACE_FULL_NAME
-
- def work(self):
- """Worker"""
-
- self.if_type = get_interface_type(self.interface)
- self.check_params()
- self.get_intf_param_type()
- self.get_link_status()
- self.show_result()
-
-
-def main():
- """Main function entry"""
-
- argument_spec = dict(
- interface=dict(required=True, type='str'),
- )
- argument_spec.update(ce_argument_spec)
- linkstatus_obj = LinkStatus(argument_spec)
- linkstatus_obj.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_lldp.py b/plugins/modules/network/cloudengine/ce_lldp.py
deleted file mode 100644
index 3502ed3ee6..0000000000
--- a/plugins/modules/network/cloudengine/ce_lldp.py
+++ /dev/null
@@ -1,791 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-
-module: ce_lldp
-short_description: Manages LLDP configuration on HUAWEI CloudEngine switches.
-description:
- - Manages LLDP configuration on HUAWEI CloudEngine switches.
-author:
- - xuxiaowei0512 (@CloudEngine-Ansible)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- lldpenable:
- description:
- - Set global LLDP enable state.
- required: false
- choices: ['enabled', 'disabled']
- type: str
- mdnstatus:
- description:
- - Set global MDN enable state.
- required: false
- choices: ['rxOnly', 'disabled']
- type: str
- interval:
- description:
- - Frequency at which LLDP advertisements are sent (in seconds).
- required: false
- type: int
- hold_multiplier:
- description:
- - Time multiplier for device information in neighbor devices.
- required: false
- type: int
- restart_delay:
- description:
- - Specifies the delay time of the interface LLDP module from disabled state to re enable.
- required: false
- type: int
- transmit_delay:
- description:
- - Delay time for sending LLDP messages.
- required: false
- type: int
- notification_interval:
- description:
- - Suppression time for sending LLDP alarm.
- required: false
- type: int
- fast_count:
- description:
- - The number of LLDP messages sent to the neighbor nodes by the specified device.
- required: false
- type: int
- mdn_notification_interval:
- description:
- - Delay time for sending MDN neighbor information change alarm.
- required: false
- type: int
- management_address:
- description:
- - The management IP address of LLDP.
- required: false
- default: null
- type: str
- bind_name:
- description:
- - Binding interface name.
- required: false
- default: null
- type: str
- state:
- description:
- - Manage the state of the resource.
- required: false
- default: present
- type: str
- choices: ['present','absent']
-'''
-
-EXAMPLES = '''
- - name: "Configure global LLDP enable state"
- ce_lldp:
- lldpenable: enabled
-
- - name: "Configure global MDN enable state"
- ce_lldp:
- mdnstatus: rxOnly
-
- - name: "Configure LLDP transmit interval and ensure global LLDP state is already enabled"
- ce_lldp:
- enable: enable
- interval: 32
-
- - name: "Configure LLDP transmit multiplier hold and ensure global LLDP state is already enabled"
- ce_lldp:
- enable: enable
- hold_multiplier: 5
-
- - name: "Configure the delay time of the interface LLDP module from disabled state to re enable"
- ce_lldp:
- enable: enable
- restart_delay: 3
-
- - name: "Reset the delay time for sending LLDP messages"
- ce_lldp:
- enable: enable
- transmit_delay: 4
-
- - name: "Configure device to send neighbor device information change alarm delay time"
- ce_lldp:
- lldpenable: enabled
- notification_interval: 6
-
- - name: "Configure the number of LLDP messages sent to the neighbor nodes by the specified device"
- ce_lldp:
- enable: enable
- fast_count: 5
-
- - name: "Configure the delay time for sending MDN neighbor information change alarm"
- ce_lldp:
- enable: enable
- mdn_notification_interval: 6
- - name: "Configuring the management IP address of LLDP"
- ce_lldp:
- enable: enable
- management_address: 10.1.0.1
-
- - name: "Configuring LLDP to manage the binding relationship between IP addresses and interfaces"
- ce_lldp:
- enable: enable
- bind_name: LoopBack2
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "lldpenable": "enabled",
- "mdnstatus": "rxOnly",
- "interval": "32",
- "hold_multiplier": "5",
- "restart_delay": "3",
- "transmit_delay": "4",
- "notification_interval": "6",
- "fast_count": "5",
- "mdn_notification_interval": "6",
- "management_address": "10.1.0.1",
- "bind_name": "LoopBack2",
- "state": "present"
- }
-existing:
- description: k/v pairs of existing global LLDP configuration.
- returned: always
- type: dict
- sample: {
- "lldpenable": "disabled",
- "mdnstatus": "disabled"
- }
-end_state:
- description: k/v pairs of global LLDP configuration after module execution.
- returned: always
- type: dict
- sample: {
- "lldpenable": "enabled",
- "mdnstatus": "rxOnly",
- "interval": "32",
- "hold_multiplier": "5",
- "restart_delay": "3",
- "transmit_delay": "4",
- "notification_interval": "6",
- "fast_count": "5",
- "mdn_notification_interval": "6",
- "management_address": "10.1.0.1",
- "bind_name": "LoopBack2"
- }
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: [
- "lldp enable",
- "lldp mdn enable",
- "lldp transmit interval 32",
- "lldp transmit multiplier 5",
- "lldp restart 3",
- "lldp transmit delay 4",
- "lldp trap-interval 6",
- "lldp fast-count 5",
- "lldp mdn trap-interval 6",
- "lldp management-address 10.1.0.1",
- "lldp management-address bind interface LoopBack 2"
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import copy
-import re
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import set_nc_config, get_nc_config
-
-CE_NC_GET_GLOBAL_LLDPENABLE_CONFIG = """
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_GLOBA_LLDPENABLE_CONFIG = """
-
-
-
- %s
-
-
-
-"""
-
-CE_NC_MERGE_GLOBA_MDNENABLE_CONFIG = """
-
-
-
- %s
-
-
-
-"""
-
-CE_NC_GET_GLOBAL_LLDP_CONFIG = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_GLOBAL_LLDP_CONFIG_HEADER = """
-
-
-
-
-"""
-
-CE_NC_MERGE_GLOBAL_LLDP_CONFIG_INTERVAL = """
- %s
-"""
-
-CE_NC_MERGE_GLOBAL_LLDP_CONFIG_HOLD_MULTIPLIER = """
- %s
-"""
-
-CE_NC_MERGE_GLOBAL_LLDP_CONFIG_RESTART_DELAY = """
- %s
-"""
-
-CE_NC_MERGE_GLOBAL_LLDP_CONFIG_TRANSMIT_DELAY = """
- %s
-"""
-
-CE_NC_MERGE_GLOBAL_LLDP_CONFIG_NOTIFICATION_INTERVAL = """
- %s
-"""
-
-CE_NC_MERGE_GLOBAL_LLDP_CONFIG_FAST_COUNT = """
- %s
-"""
-
-CE_NC_MERGE_GLOBAL_LLDP_CONFIG_MDN_NOTIFICATION_INTERVAL = """
- %s
-"""
-
-CE_NC_MERGE_GLOBAL_LLDP_CONFIG_MANAGEMENT_ADDRESS = """
- %s
-"""
-
-CE_NC_MERGE_GLOBAL_LLDP_CONFIG_BIND_NAME = """
- %s
-"""
-
-CE_NC_MERGE_GLOBAL_LLDP_CONFIG_TAIL = """
-
-
-
-
-"""
-
-
-class Lldp(object):
- """Manage global lldp enable configuration"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
- self.lldpenable = self.module.params['lldpenable'] or None
- self.interval = self.module.params['interval'] or None
- self.mdnstatus = self.module.params['mdnstatus'] or None
- self.hold_multiplier = self.module.params['hold_multiplier'] or None
- self.restart_delay = self.module.params['restart_delay'] or None
- self.transmit_delay = self.module.params['transmit_delay'] or None
- self.notification_interval = self.module.params['notification_interval'] or None
- self.fast_count = self.module.params['fast_count'] or None
- self.mdn_notification_interval = self.module.params['mdn_notification_interval'] or None
- self.management_address = self.module.params['management_address']
- self.bind_name = self.module.params['bind_name']
- self.state = self.module.params['state']
- self.lldp_conf = dict()
- self.conf_exsit = False
- self.conf_exsit_lldp = False
- self.enable_flag = 0
- self.check_params()
- self.existing_state_value = dict()
- self.existing_end_state_value = dict()
- self.changed = False
- self.proposed_changed = dict()
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def is_valid_v4addr(self):
- """check if ipv4 addr is valid"""
- if self.management_address.find('.') != -1:
- addr_list = self.management_address.split('.')
- if self.management_address == "0.0.0.0":
- self.module.fail_json(msg='Error: The management address is 0.0.0.0 .')
- if len(addr_list) != 4:
- self.module.fail_json(msg='Error: Invalid IPV4 address.')
- for each_num in addr_list:
- each_num_tmp = str(each_num)
- if not each_num_tmp.isdigit():
- self.module.fail_json(msg='Error: The ip address is not digit.')
- if (int(each_num) > 255) or (int(each_num) < 0):
- self.module.fail_json(
- msg='Error: The value of ip address is out of [0 - 255].')
- else:
- self.module.fail_json(msg='Error: Invalid IP address.')
-
- def check_params(self):
- """Check all input params"""
-
- if self.interval:
- if int(self.interval) < 5 or int(self.interval) > 32768:
- self.module.fail_json(
- msg='Error: The value of interval is out of [5 - 32768].')
-
- if self.hold_multiplier:
- if int(self.hold_multiplier) < 2 or int(self.hold_multiplier) > 10:
- self.module.fail_json(
- msg='Error: The value of hold_multiplier is out of [2 - 10].')
-
- if self.restart_delay:
- if int(self.restart_delay) < 1 or int(self.restart_delay) > 10:
- self.module.fail_json(
- msg='Error: The value of restart_delay is out of [1 - 10].')
-
- if self.transmit_delay:
- if int(self.transmit_delay) < 1 or int(self.transmit_delay) > 8192:
- self.module.fail_json(
- msg='Error: The value of transmit_delay is out of [1 - 8192].')
-
- if self.notification_interval:
- if int(self.notification_interval) < 5 or int(self.notification_interval) > 3600:
- self.module.fail_json(
- msg='Error: The value of notification_interval is out of [5 - 3600].')
-
- if self.fast_count:
- if int(self.fast_count) < 1 or int(self.fast_count) > 8:
- self.module.fail_json(
- msg='Error: The value of fast_count is out of [1 - 8].')
-
- if self.mdn_notification_interval:
- if int(self.mdn_notification_interval) < 5 or int(self.mdn_notification_interval) > 3600:
- self.module.fail_json(
- msg='Error: The value of mdn_notification_interval is out of [5 - 3600].')
-
- if self.management_address:
- self.is_valid_v4addr()
-
- if self.bind_name:
- if (len(self.bind_name) < 1) or (len(self.bind_name) > 63):
- self.module.fail_json(
- msg='Error: Bind_name length is between 1 and 63.')
-
- def init_module(self):
- """Init module object"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed"""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def config_lldp(self):
- """Configure lldp enabled and mdn enabled parameters"""
-
- if self.state == 'present':
- if (self.enable_flag == 1 and self.lldpenable == 'enabled') and not self.conf_exsit:
- if self.mdnstatus:
- xml_str = CE_NC_MERGE_GLOBA_MDNENABLE_CONFIG % self.mdnstatus
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "MDN_ENABLE_CONFIG")
-
- if self.lldpenable == 'enabled' and not self.conf_exsit:
- xml_str = CE_NC_MERGE_GLOBA_LLDPENABLE_CONFIG % self.lldpenable
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "LLDP_ENABLE_CONFIG")
-
- if self.mdnstatus:
- xml_str = CE_NC_MERGE_GLOBA_MDNENABLE_CONFIG % self.mdnstatus
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "MDN_ENABLE_CONFIG")
-
- if (self.enable_flag == 1) and not self.conf_exsit:
- if self.mdnstatus:
- xml_str = CE_NC_MERGE_GLOBA_MDNENABLE_CONFIG % self.mdnstatus
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "MDN_ENABLE_CONFIG")
-
- if (self.lldpenable == 'enabled' or self.enable_flag == 1) and not self.conf_exsit_lldp:
- if self.hold_multiplier:
- xml_str = CE_NC_MERGE_GLOBAL_LLDP_CONFIG_HEADER + \
- (CE_NC_MERGE_GLOBAL_LLDP_CONFIG_HOLD_MULTIPLIER % self.hold_multiplier) + \
- CE_NC_MERGE_GLOBAL_LLDP_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "LLDP_CONFIG_INTERVAL")
-
- if self.interval:
- xml_str = CE_NC_MERGE_GLOBAL_LLDP_CONFIG_HEADER + \
- (CE_NC_MERGE_GLOBAL_LLDP_CONFIG_INTERVAL % self.interval) + \
- CE_NC_MERGE_GLOBAL_LLDP_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "LLDP_CONFIG_INTERVAL")
-
- if self.restart_delay:
- xml_str = CE_NC_MERGE_GLOBAL_LLDP_CONFIG_HEADER + \
- (CE_NC_MERGE_GLOBAL_LLDP_CONFIG_RESTART_DELAY % self.restart_delay) + \
- CE_NC_MERGE_GLOBAL_LLDP_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "LLDP_CONFIG_INTERVAL")
-
- if self.transmit_delay:
- xml_str = CE_NC_MERGE_GLOBAL_LLDP_CONFIG_HEADER + \
- (CE_NC_MERGE_GLOBAL_LLDP_CONFIG_TRANSMIT_DELAY % self.transmit_delay) + \
- CE_NC_MERGE_GLOBAL_LLDP_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "LLDP_CONFIG_INTERVAL")
-
- if self.notification_interval:
- xml_str = CE_NC_MERGE_GLOBAL_LLDP_CONFIG_HEADER + \
- (CE_NC_MERGE_GLOBAL_LLDP_CONFIG_NOTIFICATION_INTERVAL % self.notification_interval) + \
- CE_NC_MERGE_GLOBAL_LLDP_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "LLDP_CONFIG_INTERVAL")
-
- if self.fast_count:
- xml_str = CE_NC_MERGE_GLOBAL_LLDP_CONFIG_HEADER + \
- (CE_NC_MERGE_GLOBAL_LLDP_CONFIG_FAST_COUNT % self.fast_count) + \
- CE_NC_MERGE_GLOBAL_LLDP_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "LLDP_CONFIG_INTERVAL")
-
- if self.mdn_notification_interval:
- xml_str = CE_NC_MERGE_GLOBAL_LLDP_CONFIG_HEADER + \
- (CE_NC_MERGE_GLOBAL_LLDP_CONFIG_MDN_NOTIFICATION_INTERVAL % self.mdn_notification_interval) + \
- CE_NC_MERGE_GLOBAL_LLDP_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "LLDP_CONFIG_INTERVAL")
-
- if self.management_address:
- xml_str = CE_NC_MERGE_GLOBAL_LLDP_CONFIG_HEADER + \
- (CE_NC_MERGE_GLOBAL_LLDP_CONFIG_MANAGEMENT_ADDRESS % self.management_address) + \
- CE_NC_MERGE_GLOBAL_LLDP_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "LLDP_CONFIG_INTERVAL")
-
- if self.bind_name:
- xml_str = CE_NC_MERGE_GLOBAL_LLDP_CONFIG_HEADER + \
- (CE_NC_MERGE_GLOBAL_LLDP_CONFIG_BIND_NAME % self.bind_name) + \
- CE_NC_MERGE_GLOBAL_LLDP_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "LLDP_CONFIG_INTERVAL")
-
- if self.lldpenable == 'disabled' and not self.conf_exsit:
- xml_str = CE_NC_MERGE_GLOBA_LLDPENABLE_CONFIG % self.lldpenable
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "LLDP_DISABLE_CONFIG")
-
- def show_result(self):
- """Show result"""
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
- def get_lldp_exist_config(self):
- """Get lldp existed configure"""
-
- lldp_config = list()
- lldp_dict = dict()
-
- conf_enable_str = CE_NC_GET_GLOBAL_LLDPENABLE_CONFIG
- conf_enable_obj = get_nc_config(self.module, conf_enable_str)
-
- xml_enable_str = conf_enable_obj.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get lldp enable config info
- root_enable = ElementTree.fromstring(xml_enable_str)
- ntpsite_enable = root_enable.findall("lldp/lldpSys")
- for nexthop_enable in ntpsite_enable:
- for ele_enable in nexthop_enable:
- if ele_enable.tag in ["lldpEnable", "mdnStatus"]:
- lldp_dict[ele_enable.tag] = ele_enable.text
-
- if self.state == "present":
- cur_lldp_cfg = dict(lldpenable=lldp_dict['lldpEnable'], mdnstatus=lldp_dict['mdnStatus'])
- exp_lldp_cfg = dict(lldpenable=self.lldpenable, mdnstatus=self.mdnstatus)
- if lldp_dict['lldpEnable'] == 'enabled':
- self.enable_flag = 1
- if cur_lldp_cfg == exp_lldp_cfg:
- self.conf_exsit = True
- lldp_config.append(dict(lldpenable=lldp_dict['lldpEnable'], mdnstatus=lldp_dict['mdnStatus']))
-
- conf_str = CE_NC_GET_GLOBAL_LLDP_CONFIG
- conf_obj = get_nc_config(self.module, conf_str)
- if "" in conf_obj:
- pass
-
- else:
- xml_str = conf_obj.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get all ntp config info
- root = ElementTree.fromstring(xml_str)
- ntpsite = root.findall("lldp/lldpSys/lldpSysParameter")
- for nexthop in ntpsite:
- for ele in nexthop:
- if ele.tag in ["messageTxInterval", "messageTxHoldMultiplier", "reinitDelay", "txDelay",
- "notificationInterval", "fastMessageCount", "mdnNotificationInterval",
- "configManAddr", "bindifName"]:
- lldp_dict[ele.tag] = ele.text
-
- if self.state == "present":
- cur_ntp_cfg = dict(interval=lldp_dict['messageTxInterval'],
- hold_multiplier=lldp_dict['messageTxHoldMultiplier'],
- restart_delay=lldp_dict['reinitDelay'],
- transmit_delay=lldp_dict['txDelay'],
- notification_interval=lldp_dict['notificationInterval'],
- fast_count=lldp_dict['fastMessageCount'],
- mdn_notification_interval=lldp_dict['mdnNotificationInterval'],
- management_address=lldp_dict['configManAddr'],
- bind_name=lldp_dict['bindifName'])
-
- exp_ntp_cfg = dict(interval=self.interval, hold_multiplier=self.hold_multiplier,
- restart_delay=self.restart_delay, transmit_delay=self.transmit_delay,
- notification_interval=self.notification_interval,
- fast_count=self.fast_count, mdn_notification_interval=self.mdn_notification_interval,
- management_address=self.management_address, bind_name=self.bind_name)
-
- if cur_ntp_cfg == exp_ntp_cfg:
- self.conf_exsit_lldp = True
-
- lldp_config.append(dict(interval=lldp_dict['messageTxInterval'],
- hold_multiplier=lldp_dict['messageTxHoldMultiplier'],
- restart_delay=lldp_dict['reinitDelay'], transmit_delay=lldp_dict['txDelay'],
- notification_interval=lldp_dict['notificationInterval'],
- fast_count=lldp_dict['fastMessageCount'],
- mdn_notification_interval=lldp_dict['mdnNotificationInterval'],
- management_address=lldp_dict['configManAddr'],
- bind_name=lldp_dict['bindifName']))
-
- tmp_dict = dict()
- str_1 = str(lldp_config)
- temp_1 = str_1.replace('[', '').replace(']', '').replace('{', '').replace('}', '').replace('\'', '')
- if temp_1:
- tmp_2 = temp_1.split(',')
- for i in tmp_2:
- tmp_value = re.match(r'(.*):(.*)', i)
- key_tmp = tmp_value.group(1)
- key_value = tmp_value.group(2)
- tmp_dict[key_tmp] = key_value
- return tmp_dict
-
- def get_existing(self):
- """Get existing info"""
-
- self.existing = self.get_lldp_exist_config()
-
- def get_proposed(self):
- """Get proposed info"""
-
- if self.enable_flag == 1:
- if self.lldpenable == 'enabled':
- self.proposed = dict(lldpenable=self.lldpenable)
- if self.mdnstatus:
- self.proposed = dict(mdnstatus=self.mdnstatus)
- elif self.lldpenable == 'disabled':
- self.proposed = dict(lldpenable=self.lldpenable)
- self.changed = True
- else:
- if self.mdnstatus:
- self.proposed = dict(mdnstatus=self.mdnstatus)
- else:
- if self.lldpenable == 'enabled':
- self.proposed = dict(lldpenable=self.lldpenable)
- self.changed = True
- if self.mdnstatus:
- self.proposed = dict(mdnstatus=self.mdnstatus)
- if self.enable_flag == 1 or self.lldpenable == 'enabled':
- if self.interval:
- self.proposed = dict(interval=self.interval)
- if self.hold_multiplier:
- self.proposed = dict(hold_multiplier=self.hold_multiplier)
- if self.restart_delay:
- self.proposed = dict(restart_delay=self.restart_delay)
- if self.transmit_delay:
- self.proposed = dict(transmit_delay=self.transmit_delay)
- if self.notification_interval:
- self.proposed = dict(notification_interval=self.notification_interval)
- if self.fast_count:
- self.proposed = dict(fast_count=self.fast_count)
- if self.mdn_notification_interval:
- self.proposed = dict(mdn_notification_interval=self.mdn_notification_interval)
- if self.management_address:
- self.proposed = dict(management_address=self.management_address)
- if self.bind_name:
- self.proposed = dict(bind_name=self.bind_name)
-
- def get_end_state(self):
- """Get end state info"""
-
- self.end_state = self.get_lldp_exist_config()
- existing_key_list = self.existing.keys()
- end_state_key_list = self.end_state.keys()
- for i in end_state_key_list:
- for j in existing_key_list:
- if i == j and self.existing[i] != self.end_state[j]:
- self.changed = True
-
- def get_update_cmd(self):
- """Get updated commands"""
-
- if self.conf_exsit and self.conf_exsit_lldp:
- return
-
- if self.state == "present":
- if self.lldpenable == "enabled":
- self.updates_cmd.append("lldp enable")
-
- if self.mdnstatus:
- self.updates_cmd.append("lldp mdn enable")
- if self.mdnstatus == "rxOnly":
- self.updates_cmd.append("lldp mdn enable")
- else:
- self.updates_cmd.append("undo lldp mdn enable")
- if self.interval:
- self.updates_cmd.append("lldp transmit interval %s" % self.interval)
- if self.hold_multiplier:
- self.updates_cmd.append("lldp transmit multiplier %s" % self.hold_multiplier)
- if self.restart_delay:
- self.updates_cmd.append("lldp restart %s" % self.restart_delay)
- if self.transmit_delay:
- self.updates_cmd.append("lldp transmit delay %s" % self.transmit_delay)
- if self.notification_interval:
- self.updates_cmd.append("lldp trap-interval %s" % self.notification_interval)
- if self.fast_count:
- self.updates_cmd.append("lldp fast-count %s" % self.fast_count)
- if self.mdn_notification_interval:
- self.updates_cmd.append("lldp mdn trap-interval %s" % self.mdn_notification_interval)
- if self.management_address:
- self.updates_cmd.append("lldp management-address %s" % self.management_address)
- if self.bind_name:
- self.updates_cmd.append("lldp management-address bind interface %s" % self.bind_name)
- elif self.lldpenable == "disabled":
- self.updates_cmd.append("undo lldp enable")
- else:
- if self.enable_flag == 1:
- if self.mdnstatus:
- if self.mdnstatus == "rxOnly":
- self.updates_cmd.append("lldp mdn enable")
- else:
- self.updates_cmd.append("undo lldp mdn enable")
- if self.interval:
- self.updates_cmd.append("lldp transmit interval %s" % self.interval)
- if self.hold_multiplier:
- self.updates_cmd.append("lldp transmit multiplier %s" % self.hold_multiplier)
- if self.restart_delay:
- self.updates_cmd.append("lldp restart %s" % self.restart_delay)
- if self.transmit_delay:
- self.updates_cmd.append("lldp transmit delay %s" % self.transmit_delay)
- if self.notification_interval:
- self.updates_cmd.append("lldp trap-interval %s" % self.notification_interval)
- if self.fast_count:
- self.updates_cmd.append("lldp fast-count %s" % self.fast_count)
- if self.mdn_notification_interval:
- self.updates_cmd.append("lldp mdn trap-interval %s" % self.mdn_notification_interval)
- if self.management_address:
- self.updates_cmd.append("lldp management-address %s" % self.management_address)
- if self.bind_name:
- self.updates_cmd.append("lldp management-address bind interface %s" % self.bind_name)
-
- def work(self):
- """Execute task"""
- self.check_params()
- self.get_existing()
- self.get_proposed()
- self.config_lldp()
- self.get_update_cmd()
- self.get_end_state()
- self.show_result()
-
-
-def main():
- """Main function entry"""
-
- argument_spec = dict(
- lldpenable=dict(required=False, choices=['enabled', 'disabled']),
- mdnstatus=dict(required=False, choices=['rxOnly', 'disabled']),
- interval=dict(required=False, type='int'),
- hold_multiplier=dict(required=False, type='int'),
- restart_delay=dict(required=False, type='int'),
- transmit_delay=dict(required=False, type='int'),
- notification_interval=dict(required=False, type='int'),
- fast_count=dict(required=False, type='int'),
- mdn_notification_interval=dict(required=False, type='int'),
- management_address=dict(required=False, type='str'),
- bind_name=dict(required=False, type='str'),
- state=dict(choices=['absent', 'present'], default='present'),
- )
- lldp_obj = Lldp(argument_spec)
- lldp_obj.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_lldp_interface.py b/plugins/modules/network/cloudengine/ce_lldp_interface.py
deleted file mode 100644
index 67a2355880..0000000000
--- a/plugins/modules/network/cloudengine/ce_lldp_interface.py
+++ /dev/null
@@ -1,1384 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: ce_lldp_interface
-short_description: Manages INTERFACE LLDP configuration on HUAWEI CloudEngine switches.
-description:
- - Manages INTERFACE LLDP configuration on HUAWEI CloudEngine switches.
-author: xuxiaowei0512 (@CloudEngine-Ansible)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- lldpenable:
- description:
- - Set global LLDP enable state.
- type: str
- choices: ['enabled', 'disabled']
- function_lldp_interface_flag:
- description:
- - Used to distinguish between command line functions.
- type: str
- choices: ['disableINTERFACE','tlvdisableINTERFACE','tlvenableINTERFACE','intervalINTERFACE']
- type_tlv_disable:
- description:
- - Used to distinguish between command line functions.
- type: str
- choices: ['basic_tlv', 'dot3_tlv']
- type_tlv_enable:
- description:
- - Used to distinguish between command line functions.
- type: str
- choices: ['dot1_tlv','dcbx']
- lldpadminstatus:
- description:
- - Set interface lldp enable state.
- type: str
- choices: ['txOnly', 'rxOnly', 'txAndRx', 'disabled']
- ifname:
- description:
- - Interface name.
- type: str
- txinterval:
- description:
- - LLDP send message interval.
- type: int
- txprotocolvlanid:
- description:
- - Set tx protocol vlan id.
- type: int
- txvlannameid:
- description:
- - Set tx vlan name id.
- type: int
- vlannametxenable:
- description:
- - Set vlan name tx enable or not.
- type: bool
- manaddrtxenable:
- description:
- - Make it able to send management address TLV.
- type: bool
- portdesctxenable:
- description:
- - Enabling the ability to send a description of TLV.
- type: bool
- syscaptxenable:
- description:
- - Enable the ability to send system capabilities TLV.
- type: bool
- sysdesctxenable:
- description:
- - Enable the ability to send system description TLV.
- type: bool
- sysnametxenable:
- description:
- - Enable the ability to send system name TLV.
- type: bool
- portvlantxenable:
- description:
- - Enable port vlan tx.
- type: bool
- protovlantxenable:
- description:
- - Enable protocol vlan tx.
- type: bool
- protoidtxenable:
- description:
- - Enable the ability to send protocol identity TLV.
- type: bool
- macphytxenable:
- description:
- - Enable MAC/PHY configuration and state TLV to be sent.
- type: bool
- linkaggretxenable:
- description:
- - Enable the ability to send link aggregation TLV.
- type: bool
- maxframetxenable:
- description:
- - Enable the ability to send maximum frame length TLV.
- type: bool
- eee:
- description:
- - Enable the ability to send EEE TLV.
- type: bool
- dcbx:
- description:
- - Enable the ability to send DCBX TLV.
- type: bool
- state:
- description:
- - Manage the state of the resource.
- type: str
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = '''
- - name: "Configure global LLDP enable state"
- ce_lldp_interface_interface:
- lldpenable: enabled
-
- - name: "Configure interface lldp enable state"
- ce_lldp_interface:
- function_lldp_interface_flag: disableINTERFACE
- ifname: 10GE1/0/1
- lldpadminstatus: rxOnly
- - name: "Configure LLDP transmit interval and ensure global LLDP state is already enabled"
- ce_lldp_interface:
- function_lldp_interface_flag: intervalINTERFACE
- ifname: 10GE1/0/1
- txinterval: 4
-
- - name: "Configure basic-tlv: management-address TLV"
- ce_lldp_interface:
- function_lldp_interface_flag: tlvdisableINTERFACE
- type_tlv_disable: basic_tlv
- ifname: 10GE1/0/1
- manaddrtxenable: true
-
- - name: "Configure basic-tlv: prot description TLV"
- ce_lldp_interface:
- function_lldp_interface_flag: tlvdisableINTERFACE
- type_tlv_disable: basic_tlv
- ifname: 10GE1/0/1
- portdesctxenable: true
-
- - name: "Configure basic-tlv: system capabilities TLV"
- ce_lldp_interface:
- function_lldp_interface_flag: tlvdisableINTERFACE
- type_tlv_disable: basic_tlv
- ifname: 10GE1/0/1
- syscaptxenable: true
-
- - name: "Configure basic-tlv: system description TLV"
- ce_lldp_interface:
- function_lldp_interface_flag: tlvdisableINTERFACE
- type_tlv_disable: basic_tlv
- ifname: 10GE1/0/1
- sysdesctxenable: true
-
- - name: "Configure basic-tlv: system name TLV"
- ce_lldp_interface:
- function_lldp_interface_flag: tlvdisableINTERFACE
- type_tlv_disable: basic_tlv
- ifname: 10GE1/0/1
- sysnametxenable: true
-
- - name: "TLV types that are forbidden to be published on the configuration interface, link aggregation TLV"
- ce_lldp_interface:
- function_lldp_interface_flag: tlvdisableINTERFACE
- type_tlv_disable: dot3_tlv
- ifname: 10GE1/0/1
- linkAggreTxEnable: true
-
- - name: "TLV types that are forbidden to be published on the configuration interface, MAC/PHY configuration/status TLV"
- ce_lldp_interface:
- function_lldp_interface_flag: tlvdisableINTERFACE
- type_tlv_disable: dot3_tlv
- ifname: 10GE1/0/1
- macPhyTxEnable: true
-
- - name: "TLV types that are forbidden to be published on the configuration interface, maximum frame size TLV"
- ce_lldp_interface:
- function_lldp_interface_flag: tlvdisableINTERFACE
- type_tlv_disable: dot3_tlv
- ifname: 10GE1/0/1
- maxFrameTxEnable: true
-
- - name: "TLV types that are forbidden to be published on the configuration interface, EEE TLV"
- ce_lldp_interface:
- function_lldp_interface_flag: tlvdisableINTERFACE
- type_tlv_disable: dot3_tlv
- ifname: 10GE1/0/1
- eee: true
-
- - name: "Configure the interface to publish an optional DCBX TLV type "
- ce_lldp_interface:
- function_lldp_interface_flag: tlvenableINTERFACE
- ifname: 10GE1/0/1
- type_tlv_enable: dcbx
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "lldpenable": "enabled",
- "lldpadminstatus": "rxOnly",
- "function_lldp_interface_flag": "tlvenableINTERFACE",
- "type_tlv_enable": "dot1_tlv",
- "ifname": "10GE1/0/1",
- "state": "present"
- }
-existing:
- description: k/v pairs of existing global LLDP configration
- returned: always
- type: dict
- sample: {
- "lldpenable": "disabled",
- "ifname": "10GE1/0/1",
- "lldpadminstatus": "txAndRx"
- }
-end_state:
- description: k/v pairs of global DLDP configration after module execution
- returned: always
- type: dict
- sample: {
- "lldpenable": "enabled",
- "lldpadminstatus": "rxOnly",
- "function_lldp_interface_flag": "tlvenableINTERFACE",
- "type_tlv_enable": "dot1_tlv",
- "ifname": "10GE1/0/1"
- }
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: [
- "lldp enable",
- "interface 10ge 1/0/1",
- "undo lldp disable",
- "lldp tlv-enable dot1-tlv vlan-name 4",
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import copy
-import re
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import set_nc_config, get_nc_config
-
-CE_NC_GET_GLOBAL_LLDPENABLE_CONFIG = """
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_GLOBA_LLDPENABLE_CONFIG = """
-
-
-
- %s
-
-
-
-"""
-
-CE_NC_GET_INTERFACE_LLDP_CONFIG = """
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_INTERFACE_LLDP_CONFIG = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-CE_NC_GET_INTERFACE_INTERVAl_CONFIG = """
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_INTERFACE_INTERVAl_CONFIG = """
-
-
-
-
- %s
-
- %s
-
-
-
-
-
-"""
-
-CE_NC_GET_INTERFACE_TLV_ENABLE_CONFIG = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_GET_INTERFACE_TLV_DISABLE_CONFIG = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_INTERFACE_TLV_CONFIG_HEADER = """
-
-
-
-
- %s
-
-"""
-
-CE_NC_MERGE_INTERFACE_TLV_CONFIG_ENABLE_PROTOIDTXENABLE = """
- %s
-"""
-
-CE_NC_MERGE_INTERFACE_TLV_CONFIG_ENABLE_DCBX = """
- %s
-"""
-
-CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_MANADDRTXENABLE = """
- %s
-"""
-
-CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_PORTDESCTXENABLE = """
- %s
-"""
-
-CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_SYSCAPTXENABLE = """
- %s
-"""
-
-CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_SYSDESCTXENABLE = """
- %s
-"""
-
-CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_SYSNAMETXENABLE = """
- %s
-"""
-
-CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_LINKAGGRETXENABLE = """
- %s
-"""
-
-CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_MACPHYTXENABLE = """
- %s
-"""
-
-CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_MAXFRAMETXENABLE = """
- %s
-"""
-
-CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_EEE = """
- %s
-"""
-
-CE_NC_MERGE_INTERFACE_TLV_CONFIG_TAIL = """
-
-
-
-
-
-"""
-
-CE_NC_MERGE_GLOBA_LLDPENABLE_CONFIG = """
-
-
-
- %s
-
-
-
-"""
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE"""
-
- if interface is None:
- return None
-
- iftype = None
-
- if interface.upper().startswith('GE'):
- iftype = 'ge'
- elif interface.upper().startswith('10GE'):
- iftype = '10ge'
- elif interface.upper().startswith('25GE'):
- iftype = '25ge'
- elif interface.upper().startswith('40GE'):
- iftype = '40ge'
- elif interface.upper().startswith('100GE'):
- iftype = '100ge'
- elif interface.upper().startswith('PORT-GROUP'):
- iftype = 'stack-Port'
- elif interface.upper().startswith('NULL'):
- iftype = 'null'
- else:
- return None
- return iftype.lower()
-
-
-class Lldp_interface(object):
- """Manage global lldp enable configuration"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = AnsibleModule(argument_spec=self.spec, supports_check_mode=True)
-
- self.lldpenable = self.module.params['lldpenable'] or None
- self.function_lldp_interface_flag = self.module.params['function_lldp_interface_flag']
- self.type_tlv_disable = self.module.params['type_tlv_disable']
- self.type_tlv_enable = self.module.params['type_tlv_enable']
- self.ifname = self.module.params['ifname']
- if self.function_lldp_interface_flag == 'disableINTERFACE':
- self.ifname = self.module.params['ifname']
- self.lldpadminstatus = self.module.params['lldpadminstatus']
- elif self.function_lldp_interface_flag == 'tlvdisableINTERFACE':
- if self.type_tlv_disable == 'basic_tlv':
- self.ifname = self.module.params['ifname']
- self.manaddrtxenable = self.module.params['manaddrtxenable']
- self.portdesctxenable = self.module.params['portdesctxenable']
- self.syscaptxenable = self.module.params['syscaptxenable']
- self.sysdesctxenable = self.module.params['sysdesctxenable']
- self.sysnametxenable = self.module.params['sysnametxenable']
- if self.type_tlv_disable == 'dot3_tlv':
- self.ifname = self.module.params['ifname']
- self.macphytxenable = self.module.params['macphytxenable']
- self.linkaggretxenable = self.module.params['linkaggretxenable']
- self.maxframetxenable = self.module.params['maxframetxenable']
- self.eee = self.module.params['eee']
- elif self.function_lldp_interface_flag == 'tlvenableINTERFACE':
- if self.type_tlv_enable == 'dot1_tlv':
- self.ifname = self.module.params['ifname']
- self.protoidtxenable = self.module.params['protoidtxenable']
- if self.type_tlv_enable == 'dcbx':
- self.ifname = self.module.params['ifname']
- self.dcbx = self.module.params['dcbx']
- elif self.function_lldp_interface_flag == 'intervalINTERFACE':
- self.ifname = self.module.params['ifname']
- self.txinterval = self.module.params['txinterval']
- self.state = self.module.params['state']
-
- self.lldp_conf = dict()
- self.conf_disable_exsit = False
- self.conf_interface_lldp_disable_exsit = False
- self.conf_interval_exsit = False
- self.conf_tlv_disable_exsit = False
- self.conf_tlv_enable_exsit = False
- self.enable_flag = 0
- self.check_params()
- self.existing_state_value = dict()
- self.existing_end_state_value = dict()
- self.interface_lldp_info = list()
-
- # state
- self.changed = False
- self.proposed_changed = dict()
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def check_params(self):
- """Check all input params"""
-
- if self.ifname:
- intf_type = get_interface_type(self.ifname)
- if not intf_type:
- self.module.fail_json(msg='Error: ifname name of %s is error.' % self.ifname)
- if (len(self.ifname) < 1) or (len(self.ifname) > 63):
- self.module.fail_json(msg='Error: Ifname length is beetween 1 and 63.')
-
- if self.function_lldp_interface_flag == 'intervalINTERFACE':
- if self.txinterval:
- if int(self.txinterval) < 1 or int(self.txinterval) > 32768:
- self.module.fail_json(
- msg='Error: The value of txinterval is out of [1 - 32768].')
- if self.ifname:
- intf_type = get_interface_type(self.ifname)
- if not intf_type:
- self.module.fail_json(
- msg='Error: ifname name of %s '
- 'is error.' % self.ifname)
- if (len(self.ifname) < 1) or (len(self.ifname) > 63):
- self.module.fail_json(
- msg='Error: Ifname length is beetween 1 and 63.')
-
- if self.function_lldp_interface_flag == 'tlvdisableINTERFACE':
- if self.type_tlv_disable == 'dot1_tlv':
- if self.ifname:
- intf_type = get_interface_type(self.ifname)
- if not intf_type:
- self.module.fail_json(
- msg='Error: ifname name of %s '
- 'is error.' % self.ifname)
- if (len(self.ifname) < 1) or (len(self.ifname) > 63):
- self.module.fail_json(
- msg='Error: Ifname length is beetween 1 and 63.')
-
- if self.function_lldp_interface_flag == 'tlvenableINTERFACE':
- if self.type_tlv_enable == 'dot1_tlv':
- if self.ifname:
- intf_type = get_interface_type(self.ifname)
- if not intf_type:
- self.module.fail_json(
- msg='Error: ifname name of %s '
- 'is error.' % self.ifname)
- if (len(self.ifname) < 1) or (len(self.ifname) > 63):
- self.module.fail_json(
- msg='Error: Ifname length is beetween 1 and 63.')
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already OK"""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def show_result(self):
- """Show result"""
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
- def get_lldp_enable_pre_config(self):
- """Get lldp enable configure"""
-
- lldp_dict = dict()
- lldp_config = list()
- conf_enable_str = CE_NC_GET_GLOBAL_LLDPENABLE_CONFIG
- conf_enable_obj = get_nc_config(self.module, conf_enable_str)
- xml_enable_str = conf_enable_obj.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get lldp enable config info
- root_enable = ElementTree.fromstring(xml_enable_str)
- ntpsite_enable = root_enable.findall("lldp/lldpSys")
- for nexthop_enable in ntpsite_enable:
- for ele_enable in nexthop_enable:
- if ele_enable.tag in ["lldpEnable"]:
- lldp_dict[ele_enable.tag] = ele_enable.text
- if lldp_dict['lldpEnable'] == 'enabled':
- self.enable_flag = 1
- lldp_config.append(dict(lldpenable=lldp_dict['lldpEnable']))
- return lldp_config
-
- def get_interface_lldp_disable_pre_config(self):
- """Get interface undo lldp disable configure"""
- lldp_dict = dict()
- interface_lldp_disable_dict = dict()
- if self.enable_flag == 1:
- conf_enable_str = CE_NC_GET_INTERFACE_LLDP_CONFIG
- conf_enable_obj = get_nc_config(self.module, conf_enable_str)
- if "" in conf_enable_obj:
- return
- xml_enable_str = conf_enable_obj.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_enable_str)
- lldp_disable_enable = root.findall("lldp/lldpInterfaces/lldpInterface")
- for nexthop_enable in lldp_disable_enable:
- name = nexthop_enable.find("ifName")
- status = nexthop_enable.find("lldpAdminStatus")
- if name is not None and status is not None:
- interface_lldp_disable_dict[name.text] = status.text
- return interface_lldp_disable_dict
-
- def get_interface_lldp_disable_config(self):
- lldp_config = list()
- interface_lldp_disable_dict_tmp = dict()
- if self.state == "present":
- if self.ifname:
- interface_lldp_disable_dict_tmp = self.get_interface_lldp_disable_pre_config()
- key_list = interface_lldp_disable_dict_tmp.keys()
- if len(key_list) != 0:
- for key in key_list:
- if key == self.ifname:
- if interface_lldp_disable_dict_tmp[key] != self.lldpadminstatus:
- self.conf_interface_lldp_disable_exsit = True
- else:
- self.conf_interface_lldp_disable_exsit = False
- elif self.ifname not in key_list:
- self.conf_interface_lldp_disable_exsit = True
- elif (len(key_list) == 0) and self.ifname and self.lldpadminstatus:
- self.conf_interface_lldp_disable_exsit = True
- lldp_config.append(interface_lldp_disable_dict_tmp)
- return lldp_config
-
- def get_interface_tlv_disable_config(self):
- lldp_config = list()
- lldp_dict = dict()
- cur_interface_mdn_cfg = dict()
- exp_interface_mdn_cfg = dict()
-
- if self.enable_flag == 1:
- conf_str = CE_NC_GET_INTERFACE_TLV_DISABLE_CONFIG
- conf_obj = get_nc_config(self.module, conf_str)
- if "" in conf_obj:
- return lldp_config
- xml_str = conf_obj.replace('\r', '').replace('\n', '')
- xml_str = xml_str.replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "")
- xml_str = xml_str.replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
- lldp_tlvdisable_ifname = root.findall("lldp/lldpInterfaces/lldpInterface")
- for ele in lldp_tlvdisable_ifname:
- ifname_tmp = ele.find("ifName")
- manaddrtxenable_tmp = ele.find("tlvTxEnable/manAddrTxEnable")
- portdesctxenable_tmp = ele.find("tlvTxEnable/portDescTxEnable")
- syscaptxenable_tmp = ele.find("tlvTxEnable/sysCapTxEnable")
- sysdesctxenable_tmp = ele.find("tlvTxEnable/sysDescTxEnable")
- sysnametxenable_tmp = ele.find("tlvTxEnable/sysNameTxEnable")
- linkaggretxenable_tmp = ele.find("tlvTxEnable/linkAggreTxEnable")
- macphytxenable_tmp = ele.find("tlvTxEnable/macPhyTxEnable")
- maxframetxenable_tmp = ele.find("tlvTxEnable/maxFrameTxEnable")
- eee_tmp = ele.find("tlvTxEnable/eee")
- if ifname_tmp is not None:
- if ifname_tmp.text is not None:
- cur_interface_mdn_cfg["ifname"] = ifname_tmp.text
- if ifname_tmp is not None and manaddrtxenable_tmp is not None:
- if manaddrtxenable_tmp.text is not None:
- cur_interface_mdn_cfg["manaddrtxenable"] = manaddrtxenable_tmp.text
- if ifname_tmp is not None and portdesctxenable_tmp is not None:
- if portdesctxenable_tmp.text is not None:
- cur_interface_mdn_cfg['portdesctxenable'] = portdesctxenable_tmp.text
- if ifname_tmp is not None and syscaptxenable_tmp is not None:
- if syscaptxenable_tmp.text is not None:
- cur_interface_mdn_cfg['syscaptxenable'] = syscaptxenable_tmp.text
- if ifname_tmp is not None and sysdesctxenable_tmp is not None:
- if sysdesctxenable_tmp.text is not None:
- cur_interface_mdn_cfg['sysdesctxenable'] = sysdesctxenable_tmp.text
- if ifname_tmp is not None and sysnametxenable_tmp is not None:
- if sysnametxenable_tmp.text is not None:
- cur_interface_mdn_cfg['sysnametxenable'] = sysnametxenable_tmp.text
- if ifname_tmp is not None and linkaggretxenable_tmp is not None:
- if linkaggretxenable_tmp.text is not None:
- cur_interface_mdn_cfg['linkaggretxenable'] = linkaggretxenable_tmp.text
- if ifname_tmp is not None and macphytxenable_tmp is not None:
- if macphytxenable_tmp.text is not None:
- cur_interface_mdn_cfg['macphytxenable'] = macphytxenable_tmp.text
- if ifname_tmp is not None and maxframetxenable_tmp is not None:
- if maxframetxenable_tmp.text is not None:
- cur_interface_mdn_cfg['maxframetxenable'] = maxframetxenable_tmp.text
- if ifname_tmp is not None and eee_tmp is not None:
- if eee_tmp.text is not None:
- cur_interface_mdn_cfg['eee'] = eee_tmp.text
- if self.state == "present":
- if self.function_lldp_interface_flag == 'tlvdisableINTERFACE':
- if self.type_tlv_disable == 'basic_tlv':
- if self.ifname:
- exp_interface_mdn_cfg['ifname'] = self.ifname
- if self.manaddrtxenable:
- exp_interface_mdn_cfg['manaddrtxenable'] = self.manaddrtxenable
- if self.portdesctxenable:
- exp_interface_mdn_cfg['portdesctxenable'] = self.portdesctxenable
- if self.syscaptxenable:
- exp_interface_mdn_cfg['syscaptxenable'] = self.syscaptxenable
- if self.sysdesctxenable:
- exp_interface_mdn_cfg['sysdesctxenable'] = self.sysdesctxenable
- if self.sysnametxenable:
- exp_interface_mdn_cfg['sysnametxenable'] = self.sysnametxenable
- if self.ifname == ifname_tmp.text:
- key_list = exp_interface_mdn_cfg.keys()
- key_list_cur = cur_interface_mdn_cfg.keys()
- if len(key_list) != 0:
- for key in key_list:
- if key == "ifname" and self.ifname == cur_interface_mdn_cfg['ifname']:
- lldp_config.append(dict(ifname=cur_interface_mdn_cfg['ifname']))
- if "manaddrtxenable" == key and self.ifname == cur_interface_mdn_cfg['ifname']:
- lldp_config.append(dict(manaddrtxenable=cur_interface_mdn_cfg['manaddrtxenable']))
- if "portdesctxenable" == key and self.ifname == cur_interface_mdn_cfg['ifname']:
- lldp_config.append(dict(portdesctxenable=cur_interface_mdn_cfg['portdesctxenable']))
- if "syscaptxenable" == key and self.ifname == cur_interface_mdn_cfg['ifname']:
- lldp_config.append(dict(syscaptxenable=cur_interface_mdn_cfg['syscaptxenable']))
- if "sysdesctxenable" == key and self.ifname == cur_interface_mdn_cfg['ifname']:
- lldp_config.append(dict(sysdesctxenable=cur_interface_mdn_cfg['sysdesctxenable']))
- if "sysnametxenable" == key and self.ifname == cur_interface_mdn_cfg['ifname']:
- lldp_config.append(dict(sysnametxenable=cur_interface_mdn_cfg['sysnametxenable']))
- if key in key_list_cur:
- if str(exp_interface_mdn_cfg[key]) != str(cur_interface_mdn_cfg[key]):
- self.conf_tlv_disable_exsit = True
- self.changed = True
- return lldp_config
- else:
- self.conf_tlv_disable_exsit = True
- return lldp_config
-
- if self.type_tlv_disable == 'dot3_tlv':
- if self.ifname:
- exp_interface_mdn_cfg['ifname'] = self.ifname
- if self.linkaggretxenable:
- exp_interface_mdn_cfg['linkaggretxenable'] = self.linkaggretxenable
- if self.macphytxenable:
- exp_interface_mdn_cfg['macphytxenable'] = self.macphytxenable
- if self.maxframetxenable:
- exp_interface_mdn_cfg['maxframetxenable'] = self.maxframetxenable
- if self.eee:
- exp_interface_mdn_cfg['eee'] = self.eee
- if self.ifname == ifname_tmp.text:
- key_list = exp_interface_mdn_cfg.keys()
- key_list_cur = cur_interface_mdn_cfg.keys()
- if len(key_list) != 0:
- for key in key_list:
- if key == "ifname" and self.ifname == cur_interface_mdn_cfg['ifname']:
- lldp_config.append(dict(ifname=cur_interface_mdn_cfg['ifname']))
- if "linkaggretxenable" == key and self.ifname == cur_interface_mdn_cfg['ifname']:
- lldp_config.append(dict(linkaggretxenable=cur_interface_mdn_cfg['linkaggretxenable']))
- if "macphytxenable" == key and self.ifname == cur_interface_mdn_cfg['ifname']:
- lldp_config.append(dict(macphytxenable=cur_interface_mdn_cfg['macphytxenable']))
- if "maxframetxenable" == key and self.ifname == cur_interface_mdn_cfg['ifname']:
- lldp_config.append(dict(maxframetxenable=cur_interface_mdn_cfg['maxframetxenable']))
- if "eee" == key and self.ifname == cur_interface_mdn_cfg['ifname']:
- lldp_config.append(dict(eee=cur_interface_mdn_cfg['eee']))
- if key in key_list_cur:
- if str(exp_interface_mdn_cfg[key]) != str(cur_interface_mdn_cfg[key]):
- self.conf_tlv_disable_exsit = True
- self.changed = True
- return lldp_config
- else:
- self.conf_tlv_disable_exsit = True
- return lldp_config
- return lldp_config
-
- def get_interface_tlv_enable_config(self):
- lldp_config = list()
- lldp_dict = dict()
- cur_interface_mdn_cfg = dict()
- exp_interface_mdn_cfg = dict()
- if self.enable_flag == 1:
- conf_str = CE_NC_GET_INTERFACE_TLV_ENABLE_CONFIG
- conf_obj = get_nc_config(self.module, conf_str)
- if "" in conf_obj:
- return lldp_config
- xml_str = conf_obj.replace('\r', '').replace('\n', '')
- xml_str = xml_str.replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "")
- xml_str = xml_str.replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
- lldpenablesite = root.findall("lldp/lldpInterfaces/lldpInterface")
- for ele in lldpenablesite:
- ifname_tmp = ele.find("ifName")
- protoidtxenable_tmp = ele.find("tlvTxEnable/protoIdTxEnable")
- dcbx_tmp = ele.find("tlvTxEnable/dcbx")
- if ifname_tmp is not None:
- if ifname_tmp.text is not None:
- cur_interface_mdn_cfg["ifname"] = ifname_tmp.text
- if ifname_tmp is not None and protoidtxenable_tmp is not None:
- if protoidtxenable_tmp.text is not None:
- cur_interface_mdn_cfg["protoidtxenable"] = protoidtxenable_tmp.text
- if ifname_tmp is not None and dcbx_tmp is not None:
- if dcbx_tmp.text is not None:
- cur_interface_mdn_cfg['dcbx'] = dcbx_tmp.text
- if self.state == "present":
- if self.function_lldp_interface_flag == 'tlvenableINTERFACE':
- if self.type_tlv_enable == 'dot1_tlv':
- if self.ifname:
- exp_interface_mdn_cfg['ifname'] = self.ifname
- if self.protoidtxenable:
- exp_interface_mdn_cfg['protoidtxenable'] = self.protoidtxenable
- if self.ifname == ifname_tmp.text:
- key_list = exp_interface_mdn_cfg.keys()
- key_list_cur = cur_interface_mdn_cfg.keys()
- if len(key_list) != 0:
- for key in key_list:
- if "protoidtxenable" == str(key) and self.ifname == cur_interface_mdn_cfg['ifname']:
- lldp_config.append(dict(protoidtxenable=cur_interface_mdn_cfg['protoidtxenable']))
- if key in key_list_cur:
- if str(exp_interface_mdn_cfg[key]) != str(cur_interface_mdn_cfg[key]):
- self.conf_tlv_enable_exsit = True
- self.changed = True
- return lldp_config
- else:
- self.conf_tlv_enable_exsit = True
- return lldp_config
- if self.type_tlv_enable == 'dcbx':
- if self.ifname:
- exp_interface_mdn_cfg['ifname'] = self.ifname
- if self.dcbx:
- exp_interface_mdn_cfg['dcbx'] = self.dcbx
- if self.ifname == ifname_tmp.text:
- key_list = exp_interface_mdn_cfg.keys()
- key_list_cur = cur_interface_mdn_cfg.keys()
- if len(key_list) != 0:
- for key in key_list:
- if "dcbx" == key and self.ifname == cur_interface_mdn_cfg['ifname']:
- lldp_config.append(dict(dcbx=cur_interface_mdn_cfg['dcbx']))
- if key in key_list_cur:
- if str(exp_interface_mdn_cfg[key]) != str(cur_interface_mdn_cfg[key]):
- self.conf_tlv_enable_exsit = True
- self.changed = True
- return lldp_config
- else:
- self.conf_tlv_enable_exsit = True
- return lldp_config
- return lldp_config
-
- def get_interface_interval_config(self):
- lldp_config = list()
- lldp_dict = dict()
- cur_interface_mdn_cfg = dict()
- exp_interface_mdn_cfg = dict()
- interface_lldp_disable_dict_tmp2 = self.get_interface_lldp_disable_pre_config()
- if self.enable_flag == 1:
- if interface_lldp_disable_dict_tmp2[self.ifname] != 'disabled':
- conf_str = CE_NC_GET_INTERFACE_INTERVAl_CONFIG
- conf_obj = get_nc_config(self.module, conf_str)
- if "" in conf_obj:
- return lldp_config
- xml_str = conf_obj.replace('\r', '').replace('\n', '')
- xml_str = xml_str.replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "")
- xml_str = xml_str.replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
- txintervalsite = root.findall("lldp/lldpInterfaces/lldpInterface")
- for ele in txintervalsite:
- ifname_tmp = ele.find("ifName")
- txinterval_tmp = ele.find("msgInterval/txInterval")
- if ifname_tmp is not None:
- if ifname_tmp.text is not None:
- cur_interface_mdn_cfg["ifname"] = ifname_tmp.text
- if txinterval_tmp is not None:
- if txinterval_tmp.text is not None:
- cur_interface_mdn_cfg["txinterval"] = txinterval_tmp.text
- if self.state == "present":
- if self.ifname:
- exp_interface_mdn_cfg["ifname"] = self.ifname
- if self.txinterval:
- exp_interface_mdn_cfg["txinterval"] = self.txinterval
- if self.ifname == ifname_tmp.text:
- key_list = exp_interface_mdn_cfg.keys()
- key_list_cur = cur_interface_mdn_cfg.keys()
- if len(key_list) != 0:
- for key in key_list:
- if "txinterval" == str(key) and self.ifname == cur_interface_mdn_cfg['ifname']:
- lldp_config.append(dict(ifname=cur_interface_mdn_cfg['ifname'], txinterval=exp_interface_mdn_cfg['txinterval']))
- if key in key_list_cur:
- if str(exp_interface_mdn_cfg[key]) != str(cur_interface_mdn_cfg[key]):
- self.conf_interval_exsit = True
- lldp_config.append(cur_interface_mdn_cfg)
- return lldp_config
- else:
- self.conf_interval_exsit = True
- return lldp_config
- return lldp_config
-
- def config_global_lldp_enable(self):
- if self.state == 'present':
- if self.enable_flag == 0 and self.lldpenable == 'enabled':
- xml_str = CE_NC_MERGE_GLOBA_LLDPENABLE_CONFIG % self.lldpenable
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "LLDP_ENABLE_CONFIG")
- self.changed = True
- elif self.enable_flag == 1 and self.lldpenable == 'disabled':
- xml_str = CE_NC_MERGE_GLOBA_LLDPENABLE_CONFIG % self.lldpenable
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "LLDP_ENABLE_CONFIG")
- self.changed = True
-
- def config_interface_lldp_disable_config(self):
- if self.function_lldp_interface_flag == 'disableINTERFACE':
- if self.enable_flag == 1 and self.conf_interface_lldp_disable_exsit:
- if self.ifname:
- xml_str = CE_NC_MERGE_INTERFACE_LLDP_CONFIG % (self.ifname, self.lldpadminstatus)
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "INTERFACE_LLDP_DISABLE_CONFIG")
- self.changed = True
-
- def config_interface_tlv_disable_config(self):
- if self.function_lldp_interface_flag == 'tlvdisableINTERFACE':
- if self.enable_flag == 1 and self.conf_tlv_disable_exsit:
- if self.type_tlv_disable == 'basic_tlv':
- if self.ifname:
- if self.portdesctxenable:
- xml_str = (CE_NC_MERGE_INTERFACE_TLV_CONFIG_HEADER % self.ifname) + \
- (CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_PORTDESCTXENABLE % self.portdesctxenable) + \
- CE_NC_MERGE_INTERFACE_TLV_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "TLV_DISABLE_PORTDESCTXENABLE")
- self.changed = True
- if self.manaddrtxenable:
- xml_str = (CE_NC_MERGE_INTERFACE_TLV_CONFIG_HEADER % self.ifname) + \
- (CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_MANADDRTXENABLE % self.manaddrtxenable) + \
- CE_NC_MERGE_INTERFACE_TLV_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "TLV_DISABLE_MANADDRTXENABLE")
- self.changed = True
- if self.syscaptxenable:
- xml_str = (CE_NC_MERGE_INTERFACE_TLV_CONFIG_HEADER % self.ifname) + \
- (CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_SYSCAPTXENABLE % self.syscaptxenable) + \
- CE_NC_MERGE_INTERFACE_TLV_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "TLV_DISABLE_SYSCAPTXENABLE")
- self.changed = True
- if self.sysdesctxenable:
- xml_str = (CE_NC_MERGE_INTERFACE_TLV_CONFIG_HEADER % self.ifname) + \
- (CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_SYSDESCTXENABLE % self.sysdesctxenable) + \
- CE_NC_MERGE_INTERFACE_TLV_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "TLV_DISABLE_SYSDESCTXENABLE")
- self.changed = True
- if self.sysnametxenable:
- xml_str = (CE_NC_MERGE_INTERFACE_TLV_CONFIG_HEADER % self.ifname) + \
- (CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_SYSNAMETXENABLE % self.sysnametxenable) + \
- CE_NC_MERGE_INTERFACE_TLV_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "TLV_DISABLE_SYSNAMETXENABLE")
- self.changed = True
- if self.type_tlv_disable == 'dot3_tlv':
- if self.ifname:
- if self.linkaggretxenable:
- xml_str = (CE_NC_MERGE_INTERFACE_TLV_CONFIG_HEADER % self.ifname) + \
- (CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_LINKAGGRETXENABLE % self.linkaggretxenable) + \
- CE_NC_MERGE_INTERFACE_TLV_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "TLV_DISABLE_LINKAGGRETXENABLE")
- self.changed = True
- if self.macphytxenable:
- xml_str = (CE_NC_MERGE_INTERFACE_TLV_CONFIG_HEADER % self.ifname) + \
- (CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_MACPHYTXENABLE % self.macphytxenable) + \
- CE_NC_MERGE_INTERFACE_TLV_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "TLV_DISABLE_MACPHYTXENABLE")
- self.changed = True
- if self.maxframetxenable:
- xml_str = (CE_NC_MERGE_INTERFACE_TLV_CONFIG_HEADER % self.ifname) + \
- (CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_MAXFRAMETXENABLE % self.maxframetxenable) + \
- CE_NC_MERGE_INTERFACE_TLV_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "TLV_DISABLE_MAXFRAMETXENABLE")
- self.changed = True
- if self.eee:
- xml_str = (CE_NC_MERGE_INTERFACE_TLV_CONFIG_HEADER % self.ifname) + \
- (CE_NC_MERGE_INTERFACE_TLV_CONFIG_DISABLE_EEE % self.eee) + \
- CE_NC_MERGE_INTERFACE_TLV_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "TLV_DISABLE_EEE")
- self.changed = True
-
- def config_interface_tlv_enable_config(self):
- if self.function_lldp_interface_flag == 'tlvenableINTERFACE':
- if self.enable_flag == 1 and self.conf_tlv_enable_exsit:
- if self.type_tlv_enable == 'dot1_tlv':
- if self.ifname:
- if self.protoidtxenable:
- xml_str = (CE_NC_MERGE_INTERFACE_TLV_CONFIG_HEADER % self.ifname) + \
- (CE_NC_MERGE_INTERFACE_TLV_CONFIG_ENABLE_PROTOIDTXENABLE % self.protoidtxenable) + \
- CE_NC_MERGE_INTERFACE_TLV_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "TLV_ENABLE_DOT1_PORT_VLAN")
- self.changed = True
- if self.type_tlv_enable == 'dcbx':
- if self.ifname:
- if self.dcbx:
- xml_str = (CE_NC_MERGE_INTERFACE_TLV_CONFIG_HEADER % self.ifname) + \
- (CE_NC_MERGE_INTERFACE_TLV_CONFIG_ENABLE_DCBX % self.dcbx) + \
- CE_NC_MERGE_INTERFACE_TLV_CONFIG_TAIL
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "TLV_ENABLE_DCBX_VLAN")
- self.changed = True
-
- def config_interface_interval_config(self):
- if self.function_lldp_interface_flag == 'intervalINTERFACE':
- tmp = self.get_interface_lldp_disable_pre_config()
- if self.enable_flag == 1 and self.conf_interval_exsit and tmp[self.ifname] != 'disabled':
- if self.ifname:
- if self.txinterval:
- xml_str = CE_NC_MERGE_INTERFACE_INTERVAl_CONFIG % (self.ifname, self.txinterval)
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "INTERFACE_INTERVAL_CONFIG")
- self.changed = True
-
- def get_existing(self):
- """get existing information"""
- self.get_lldp_enable_pre_config()
- if self.lldpenable:
- self.existing['globalLLDPENABLE'] = self.get_lldp_enable_pre_config()
- if self.function_lldp_interface_flag == 'disableINTERFACE':
- self.existing['disableINTERFACE'] = self.get_interface_lldp_disable_config()
- if self.function_lldp_interface_flag == 'tlvdisableINTERFACE':
- self.existing['tlvdisableINTERFACE'] = self.get_interface_tlv_disable_config()
- if self.function_lldp_interface_flag == 'tlvenableINTERFACE':
- self.existing['tlvenableINTERFACE'] = self.get_interface_tlv_enable_config()
- if self.function_lldp_interface_flag == 'intervalINTERFACE':
- self.existing['intervalINTERFACE'] = self.get_interface_interval_config()
-
- def get_proposed(self):
- """get proposed"""
- if self.lldpenable:
- self.proposed = dict(lldpenable=self.lldpenable)
- if self.function_lldp_interface_flag == 'disableINTERFACE':
- if self.enable_flag == 1:
- self.proposed = dict(ifname=self.ifname, lldpadminstatus=self.lldpadminstatus)
- if self.function_lldp_interface_flag == 'tlvdisableINTERFACE':
- if self.enable_flag == 1:
- if self.type_tlv_disable == 'basic_tlv':
- if self.ifname:
- if self.manaddrtxenable:
- self.proposed = dict(ifname=self.ifname, manaddrtxenable=self.manaddrtxenable)
- if self.portdesctxenable:
- self.proposed = dict(ifname=self.ifname, portdesctxenable=self.portdesctxenable)
- if self.syscaptxenable:
- self.proposed = dict(ifname=self.ifname, syscaptxenable=self.syscaptxenable)
- if self.sysdesctxenable:
- self.proposed = dict(ifname=self.ifname, sysdesctxenable=self.sysdesctxenable)
- if self.sysnametxenable:
- self.proposed = dict(ifname=self.ifname, sysnametxenable=self.sysnametxenable)
- if self.type_tlv_disable == 'dot3_tlv':
- if self.ifname:
- if self.linkaggretxenable:
- self.proposed = dict(ifname=self.ifname, linkaggretxenable=self.linkaggretxenable)
- if self.macphytxenable:
- self.proposed = dict(ifname=self.ifname, macphytxenable=self.macphytxenable)
- if self.maxframetxenable:
- self.proposed = dict(ifname=self.ifname, maxframetxenable=self.maxframetxenable)
- if self.eee:
- self.proposed = dict(ifname=self.ifname, eee=self.eee)
- if self.function_lldp_interface_flag == 'tlvenableINTERFACE':
- if self.enable_flag == 1:
- if self.type_tlv_enable == 'dot1_tlv':
- if self.ifname:
- if self.protoidtxenable:
- self.proposed = dict(ifname=self.ifname, protoidtxenable=self.protoidtxenable)
- if self.type_tlv_enable == 'dcbx':
- if self.ifname:
- if self.dcbx:
- self.proposed = dict(ifname=self.ifname, dcbx=self.dcbx)
- if self.function_lldp_interface_flag == 'intervalINTERFACE':
- tmp1 = self.get_interface_lldp_disable_pre_config()
- if self.enable_flag == 1 and tmp1[self.ifname] != 'disabled':
- self.proposed = dict(ifname=self.ifname, txinterval=self.txinterval)
-
- def config_lldp_interface(self):
- """config lldp interface"""
- if self.lldpenable:
- self.config_global_lldp_enable()
- if self.function_lldp_interface_flag == 'disableINTERFACE':
- self.config_interface_lldp_disable_config()
- elif self.function_lldp_interface_flag == 'tlvdisableINTERFACE':
- self.config_interface_tlv_disable_config()
- elif self.function_lldp_interface_flag == 'tlvenableINTERFACE':
- self.config_interface_tlv_enable_config()
- elif self.function_lldp_interface_flag == 'intervalINTERFACE':
- self.config_interface_interval_config()
-
- def get_end_state(self):
- """get end_state information"""
- self.get_lldp_enable_pre_config()
- if self.lldpenable:
- self.end_state['globalLLDPENABLE'] = self.get_lldp_enable_pre_config()
- if self.function_lldp_interface_flag == 'disableINTERFACE':
- self.end_state['disableINTERFACE'] = self.get_interface_lldp_disable_config()
- if self.function_lldp_interface_flag == 'tlvdisableINTERFACE':
- self.end_state['tlvdisableINTERFACE'] = self.get_interface_tlv_disable_config()
- if self.function_lldp_interface_flag == 'tlvenableINTERFACE':
- self.end_state['tlvenableINTERFACE'] = self.get_interface_tlv_enable_config()
- if self.function_lldp_interface_flag == 'intervalINTERFACE':
- self.end_state['intervalINTERFACE'] = self.get_interface_interval_config()
-
- def get_update_cmd(self):
- """Get updated commands"""
-
- cmds = []
- if self.state == "present":
- if self.lldpenable == "enabled":
- cmds.append("lldp enable")
- if self.function_lldp_interface_flag == 'disableINTERFACE':
- if self.ifname:
- cmds.append("%s %s" % ("interface", self.ifname))
- if self.lldpadminstatus == 'disabled':
- cmds.append("lldp disable")
- else:
- cmds.append("undo lldp disable")
- elif self.function_lldp_interface_flag == 'tlvdisableINTERFACE':
- if self.type_tlv_disable == 'basic_tlv':
- if self.ifname:
- cmds.append("%s %s" % ("interface", self.ifname))
- if self.manaddrtxenable:
- if self.manaddrtxenable == "false":
- cmds.append("lldp tlv-disable basic-tlv management-address")
- if self.manaddrtxenable == "true":
- cmds.append("undo lldp tlv-disable basic-tlv management-address")
- if self.portdesctxenable:
- if self.portdesctxenable == "false":
- cmds.append("lldp tlv-disable basic-tlv port-description")
- if self.portdesctxenable == "true":
- cmds.append("undo lldp tlv-disable basic-tlv port-description")
- if self.syscaptxenable:
- if self.syscaptxenable == "false":
- cmds.append("lldp tlv-disable basic-tlv system-capability")
- if self.syscaptxenable == "true":
- cmds.append("undo lldp tlv-disable basic-tlv system-capability")
- if self.sysdesctxenable:
- if self.sysdesctxenable == "false":
- cmds.append("lldp tlv-disable basic-tlv system-description")
- if self.sysdesctxenable == "true":
- cmds.append("undo lldp tlv-disable basic-tlv system-description")
- if self.sysnametxenable:
- if self.sysnametxenable == "false":
- cmds.append("lldp tlv-disable basic-tlv system-name")
- if self.sysnametxenable == "true":
- cmds.append("undo lldp tlv-disable basic-tlv system-name")
- if self.type_tlv_disable == 'dot3_tlv':
- if self.ifname:
- cmds.append("%s %s" % ("interface", self.ifname))
- if self.linkaggretxenable:
- if self.linkaggretxenable == "false":
- cmds.append("lldp tlv-disable dot3-tlv link-aggregation")
- if self.linkaggretxenable == "true":
- cmds.append("undo lldp tlv-disable dot3-tlv link-aggregation")
- if self.macphytxenable:
- if self.macphytxenable == "false":
- cmds.append("lldp tlv-disable dot3-tlv mac-physic")
- if self.macphytxenable == "true":
- cmds.append("undo lldp tlv-disable dot3-tlv mac-physic")
- if self.maxframetxenable:
- if self.maxframetxenable == "false":
- cmds.append("lldp tlv-disable dot3-tlv max-frame-size")
- if self.maxframetxenable == "true":
- cmds.append("undo lldp tlv-disable dot3-tlv max-frame-size")
- if self.eee:
- if self.eee == "false":
- cmds.append("lldp tlv-disable dot3-tlv eee")
- if self.eee == "true":
- cmds.append("undo lldp tlv-disable dot3-tlv eee")
- elif self.function_lldp_interface_flag == 'tlvenableINTERFACE':
- if self.type_tlv_enable == 'dot1_tlv':
- if self.ifname:
- cmds.append("%s %s" % ("interface", self.ifname))
- if self.protoidtxenable:
- if self.protoidtxenable == "false":
- cmds.append("undo lldp tlv-enable dot1-tlv protocol-identity")
- if self.protoidtxenable == "true":
- cmds.append("lldp tlv-enable dot1-tlv protocol-identity")
- if self.type_tlv_enable == 'dcbx':
- if self.ifname:
- cmds.append("%s %s" % ("interface", self.ifname))
- if self.dcbx:
- if self.dcbx == "false":
- cmds.append("undo lldp tlv-enable dcbx")
- if self.dcbx == "true":
- cmds.append("lldp tlv-enable dcbx")
- elif self.function_lldp_interface_flag == 'intervalINTERFACE':
- if self.ifname:
- cmds.append("%s %s" % ("interface", self.ifname))
- if self.txinterval:
- cmds.append("lldp transmit fast-mode interval %s" % self.txinterval)
- elif self.lldpenable == "disabled":
- cmds.append("undo lldp enable")
- else:
- if self.enable_flag == 1:
- if self.function_lldp_interface_flag == 'disableINTERFACE':
- if self.ifname:
- cmds.append("interface %s" % self.ifname)
- if self.lldpadminstatus == 'disabled':
- cmds.append("lldp disable")
- else:
- cmds.append("undo lldp disable")
- elif self.function_lldp_interface_flag == 'tlvdisableINTERFACE':
- if self.type_tlv_disable == 'basic_tlv':
- if self.ifname:
- cmds.append("interface %s" % self.ifname)
- if self.manaddrtxenable:
- if self.manaddrtxenable == "false":
- cmds.append("lldp tlv-disable basic-tlv management-address")
- if self.manaddrtxenable == "true":
- cmds.append("undo lldp tlv-disable basic-tlv management-address")
- if self.portdesctxenable:
- if self.portdesctxenable == "false":
- cmds.append("lldp tlv-disable basic-tlv port-description")
- if self.portdesctxenable == "true":
- cmds.append("undo lldp tlv-disable basic-tlv port-description")
- if self.syscaptxenable:
- if self.syscaptxenable == "false":
- cmds.append("lldp tlv-disable basic-tlv system-capability")
- if self.syscaptxenable == "true":
- cmds.append("undo lldp tlv-disable basic-tlv system-capability")
- if self.sysdesctxenable:
- if self.sysdesctxenable == "false":
- cmds.append("lldp tlv-disable basic-tlv system-description")
- if self.sysdesctxenable == "true":
- cli_str = "%s %s\n" % (cli_str, "undo lldp tlv-disable basic-tlv system-description")
- if self.sysnametxenable:
- if self.sysnametxenable == "false":
- cmds.append("lldp tlv-disable basic-tlv system-name")
- if self.sysnametxenable == "true":
- cmds.append("undo lldp tlv-disable basic-tlv system-name")
- if self.type_tlv_disable == 'dot3_tlv':
- if self.ifname:
- cmds.append("interface %s" % self.ifname)
- if self.linkaggretxenable:
- if self.linkaggretxenable == "false":
- cmds.append("lldp tlv-disable dot3-tlv link-aggregation")
- if self.linkaggretxenable == "true":
- cmds.append("undo lldp tlv-disable dot3-tlv link-aggregation")
- if self.macphytxenable:
- if self.macphytxenable == "false":
- cmds.append("lldp tlv-disable dot3-tlv mac-physic")
- if self.macphytxenable == "true":
- cli_str = "%s %s\n" % (cli_str, "undo lldp tlv-disable dot3-tlv mac-physic")
- if self.maxframetxenable:
- if self.maxframetxenable == "false":
- cmds.append("lldp tlv-disable dot3-tlv max-frame-size")
- if self.maxframetxenable == "true":
- cmds.append("undo lldp tlv-disable dot3-tlv max-frame-size")
- if self.eee:
- if self.eee == "false":
- cmds.append("lldp tlv-disable dot3-tlv eee")
- if self.eee == "true":
- cmds.append("undo lldp tlv-disable dot3-tlv eee")
- elif self.function_lldp_interface_flag == 'tlvenableINTERFACE':
- if self.type_tlv_enable == 'dot1_tlv':
- if self.ifname:
- cmds.append("interface %s" % self.ifname)
- if self.protoidtxenable:
- if self.protoidtxenable == "false":
- cmds.append("undo lldp tlv-enable dot1-tlv protocol-identity")
- if self.protoidtxenable == "true":
- cmds.append("lldp tlv-enable dot1-tlv protocol-identity")
- if self.type_tlv_enable == 'dcbx':
- if self.ifname:
- cmds.append("interface %s" % self.ifname)
- if self.dcbx:
- if self.dcbx == "false":
- cmds.append("undo lldp tlv-enable dcbx")
- if self.dcbx == "true":
- cmds.append("lldp tlv-enable dcbx")
- elif self.function_lldp_interface_flag == 'intervalINTERFACE':
- if self.ifname:
- cmds.append("interface %s" % self.ifname)
- if self.txinterval:
- cmds.append("lldp transmit fast-mode interval %s" % self.txinterval)
- self.updates_cmd = cmds
-
- def work(self):
- """Execute task"""
- self.check_params()
- self.get_existing()
- self.get_proposed()
- self.config_lldp_interface()
- self.get_update_cmd()
- self.get_end_state()
- self.show_result()
-
-
-def main():
- """Main function"""
-
- argument_spec = dict(
- lldpenable=dict(choices=['enabled', 'disabled']),
- function_lldp_interface_flag=dict(choices=['disableINTERFACE', 'tlvdisableINTERFACE', 'tlvenableINTERFACE', 'intervalINTERFACE'], type='str'),
- type_tlv_disable=dict(choices=['basic_tlv', 'dot3_tlv'], type='str'),
- type_tlv_enable=dict(choices=['dot1_tlv', 'dcbx'], type='str'),
- ifname=dict(type='str'),
- lldpadminstatus=dict(choices=['txOnly', 'rxOnly', 'txAndRx', 'disabled'], type='str'),
- manaddrtxenable=dict(type='bool'),
- portdesctxenable=dict(type='bool'),
- syscaptxenable=dict(type='bool'),
- sysdesctxenable=dict(type='bool'),
- sysnametxenable=dict(type='bool'),
- portvlantxenable=dict(type='bool'),
- protovlantxenable=dict(type='bool'),
- txprotocolvlanid=dict(type='int'),
- vlannametxenable=dict(type='bool'),
- txvlannameid=dict(type='int'),
- txinterval=dict(type='int'),
- protoidtxenable=dict(type='bool'),
- macphytxenable=dict(type='bool'),
- linkaggretxenable=dict(type='bool'),
- maxframetxenable=dict(type='bool'),
- eee=dict(type='bool'),
- dcbx=dict(type='bool'),
- state=dict(type='str', choices=['absent', 'present'], default='present'),
- )
-
- lldp_interface_obj = Lldp_interface(argument_spec)
- lldp_interface_obj.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_mdn_interface.py b/plugins/modules/network/cloudengine/ce_mdn_interface.py
deleted file mode 100644
index 583d81504f..0000000000
--- a/plugins/modules/network/cloudengine/ce_mdn_interface.py
+++ /dev/null
@@ -1,402 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-
-module: ce_mdn_interface
-short_description: Manages MDN configuration on HUAWEI CloudEngine switches.
-description:
- - Manages MDN configuration on HUAWEI CloudEngine switches.
-author: xuxiaowei0512 (@CloudEngine-Ansible)
-options:
- lldpenable:
- description:
- - Set global LLDP enable state.
- type: str
- choices: ['enabled', 'disabled']
- mdnstatus:
- description:
- - Set interface MDN enable state.
- type: str
- choices: ['rxOnly', 'disabled']
- ifname:
- description:
- - Interface name.
- type: str
- state:
- description:
- - Manage the state of the resource.
- default: present
- type: str
- choices: ['present','absent']
-notes:
- - This module requires the netconf system service be enabled on
- the remote device being managed.
- - This module works with connection C(netconf).
-'''
-
-EXAMPLES = '''
- - name: "Configure global LLDP enable state"
- ce_mdn_interface:
- lldpenable: enabled
-
- - name: "Configure interface MDN enable state"
- ce_mdn_interface:
- ifname: 10GE1/0/1
- mdnstatus: rxOnly
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "lldpenable": "enabled",
- "ifname": "10GE1/0/1",
- "mdnstatus": "rxOnly",
- "state":"present"
- }
-existing:
- description: k/v pairs of existing global LLDP configration
- returned: always
- type: dict
- sample: {
- "lldpenable": "enabled",
- "ifname": "10GE1/0/1",
- "mdnstatus": "disabled"
- }
-end_state:
- description: k/v pairs of global LLDP configration after module execution
- returned: always
- type: dict
- sample: {
- "lldpenable": "enabled",
- "ifname": "10GE1/0/1",
- "mdnstatus": "rxOnly"
- }
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: [
- "interface 10ge 1/0/1",
- "lldp mdn enable",
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import copy
-import re
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import set_nc_config, get_nc_config, execute_nc_action
-
-CE_NC_GET_GLOBAL_LLDPENABLE_CONFIG = """
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_GLOBA_LLDPENABLE_CONFIG = """
-
-
-
- %s
-
-
-
-"""
-
-CE_NC_GET_INTERFACE_MDNENABLE_CONFIG = """
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_INTERFACE_MDNENABLE_CONFIG = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE, ..."""
-
- if interface is None:
- return None
-
- iftype = None
-
- if interface.upper().startswith('GE'):
- iftype = 'ge'
- elif interface.upper().startswith('10GE'):
- iftype = '10ge'
- elif interface.upper().startswith('25GE'):
- iftype = '25ge'
- elif interface.upper().startswith('40GE'):
- iftype = '40ge'
- elif interface.upper().startswith('100GE'):
- iftype = '100ge'
- elif interface.upper().startswith('PORT-GROUP'):
- iftype = 'stack-Port'
- elif interface.upper().startswith('NULL'):
- iftype = 'null'
- else:
- return None
- return iftype.lower()
-
-
-class Interface_mdn(object):
- """Manage global lldp enable configration"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # LLDP global configration info
- self.lldpenable = self.module.params['lldpenable'] or None
- self.ifname = self.module.params['ifname']
- self.mdnstatus = self.module.params['mdnstatus'] or None
- self.state = self.module.params['state']
- self.lldp_conf = dict()
- self.conf_exsit = False
- self.enable_flag = 0
- self.check_params()
-
- # state
- self.changed = False
- self.proposed_changed = dict()
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def check_params(self):
- """Check all input params"""
-
- if self.ifname:
- intf_type = get_interface_type(self.ifname)
- if not intf_type:
- self.module.fail_json(
- msg='Error: ifname name of %s '
- 'is error.' % self.ifname)
- if (len(self.ifname) < 1) or (len(self.ifname) > 63):
- self.module.fail_json(
- msg='Error: Ifname length is beetween 1 and 63.')
-
- def init_module(self):
- """Init module object"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed"""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def config_interface_mdn(self):
- """Configure lldp enabled and interface mdn enabled parameters"""
-
- if self.state == 'present':
- if self.enable_flag == 0 and self.lldpenable == 'enabled':
- xml_str = CE_NC_MERGE_GLOBA_LLDPENABLE_CONFIG % self.lldpenable
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "LLDP_ENABLE_CONFIG")
- self.changed = True
- elif self.enable_flag == 1 and self.lldpenable == 'disabled':
- xml_str = CE_NC_MERGE_GLOBA_LLDPENABLE_CONFIG % self.lldpenable
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "LLDP_ENABLE_CONFIG")
- self.changed = True
- elif self.enable_flag == 1 and self.conf_exsit:
- xml_str = CE_NC_MERGE_INTERFACE_MDNENABLE_CONFIG % (self.ifname, self.mdnstatus)
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "INTERFACE_MDN_ENABLE_CONFIG")
- self.changed = True
-
- def show_result(self):
- """Show result"""
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
- def get_interface_mdn_exist_config(self):
- """Get lldp existed configure"""
-
- lldp_config = list()
- lldp_dict = dict()
- conf_enable_str = CE_NC_GET_GLOBAL_LLDPENABLE_CONFIG
- conf_enable_obj = get_nc_config(self.module, conf_enable_str)
- xml_enable_str = conf_enable_obj.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get lldp enable config info
- root_enable = ElementTree.fromstring(xml_enable_str)
- ntpsite_enable = root_enable.findall("lldp/lldpSys")
- for nexthop_enable in ntpsite_enable:
- for ele_enable in nexthop_enable:
- if ele_enable.tag in ["lldpEnable"]:
- lldp_dict[ele_enable.tag] = ele_enable.text
-
- if self.state == "present":
- if lldp_dict['lldpEnable'] == 'enabled':
- self.enable_flag = 1
- lldp_config.append(dict(lldpenable=lldp_dict['lldpEnable']))
-
- if self.enable_flag == 1:
- conf_str = CE_NC_GET_INTERFACE_MDNENABLE_CONFIG
- conf_obj = get_nc_config(self.module, conf_str)
- if "" in conf_obj:
- return lldp_config
- xml_str = conf_obj.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- # get all ntp config info
- root = ElementTree.fromstring(xml_str)
- ntpsite = root.findall("lldp/mdnInterfaces/mdnInterface")
- for nexthop in ntpsite:
- for ele in nexthop:
- if ele.tag in ["ifName", "mdnStatus"]:
- lldp_dict[ele.tag] = ele.text
- if self.state == "present":
- cur_interface_mdn_cfg = dict(ifname=lldp_dict['ifName'], mdnstatus=lldp_dict['mdnStatus'])
- exp_interface_mdn_cfg = dict(ifname=self.ifname, mdnstatus=self.mdnstatus)
- if self.ifname == lldp_dict['ifName']:
- if cur_interface_mdn_cfg != exp_interface_mdn_cfg:
- self.conf_exsit = True
- lldp_config.append(dict(ifname=lldp_dict['ifName'], mdnstatus=lldp_dict['mdnStatus']))
- return lldp_config
- lldp_config.append(dict(ifname=lldp_dict['ifName'], mdnstatus=lldp_dict['mdnStatus']))
- return lldp_config
-
- def get_existing(self):
- """Get existing info"""
-
- self.existing = self.get_interface_mdn_exist_config()
-
- def get_proposed(self):
- """Get proposed info"""
-
- if self.lldpenable:
- self.proposed = dict(lldpenable=self.lldpenable)
- if self.enable_flag == 1:
- if self.ifname:
- self.proposed = dict(ifname=self.ifname, mdnstatus=self.mdnstatus)
-
- def get_end_state(self):
- """Get end state info"""
-
- self.end_state = self.get_interface_mdn_exist_config()
-
- def get_update_cmd(self):
- """Get updated commands"""
-
- update_list = list()
- if self.state == "present":
- if self.lldpenable == "enabled":
- cli_str = "lldp enable"
- update_list.append(cli_str)
- if self.ifname:
- cli_str = "%s %s" % ("interface", self.ifname)
- update_list.append(cli_str)
- if self.mdnstatus:
- if self.mdnstatus == "rxOnly":
- cli_str = "lldp mdn enable"
- update_list.append(cli_str)
- else:
- cli_str = "undo lldp mdn enable"
- update_list.append(cli_str)
-
- elif self.lldpenable == "disabled":
- cli_str = "undo lldp enable"
- update_list.append(cli_str)
- else:
- if self.enable_flag == 1:
- if self.ifname:
- cli_str = "%s %s" % ("interface", self.ifname)
- update_list.append(cli_str)
- if self.mdnstatus:
- if self.mdnstatus == "rxOnly":
- cli_str = "lldp mdn enable"
- update_list.append(cli_str)
- else:
- cli_str = "undo lldp mdn enable"
- update_list.append(cli_str)
-
- self.updates_cmd.append(update_list)
-
- def work(self):
- """Excute task"""
- self.check_params()
- self.get_existing()
- self.get_proposed()
- self.config_interface_mdn()
- self.get_update_cmd()
- self.get_end_state()
- self.show_result()
-
-
-def main():
- """Main function entry"""
-
- argument_spec = dict(
- lldpenable=dict(type='str', choices=['enabled', 'disabled']),
- mdnstatus=dict(type='str', choices=['rxOnly', 'disabled']),
- ifname=dict(type='str'),
- state=dict(choices=['absent', 'present'], default='present'),
- )
- lldp_obj = Interface_mdn(argument_spec)
- lldp_obj.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_mlag_config.py b/plugins/modules/network/cloudengine/ce_mlag_config.py
deleted file mode 100644
index 1e40ae94a7..0000000000
--- a/plugins/modules/network/cloudengine/ce_mlag_config.py
+++ /dev/null
@@ -1,916 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_mlag_config
-short_description: Manages MLAG configuration on HUAWEI CloudEngine switches.
-description:
- - Manages MLAG configuration on HUAWEI CloudEngine switches.
-author:
- - Li Yanfeng (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- dfs_group_id:
- description:
- - ID of a DFS group. The value is 1.
- default: present
- nickname:
- description:
- - The nickname bound to a DFS group. The value is an integer that ranges from 1 to 65471.
- pseudo_nickname:
- description:
- - A pseudo nickname of a DFS group. The value is an integer that ranges from 1 to 65471.
- pseudo_priority:
- description:
- - The priority of a pseudo nickname. The value is an integer that ranges from 128 to 255.
- The default value is 192. A larger value indicates a higher priority.
- ip_address:
- description:
- - IP address bound to the DFS group. The value is in dotted decimal notation.
- vpn_instance_name:
- description:
- - Name of the VPN instance bound to the DFS group. The value is a string of 1 to 31 case-sensitive
- characters without spaces. If the character string is quoted by double quotation marks, the character
- string can contain spaces. The value _public_ is reserved and cannot be used as the VPN instance name.
- priority_id:
- description:
- - Priority of a DFS group. The value is an integer that ranges from 1 to 254. The default value is 100.
- eth_trunk_id:
- description:
- - Name of the peer-link interface. The value is in the range from 0 to 511.
- peer_link_id:
- description:
- - Number of the peer-link interface. The value is 1.
- state:
- description:
- - Specify desired state of the resource.
- default: present
- choices: ['present','absent']
-'''
-
-EXAMPLES = '''
-- name: mlag config module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Create DFS Group id
- ce_mlag_config:
- dfs_group_id: 1
- provider: "{{ cli }}"
- - name: Set dfs-group priority
- ce_mlag_config:
- dfs_group_id: 1
- priority_id: 3
- state: present
- provider: "{{ cli }}"
- - name: Set pseudo nickname
- ce_mlag_config:
- dfs_group_id: 1
- pseudo_nickname: 3
- pseudo_priority: 130
- state: present
- provider: "{{ cli }}"
- - name: Set ip
- ce_mlag_config:
- dfs_group_id: 1
- ip_address: 11.1.1.2
- vpn_instance_name: 6
- provider: "{{ cli }}"
- - name: Set peer link
- ce_mlag_config:
- eth_trunk_id: 3
- peer_link_id: 2
- state: present
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: { "eth_trunk_id": "3",
- "peer_link_id": "1",
- "state": "present"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: { }
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: { "eth_trunk_id": "Eth-Trunk3",
- "peer_link_id": "1"}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: {"peer-link 1"}
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-
-CE_NC_GET_DFS_GROUP_INFO = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-CE_NC_GET_PEER_LINK_INFO = """
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_CREATE_DFS_GROUP_INFO_HEADER = """
-
-
-
-
- %s
-"""
-
-CE_NC_CREATE_DFS_GROUP_INFO_TAIL = """
-
-
-
-
-"""
-
-CE_NC_MERGE_DFS_GROUP_INFO_HEADER = """
-
-
-
-
- %s
-"""
-
-CE_NC_MERGE_DFS_GROUP_INFO_TAIL = """
-
-
-
-
-"""
-
-CE_NC_DELETE_DFS_GROUP_ATTRIBUTE_HEADER = """
-
-
-
-
- %s
-"""
-
-CE_NC_DELETE_DFS_GROUP_ATTRIBUTE_TAIL = """
-
-
-
-
-"""
-
-CE_NC_DELETE_DFS_GROUP_INFO_HEADER = """
-
-
-
-
- %s
-"""
-
-CE_NC_DELETE_DFS_GROUP_INFO_TAIL = """
-
-
-
-
-"""
-
-CE_NC_CREATE_PEER_LINK_INFO = """
-
-
-
-
- 1
- %s
- %s
-
-
-
-
-"""
-
-CE_NC_MERGE_PEER_LINK_INFO = """
-
-
-
-
- 1
- %s
- %s
-
-
-
-
-"""
-CE_NC_DELETE_PEER_LINK_INFO = """
-
-
-
-
- 1
- %s
- %s
-
-
-
-
-"""
-
-
-def is_valid_address(address):
- """check ip-address is valid"""
-
- if address.find('.') != -1:
- addr_list = address.split('.')
- if len(addr_list) != 4:
- return False
- for each_num in addr_list:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- return True
-
- return False
-
-
-class MlagConfig(object):
- """
- Manages Manages MLAG config information.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.dfs_group_id = self.module.params['dfs_group_id']
- self.nickname = self.module.params['nickname']
- self.pseudo_nickname = self.module.params['pseudo_nickname']
- self.pseudo_priority = self.module.params['pseudo_priority']
- self.ip_address = self.module.params['ip_address']
- self.vpn_instance_name = self.module.params['vpn_instance_name']
- self.priority_id = self.module.params['priority_id']
- self.eth_trunk_id = self.module.params['eth_trunk_id']
- self.peer_link_id = self.module.params['peer_link_id']
- self.state = self.module.params['state']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.existing = dict()
- self.proposed = dict()
- self.end_state = dict()
-
- self.commands = list()
- # DFS group info
- self.dfs_group_info = None
- # peer link info
- self.peer_link_info = None
-
- def init_module(self):
- """ init module """
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def check_response(self, con_obj, xml_name):
- """Check if response message is already succeed."""
-
- xml_str = con_obj.xml
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_dfs_group_info(self):
- """ get dfs group attributes info."""
-
- dfs_group_info = dict()
- conf_str = CE_NC_GET_DFS_GROUP_INFO
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return dfs_group_info
- else:
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
- dfs_info = root.findall(
- "dfs/groupInstances/groupInstance")
- if dfs_info:
- for tmp in dfs_info:
- for site in tmp:
- if site.tag in ["groupId", "priority", "ipAddress", "srcVpnName"]:
- dfs_group_info[site.tag] = site.text
-
- dfs_nick_info = root.findall(
- "dfs/groupInstances/groupInstance/trillType")
-
- if dfs_nick_info:
- for tmp in dfs_nick_info:
- for site in tmp:
- if site.tag in ["localNickname", "pseudoNickname", "pseudoPriority"]:
- dfs_group_info[site.tag] = site.text
- return dfs_group_info
-
- def get_peer_link_info(self):
- """ get peer link info."""
-
- peer_link_info = dict()
- conf_str = CE_NC_GET_PEER_LINK_INFO
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return peer_link_info
- else:
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- link_info = root.findall(
- "mlag/peerlinks/peerlink")
- if link_info:
- for tmp in link_info:
- for site in tmp:
- if site.tag in ["linkId", "portName"]:
- peer_link_info[site.tag] = site.text
- return peer_link_info
-
- def is_dfs_group_info_change(self):
- """whether dfs group info"""
- if not self.dfs_group_info:
- return False
-
- if self.priority_id and self.dfs_group_info["priority"] != self.priority_id:
- return True
- if self.ip_address and self.dfs_group_info["ipAddress"] != self.ip_address:
- return True
- if self.vpn_instance_name and self.dfs_group_info["srcVpnName"] != self.vpn_instance_name:
- return True
- if self.nickname and self.dfs_group_info["localNickname"] != self.nickname:
- return True
- if self.pseudo_nickname and self.dfs_group_info["pseudoNickname"] != self.pseudo_nickname:
- return True
- if self.pseudo_priority and self.dfs_group_info["pseudoPriority"] != self.pseudo_priority:
- return True
- return False
-
- def check_dfs_group_info_change(self):
- """check dfs group info"""
- if not self.dfs_group_info:
- return True
-
- if self.priority_id and self.dfs_group_info["priority"] == self.priority_id:
- return True
- if self.ip_address and self.dfs_group_info["ipAddress"] == self.ip_address:
- return True
- if self.vpn_instance_name and self.dfs_group_info["srcVpnName"] == self.vpn_instance_name:
- return True
- if self.nickname and self.dfs_group_info["localNickname"] == self.nickname:
- return True
- if self.pseudo_nickname and self.dfs_group_info["pseudoNickname"] == self.pseudo_nickname:
- return True
- if self.pseudo_priority and self.dfs_group_info["pseudoPriority"] == self.pseudo_priority:
- return True
- return False
-
- def modify_dfs_group(self):
- """modify dfs group info"""
-
- if self.is_dfs_group_info_change():
-
- conf_str = CE_NC_MERGE_DFS_GROUP_INFO_HEADER % self.dfs_group_id
- if self.priority_id and self.dfs_group_info["priority"] != self.priority_id:
- conf_str += "%s" % self.priority_id
- if self.ip_address and self.dfs_group_info["ipAddress"] != self.ip_address:
- conf_str += "%s" % self.ip_address
- if self.vpn_instance_name and self.dfs_group_info["srcVpnName"] != self.vpn_instance_name:
- if not self.ip_address:
- self.module.fail_json(
- msg='Error: ip_address can not be null if vpn_instance_name is exist.')
- conf_str += "%s" % self.vpn_instance_name
-
- if self.nickname or self.pseudo_nickname or self.pseudo_priority:
- conf_str += ""
- if self.nickname and self.dfs_group_info["localNickname"] != self.nickname:
- conf_str += "%s" % self.nickname
- if self.pseudo_nickname and self.dfs_group_info["pseudoNickname"] != self.pseudo_nickname:
- conf_str += "%s" % self.pseudo_nickname
-
- if self.pseudo_priority and self.dfs_group_info["pseudoPriority"] != self.pseudo_priority:
- if not self.pseudo_nickname:
- self.module.fail_json(
- msg='Error: pseudo_nickname can not be null if pseudo_priority is exist.')
- conf_str += "%s" % self.pseudo_priority
- conf_str += ""
-
- conf_str += CE_NC_MERGE_DFS_GROUP_INFO_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: Merge DFS group info failed.')
-
- self.updates_cmd.append("dfs-group 1")
- if self.priority_id:
- self.updates_cmd.append("priority %s" % self.priority_id)
- if self.ip_address:
- if self.vpn_instance_name:
- self.updates_cmd.append(
- "source ip %s vpn-instance %s" % (self.ip_address, self.vpn_instance_name))
- else:
- self.updates_cmd.append("source ip %s" % self.ip_address)
- if self.nickname:
- self.updates_cmd.append("source nickname %s" % self.nickname)
- if self.pseudo_nickname:
- if self.pseudo_priority:
- self.updates_cmd.append(
- "pseudo-nickname %s priority %s" % (self.pseudo_nickname, self.pseudo_priority))
- else:
- self.updates_cmd.append(
- "pseudo-nickname %s" % self.pseudo_nickname)
-
- self.changed = True
-
- def create_dfs_group(self):
- """create dfs group info"""
-
- conf_str = CE_NC_CREATE_DFS_GROUP_INFO_HEADER % self.dfs_group_id
- if self.priority_id and self.priority_id != 100:
- conf_str += "%s" % self.priority_id
- if self.ip_address:
- conf_str += "%s" % self.ip_address
- if self.vpn_instance_name:
- if not self.ip_address:
- self.module.fail_json(
- msg='Error: ip_address can not be null if vpn_instance_name is exist.')
- conf_str += "%s" % self.vpn_instance_name
-
- if self.nickname or self.pseudo_nickname or self.pseudo_priority:
- conf_str += ""
- if self.nickname:
- conf_str += "%s" % self.nickname
- if self.pseudo_nickname:
- conf_str += "%s" % self.pseudo_nickname
- if self.pseudo_priority:
- if not self.pseudo_nickname:
- self.module.fail_json(
- msg='Error: pseudo_nickname can not be null if pseudo_priority is exist.')
- conf_str += "%s" % self.pseudo_priority
- conf_str += ""
-
- conf_str += CE_NC_CREATE_DFS_GROUP_INFO_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: Merge DFS group info failed.')
-
- self.updates_cmd.append("dfs-group 1")
- if self.priority_id:
- self.updates_cmd.append("priority %s" % self.priority_id)
- if self.ip_address:
- if self.vpn_instance_name:
- self.updates_cmd.append(
- "source ip %s vpn-instance %s" % (self.ip_address, self.vpn_instance_name))
- else:
- self.updates_cmd.append("source ip %s" % self.ip_address)
- if self.nickname:
- self.updates_cmd.append("source nickname %s" % self.nickname)
- if self.pseudo_nickname:
- if self.pseudo_priority:
- self.updates_cmd.append(
- "pseudo-nickname %s priority %s" % (self.pseudo_nickname, self.pseudo_priority))
- else:
- self.updates_cmd.append(
- "pseudo-nickname %s" % self.pseudo_nickname)
-
- self.changed = True
-
- def delete_dfs_group(self):
- """delete dfg group"""
-
- conf_str = CE_NC_DELETE_DFS_GROUP_INFO_HEADER % self.dfs_group_id
- conf_str += CE_NC_DELETE_DFS_GROUP_INFO_TAIL
-
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: Delete DFS group id failed.')
- self.updates_cmd.append("undo dfs-group 1")
- self.changed = True
-
- def delete_dfs_group_attribute(self):
- """delete dfg group attribute info"""
-
- conf_str = CE_NC_DELETE_DFS_GROUP_ATTRIBUTE_HEADER % self.dfs_group_id
- change = False
- if self.priority_id and self.dfs_group_info["priority"] == self.priority_id:
- conf_str += "%s" % self.priority_id
- change = True
- self.updates_cmd.append("undo priority %s" % self.priority_id)
- if self.ip_address and self.dfs_group_info["ipAddress"] == self.ip_address:
- if self.vpn_instance_name and self.dfs_group_info["srcVpnName"] == self.vpn_instance_name:
- conf_str += "%s" % self.ip_address
- conf_str += "%s" % self.vpn_instance_name
- self.updates_cmd.append(
- "undo source ip %s vpn-instance %s" % (self.ip_address, self.vpn_instance_name))
- else:
- conf_str += "%s" % self.ip_address
- self.updates_cmd.append("undo source ip %s" % self.ip_address)
- change = True
-
- conf_str += CE_NC_DELETE_DFS_GROUP_ATTRIBUTE_TAIL
-
- if change:
- self.updates_cmd.append("undo dfs-group 1")
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: Delete DFS group attribute failed.')
- self.changed = True
-
- def delete_dfs_group_nick(self):
-
- conf_str = CE_NC_DELETE_DFS_GROUP_ATTRIBUTE_HEADER % self.dfs_group_id
- conf_str = conf_str.replace('', '')
- change = False
-
- if self.nickname or self.pseudo_nickname:
- conf_str += ""
- if self.nickname and self.dfs_group_info["localNickname"] == self.nickname:
- conf_str += "%s" % self.nickname
- change = True
- self.updates_cmd.append("undo source nickname %s" % self.nickname)
- if self.pseudo_nickname and self.dfs_group_info["pseudoNickname"] == self.pseudo_nickname:
- conf_str += "%s" % self.pseudo_nickname
- if self.pseudo_priority and self.dfs_group_info["pseudoPriority"] == self.pseudo_priority:
- self.updates_cmd.append(
- "undo pseudo-nickname %s priority %s" % (self.pseudo_nickname, self.pseudo_priority))
- if not self.pseudo_priority:
- self.updates_cmd.append(
- "undo pseudo-nickname %s" % self.pseudo_nickname)
- change = True
- conf_str += ""
-
- conf_str += CE_NC_DELETE_DFS_GROUP_ATTRIBUTE_TAIL
-
- if change:
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: Delete DFS group attribute failed.')
- self.changed = True
-
- def modify_peer_link(self):
- """modify peer link info"""
-
- eth_trunk_id = "Eth-Trunk"
- eth_trunk_id += self.eth_trunk_id
- if self.eth_trunk_id and eth_trunk_id != self.peer_link_info.get("portName"):
- conf_str = CE_NC_MERGE_PEER_LINK_INFO % (
- self.peer_link_id, eth_trunk_id)
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: Merge peer link failed.')
- self.updates_cmd.append("peer-link %s" % self.peer_link_id)
- self.changed = True
-
- def delete_peer_link(self):
- """delete peer link info"""
-
- eth_trunk_id = "Eth-Trunk"
- eth_trunk_id += self.eth_trunk_id
- if self.eth_trunk_id and eth_trunk_id == self.peer_link_info.get("portName"):
- conf_str = CE_NC_DELETE_PEER_LINK_INFO % (
- self.peer_link_id, eth_trunk_id)
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: Delete peer link failed.')
- self.updates_cmd.append("undo peer-link %s" % self.peer_link_id)
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- # dfs_group_id check
- if self.dfs_group_id:
- if self.dfs_group_id != "1":
- self.module.fail_json(
- msg='Error: The value of dfs_group_id must be 1.')
-
- # nickname check
- if self.nickname:
- if not self.nickname.isdigit():
- self.module.fail_json(
- msg='Error: The value of nickname is an integer.')
- if int(self.nickname) < 1 or int(self.nickname) > 65471:
- self.module.fail_json(
- msg='Error: The nickname is not in the range from 1 to 65471.')
-
- # pseudo_nickname check
- if self.pseudo_nickname:
- if not self.pseudo_nickname.isdigit():
- self.module.fail_json(
- msg='Error: The value of pseudo_nickname is an integer.')
- if int(self.pseudo_nickname) < 1 or int(self.pseudo_nickname) > 65471:
- self.module.fail_json(
- msg='Error: The pseudo_nickname is not in the range from 1 to 65471.')
-
- # pseudo_priority check
- if self.pseudo_priority:
- if not self.pseudo_priority.isdigit():
- self.module.fail_json(
- msg='Error: The value of pseudo_priority is an integer.')
- if int(self.pseudo_priority) < 128 or int(self.pseudo_priority) > 255:
- self.module.fail_json(
- msg='Error: The pseudo_priority is not in the range from 128 to 255.')
-
- # ip_address check
- if self.ip_address:
- if not is_valid_address(self.ip_address):
- self.module.fail_json(
- msg='Error: The %s is not a valid ip address.' % self.ip_address)
-
- # vpn_instance_name check
- if self.vpn_instance_name:
- if len(self.vpn_instance_name) > 31 \
- or len(self.vpn_instance_name.replace(' ', '')) < 1:
- self.module.fail_json(
- msg='Error: The length of vpn_instance_name is not in the range from 1 to 31.')
-
- # priority_id check
- if self.priority_id:
- if not self.priority_id.isdigit():
- self.module.fail_json(
- msg='Error: The value of priority_id is an integer.')
- if int(self.priority_id) < 1 or int(self.priority_id) > 254:
- self.module.fail_json(
- msg='Error: The priority_id is not in the range from 1 to 254.')
-
- # peer_link_id check
- if self.peer_link_id:
- if self.peer_link_id != "1":
- self.module.fail_json(
- msg='Error: The value of peer_link_id must be 1.')
-
- # eth_trunk_id check
- if self.eth_trunk_id:
- if not self.eth_trunk_id.isdigit():
- self.module.fail_json(
- msg='Error: The value of eth_trunk_id is an integer.')
- if int(self.eth_trunk_id) < 0 or int(self.eth_trunk_id) > 511:
- self.module.fail_json(
- msg='Error: The value of eth_trunk_id is not in the range from 0 to 511.')
-
- def get_proposed(self):
- """get proposed info"""
-
- if self.dfs_group_id:
- self.proposed["dfs_group_id"] = self.dfs_group_id
- if self.nickname:
- self.proposed["nickname"] = self.nickname
- if self.pseudo_nickname:
- self.proposed["pseudo_nickname"] = self.pseudo_nickname
- if self.pseudo_priority:
- self.proposed["pseudo_priority"] = self.pseudo_priority
- if self.ip_address:
- self.proposed["ip_address"] = self.ip_address
- if self.vpn_instance_name:
- self.proposed["vpn_instance_name"] = self.vpn_instance_name
- if self.priority_id:
- self.proposed["priority_id"] = self.priority_id
- if self.eth_trunk_id:
- self.proposed["eth_trunk_id"] = self.eth_trunk_id
- if self.peer_link_id:
- self.proposed["peer_link_id"] = self.peer_link_id
- if self.state:
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
- if self.dfs_group_id:
- self.dfs_group_info = self.get_dfs_group_info()
- if self.peer_link_id and self.eth_trunk_id:
- self.peer_link_info = self.get_peer_link_info()
- if self.dfs_group_info:
- if self.dfs_group_id:
- self.existing["dfs_group_id"] = self.dfs_group_info["groupId"]
- if self.nickname:
- self.existing["nickname"] = self.dfs_group_info[
- "localNickname"]
- if self.pseudo_nickname:
- self.existing["pseudo_nickname"] = self.dfs_group_info[
- "pseudoNickname"]
- if self.pseudo_priority:
- self.existing["pseudo_priority"] = self.dfs_group_info[
- "pseudoPriority"]
- if self.ip_address:
- self.existing["ip_address"] = self.dfs_group_info["ipAddress"]
- if self.vpn_instance_name:
- self.existing["vpn_instance_name"] = self.dfs_group_info[
- "srcVpnName"]
- if self.priority_id:
- self.existing["priority_id"] = self.dfs_group_info["priority"]
- if self.peer_link_info:
- if self.eth_trunk_id:
- self.existing["eth_trunk_id"] = self.peer_link_info["portName"]
- if self.peer_link_id:
- self.existing["peer_link_id"] = self.peer_link_info["linkId"]
-
- def get_end_state(self):
- """get end state info"""
- if self.dfs_group_id:
- self.dfs_group_info = self.get_dfs_group_info()
- if self.peer_link_id and self.eth_trunk_id:
- self.peer_link_info = self.get_peer_link_info()
-
- if self.dfs_group_info:
- if self.dfs_group_id:
- self.end_state["dfs_group_id"] = self.dfs_group_info["groupId"]
- if self.nickname:
- self.end_state["nickname"] = self.dfs_group_info[
- "localNickname"]
- if self.pseudo_nickname:
- self.end_state["pseudo_nickname"] = self.dfs_group_info[
- "pseudoNickname"]
- if self.pseudo_priority:
- self.end_state["pseudo_priority"] = self.dfs_group_info[
- "pseudoPriority"]
- if self.ip_address:
- self.end_state["ip_address"] = self.dfs_group_info["ipAddress"]
- if self.vpn_instance_name:
- self.end_state["vpn_instance_name"] = self.dfs_group_info[
- "srcVpnName"]
- if self.priority_id:
- self.end_state["priority_id"] = self.dfs_group_info["priority"]
- if self.peer_link_info:
- if self.eth_trunk_id:
- self.end_state[
- "eth_trunk_id"] = self.peer_link_info["portName"]
- if self.peer_link_id:
- self.end_state["peer_link_id"] = self.peer_link_info["linkId"]
- if self.end_state == self.existing:
- self.changed = False
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.get_existing()
- self.get_proposed()
- if self.dfs_group_id:
- if self.state == "present":
- if self.dfs_group_info:
- if self.nickname or self.pseudo_nickname or self.pseudo_priority or self.priority_id \
- or self.ip_address or self.vpn_instance_name:
- if self.nickname:
- if self.dfs_group_info["ipAddress"] not in ["0.0.0.0", None]:
- self.module.fail_json(msg='Error: nickname and ip_address can not be exist at the '
- 'same time.')
- if self.ip_address:
- if self.dfs_group_info["localNickname"] not in ["0", None]:
- self.module.fail_json(msg='Error: nickname and ip_address can not be exist at the '
- 'same time.')
- self.modify_dfs_group()
- else:
- self.create_dfs_group()
- else:
- if not self.dfs_group_info:
- self.module.fail_json(
- msg='Error: DFS Group does not exist.')
- if not self.nickname and not self.pseudo_nickname and not self.pseudo_priority and not self.priority_id\
- and not self.ip_address and not self.vpn_instance_name:
- self.delete_dfs_group()
- else:
- self.updates_cmd.append("dfs-group 1")
- self.delete_dfs_group_attribute()
- self.delete_dfs_group_nick()
- if "undo dfs-group 1" in self.updates_cmd:
- self.updates_cmd = ["undo dfs-group 1"]
-
- if self.eth_trunk_id and not self.peer_link_id:
- self.module.fail_json(
- msg='Error: eth_trunk_id and peer_link_id must be config at the same time.')
- if self.peer_link_id and not self.eth_trunk_id:
- self.module.fail_json(
- msg='Error: eth_trunk_id and peer_link_id must be config at the same time.')
-
- if self.eth_trunk_id and self.peer_link_id:
- if self.state == "present":
- self.modify_peer_link()
- else:
- if self.peer_link_info:
- self.delete_peer_link()
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- dfs_group_id=dict(type='str'),
- nickname=dict(type='str'),
- pseudo_nickname=dict(type='str'),
- pseudo_priority=dict(type='str'),
- ip_address=dict(type='str'),
- vpn_instance_name=dict(type='str'),
- priority_id=dict(type='str'),
- eth_trunk_id=dict(type='str'),
- peer_link_id=dict(type='str'),
- state=dict(type='str', default='present',
- choices=['present', 'absent'])
- )
- argument_spec.update(ce_argument_spec)
- module = MlagConfig(argument_spec=argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_mlag_interface.py b/plugins/modules/network/cloudengine/ce_mlag_interface.py
deleted file mode 100644
index b5ec70554e..0000000000
--- a/plugins/modules/network/cloudengine/ce_mlag_interface.py
+++ /dev/null
@@ -1,1042 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_mlag_interface
-short_description: Manages MLAG interfaces on HUAWEI CloudEngine switches.
-description:
- - Manages MLAG interface attributes on HUAWEI CloudEngine switches.
-author:
- - Li Yanfeng (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- eth_trunk_id:
- description:
- - Name of the local M-LAG interface. The value is ranging from 0 to 511.
- dfs_group_id:
- description:
- - ID of a DFS group.The value is 1.
- default: present
- mlag_id:
- description:
- - ID of the M-LAG. The value is an integer that ranges from 1 to 2048.
- mlag_system_id:
- description:
- - M-LAG global LACP system MAC address. The value is a string of 0 to 255 characters. The default value
- is the MAC address of the Ethernet port of MPU.
- mlag_priority_id:
- description:
- - M-LAG global LACP system priority. The value is an integer ranging from 0 to 65535.
- The default value is 32768.
- interface:
- description:
- - Name of the interface that enters the Error-Down state when the peer-link fails.
- The value is a string of 1 to 63 characters.
- mlag_error_down:
- description:
- - Configure the interface on the slave device to enter the Error-Down state.
- choices: ['enable','disable']
- state:
- description:
- - Specify desired state of the resource.
- default: present
- choices: ['present','absent']
-
-'''
-
-EXAMPLES = '''
-- name: mlag interface module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Set interface mlag error down
- ce_mlag_interface:
- interface: 10GE2/0/1
- mlag_error_down: enable
- provider: "{{ cli }}"
- - name: Create mlag
- ce_mlag_interface:
- eth_trunk_id: 1
- dfs_group_id: 1
- mlag_id: 4
- provider: "{{ cli }}"
- - name: Set mlag global attribute
- ce_mlag_interface:
- mlag_system_id: 0020-1409-0407
- mlag_priority_id: 5
- provider: "{{ cli }}"
- - name: Set mlag interface attribute
- ce_mlag_interface:
- eth_trunk_id: 1
- mlag_system_id: 0020-1409-0400
- mlag_priority_id: 3
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: { "interface": "eth-trunk1",
- "mlag_error_down": "disable",
- "state": "present"
- }
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: { "mlagErrorDownInfos": [
- {
- "dfsgroupId": "1",
- "portName": "Eth-Trunk1"
- }
- ]
- }
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: { "interface eth-trunk1",
- "undo m-lag unpaired-port suspend"}
-'''
-
-import re
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import load_config
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-CE_NC_GET_MLAG_INFO = """
-
-
-
-
- %s
-
-
-
-
-"""
-
-CE_NC_CREATE_MLAG_INFO = """
-
-
-
-
- %s
- %s
- %s
-
-
-
-
-"""
-
-CE_NC_DELETE_MLAG_INFO = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-CE_NC_GET_LACP_MLAG_INFO = """
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_SET_LACP_MLAG_INFO_HEAD = """
-
-
-
-
- %s
-
-"""
-
-CE_NC_SET_LACP_MLAG_INFO_TAIL = """
-
-
-
-
-
-"""
-
-CE_NC_GET_GLOBAL_LACP_MLAG_INFO = """
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_SET_GLOBAL_LACP_MLAG_INFO_HEAD = """
-
-
-
-
-"""
-
-CE_NC_SET_GLOBAL_LACP_MLAG_INFO_TAIL = """
-
-
-
-
-"""
-
-CE_NC_GET_MLAG_ERROR_DOWN_INFO = """
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_CREATE_MLAG_ERROR_DOWN_INFO = """
-
-
-
-
- 1
- %s
-
-
-
-
-"""
-
-CE_NC_DELETE_MLAG_ERROR_DOWN_INFO = """
-
-
-
-
- 1
- %s
-
-
-
-
-
-"""
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- iftype = None
-
- if interface.upper().startswith('GE'):
- iftype = 'ge'
- elif interface.upper().startswith('10GE'):
- iftype = '10ge'
- elif interface.upper().startswith('25GE'):
- iftype = '25ge'
- elif interface.upper().startswith('40GE'):
- iftype = '40ge'
- elif interface.upper().startswith('100GE'):
- iftype = '100ge'
- elif interface.upper().startswith('ETH-TRUNK'):
- iftype = 'eth-trunk'
- elif interface.upper().startswith('NULL'):
- iftype = 'null'
- else:
- return None
-
- return iftype.lower()
-
-
-class MlagInterface(object):
- """
- Manages Manages MLAG interface information.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.eth_trunk_id = self.module.params['eth_trunk_id']
- self.dfs_group_id = self.module.params['dfs_group_id']
- self.mlag_id = self.module.params['mlag_id']
- self.mlag_system_id = self.module.params['mlag_system_id']
- self.mlag_priority_id = self.module.params['mlag_priority_id']
- self.interface = self.module.params['interface']
- self.mlag_error_down = self.module.params['mlag_error_down']
- self.state = self.module.params['state']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.existing = dict()
- self.proposed = dict()
- self.end_state = dict()
-
- # mlag info
- self.commands = list()
- self.mlag_info = None
- self.mlag_global_info = None
- self.mlag_error_down_info = None
- self.mlag_trunk_attribute_info = None
-
- def init_module(self):
- """ init module """
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def cli_add_command(self, command, undo=False):
- """add command to self.update_cmd and self.commands"""
-
- if undo and command.lower() not in ["quit", "return"]:
- cmd = "undo " + command
- else:
- cmd = command
-
- self.commands.append(cmd) # set to device
- if command.lower() not in ["quit", "return"]:
- self.updates_cmd.append(cmd) # show updates result
-
- def cli_load_config(self, commands):
- """load config by cli"""
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def get_mlag_info(self):
- """ get mlag info."""
-
- mlag_info = dict()
- conf_str = CE_NC_GET_MLAG_INFO % ("Eth-Trunk%s" % self.eth_trunk_id)
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return mlag_info
- else:
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- mlag_info["mlagInfos"] = list()
- root = ElementTree.fromstring(xml_str)
- dfs_mlag_infos = root.findall(
- "./mlag/mlagInstances/mlagInstance")
-
- if dfs_mlag_infos:
- for dfs_mlag_info in dfs_mlag_infos:
- mlag_dict = dict()
- for ele in dfs_mlag_info:
- if ele.tag in ["dfsgroupId", "mlagId", "localMlagPort"]:
- mlag_dict[ele.tag] = ele.text
- mlag_info["mlagInfos"].append(mlag_dict)
- return mlag_info
-
- def get_mlag_global_info(self):
- """ get mlag global info."""
-
- mlag_global_info = dict()
- conf_str = CE_NC_GET_GLOBAL_LACP_MLAG_INFO
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return mlag_global_info
- else:
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- global_info = root.findall(
- "./ifmtrunk/lacpSysInfo/lacpMlagGlobal")
-
- if global_info:
- for tmp in global_info:
- for site in tmp:
- if site.tag in ["lacpMlagSysId", "lacpMlagPriority"]:
- mlag_global_info[site.tag] = site.text
- return mlag_global_info
-
- def get_mlag_trunk_attribute_info(self):
- """ get mlag global info."""
-
- mlag_trunk_attribute_info = dict()
- eth_trunk = "Eth-Trunk"
- eth_trunk += self.eth_trunk_id
- conf_str = CE_NC_GET_LACP_MLAG_INFO % eth_trunk
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return mlag_trunk_attribute_info
- else:
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- global_info = root.findall(
- "./ifmtrunk/TrunkIfs/TrunkIf/lacpMlagIf")
-
- if global_info:
- for tmp in global_info:
- for site in tmp:
- if site.tag in ["lacpMlagSysId", "lacpMlagPriority"]:
- mlag_trunk_attribute_info[site.tag] = site.text
- return mlag_trunk_attribute_info
-
- def get_mlag_error_down_info(self):
- """ get error down info."""
-
- mlag_error_down_info = dict()
- conf_str = CE_NC_GET_MLAG_ERROR_DOWN_INFO
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return mlag_error_down_info
- else:
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- mlag_error_down_info["mlagErrorDownInfos"] = list()
- root = ElementTree.fromstring(xml_str)
- mlag_error_infos = root.findall(
- "./mlag/errordowns/errordown")
-
- if mlag_error_infos:
- for mlag_error_info in mlag_error_infos:
- mlag_error_dict = dict()
- for ele in mlag_error_info:
- if ele.tag in ["dfsgroupId", "portName"]:
- mlag_error_dict[ele.tag] = ele.text
- mlag_error_down_info[
- "mlagErrorDownInfos"].append(mlag_error_dict)
- return mlag_error_down_info
-
- def check_macaddr(self):
- """check mac-address whether valid"""
-
- valid_char = '0123456789abcdef-'
- mac = self.mlag_system_id
-
- if len(mac) > 16:
- return False
-
- mac_list = re.findall(r'([0-9a-fA-F]+)', mac)
- if len(mac_list) != 3:
- return False
-
- if mac.count('-') != 2:
- return False
-
- for _, value in enumerate(mac, start=0):
- if value.lower() not in valid_char:
- return False
- if all((int(mac_list[0], base=16) == 0, int(mac_list[1], base=16) == 0, int(mac_list[2], base=16) == 0)):
- return False
- a = "000" + mac_list[0]
- b = "000" + mac_list[1]
- c = "000" + mac_list[2]
- self.mlag_system_id = "-".join([a[-4:], b[-4:], c[-4:]])
- return True
-
- def check_params(self):
- """Check all input params"""
-
- # eth_trunk_id check
- if self.eth_trunk_id:
- if not self.eth_trunk_id.isdigit():
- self.module.fail_json(
- msg='Error: The value of eth_trunk_id is an integer.')
- if int(self.eth_trunk_id) < 0 or int(self.eth_trunk_id) > 511:
- self.module.fail_json(
- msg='Error: The value of eth_trunk_id is not in the range from 0 to 511.')
-
- # dfs_group_id check
- if self.dfs_group_id:
- if self.dfs_group_id != "1":
- self.module.fail_json(
- msg='Error: The value of dfs_group_id must be 1.')
-
- # mlag_id check
- if self.mlag_id:
- if not self.mlag_id.isdigit():
- self.module.fail_json(
- msg='Error: The value of mlag_id is an integer.')
- if int(self.mlag_id) < 1 or int(self.mlag_id) > 2048:
- self.module.fail_json(
- msg='Error: The value of mlag_id is not in the range from 1 to 2048.')
-
- # mlag_system_id check
- if self.mlag_system_id:
- if not self.check_macaddr():
- self.module.fail_json(
- msg="Error: mlag_system_id has invalid value %s." % self.mlag_system_id)
-
- # mlag_priority_id check
- if self.mlag_priority_id:
- if not self.mlag_priority_id.isdigit():
- self.module.fail_json(
- msg='Error: The value of mlag_priority_id is an integer.')
- if int(self.mlag_priority_id) < 0 or int(self.mlag_priority_id) > 254:
- self.module.fail_json(
- msg='Error: The value of mlag_priority_id is not in the range from 0 to 254.')
-
- # interface check
- if self.interface:
- intf_type = get_interface_type(self.interface)
- if not intf_type:
- self.module.fail_json(
- msg='Error: Interface name of %s '
- 'is error.' % self.interface)
-
- def is_mlag_info_change(self):
- """whether mlag info change"""
-
- if not self.mlag_info:
- return True
-
- eth_trunk = "Eth-Trunk"
- eth_trunk += self.eth_trunk_id
- for info in self.mlag_info["mlagInfos"]:
- if info["mlagId"] == self.mlag_id and info["localMlagPort"] == eth_trunk:
- return False
- return True
-
- def is_mlag_info_exist(self):
- """whether mlag info exist"""
-
- if not self.mlag_info:
- return False
-
- eth_trunk = "Eth-Trunk"
- eth_trunk += self.eth_trunk_id
-
- for info in self.mlag_info["mlagInfos"]:
- if info["localMlagPort"] == eth_trunk:
- return True
- return False
-
- def is_mlag_error_down_info_change(self):
- """whether mlag error down info change"""
-
- if not self.mlag_error_down_info:
- return True
-
- for info in self.mlag_error_down_info["mlagErrorDownInfos"]:
- if info["portName"].upper() == self.interface.upper():
- return False
- return True
-
- def is_mlag_error_down_info_exist(self):
- """whether mlag error down info exist"""
-
- if not self.mlag_error_down_info:
- return False
-
- for info in self.mlag_error_down_info["mlagErrorDownInfos"]:
- if info["portName"].upper() == self.interface.upper():
- return True
- return False
-
- def is_mlag_interface_info_change(self):
- """whether mlag interface attribute info change"""
-
- if not self.mlag_trunk_attribute_info:
- return True
-
- if self.mlag_system_id:
- if self.mlag_trunk_attribute_info["lacpMlagSysId"] != self.mlag_system_id:
- return True
- if self.mlag_priority_id:
- if self.mlag_trunk_attribute_info["lacpMlagPriority"] != self.mlag_priority_id:
- return True
- return False
-
- def is_mlag_interface_info_exist(self):
- """whether mlag interface attribute info exist"""
-
- if not self.mlag_trunk_attribute_info:
- return False
-
- if self.mlag_system_id:
- if self.mlag_priority_id:
- if self.mlag_trunk_attribute_info["lacpMlagSysId"] == self.mlag_system_id \
- and self.mlag_trunk_attribute_info["lacpMlagPriority"] == self.mlag_priority_id:
- return True
- else:
- if self.mlag_trunk_attribute_info["lacpMlagSysId"] == self.mlag_system_id:
- return True
-
- if self.mlag_priority_id:
- if self.mlag_system_id:
- if self.mlag_trunk_attribute_info["lacpMlagSysId"] == self.mlag_system_id \
- and self.mlag_trunk_attribute_info["lacpMlagPriority"] == self.mlag_priority_id:
- return True
- else:
- if self.mlag_trunk_attribute_info["lacpMlagPriority"] == self.mlag_priority_id:
- return True
-
- return False
-
- def is_mlag_global_info_change(self):
- """whether mlag global attribute info change"""
-
- if not self.mlag_global_info:
- return True
-
- if self.mlag_system_id:
- if self.mlag_global_info["lacpMlagSysId"] != self.mlag_system_id:
- return True
- if self.mlag_priority_id:
- if self.mlag_global_info["lacpMlagPriority"] != self.mlag_priority_id:
- return True
- return False
-
- def is_mlag_global_info_exist(self):
- """whether mlag global attribute info exist"""
-
- if not self.mlag_global_info:
- return False
-
- if self.mlag_system_id:
- if self.mlag_priority_id:
- if self.mlag_global_info["lacpMlagSysId"] == self.mlag_system_id \
- and self.mlag_global_info["lacpMlagPriority"] == self.mlag_priority_id:
- return True
- else:
- if self.mlag_global_info["lacpMlagSysId"] == self.mlag_system_id:
- return True
-
- if self.mlag_priority_id:
- if self.mlag_system_id:
- if self.mlag_global_info["lacpMlagSysId"] == self.mlag_system_id \
- and self.mlag_global_info["lacpMlagPriority"] == self.mlag_priority_id:
- return True
- else:
- if self.mlag_global_info["lacpMlagPriority"] == self.mlag_priority_id:
- return True
-
- return False
-
- def create_mlag(self):
- """create mlag info"""
-
- if self.is_mlag_info_change():
- mlag_port = "Eth-Trunk"
- mlag_port += self.eth_trunk_id
- conf_str = CE_NC_CREATE_MLAG_INFO % (
- self.dfs_group_id, self.mlag_id, mlag_port)
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: create mlag info failed.')
-
- self.updates_cmd.append("interface %s" % mlag_port)
- self.updates_cmd.append("dfs-group %s m-lag %s" %
- (self.dfs_group_id, self.mlag_id))
- self.changed = True
-
- def delete_mlag(self):
- """delete mlag info"""
-
- if self.is_mlag_info_exist():
- mlag_port = "Eth-Trunk"
- mlag_port += self.eth_trunk_id
- conf_str = CE_NC_DELETE_MLAG_INFO % (
- self.dfs_group_id, mlag_port)
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: delete mlag info failed.')
-
- self.updates_cmd.append("interface %s" % mlag_port)
- self.updates_cmd.append(
- "undo dfs-group %s m-lag %s" % (self.dfs_group_id, self.mlag_id))
- self.changed = True
-
- def create_mlag_error_down(self):
- """create mlag error down info"""
-
- if self.is_mlag_error_down_info_change():
- conf_str = CE_NC_CREATE_MLAG_ERROR_DOWN_INFO % self.interface
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: create mlag error down info failed.')
-
- self.updates_cmd.append("interface %s" % self.interface)
- self.updates_cmd.append("m-lag unpaired-port suspend")
- self.changed = True
-
- def delete_mlag_error_down(self):
- """delete mlag error down info"""
-
- if self.is_mlag_error_down_info_exist():
-
- conf_str = CE_NC_DELETE_MLAG_ERROR_DOWN_INFO % self.interface
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: delete mlag error down info failed.')
-
- self.updates_cmd.append("interface %s" % self.interface)
- self.updates_cmd.append("undo m-lag unpaired-port suspend")
- self.changed = True
-
- def set_mlag_interface(self):
- """set mlag interface attribute info"""
-
- if self.is_mlag_interface_info_change():
- mlag_port = "Eth-Trunk"
- mlag_port += self.eth_trunk_id
- conf_str = CE_NC_SET_LACP_MLAG_INFO_HEAD % mlag_port
- if self.mlag_priority_id:
- conf_str += "%s" % self.mlag_priority_id
- if self.mlag_system_id:
- conf_str += "%s" % self.mlag_system_id
- conf_str += CE_NC_SET_LACP_MLAG_INFO_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: set mlag interface attribute info failed.')
-
- self.updates_cmd.append("interface %s" % mlag_port)
- if self.mlag_priority_id:
- self.updates_cmd.append(
- "lacp m-lag priority %s" % self.mlag_priority_id)
-
- if self.mlag_system_id:
- self.updates_cmd.append(
- "lacp m-lag system-id %s" % self.mlag_system_id)
- self.changed = True
-
- def delete_mlag_interface(self):
- """delete mlag interface attribute info"""
-
- if self.is_mlag_interface_info_exist():
- mlag_port = "Eth-Trunk"
- mlag_port += self.eth_trunk_id
- conf_str = CE_NC_SET_LACP_MLAG_INFO_HEAD % mlag_port
- cmd = "interface %s" % mlag_port
- self.cli_add_command(cmd)
-
- if self.mlag_priority_id:
- cmd = "lacp m-lag priority %s" % self.mlag_priority_id
- conf_str += ""
- self.cli_add_command(cmd, True)
-
- if self.mlag_system_id:
- cmd = "lacp m-lag system-id %s" % self.mlag_system_id
- conf_str += ""
- self.cli_add_command(cmd, True)
-
- if self.commands:
- conf_str += CE_NC_SET_LACP_MLAG_INFO_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: set mlag interface atrribute info failed.')
-
- self.changed = True
-
- def set_mlag_global(self):
- """set mlag global attribute info"""
-
- if self.is_mlag_global_info_change():
- conf_str = CE_NC_SET_GLOBAL_LACP_MLAG_INFO_HEAD
- if self.mlag_priority_id:
- conf_str += "%s" % self.mlag_priority_id
- if self.mlag_system_id:
- conf_str += "%s" % self.mlag_system_id
- conf_str += CE_NC_SET_GLOBAL_LACP_MLAG_INFO_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: set mlag interface attribute info failed.')
-
- if self.mlag_priority_id:
- self.updates_cmd.append(
- "lacp m-lag priority %s" % self.mlag_priority_id)
-
- if self.mlag_system_id:
- self.updates_cmd.append(
- "lacp m-lag system-id %s" % self.mlag_system_id)
- self.changed = True
-
- def delete_mlag_global(self):
- """delete mlag global attribute info"""
-
- xml_str = ''
- if self.is_mlag_global_info_exist():
- if self.mlag_priority_id:
- cmd = "lacp m-lag priority %s" % self.mlag_priority_id
- xml_str += ''
- self.cli_add_command(cmd, True)
-
- if self.mlag_system_id:
- cmd = "lacp m-lag system-id %s" % self.mlag_system_id
- xml_str += ''
- self.cli_add_command(cmd, True)
-
- if xml_str != '':
- conf_str = CE_NC_SET_GLOBAL_LACP_MLAG_INFO_HEAD + xml_str + CE_NC_SET_GLOBAL_LACP_MLAG_INFO_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: set mlag interface atrribute info failed.')
- self.changed = True
-
- def get_proposed(self):
- """get proposed info"""
-
- if self.eth_trunk_id:
- self.proposed["eth_trunk_id"] = self.eth_trunk_id
- if self.dfs_group_id:
- self.proposed["dfs_group_id"] = self.dfs_group_id
- if self.mlag_id:
- self.proposed["mlag_id"] = self.mlag_id
- if self.mlag_system_id:
- self.proposed["mlag_system_id"] = self.mlag_system_id
- if self.mlag_priority_id:
- self.proposed["mlag_priority_id"] = self.mlag_priority_id
- if self.interface:
- self.proposed["interface"] = self.interface
- if self.mlag_error_down:
- self.proposed["mlag_error_down"] = self.mlag_error_down
- if self.state:
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- self.mlag_info = self.get_mlag_info()
- self.mlag_global_info = self.get_mlag_global_info()
- self.mlag_error_down_info = self.get_mlag_error_down_info()
-
- if self.eth_trunk_id or self.dfs_group_id or self.mlag_id:
- if not self.mlag_system_id and not self.mlag_priority_id:
- if self.mlag_info:
- self.existing["mlagInfos"] = self.mlag_info["mlagInfos"]
-
- if self.mlag_system_id or self.mlag_priority_id:
- if self.eth_trunk_id:
- if self.mlag_trunk_attribute_info:
- if self.mlag_system_id:
- self.existing["lacpMlagSysId"] = self.mlag_trunk_attribute_info[
- "lacpMlagSysId"]
- if self.mlag_priority_id:
- self.existing["lacpMlagPriority"] = self.mlag_trunk_attribute_info[
- "lacpMlagPriority"]
- else:
- if self.mlag_global_info:
- if self.mlag_system_id:
- self.existing["lacpMlagSysId"] = self.mlag_global_info[
- "lacpMlagSysId"]
- if self.mlag_priority_id:
- self.existing["lacpMlagPriority"] = self.mlag_global_info[
- "lacpMlagPriority"]
-
- if self.interface or self.mlag_error_down:
- if self.mlag_error_down_info:
- self.existing["mlagErrorDownInfos"] = self.mlag_error_down_info[
- "mlagErrorDownInfos"]
-
- def get_end_state(self):
- """get end state info"""
-
- if self.eth_trunk_id or self.dfs_group_id or self.mlag_id:
- self.mlag_info = self.get_mlag_info()
- if not self.mlag_system_id and not self.mlag_priority_id:
- if self.mlag_info:
- self.end_state["mlagInfos"] = self.mlag_info["mlagInfos"]
-
- if self.mlag_system_id or self.mlag_priority_id:
- if self.eth_trunk_id:
- self.mlag_trunk_attribute_info = self.get_mlag_trunk_attribute_info()
- if self.mlag_trunk_attribute_info:
- if self.mlag_system_id:
- self.end_state["lacpMlagSysId"] = self.mlag_trunk_attribute_info[
- "lacpMlagSysId"]
- if self.mlag_priority_id:
- self.end_state["lacpMlagPriority"] = self.mlag_trunk_attribute_info[
- "lacpMlagPriority"]
- else:
- self.mlag_global_info = self.get_mlag_global_info()
- if self.mlag_global_info:
- if self.mlag_system_id:
- self.end_state["lacpMlagSysId"] = self.mlag_global_info[
- "lacpMlagSysId"]
- if self.mlag_priority_id:
- self.end_state["lacpMlagPriority"] = self.mlag_global_info[
- "lacpMlagPriority"]
-
- if self.interface or self.mlag_error_down:
- self.mlag_error_down_info = self.get_mlag_error_down_info()
- if self.mlag_error_down_info:
- self.end_state["mlagErrorDownInfos"] = self.mlag_error_down_info[
- "mlagErrorDownInfos"]
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.get_proposed()
- self.get_existing()
-
- if self.eth_trunk_id or self.dfs_group_id or self.mlag_id:
- self.mlag_info = self.get_mlag_info()
- if self.eth_trunk_id and self.dfs_group_id and self.mlag_id:
- if self.state == "present":
- self.create_mlag()
- else:
- self.delete_mlag()
- else:
- if not self.mlag_system_id and not self.mlag_priority_id:
- self.module.fail_json(
- msg='Error: eth_trunk_id, dfs_group_id, mlag_id must be config at the same time.')
-
- if self.mlag_system_id or self.mlag_priority_id:
-
- if self.eth_trunk_id:
- self.mlag_trunk_attribute_info = self.get_mlag_trunk_attribute_info()
- if self.mlag_system_id or self.mlag_priority_id:
- if self.state == "present":
- self.set_mlag_interface()
- else:
- self.delete_mlag_interface()
- else:
- self.mlag_global_info = self.get_mlag_global_info()
- if self.mlag_system_id or self.mlag_priority_id:
- if self.state == "present":
- self.set_mlag_global()
- else:
- self.delete_mlag_global()
-
- if self.interface or self.mlag_error_down:
- self.mlag_error_down_info = self.get_mlag_error_down_info()
- if self.interface and self.mlag_error_down:
- if self.mlag_error_down == "enable":
- self.create_mlag_error_down()
- else:
- self.delete_mlag_error_down()
- else:
- self.module.fail_json(
- msg='Error: interface, mlag_error_down must be config at the same time.')
-
- self.get_end_state()
- if self.existing == self.end_state:
- self.changed = False
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- eth_trunk_id=dict(type='str'),
- dfs_group_id=dict(type='str'),
- mlag_id=dict(type='str'),
- mlag_system_id=dict(type='str'),
- mlag_priority_id=dict(type='str'),
- interface=dict(type='str'),
- mlag_error_down=dict(type='str', choices=['enable', 'disable']),
- state=dict(type='str', default='present',
- choices=['present', 'absent'])
- )
- argument_spec.update(ce_argument_spec)
- module = MlagInterface(argument_spec=argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_mtu.py b/plugins/modules/network/cloudengine/ce_mtu.py
deleted file mode 100644
index 54d31a664c..0000000000
--- a/plugins/modules/network/cloudengine/ce_mtu.py
+++ /dev/null
@@ -1,585 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_mtu
-short_description: Manages MTU settings on HUAWEI CloudEngine switches.
-description:
- - Manages MTU settings on HUAWEI CloudEngine switches.
-author: QijunPan (@QijunPan)
-notes:
- - Either C(sysmtu) param is required or C(interface) AND C(mtu) params are req'd.
- - C(state=absent) unconfigures a given MTU if that value is currently present.
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- interface:
- description:
- - Full name of interface, i.e. 40GE1/0/22.
- mtu:
- description:
- - MTU for a specific interface.
- The value is an integer ranging from 46 to 9600, in bytes.
- jumbo_max:
- description:
- - Maximum frame size. The default value is 9216.
- The value is an integer and expressed in bytes. The value range is 1536 to 12224 for the CE12800
- and 1536 to 12288 for ToR switches.
- jumbo_min:
- description:
- - Non-jumbo frame size threshold. The default value is 1518.
- The value is an integer that ranges from 1518 to jumbo_max, in bytes.
- state:
- description:
- - Specify desired state of the resource.
- default: present
- choices: ['present','absent']
-'''
-
-EXAMPLES = '''
-- name: Mtu test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Config jumboframe on 40GE1/0/22"
- ce_mtu:
- interface: 40GE1/0/22
- jumbo_max: 9000
- jumbo_min: 8000
- provider: "{{ cli }}"
-
- - name: "Config mtu on 40GE1/0/22 (routed interface)"
- ce_mtu:
- interface: 40GE1/0/22
- mtu: 1600
- provider: "{{ cli }}"
-
- - name: "Config mtu on 40GE1/0/23 (switched interface)"
- ce_mtu:
- interface: 40GE1/0/22
- mtu: 9216
- provider: "{{ cli }}"
-
- - name: "Config mtu and jumboframe on 40GE1/0/22 (routed interface)"
- ce_mtu:
- interface: 40GE1/0/22
- mtu: 1601
- jumbo_max: 9001
- jumbo_min: 8001
- provider: "{{ cli }}"
-
- - name: "Unconfigure mtu and jumboframe on a given interface"
- ce_mtu:
- state: absent
- interface: 40GE1/0/22
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"mtu": "1700", "jumbo_max": "9000", jumbo_min: "8000"}
-existing:
- description: k/v pairs of existing mtu/sysmtu on the interface/system
- returned: always
- type: dict
- sample: {"mtu": "1600", "jumbo_max": "9216", "jumbo_min": "1518"}
-end_state:
- description: k/v pairs of mtu/sysmtu values after module execution
- returned: always
- type: dict
- sample: {"mtu": "1700", "jumbo_max": "9000", jumbo_min: "8000"}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["interface 40GE1/0/23", "mtu 1700", "jumboframe enable 9000 8000"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import re
-import copy
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec, load_config
-from ansible.module_utils.connection import exec_command
-
-
-def is_interface_support_setjumboframe(interface):
- """is interface support set jumboframe"""
-
- if interface is None:
- return False
- support_flag = False
- if interface.upper().startswith('GE'):
- support_flag = True
- elif interface.upper().startswith('10GE'):
- support_flag = True
- elif interface.upper().startswith('25GE'):
- support_flag = True
- elif interface.upper().startswith('4X10GE'):
- support_flag = True
- elif interface.upper().startswith('40GE'):
- support_flag = True
- elif interface.upper().startswith('100GE'):
- support_flag = True
- else:
- support_flag = False
- return support_flag
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- iftype = None
-
- if interface.upper().startswith('GE'):
- iftype = 'ge'
- elif interface.upper().startswith('10GE'):
- iftype = '10ge'
- elif interface.upper().startswith('25GE'):
- iftype = '25ge'
- elif interface.upper().startswith('4X10GE'):
- iftype = '4x10ge'
- elif interface.upper().startswith('40GE'):
- iftype = '40ge'
- elif interface.upper().startswith('100GE'):
- iftype = '100ge'
- elif interface.upper().startswith('VLANIF'):
- iftype = 'vlanif'
- elif interface.upper().startswith('LOOPBACK'):
- iftype = 'loopback'
- elif interface.upper().startswith('METH'):
- iftype = 'meth'
- elif interface.upper().startswith('ETH-TRUNK'):
- iftype = 'eth-trunk'
- elif interface.upper().startswith('VBDIF'):
- iftype = 'vbdif'
- elif interface.upper().startswith('NVE'):
- iftype = 'nve'
- elif interface.upper().startswith('TUNNEL'):
- iftype = 'tunnel'
- elif interface.upper().startswith('ETHERNET'):
- iftype = 'ethernet'
- elif interface.upper().startswith('FCOE-PORT'):
- iftype = 'fcoe-port'
- elif interface.upper().startswith('FABRIC-PORT'):
- iftype = 'fabric-port'
- elif interface.upper().startswith('STACK-PORT'):
- iftype = 'stack-Port'
- elif interface.upper().startswith('NULL'):
- iftype = 'null'
- else:
- return None
-
- return iftype.lower()
-
-
-class Mtu(object):
- """set mtu"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # interface info
- self.interface = self.module.params['interface']
- self.mtu = self.module.params['mtu']
- self.state = self.module.params['state']
- self.jbf_max = self.module.params['jumbo_max'] or None
- self.jbf_min = self.module.params['jumbo_min'] or None
- self.jbf_config = list()
- self.jbf_cli = ""
- self.commands = list()
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
- self.intf_info = dict() # one interface info
- self.intf_type = None # loopback tunnel ...
-
- def init_module(self):
- """ init_module"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def get_config(self, flags=None):
- """Retrieves the current config from the device or cache
- """
- flags = [] if flags is None else flags
-
- cmd = 'display current-configuration '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- cfg = str(out).strip()
-
- return cfg
-
- def get_interface_dict(self, ifname):
- """ get one interface attributes dict."""
- intf_info = dict()
-
- flags = list()
- exp = r"| ignore-case section include ^#\s+interface %s\s+" % ifname.replace(" ", "")
- flags.append(exp)
- output = self.get_config(flags)
- output_list = output.split('\n')
- if output_list is None:
- return intf_info
-
- mtu = None
- for config in output_list:
- config = config.strip()
- if config.startswith('mtu'):
- mtu = re.findall(r'.*mtu\s*([0-9]*)', output)[0]
-
- intf_info = dict(ifName=ifname,
- ifMtu=mtu)
-
- return intf_info
-
- def prase_jumboframe_para(self, config_str):
- """prase_jumboframe_para"""
-
- interface_cli = "interface %s" % (self.interface.replace(" ", "").lower())
- if config_str.find(interface_cli) == -1:
- self.module.fail_json(msg='Error: Interface does not exist.')
-
- try:
- npos1 = config_str.index('jumboframe enable')
- except ValueError:
- # return default vale
- return [9216, 1518]
- try:
- npos2 = config_str.index('\n', npos1)
- config_str_tmp = config_str[npos1:npos2]
- except ValueError:
- config_str_tmp = config_str[npos1:]
-
- return re.findall(r'([0-9]+)', config_str_tmp)
-
- def cli_load_config(self):
- """load config by cli"""
-
- if not self.module.check_mode:
- if len(self.commands) > 1:
- load_config(self.module, self.commands)
- self.changed = True
-
- def cli_add_command(self, command, undo=False):
- """add command to self.update_cmd and self.commands"""
-
- if undo and command.lower() not in ["quit", "return"]:
- cmd = "undo " + command
- else:
- cmd = command
-
- self.commands.append(cmd) # set to device
-
- def get_jumboframe_config(self):
- """ get_jumboframe_config"""
-
- flags = list()
- exp = r"| ignore-case section include ^#\s+interface %s\s+" % self.interface.replace(" ", "")
- flags.append(exp)
- output = self.get_config(flags)
- output = output.replace('*', '').lower()
-
- return self.prase_jumboframe_para(output)
-
- def set_jumboframe(self):
- """ set_jumboframe"""
-
- if self.state == "present":
- if not self.jbf_max and not self.jbf_min:
- return
-
- jbf_value = self.get_jumboframe_config()
- self.jbf_config = copy.deepcopy(jbf_value)
- if len(jbf_value) == 1:
- jbf_value.append("1518")
- self.jbf_config.append("1518")
- if not self.jbf_max:
- return
-
- if (len(jbf_value) > 2) or (len(jbf_value) == 0):
- self.module.fail_json(
- msg='Error: Get jubmoframe config value num error.')
- if self.jbf_min is None:
- if jbf_value[0] == self.jbf_max:
- return
- else:
- if (jbf_value[0] == self.jbf_max) \
- and (jbf_value[1] == self.jbf_min):
- return
- if jbf_value[0] != self.jbf_max:
- jbf_value[0] = self.jbf_max
- if (jbf_value[1] != self.jbf_min) and (self.jbf_min is not None):
- jbf_value[1] = self.jbf_min
- else:
- jbf_value.pop(1)
- else:
- jbf_value = self.get_jumboframe_config()
- self.jbf_config = copy.deepcopy(jbf_value)
- if (jbf_value == [9216, 1518]):
- return
- jbf_value = [9216, 1518]
-
- if len(jbf_value) == 2:
- self.jbf_cli = "jumboframe enable %s %s" % (
- jbf_value[0], jbf_value[1])
- else:
- self.jbf_cli = "jumboframe enable %s" % (jbf_value[0])
- self.cli_add_command(self.jbf_cli)
-
- if self.state == "present":
- if self.jbf_min:
- self.updates_cmd.append(
- "jumboframe enable %s %s" % (self.jbf_max, self.jbf_min))
- else:
- self.updates_cmd.append("jumboframe enable %s" % (self.jbf_max))
- else:
- self.updates_cmd.append("undo jumboframe enable")
-
- return
-
- def merge_interface(self, ifname, mtu):
- """ Merge interface mtu."""
-
- xmlstr = ''
- change = False
-
- command = "interface %s" % ifname
- self.cli_add_command(command)
-
- if self.state == "present":
- if mtu and self.intf_info["ifMtu"] != mtu:
- command = "mtu %s" % mtu
- self.cli_add_command(command)
- self.updates_cmd.append("mtu %s" % mtu)
- change = True
- else:
- if self.intf_info["ifMtu"] != '1500' and self.intf_info["ifMtu"]:
- command = "mtu 1500"
- self.cli_add_command(command)
- self.updates_cmd.append("undo mtu")
- change = True
-
- return
-
- def check_params(self):
- """Check all input params"""
-
- # interface type check
- if self.interface:
- self.intf_type = get_interface_type(self.interface)
- if not self.intf_type:
- self.module.fail_json(
- msg='Error: Interface name of %s '
- 'is error.' % self.interface)
-
- if not self.intf_type:
- self.module.fail_json(
- msg='Error: Interface %s is error.')
-
- # mtu check mtu
- if self.mtu:
- if not self.mtu.isdigit():
- self.module.fail_json(msg='Error: Mtu is invalid.')
- # check mtu range
- if int(self.mtu) < 46 or int(self.mtu) > 9600:
- self.module.fail_json(
- msg='Error: Mtu is not in the range from 46 to 9600.')
- # get interface info
- self.intf_info = self.get_interface_dict(self.interface)
- if not self.intf_info:
- self.module.fail_json(msg='Error: interface does not exist.')
-
- # check interface can set jumbo frame
- if self.state == 'present':
- if self.jbf_max:
- if not is_interface_support_setjumboframe(self.interface):
- self.module.fail_json(
- msg='Error: Interface %s does not support jumboframe set.' % self.interface)
- if not self.jbf_max.isdigit():
- self.module.fail_json(
- msg='Error: Max jumboframe is not digit.')
- if (int(self.jbf_max) > 12288) or (int(self.jbf_max) < 1536):
- self.module.fail_json(
- msg='Error: Max jumboframe is between 1536 to 12288.')
-
- if self.jbf_min:
- if not self.jbf_min.isdigit():
- self.module.fail_json(
- msg='Error: Min jumboframe is not digit.')
- if not self.jbf_max:
- self.module.fail_json(
- msg='Error: please specify max jumboframe value.')
- if (int(self.jbf_min) > int(self.jbf_max)) or (int(self.jbf_min) < 1518):
- self.module.fail_json(
- msg='Error: Min jumboframe is between '
- '1518 to jumboframe max value.')
-
- if self.jbf_min is not None:
- if self.jbf_max is None:
- self.module.fail_json(
- msg='Error: please input MAX jumboframe '
- 'value.')
-
- def get_proposed(self):
- """ get_proposed"""
-
- self.proposed['state'] = self.state
- if self.interface:
- self.proposed["interface"] = self.interface
-
- if self.state == 'present':
- if self.mtu:
- self.proposed["mtu"] = self.mtu
- if self.jbf_max:
- if self.jbf_min:
- self.proposed["jumboframe"] = "jumboframe enable %s %s" % (
- self.jbf_max, self.jbf_min)
- else:
- self.proposed[
- "jumboframe"] = "jumboframe enable %s %s" % (self.jbf_max, 1518)
-
- def get_existing(self):
- """ get_existing"""
-
- if self.intf_info:
- self.existing["interface"] = self.intf_info["ifName"]
- self.existing["mtu"] = self.intf_info["ifMtu"]
-
- if self.intf_info:
- if not self.existing["interface"]:
- self.existing["interface"] = self.interface
-
- if len(self.jbf_config) != 2:
- return
-
- self.existing["jumboframe"] = "jumboframe enable %s %s" % (
- self.jbf_config[0], self.jbf_config[1])
-
- def get_end_state(self):
- """ get_end_state"""
-
- if self.intf_info:
- end_info = self.get_interface_dict(self.interface)
- if end_info:
- self.end_state["interface"] = end_info["ifName"]
- self.end_state["mtu"] = end_info["ifMtu"]
- if self.intf_info:
- if not self.end_state["interface"]:
- self.end_state["interface"] = self.interface
-
- if self.state == 'absent':
- self.end_state["jumboframe"] = "jumboframe enable %s %s" % (
- 9216, 1518)
- elif not self.jbf_max and not self.jbf_min:
- if len(self.jbf_config) != 2:
- return
- self.end_state["jumboframe"] = "jumboframe enable %s %s" % (
- self.jbf_config[0], self.jbf_config[1])
- elif self.jbf_min:
- self.end_state["jumboframe"] = "jumboframe enable %s %s" % (
- self.jbf_max, self.jbf_min)
- else:
- self.end_state[
- "jumboframe"] = "jumboframe enable %s %s" % (self.jbf_max, 1518)
- if self.end_state == self.existing:
- self.changed = False
-
- def work(self):
- """worker"""
- self.check_params()
-
- self.get_proposed()
-
- self.merge_interface(self.interface, self.mtu)
- self.set_jumboframe()
- self.cli_load_config()
-
- self.get_existing()
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ main"""
-
- argument_spec = dict(
- interface=dict(required=True, type='str'),
- mtu=dict(type='str'),
- state=dict(choices=['absent', 'present'],
- default='present', required=False),
- jumbo_max=dict(type='str'),
- jumbo_min=dict(type='str'),
- )
- argument_spec.update(ce_argument_spec)
- interface = Mtu(argument_spec)
- interface.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_multicast_global.py b/plugins/modules/network/cloudengine/ce_multicast_global.py
deleted file mode 100644
index c5cafce220..0000000000
--- a/plugins/modules/network/cloudengine/ce_multicast_global.py
+++ /dev/null
@@ -1,289 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_multicast_global
-author: xuxiaowei0512 (@xuxiaowei0512)
-short_description: Manages multicast global configuration on HUAWEI CloudEngine switches.
-description:
- - Manages multicast global on HUAWEI CloudEngine switches.
-notes:
- - If no vrf is supplied, vrf is set to default.
- - If I(state=absent), the route will be removed, regardless of the non-required parameters.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - This module works with connection C(netconf).
-options:
- aftype:
- description:
- - Destination ip address family type of static route.
- required: true
- type: str
- choices: ['v4','v6']
- vrf:
- description:
- - VPN instance of destination ip address.
- type: str
- state:
- description:
- - Specify desired state of the resource.
- type: str
- default: present
- choices: ['present','absent']
-'''
-
-EXAMPLES = '''
----
- - name: multicast routing-enable
- ce_multicast_global:
- aftype: v4
- state: absent
- provider: "{{ cli }}"
- - name: multicast routing-enable
- ce_multicast_global:
- aftype: v4
- state: present
- provider: "{{ cli }}"
- - name: multicast routing-enable
- ce_multicast_global:
- aftype: v4
- vrf: vrf1
- provider: "{{ cli }}"
-
-'''
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"addressFamily": "ipv4unicast", "state": "present", "vrfName": "_public_"}
-existing:
- description: k/v pairs of existing switchport
- returned: always
- type: dict
- sample: {}
-end_state:
- description: k/v pairs of switchport after module execution
- returned: always
- type: dict
- sample: {"addressFamily": "ipv4unicast", "state": "present", "vrfName": "_public_"}
-updates:
- description: command list sent to the device
- returned: always
- type: list
- sample: ["multicast routing-enable"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config
-
-CE_NC_GET_MULTICAST_GLOBAL = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-CE_NC_MERGE_MULTICAST_GLOBAL = """
-
-
-
- %s
- %s
-
-
-
-"""
-CE_NC_DELETE_MULTICAST_GLOBAL = """
-
-
-
- %s
- %s
-
-
-
-"""
-
-
-def build_config_xml(xmlstr):
- """build config xml"""
-
- return ' ' + xmlstr + ' '
-
-
-class MulticastGlobal(object):
- """multicast global module"""
-
- def __init__(self, argument_spec):
- """multicast global info"""
- self.spec = argument_spec
- self.module = None
- self._initmodule_()
-
- self.aftype = self.module.params['aftype']
- self.state = self.module.params['state']
- if self.aftype == "v4":
- self.version = "ipv4unicast"
- else:
- self.version = "ipv6unicast"
- # vpn instance info
- self.vrf = self.module.params['vrf']
- if self.vrf is None:
- self.vrf = "_public_"
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- self.multicast_global_info = dict()
-
- def _initmodule_(self):
- """init module"""
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=False)
-
- def _checkresponse_(self, xml_str, xml_name):
- """check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def set_change_state(self):
- """set change state"""
- state = self.state
- change = False
- self.get_multicast_global()
- # new or edit
- if state == 'present':
- if not self.multicast_global_info.get('multicast_global'):
- # i.e. self.multicast_global_info['multicast_global'] has not value
- change = True
- else:
- # delete
- if self.multicast_global_info.get('multicast_global'):
- # i.e. self.multicast_global_info['multicast_global'] has value
- change = True
- self.changed = change
-
- def get_multicast_global(self):
- """get one data"""
- self.multicast_global_info["multicast_global"] = list()
- getxmlstr = CE_NC_GET_MULTICAST_GLOBAL % (
- self.version, self.vrf)
- xml_str = get_nc_config(self.module, getxmlstr)
- if 'data/' in xml_str:
- return
- xml_str = xml_str.replace('\r', '').replace('\n', ''). \
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', ""). \
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
- mcast_enable = root.findall(
- "mcastbase/mcastAfsEnables/mcastAfsEnable")
- if mcast_enable:
- # i.e. mcast_enable = [{vrfName:11,addressFamily:'xx'},{vrfName:22,addressFamily:'xx'}...]
- for mcast_enable_key in mcast_enable:
- # i.e. mcast_enable_key = {vrfName:11,addressFamily:'xx'}
- mcast_info = dict()
- for ele in mcast_enable_key:
- if ele.tag in ["vrfName", "addressFamily"]:
- mcast_info[ele.tag] = ele.text
- self.multicast_global_info['multicast_global'].append(mcast_info)
-
- def get_existing(self):
- """get existing information"""
- self.set_change_state()
- self.existing["multicast_global"] = self.multicast_global_info["multicast_global"]
-
- def get_proposed(self):
- """get proposed information"""
- self.proposed['addressFamily'] = self.version
- self.proposed['state'] = self.state
- self.proposed['vrfName'] = self.vrf
-
- def set_multicast_global(self):
- """set multicast global"""
- if not self.changed:
- return
- version = self.version
- state = self.state
- if state == "present":
- configxmlstr = CE_NC_MERGE_MULTICAST_GLOBAL % (self.vrf, version)
- else:
- configxmlstr = CE_NC_DELETE_MULTICAST_GLOBAL % (self.vrf, version)
-
- conf_str = build_config_xml(configxmlstr)
- recv_xml = set_nc_config(self.module, conf_str)
- self._checkresponse_(recv_xml, "SET_MULTICAST_GLOBAL")
-
- def set_update_cmd(self):
- """set update command"""
- if not self.changed:
- return
- if self.state == "present":
- self.updates_cmd.append('multicast routing-enable')
- else:
- self.updates_cmd.append('undo multicast routing-enable')
-
- def get_end_state(self):
- """get end state information"""
- self.get_multicast_global()
- self.end_state["multicast_global"] = self.multicast_global_info["multicast_global"]
-
- def work(self):
- """worker"""
- self.get_existing()
- self.get_proposed()
- self.set_multicast_global()
- self.set_update_cmd()
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['existing'] = self.existing
- self.results['proposed'] = self.proposed
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
- self.module.exit_json(**self.results)
-
-
-def main():
- """main"""
-
- argument_spec = dict(
- aftype=dict(choices=['v4', 'v6'], required=True),
- vrf=dict(required=False, type='str'),
- state=dict(choices=['absent', 'present'], default='present', required=False),
- )
- interface = MulticastGlobal(argument_spec)
- interface.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_multicast_igmp_enable.py b/plugins/modules/network/cloudengine/ce_multicast_igmp_enable.py
deleted file mode 100644
index 9a57337859..0000000000
--- a/plugins/modules/network/cloudengine/ce_multicast_igmp_enable.py
+++ /dev/null
@@ -1,544 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_multicast_igmp_enable
-author: xuxiaowei0512 (@CloudEngine-Ansible)
-short_description: Manages multicast igmp enable configuration on HUAWEI CloudEngine switches.
-description:
- - Manages multicast igmp on HUAWEI CloudEngine switches.
-notes:
- - If no vrf is supplied, vrf is set to default.
- If I(state=absent), the route will be removed, regardless of the
- non-required parameters.
- - This module requires the netconf system service be enabled on
- the remote device being managed.
- - This module works with connection C(netconf).
-options:
- aftype:
- description:
- - Destination ip address family type of static route.
- required: true
- type: str
- choices: ['v4','v6']
- features:
- description:
- - Distinguish between Globally Enabled IGMP or
- - Enabled IGMP under vlanID.
- required: true
- type: str
- choices: ['global','vlan']
- vlan_id:
- description:
- - Virtual LAN identity.
- type: int
- igmp:
- description:
- - Enable Layer 2 multicast Snooping in a VLAN.
- type: bool
- version:
- description:
- - Specifies the IGMP version that can be processed.
- default: 2
- type: int
- proxy:
- description:
- - Layer 2 multicast snooping proxy is enabled.
- type: bool
- state:
- description:
- - Specify desired state of the resource.
- choices: ['present','absent']
- default: present
- type: str
-'''
-
-EXAMPLES = '''
-
- - name: configure global igmp enable
- ce_multicast_igmp_enable:
- aftype: v4
- features: 'global'
- state: present
-
- - name: configure global igmp disable
- ce_multicast_igmp_enable:
- features: 'global'
- aftype: v4
- state: absent
-
- - name: configure vlan igmp enable
- ce_multicast_igmp_enable:
- features: 'vlan'
- aftype: v4
- vlan_id: 1
- igmp: true
-
- - name: new proxy,igmp,version
- ce_multicast_igmp_enable:
- features: 'vlan'
- aftype: v4
- vlan_id: 1
- proxy: true
- igmp: true
- version: 1
-
- - name: modify proxy,igmp,version
- ce_multicast_igmp_enable:
- features: 'vlan'
- aftype: v4
- vlan_id: 1
- version: 2
-
- - name: delete proxy,igmp,version
- ce_multicast_igmp_enable:
- features: 'vlan'
- aftype: v4
- vlan_id: 1
- state: absent
-'''
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"addrFamily": "ipv4unicast", "features": "vlan", "proxyEnable": "false",
- "snoopingEnable": "false", "state": "absent", "version": 2, "vlanId": 1}
-existing:
- description: k/v pairs of existing switchport
- returned: always
- type: dict
- sample: {}
-end_state:
- description: k/v pairs of switchport after module execution
- returned: always
- type: dict
- sample: {}
-updates:
- description: command list sent to the device
- returned: always
- type: list
- sample: ["undo igmp snooping enable",
- "undo igmp snooping version",
- "undo igmp snooping proxy"]
-changed:
- description: check if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config
-
-CE_NC_GET_IGMP_GLOBAL = """
-
-
-
-
- %s
-
-
-
-
-"""
-CE_NC_MERGE_IGMP_SYSVIEW = """
-
-
-
- %s
-
-
-
-"""
-CE_NC_DELETE_IGMP_SYSVIEW = """
-
-
-
- %s
-
-
-
-"""
-CE_NC_GET_IGMP_VLAN_INFO = """
-
-
-
-
-
- %s
- %s
-
-
-
-
-
-
-
-
-"""
-CE_NC_MERGE_IGMP_VLANVIEW = """
-
-
-
-
- %s
- %s%s%s%s
-
-
-
-
-"""
-CE_NC_MERGE_IGMP_VLANVIEW_SNOENABLE = """
-%s
-"""
-CE_NC_MERGE_IGMP_VLANVIEW_VERSION = """
-%s
-"""
-CE_NC_MERGE_IGMP_VLANVIEW_PROXYENABLE = """
-%s
-"""
-CE_NC_DELETE_IGMP_VLANVIEW = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-
-def get_xml(xml, value):
- """operate xml"""
- tempxml = xml % value
- return tempxml
-
-
-def build_config_xml(xmlstr):
- """build config xml"""
-
- return ' ' + xmlstr + ' '
-
-
-class IgmpSnoop(object):
- """igmp snooping module"""
-
- def __init__(self, argument_spec):
- """igmp snooping info"""
- self.spec = argument_spec
- self.module = None
- self._initmodule_()
-
- self.aftype = self.module.params['aftype']
- self.state = self.module.params['state']
- if self.aftype == "v4":
- self.addr_family = "ipv4unicast"
- else:
- self.addr_family = "ipv6unicast"
- self.features = self.module.params['features']
- self.vlan_id = self.module.params['vlan_id']
- self.igmp = str(self.module.params['igmp']).lower()
- self.version = self.module.params['version']
- if self.version is None:
- self.version = 2
- self.proxy = str(self.module.params['proxy']).lower()
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
- self.igmp_info_data = dict()
-
- def _initmodule_(self):
- """init module"""
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=False)
-
- def _checkresponse_(self, xml_str, xml_name):
- """check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def _checkparams_(self):
- """check all input params"""
- # check vlan id
- if self.features == 'vlan':
- if not self.vlan_id:
- self.module.fail_json(msg='Error: missing required arguments: vlan_id.')
-
- if self.vlan_id:
- if self.vlan_id <= 0 or self.vlan_id > 4094:
- self.module.fail_json(
- msg='Error: Vlan id is not in the range from 1 to 4094.')
- # check version
- if self.version:
- if self.version <= 0 or self.version > 3:
- self.module.fail_json(
- msg='Error: Version id is not in the range from 1 to 3.')
-
- def set_change_state(self):
- """set change state"""
- state = self.state
- change = False
- # vlan view igmp
- if self.features == 'vlan':
- self.get_igmp_vlan()
- change = self.compare_data()
- else:
- # sys view igmp(global)
- self.get_igmp_global()
- # new or edit
- if state == 'present':
- if not self.igmp_info_data["igmp_info"]:
- # igmp_info_data has not igmp_info value.
- change = True
- else:
- # delete
- if self.igmp_info_data["igmp_info"]:
- # igmp_info_data has not igmp_info value.
- change = True
- self.changed = change
-
- def compare_data(self):
- """compare new data and old data"""
- state = self.state
- change = False
- # new or edit
- if state == 'present':
- # edit
- if self.igmp_info_data["igmp_info"]:
- for data in self.igmp_info_data["igmp_info"]:
- if self.addr_family == data["addrFamily"] and str(self.vlan_id) == data["vlanId"]:
- if self.igmp:
- if self.igmp != data["snoopingEnable"]:
- change = True
- if self.version:
- if str(self.version) != data["version"]:
- change = True
- if self.proxy:
- if self.proxy != data["proxyEnable"]:
- change = True
- # new
- else:
- change = True
- else:
- # delete
- if self.igmp_info_data["igmp_info"]:
- change = True
- return change
-
- def get_igmp_vlan(self):
- """get igmp vlan info data"""
- self.igmp_info_data["igmp_info"] = list()
- getxmlstr = CE_NC_GET_IGMP_VLAN_INFO % (self.addr_family, self.vlan_id)
- xml_str = get_nc_config(self.module, getxmlstr)
- if 'data/' in xml_str:
- return
- xml_str = xml_str.replace('\r', '').replace('\n', ''). \
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', ""). \
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
- igmp_enable = root.findall(
- "l2mc/vlan/l2McVlanCfgs/l2McVlanCfg")
- if igmp_enable:
- # igmp_enable = [{addressFamily:'xx'}]
- for igmp_enable_key in igmp_enable:
- # igmp_enable_key = {addressFamily:'xx'}
- igmp_global_info = dict()
- for ele in igmp_enable_key:
- if ele.tag in ["addrFamily", "vlanId", "snoopingEnable", "version", "proxyEnable"]:
- igmp_global_info[ele.tag] = ele.text
- self.igmp_info_data["igmp_info"].append(igmp_global_info)
-
- def get_igmp_global(self):
- """get igmp global data"""
- self.igmp_info_data["igmp_info"] = list()
- getxmlstr = CE_NC_GET_IGMP_GLOBAL % (
- self.addr_family)
- xml_str = get_nc_config(self.module, getxmlstr)
- if 'data/' in xml_str:
- return
- xml_str = xml_str.replace('\r', '').replace('\n', ''). \
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', ""). \
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
- igmp_enable = root.findall(
- 'l2mc/l2McSnpgEnables/l2McSnpgEnable')
- if igmp_enable:
- # igmp_enable = [{addressFamily:'xx'}]
- for igmp_enable_key in igmp_enable:
- # igmp_enable_key = {addressFamily:'xx'}
- igmp_global_info = dict()
- for ele in igmp_enable_key:
- if ele.tag in ["addrFamily"]:
- igmp_global_info[ele.tag] = ele.text
- self.igmp_info_data["igmp_info"].append(igmp_global_info)
-
- def set_vlanview_igmp(self):
- """set igmp of vlanview"""
- if not self.changed:
- return
- addr_family = self.addr_family
- state = self.state
- igmp_xml = """\n"""
- version_xml = """\n"""
- proxy_xml = """\n"""
- if state == "present":
- if self.igmp:
- igmp_xml = get_xml(CE_NC_MERGE_IGMP_VLANVIEW_SNOENABLE, self.igmp.lower())
- if str(self.version):
- version_xml = get_xml(CE_NC_MERGE_IGMP_VLANVIEW_VERSION, self.version)
- if self.proxy:
- proxy_xml = get_xml(CE_NC_MERGE_IGMP_VLANVIEW_PROXYENABLE, self.proxy.lower())
- configxmlstr = CE_NC_MERGE_IGMP_VLANVIEW % (
- addr_family, self.vlan_id, igmp_xml, version_xml, proxy_xml)
- else:
- configxmlstr = CE_NC_DELETE_IGMP_VLANVIEW % (addr_family, self.vlan_id)
- conf_str = build_config_xml(configxmlstr)
- recv_xml = set_nc_config(self.module, conf_str)
- self._checkresponse_(recv_xml, "SET_VLANVIEW_IGMP")
-
- def set_sysview_igmp(self):
- """set igmp of sysview"""
- if not self.changed:
- return
- version = self.addr_family
- state = self.state
- if state == "present":
- configxmlstr = CE_NC_MERGE_IGMP_SYSVIEW % (version)
- else:
- configxmlstr = CE_NC_DELETE_IGMP_SYSVIEW % (version)
-
- conf_str = build_config_xml(configxmlstr)
- recv_xml = set_nc_config(self.module, conf_str)
- self._checkresponse_(recv_xml, "SET_SYSVIEW_IGMP")
-
- def set_sysview_cmd(self):
- """set sysview update command"""
- if not self.changed:
- return
- if self.state == "present":
- self.updates_cmd.append('igmp snooping enable')
- else:
- self.updates_cmd.append('undo igmp snooping enable')
-
- def set_vlanview_cmd(self):
- """set vlanview update command"""
- if not self.changed:
- return
- if self.state == "present":
- if self.igmp:
- if self.igmp.lower() == 'true':
- self.updates_cmd.append('igmp snooping enable')
- else:
- self.updates_cmd.append('undo igmp snooping enable')
- if str(self.version):
- self.updates_cmd.append('igmp snooping version %s' % (self.version))
- else:
- self.updates_cmd.append('undo igmp snooping version')
- if self.proxy:
- if self.proxy.lower() == 'true':
- self.updates_cmd.append('igmp snooping proxy')
- else:
- self.updates_cmd.append('undo igmp snooping proxy')
-
- else:
- self.updates_cmd.append('undo igmp snooping enable')
- self.updates_cmd.append('undo igmp snooping version')
- self.updates_cmd.append('undo igmp snooping proxy')
-
- def get_existing(self):
- """get existing information"""
- self.set_change_state()
- self.existing["igmp_info"] = self.igmp_info_data["igmp_info"]
-
- def get_proposed(self):
- """get proposed information"""
- self.proposed['addrFamily'] = self.addr_family
- self.proposed['features'] = self.features
- if self.features == 'vlan':
- self.proposed['snoopingEnable'] = self.igmp
- self.proposed['version'] = self.version
- self.proposed['vlanId'] = self.vlan_id
- self.proposed['proxyEnable'] = self.proxy
- self.proposed['state'] = self.state
-
- def set_igmp_netconf(self):
- """config netconf"""
- if self.features == 'vlan':
- self.set_vlanview_igmp()
- else:
- self.set_sysview_igmp()
-
- def set_update_cmd(self):
- """set update command"""
- if self.features == 'vlan':
- self.set_vlanview_cmd()
- else:
- self.set_sysview_cmd()
-
- def get_end_state(self):
- """get end state information"""
- if self.features == 'vlan':
- self.get_igmp_vlan()
- else:
- # sys view igmp(global)
- self.get_igmp_global()
- self.end_state["igmp_info"] = self.igmp_info_data["igmp_info"]
-
- def work(self):
- """worker"""
- self._checkparams_()
- self.get_existing()
- self.get_proposed()
- self.set_igmp_netconf()
- self.set_update_cmd()
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['existing'] = self.existing
- self.results['proposed'] = self.proposed
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
- self.module.exit_json(**self.results)
-
-
-def main():
- """main"""
- argument_spec = dict(
- aftype=dict(choices=['v4', 'v6'], required=True),
- features=dict(required=True, choices=['global', 'vlan'], type='str'),
- vlan_id=dict(type='int'),
- igmp=dict(type='bool', default=False),
- version=dict(type='int', default=2),
- proxy=dict(type='bool', default=False),
- state=dict(choices=['absent', 'present'], default='present'),
- )
- interface = IgmpSnoop(argument_spec)
- interface.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_netconf.py b/plugins/modules/network/cloudengine/ce_netconf.py
deleted file mode 100644
index 141731f08c..0000000000
--- a/plugins/modules/network/cloudengine/ce_netconf.py
+++ /dev/null
@@ -1,206 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_netconf
-short_description: Run an arbitrary netconf command on HUAWEI CloudEngine switches.
-description:
- - Sends an arbitrary netconf command on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- rpc:
- description:
- - The type of rpc.
- required: true
- choices: ['get', 'edit-config', 'execute-action', 'execute-cli']
- cfg_xml:
- description:
- - The config xml string.
- required: true
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine netconf test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Netconf get operation"
- ce_netconf:
- rpc: get
- cfg_xml: '
-
-
-
- 10
-
-
-
-
-
-
-
-
- '
- provider: "{{ cli }}"
-
- - name: "Netconf edit-config operation"
- ce_netconf:
- rpc: edit-config
- cfg_xml: '
-
-
-
- default_wdz
- local
- invalid
-
-
-
- '
- provider: "{{ cli }}"
-
- - name: "Netconf execute-action operation"
- ce_netconf:
- rpc: execute-action
- cfg_xml: '
-
-
- ipv4unicast
-
-
- '
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"result": ["ok"]}
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import execute_nc_action, ce_argument_spec, execute_nc_cli
-
-
-def main():
- """ main """
-
- argument_spec = dict(
- rpc=dict(choices=['get', 'edit-config',
- 'execute-action', 'execute-cli'], required=True),
- cfg_xml=dict(required=True)
- )
-
- argument_spec.update(ce_argument_spec)
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
-
- rpc = module.params['rpc']
- cfg_xml = module.params['cfg_xml']
- changed = False
- end_state = dict()
-
- if rpc == "get":
-
- response = get_nc_config(module, cfg_xml)
-
- if "" in response:
- end_state["result"] = ""
- else:
- tmp1 = response.split(r"")
- tmp2 = tmp1[1].split(r"")
- result = tmp2[0].split("\n")
-
- end_state["result"] = result
-
- elif rpc == "edit-config":
-
- response = set_nc_config(module, cfg_xml)
-
- if "" not in response:
- module.fail_json(msg='rpc edit-config failed.')
-
- changed = True
- end_state["result"] = "ok"
-
- elif rpc == "execute-action":
-
- response = execute_nc_action(module, cfg_xml)
-
- if "" not in response:
- module.fail_json(msg='rpc execute-action failed.')
-
- changed = True
- end_state["result"] = "ok"
-
- elif rpc == "execute-cli":
-
- response = execute_nc_cli(module, cfg_xml)
-
- if "" in response:
- end_state["result"] = ""
- else:
- tmp1 = response.split(r"")
- tmp2 = tmp1[1].split(r"")
- result = tmp2[0].split("\n")
-
- end_state["result"] = result
-
- else:
- module.fail_json(msg='please input correct rpc.')
-
- results = dict()
- results['changed'] = changed
- results['end_state'] = end_state
-
- module.exit_json(**results)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_netstream_aging.py b/plugins/modules/network/cloudengine/ce_netstream_aging.py
deleted file mode 100644
index f4e6e87f81..0000000000
--- a/plugins/modules/network/cloudengine/ce_netstream_aging.py
+++ /dev/null
@@ -1,520 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_netstream_aging
-short_description: Manages timeout mode of NetStream on HUAWEI CloudEngine switches.
-description:
- - Manages timeout mode of NetStream on HUAWEI CloudEngine switches.
-author: YangYang (@QijunPan)
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- timeout_interval:
- description:
- - Netstream timeout interval.
- If is active type the interval is 1-60.
- If is inactive ,the interval is 5-600.
- default: 30
- type:
- description:
- - Specifies the packet type of netstream timeout active interval.
- choices: ['ip', 'vxlan']
- state:
- description:
- - Specify desired state of the resource.
- choices: ['present', 'absent']
- default: present
- timeout_type:
- description:
- - Netstream timeout type.
- choices: ['active', 'inactive', 'tcp-session', 'manual']
- manual_slot:
- description:
- - Specifies the slot number of netstream manual timeout.
-'''
-
-EXAMPLES = '''
-- name: netstream aging module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Configure netstream ip timeout active interval , the interval is 40 minutes.
- ce_netstream_aging:
- timeout_interval: 40
- type: ip
- timeout_type: active
- state: present
- provider: "{{ cli }}"
-
- - name: Configure netstream vxlan timeout active interval , the interval is 40 minutes.
- ce_netstream_aging:
- timeout_interval: 40
- type: vxlan
- timeout_type: active
- active_state: present
- provider: "{{ cli }}"
-
- - name: Delete netstream ip timeout active interval , set the ip timeout interval to 30 minutes.
- ce_netstream_aging:
- type: ip
- timeout_type: active
- state: absent
- provider: "{{ cli }}"
-
- - name: Delete netstream vxlan timeout active interval , set the vxlan timeout interval to 30 minutes.
- ce_netstream_aging:
- type: vxlan
- timeout_type: active
- state: absent
- provider: "{{ cli }}"
-
- - name: Enable netstream ip tcp session timeout.
- ce_netstream_aging:
- type: ip
- timeout_type: tcp-session
- state: present
- provider: "{{ cli }}"
-
- - name: Enable netstream vxlan tcp session timeout.
- ce_netstream_aging:
- type: vxlan
- timeout_type: tcp-session
- state: present
- provider: "{{ cli }}"
-
- - name: Disable netstream ip tcp session timeout.
- ce_netstream_aging:
- type: ip
- timeout_type: tcp-session
- state: absent
- provider: "{{ cli }}"
-
- - name: Disable netstream vxlan tcp session timeout.
- ce_netstream_aging:
- type: vxlan
- timeout_type: tcp-session
- state: absent
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: verbose mode
- type: dict
- sample: {"timeout_interval": "40",
- "type": "ip",
- "state": "absent",
- "timeout_type": active}
-existing:
- description: k/v pairs of existing configuration
- returned: verbose mode
- type: dict
- sample: {"active_timeout": [
- {
- "ip": "40",
- "vxlan": 30
- }
- ],
- "inactive_timeout": [
- {
- "ip": 30,
- "vxlan": 30
- }
- ],
- "tcp_timeout": [
- {
- "ip": "disable",
- "vxlan": "disable"
- }
- ]}
-end_state:
- description: k/v pairs of configuration after module execution
- returned: verbose mode
- type: dict
- sample: {"active_timeout": [
- {
- "ip": 30,
- "vxlan": 30
- }
- ],
- "inactive_timeout": [
- {
- "ip": 30,
- "vxlan": 30
- }
- ],
- "tcp_timeout": [
- {
- "ip": "disable",
- "vxlan": "disable"
- }
- ]}
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: ["undo netstream timeout ip active 40"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import exec_command, load_config
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec
-
-
-class NetStreamAging(object):
- """
- Manages netstream aging.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.timeout_interval = self.module.params['timeout_interval']
- self.type = self.module.params['type']
- self.state = self.module.params['state']
- self.timeout_type = self.module.params['timeout_type']
- self.manual_slot = self.module.params['manual_slot']
-
- # host info
- self.host = self.module.params['host']
- self.username = self.module.params['username']
- self.port = self.module.params['port']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.commands = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- # local parameters
- self.existing["active_timeout"] = list()
- self.existing["inactive_timeout"] = list()
- self.existing["tcp_timeout"] = list()
- self.end_state["active_timeout"] = list()
- self.end_state["inactive_timeout"] = list()
- self.end_state["tcp_timeout"] = list()
- self.active_changed = False
- self.inactive_changed = False
- self.tcp_changed = False
-
- def init_module(self):
- """init module"""
-
- self.module = AnsibleModule(argument_spec=self.spec, supports_check_mode=True)
-
- def cli_load_config(self, commands):
- """load config by cli"""
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def cli_add_command(self, command, undo=False):
- """add command to self.update_cmd and self.commands"""
-
- if undo and command.lower() not in ["quit", "return"]:
- cmd = "undo " + command
- else:
- cmd = command
-
- self.commands.append(cmd)
- if command.lower() not in ["quit", "return"]:
- self.updates_cmd.append(cmd)
-
- def get_exist_timer_out_para(self):
- """Get exist netstream timeout parameters"""
-
- active_tmp = dict()
- inactive_tmp = dict()
- tcp_tmp = dict()
- active_tmp["ip"] = "30"
- active_tmp["vxlan"] = "30"
- inactive_tmp["ip"] = "30"
- inactive_tmp["vxlan"] = "30"
- tcp_tmp["ip"] = "absent"
- tcp_tmp["vxlan"] = "absent"
-
- cmd = "display current-configuration | include ^netstream timeout"
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- config = str(out).strip()
- if config:
- config = config.lstrip()
- config_list = config.split('\n')
- for config_mem in config_list:
- config_mem = config_mem.lstrip()
- config_mem_list = config_mem.split(' ')
- if len(config_mem_list) > 4 and config_mem_list[2] == "ip":
- if config_mem_list[3] == "active":
- active_tmp["ip"] = config_mem_list[4]
- if config_mem_list[3] == "inactive":
- inactive_tmp["ip"] = config_mem_list[4]
- if config_mem_list[3] == "tcp-session":
- tcp_tmp["ip"] = "present"
- if len(config_mem_list) > 4 and config_mem_list[2] == "vxlan":
- if config_mem_list[4] == "active":
- active_tmp["vxlan"] = config_mem_list[5]
- if config_mem_list[4] == "inactive":
- inactive_tmp["vxlan"] = config_mem_list[5]
- if config_mem_list[4] == "tcp-session":
- tcp_tmp["vxlan"] = "present"
- self.existing["active_timeout"].append(active_tmp)
- self.existing["inactive_timeout"].append(inactive_tmp)
- self.existing["tcp_timeout"].append(tcp_tmp)
-
- def get_end_timer_out_para(self):
- """Get end netstream timeout parameters"""
-
- active_tmp = dict()
- inactive_tmp = dict()
- tcp_tmp = dict()
- active_tmp["ip"] = "30"
- active_tmp["vxlan"] = "30"
- inactive_tmp["ip"] = "30"
- inactive_tmp["vxlan"] = "30"
- tcp_tmp["ip"] = "absent"
- tcp_tmp["vxlan"] = "absent"
- cmd = "display current-configuration | include ^netstream timeout"
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- config = str(out).strip()
- if config:
- config = config.lstrip()
- config_list = config.split('\n')
- for config_mem in config_list:
- config_mem = config_mem.lstrip()
- config_mem_list = config_mem.split(' ')
- if len(config_mem_list) > 4 and config_mem_list[2] == "ip":
- if config_mem_list[3] == "active":
- active_tmp["ip"] = config_mem_list[4]
- if config_mem_list[3] == "inactive":
- inactive_tmp["ip"] = config_mem_list[4]
- if config_mem_list[3] == "tcp-session":
- tcp_tmp["ip"] = "present"
- if len(config_mem_list) > 4 and config_mem_list[2] == "vxlan":
- if config_mem_list[4] == "active":
- active_tmp["vxlan"] = config_mem_list[5]
- if config_mem_list[4] == "inactive":
- inactive_tmp["vxlan"] = config_mem_list[5]
- if config_mem_list[4] == "tcp-session":
- tcp_tmp["vxlan"] = "present"
- self.end_state["active_timeout"].append(active_tmp)
- self.end_state["inactive_timeout"].append(inactive_tmp)
- self.end_state["tcp_timeout"].append(tcp_tmp)
-
- def check_params(self):
- """Check all input params"""
-
- # interval check
- if not str(self.timeout_interval).isdigit():
- self.module.fail_json(
- msg='Error: Timeout interval should be numerical.')
- if self.timeout_type == "active":
- if int(self.timeout_interval) < 1 or int(self.timeout_interval) > 60:
- self.module.fail_json(
- msg="Error: Active interval should between 1 - 60 minutes.")
- if self.timeout_type == "inactive":
- if int(self.timeout_interval) < 5 or int(self.timeout_interval) > 600:
- self.module.fail_json(
- msg="Error: Inactive interval should between 5 - 600 seconds.")
- if self.timeout_type == "manual":
- if not self.manual_slot:
- self.module.fail_json(
- msg="Error: If use manual timeout mode,slot number is needed.")
- if re.match(r'^\d+(\/\d*)?$', self.manual_slot) is None:
- self.module.fail_json(
- msg='Error: Slot number should be numerical.')
-
- def get_proposed(self):
- """get proposed info"""
-
- if self.timeout_interval:
- self.proposed["timeout_interval"] = self.timeout_interval
- if self.timeout_type:
- self.proposed["timeout_type"] = self.timeout_type
- if self.type:
- self.proposed["type"] = self.type
- if self.state:
- self.proposed["state"] = self.state
- if self.manual_slot:
- self.proposed["manual_slot"] = self.manual_slot
-
- def get_existing(self):
- """get existing info"""
- active_tmp = dict()
- inactive_tmp = dict()
- tcp_tmp = dict()
-
- self.get_exist_timer_out_para()
-
- if self.timeout_type == "active":
- for active_tmp in self.existing["active_timeout"]:
- if self.state == "present":
- if str(active_tmp[self.type]) != self.timeout_interval:
- self.active_changed = True
- else:
- if self.timeout_interval != "30":
- if str(active_tmp[self.type]) != "30":
- if str(active_tmp[self.type]) != self.timeout_interval:
- self.module.fail_json(
- msg='Error: The specified active interval do not exist.')
- if str(active_tmp[self.type]) != "30":
- self.timeout_interval = active_tmp[self.type]
- self.active_changed = True
- if self.timeout_type == "inactive":
- for inactive_tmp in self.existing["inactive_timeout"]:
- if self.state == "present":
- if str(inactive_tmp[self.type]) != self.timeout_interval:
- self.inactive_changed = True
- else:
- if self.timeout_interval != "30":
- if str(inactive_tmp[self.type]) != "30":
- if str(inactive_tmp[self.type]) != self.timeout_interval:
- self.module.fail_json(
- msg='Error: The specified inactive interval do not exist.')
- if str(inactive_tmp[self.type]) != "30":
- self.timeout_interval = inactive_tmp[self.type]
- self.inactive_changed = True
- if self.timeout_type == "tcp-session":
- for tcp_tmp in self.existing["tcp_timeout"]:
- if str(tcp_tmp[self.type]) != self.state:
- self.tcp_changed = True
-
- def operate_time_out(self):
- """configure timeout parameters"""
-
- cmd = ""
- if self.timeout_type == "manual":
- if self.type == "ip":
- self.cli_add_command("quit")
- cmd = "reset netstream cache ip slot %s" % self.manual_slot
- self.cli_add_command(cmd)
- elif self.type == "vxlan":
- self.cli_add_command("quit")
- cmd = "reset netstream cache vxlan inner-ip slot %s" % self.manual_slot
- self.cli_add_command(cmd)
-
- if not self.active_changed and not self.inactive_changed and not self.tcp_changed:
- if self.commands:
- self.cli_load_config(self.commands)
- self.changed = True
- return
-
- if self.active_changed or self.inactive_changed:
- if self.type == "ip":
- cmd = "netstream timeout ip %s %s" % (self.timeout_type, self.timeout_interval)
- elif self.type == "vxlan":
- cmd = "netstream timeout vxlan inner-ip %s %s" % (self.timeout_type, self.timeout_interval)
- if self.state == "absent":
- self.cli_add_command(cmd, undo=True)
- else:
- self.cli_add_command(cmd)
- if self.timeout_type == "tcp-session" and self.tcp_changed:
- if self.type == "ip":
- if self.state == "present":
- cmd = "netstream timeout ip tcp-session"
- else:
- cmd = "undo netstream timeout ip tcp-session"
-
- elif self.type == "vxlan":
- if self.state == "present":
- cmd = "netstream timeout vxlan inner-ip tcp-session"
- else:
- cmd = "undo netstream timeout vxlan inner-ip tcp-session"
- self.cli_add_command(cmd)
- if self.commands:
- self.cli_load_config(self.commands)
- self.changed = True
-
- def get_end_state(self):
- """get end state info"""
-
- self.get_end_timer_out_para()
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.get_existing()
- self.get_proposed()
- self.operate_time_out()
- self.get_end_state()
- if self.existing == self.end_state:
- self.changed = False
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- timeout_interval=dict(required=False, type='str', default='30'),
- type=dict(required=False, choices=['ip', 'vxlan']),
- state=dict(required=False, choices=['present', 'absent'], default='present'),
- timeout_type=dict(required=False, choices=['active', 'inactive', 'tcp-session', 'manual']),
- manual_slot=dict(required=False, type='str'),
- )
- argument_spec.update(ce_argument_spec)
- module = NetStreamAging(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_netstream_export.py b/plugins/modules/network/cloudengine/ce_netstream_export.py
deleted file mode 100644
index b5c01d05a7..0000000000
--- a/plugins/modules/network/cloudengine/ce_netstream_export.py
+++ /dev/null
@@ -1,561 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_netstream_export
-short_description: Manages netstream export on HUAWEI CloudEngine switches.
-description:
- - Configure NetStream flow statistics exporting and versions for exported packets on HUAWEI CloudEngine switches.
-author: Zhijin Zhou (@QijunPan)
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- type:
- description:
- - Specifies NetStream feature.
- required: true
- choices: ['ip', 'vxlan']
- source_ip:
- description:
- - Specifies source address which can be IPv6 or IPv4 of the exported NetStream packet.
- host_ip:
- description:
- - Specifies destination address which can be IPv6 or IPv4 of the exported NetStream packet.
- host_port:
- description:
- - Specifies the destination UDP port number of the exported packets.
- The value is an integer that ranges from 1 to 65535.
- host_vpn:
- description:
- - Specifies the VPN instance of the exported packets carrying flow statistics.
- Ensure the VPN instance has been created on the device.
- version:
- description:
- - Sets the version of exported packets.
- choices: ['5', '9']
- as_option:
- description:
- - Specifies the AS number recorded in the statistics as the original or the peer AS number.
- choices: ['origin', 'peer']
- bgp_nexthop:
- description:
- - Configures the statistics to carry BGP next hop information. Currently, only V9 supports the exported
- packets carrying BGP next hop information.
- choices: ['enable','disable']
- default: 'disable'
- state:
- description:
- - Manage the state of the resource.
- choices: ['present','absent']
- default: present
-'''
-
-EXAMPLES = '''
-- name: netstream export module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Configures the source address for the exported packets carrying IPv4 flow statistics.
- ce_netstream_export:
- type: ip
- source_ip: 192.8.2.2
- provider: "{{ cli }}"
-
- - name: Configures the source IP address for the exported packets carrying VXLAN flexible flow statistics.
- ce_netstream_export:
- type: vxlan
- source_ip: 192.8.2.3
- provider: "{{ cli }}"
-
- - name: Configures the destination IP address and destination UDP port number for the exported packets carrying IPv4 flow statistics.
- ce_netstream_export:
- type: ip
- host_ip: 192.8.2.4
- host_port: 25
- host_vpn: test
- provider: "{{ cli }}"
-
- - name: Configures the destination IP address and destination UDP port number for the exported packets carrying VXLAN flexible flow statistics.
- ce_netstream_export:
- type: vxlan
- host_ip: 192.8.2.5
- host_port: 26
- host_vpn: test
- provider: "{{ cli }}"
-
- - name: Configures the version number of the exported packets carrying IPv4 flow statistics.
- ce_netstream_export:
- type: ip
- version: 9
- as_option: origin
- bgp_nexthop: enable
- provider: "{{ cli }}"
-
- - name: Configures the version for the exported packets carrying VXLAN flexible flow statistics.
- ce_netstream_export:
- type: vxlan
- version: 9
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "as_option": "origin",
- "bgp_nexthop": "enable",
- "host_ip": "192.8.5.6",
- "host_port": "26",
- "host_vpn": "test",
- "source_ip": "192.8.2.5",
- "state": "present",
- "type": "ip",
- "version": "9"
- }
-existing:
- description: k/v pairs of existing attributes on the device
- returned: always
- type: dict
- sample: {
- "as_option": null,
- "bgp_nexthop": "disable",
- "host_ip": null,
- "host_port": null,
- "host_vpn": null,
- "source_ip": null,
- "type": "ip",
- "version": null
- }
-end_state:
- description: k/v pairs of end attributes on the device
- returned: always
- type: dict
- sample: {
- "as_option": "origin",
- "bgp_nexthop": "enable",
- "host_ip": "192.8.5.6",
- "host_port": "26",
- "host_vpn": "test",
- "source_ip": "192.8.2.5",
- "type": "ip",
- "version": "9"
- }
-updates:
- description: command list sent to the device
- returned: always
- type: list
- sample: [
- "netstream export ip source 192.8.2.5",
- "netstream export ip host 192.8.5.6 26 vpn-instance test",
- "netstream export ip version 9 origin-as bgp-nexthop"
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import exec_command, load_config
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec
-
-
-def is_ipv4_addr(ip_addr):
- """check ipaddress validate"""
-
- rule1 = r'(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.'
- rule2 = r'(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])'
- ipv4_regex = '%s%s%s%s%s%s' % ('^', rule1, rule1, rule1, rule2, '$')
-
- return bool(re.match(ipv4_regex, ip_addr))
-
-
-def is_config_exist(cmp_cfg, test_cfg):
- """is configuration exist"""
-
- test_cfg_tmp = test_cfg + ' *$' + '|' + test_cfg + ' *\n'
- obj = re.compile(test_cfg_tmp)
- result = re.findall(obj, cmp_cfg)
- if not result:
- return False
- return True
-
-
-class NetstreamExport(object):
- """Manage NetStream export"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.__init_module__()
-
- # NetStream export configuration parameters
- self.type = self.module.params['type']
- self.source_ip = self.module.params['source_ip']
- self.host_ip = self.module.params['host_ip']
- self.host_port = self.module.params['host_port']
- self.host_vpn = self.module.params['host_vpn']
- self.version = self.module.params['version']
- self.as_option = self.module.params['as_option']
- self.bgp_netxhop = self.module.params['bgp_nexthop']
- self.state = self.module.params['state']
-
- self.commands = list()
- self.config = None
- self.exist_conf = dict()
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def __init_module__(self):
- """init module"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def cli_load_config(self, commands):
- """load config by cli"""
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def get_netstream_config(self):
- """get current netstream configuration"""
-
- cmd = "display current-configuration | include ^netstream export"
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- config = str(out).strip()
- return config
-
- def get_existing(self):
- """get existing config"""
-
- self.existing = dict(type=self.type,
- source_ip=self.exist_conf['source_ip'],
- host_ip=self.exist_conf['host_ip'],
- host_port=self.exist_conf['host_port'],
- host_vpn=self.exist_conf['host_vpn'],
- version=self.exist_conf['version'],
- as_option=self.exist_conf['as_option'],
- bgp_nexthop=self.exist_conf['bgp_netxhop'])
-
- def get_proposed(self):
- """get proposed config"""
-
- self.proposed = dict(type=self.type,
- source_ip=self.source_ip,
- host_ip=self.host_ip,
- host_port=self.host_port,
- host_vpn=self.host_vpn,
- version=self.version,
- as_option=self.as_option,
- bgp_nexthop=self.bgp_netxhop,
- state=self.state)
-
- def get_end_state(self):
- """get end config"""
- self.get_config_data()
- self.end_state = dict(type=self.type,
- source_ip=self.exist_conf['source_ip'],
- host_ip=self.exist_conf['host_ip'],
- host_port=self.exist_conf['host_port'],
- host_vpn=self.exist_conf['host_vpn'],
- version=self.exist_conf['version'],
- as_option=self.exist_conf['as_option'],
- bgp_nexthop=self.exist_conf['bgp_netxhop'])
-
- def show_result(self):
- """show result"""
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
- def cli_add_command(self, command, undo=False):
- """add command to self.update_cmd and self.commands"""
-
- if undo and command.lower() not in ["quit", "return"]:
- cmd = "undo " + command
- else:
- cmd = command
-
- self.commands.append(cmd) # set to device
- if command.lower() not in ["quit", "return"]:
- if cmd not in self.updates_cmd:
- self.updates_cmd.append(cmd) # show updates result
-
- def config_nets_export_src_addr(self):
- """Configures the source address for the exported packets"""
-
- if is_ipv4_addr(self.source_ip):
- if self.type == 'ip':
- cmd = "netstream export ip source %s" % self.source_ip
- else:
- cmd = "netstream export vxlan inner-ip source %s" % self.source_ip
- else:
- if self.type == 'ip':
- cmd = "netstream export ip source ipv6 %s" % self.source_ip
- else:
- cmd = "netstream export vxlan inner-ip source ipv6 %s" % self.source_ip
-
- if is_config_exist(self.config, cmd):
- self.exist_conf['source_ip'] = self.source_ip
- if self.state == 'present':
- return
- else:
- undo = True
- else:
- if self.state == 'absent':
- return
- else:
- undo = False
-
- self.cli_add_command(cmd, undo)
-
- def config_nets_export_host_addr(self):
- """Configures the destination IP address and destination UDP port number"""
-
- if is_ipv4_addr(self.host_ip):
- if self.type == 'ip':
- cmd = 'netstream export ip host %s %s' % (self.host_ip, self.host_port)
- else:
- cmd = 'netstream export vxlan inner-ip host %s %s' % (self.host_ip, self.host_port)
- else:
- if self.type == 'ip':
- cmd = 'netstream export ip host ipv6 %s %s' % (self.host_ip, self.host_port)
- else:
- cmd = 'netstream export vxlan inner-ip host ipv6 %s %s' % (self.host_ip, self.host_port)
-
- if self.host_vpn:
- cmd += " vpn-instance %s" % self.host_vpn
-
- if is_config_exist(self.config, cmd):
- self.exist_conf['host_ip'] = self.host_ip
- self.exist_conf['host_port'] = self.host_port
- if self.host_vpn:
- self.exist_conf['host_vpn'] = self.host_vpn
-
- if self.state == 'present':
- return
- else:
- undo = True
- else:
- if self.state == 'absent':
- return
- else:
- undo = False
-
- self.cli_add_command(cmd, undo)
-
- def config_nets_export_vxlan_ver(self):
- """Configures the version for the exported packets carrying VXLAN flexible flow statistics"""
-
- cmd = 'netstream export vxlan inner-ip version 9'
-
- if is_config_exist(self.config, cmd):
- self.exist_conf['version'] = self.version
-
- if self.state == 'present':
- return
- else:
- undo = True
- else:
- if self.state == 'absent':
- return
- else:
- undo = False
-
- self.cli_add_command(cmd, undo)
-
- def config_nets_export_ip_ver(self):
- """Configures the version number of the exported packets carrying IPv4 flow statistics"""
-
- cmd = 'netstream export ip version %s' % self.version
- if self.version == '5':
- if self.as_option == 'origin':
- cmd += ' origin-as'
- elif self.as_option == 'peer':
- cmd += ' peer-as'
- else:
- if self.as_option == 'origin':
- cmd += ' origin-as'
- elif self.as_option == 'peer':
- cmd += ' peer-as'
-
- if self.bgp_netxhop == 'enable':
- cmd += ' bgp-nexthop'
-
- if cmd == 'netstream export ip version 5':
- cmd_tmp = "netstream export ip version"
- if cmd_tmp in self.config:
- if self.state == 'present':
- self.cli_add_command(cmd, False)
- else:
- self.exist_conf['version'] = self.version
- return
-
- if is_config_exist(self.config, cmd):
- self.exist_conf['version'] = self.version
- self.exist_conf['as_option'] = self.as_option
- self.exist_conf['bgp_netxhop'] = self.bgp_netxhop
-
- if self.state == 'present':
- return
- else:
- undo = True
- else:
- if self.state == 'absent':
- return
- else:
- undo = False
-
- self.cli_add_command(cmd, undo)
-
- def config_netstream_export(self):
- """configure netstream export"""
-
- if self.commands:
- self.cli_load_config(self.commands)
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- if not self.type:
- self.module.fail_json(msg='Error: The value of type cannot be empty.')
-
- if self.host_port:
- if not self.host_port.isdigit():
- self.module.fail_json(msg='Error: Host port is invalid.')
- if int(self.host_port) < 1 or int(self.host_port) > 65535:
- self.module.fail_json(msg='Error: Host port is not in the range from 1 to 65535.')
-
- if self.host_vpn:
- if self.host_vpn == '_public_':
- self.module.fail_json(
- msg='Error: The host vpn name _public_ is reserved.')
- if len(self.host_vpn) < 1 or len(self.host_vpn) > 31:
- self.module.fail_json(msg='Error: The host vpn name length is not in the range from 1 to 31.')
-
- if self.type == 'vxlan' and self.version == '5':
- self.module.fail_json(msg="Error: When type is vxlan, version must be 9.")
-
- if self.type == 'ip' and self.version == '5' and self.bgp_netxhop == 'enable':
- self.module.fail_json(msg="Error: When type=ip and version=5, bgp_netxhop is not supported.")
-
- if (self.host_ip and not self.host_port) or (self.host_port and not self.host_ip):
- self.module.fail_json(msg="Error: host_ip and host_port must both exist or not exist.")
-
- def get_config_data(self):
- """get configuration commands and current configuration"""
-
- self.exist_conf['type'] = self.type
- self.exist_conf['source_ip'] = None
- self.exist_conf['host_ip'] = None
- self.exist_conf['host_port'] = None
- self.exist_conf['host_vpn'] = None
- self.exist_conf['version'] = None
- self.exist_conf['as_option'] = None
- self.exist_conf['bgp_netxhop'] = 'disable'
-
- self.config = self.get_netstream_config()
-
- if self.type and self.source_ip:
- self.config_nets_export_src_addr()
-
- if self.type and self.host_ip and self.host_port:
- self.config_nets_export_host_addr()
-
- if self.type == 'vxlan' and self.version == '9':
- self.config_nets_export_vxlan_ver()
-
- if self.type == 'ip' and self.version:
- self.config_nets_export_ip_ver()
-
- def work(self):
- """execute task"""
-
- self.check_params()
- self.get_proposed()
- self.get_config_data()
- self.get_existing()
-
- self.config_netstream_export()
-
- self.get_end_state()
- self.show_result()
-
-
-def main():
- """main function entry"""
-
- argument_spec = dict(
- type=dict(required=True, type='str', choices=['ip', 'vxlan']),
- source_ip=dict(required=False, type='str'),
- host_ip=dict(required=False, type='str'),
- host_port=dict(required=False, type='str'),
- host_vpn=dict(required=False, type='str'),
- version=dict(required=False, type='str', choices=['5', '9']),
- as_option=dict(required=False, type='str', choices=['origin', 'peer']),
- bgp_nexthop=dict(required=False, type='str', choices=['enable', 'disable'], default='disable'),
- state=dict(choices=['absent', 'present'], default='present', required=False)
- )
- argument_spec.update(ce_argument_spec)
- netstream_export = NetstreamExport(argument_spec)
- netstream_export.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_netstream_global.py b/plugins/modules/network/cloudengine/ce_netstream_global.py
deleted file mode 100644
index ac8c61e06f..0000000000
--- a/plugins/modules/network/cloudengine/ce_netstream_global.py
+++ /dev/null
@@ -1,946 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_netstream_global
-short_description: Manages global parameters of NetStream on HUAWEI CloudEngine switches.
-description:
- - Manages global parameters of NetStream on HUAWEI CloudEngine switches.
-author: YangYang (@QijunPan)
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- type:
- description:
- - Specifies the type of netstream global.
- choices: ['ip', 'vxlan']
- default: 'ip'
- state:
- description:
- - Specify desired state of the resource.
- choices: ['present', 'absent']
- default: present
- interface:
- description:
- - Netstream global interface.
- required: true
- sampler_interval:
- description:
- - Specifies the netstream sampler interval, length is 1 - 65535.
- sampler_direction:
- description:
- - Specifies the netstream sampler direction.
- choices: ['inbound', 'outbound']
- statistics_direction:
- description:
- - Specifies the netstream statistic direction.
- choices: ['inbound', 'outbound']
- statistics_record:
- description:
- - Specifies the flexible netstream statistic record, length is 1 - 32.
- index_switch:
- description:
- - Specifies the netstream index-switch.
- choices: ['16', '32']
- default: '16'
-'''
-
-EXAMPLES = '''
-- name: netstream global module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Configure a netstream sampler at interface 10ge1/0/2, direction is outbound,interval is 30.
- ce_netstream_global:
- interface: 10ge1/0/2
- type: ip
- sampler_interval: 30
- sampler_direction: outbound
- state: present
- provider: "{{ cli }}"
- - name: Configure a netstream flexible statistic at interface 10ge1/0/2, record is test1, type is ip.
- ce_netstream_global:
- type: ip
- interface: 10ge1/0/2
- statistics_record: test1
- provider: "{{ cli }}"
- - name: Set the vxlan index-switch to 32.
- ce_netstream_global:
- type: vxlan
- interface: all
- index_switch: 32
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: verbose mode
- type: dict
- sample: {"index_switch": "16",
- "interface": "10ge1/0/2",
- "state": "present",
- "statistics_record": "test",
- "type": "vxlan"}
-existing:
- description: k/v pairs of existing configuration
- returned: verbose mode
- type: dict
- sample: {"flexible_statistic": [
- {
- "interface": "10ge1/0/2",
- "statistics_record": [],
- "type": "ip"
- },
- {
- "interface": "10ge1/0/2",
- "statistics_record": [],
- "type": "vxlan"
- }
- ],
- "index-switch": [
- {
- "index-switch": "16",
- "type": "ip"
- },
- {
- "index-switch": "16",
- "type": "vxlan"
- }
- ],
- "ip_record": [
- "test",
- "test1"
- ],
- "sampler": [
- {
- "interface": "all",
- "sampler_direction": "null",
- "sampler_interval": "null"
- }
- ],
- "statistic": [
- {
- "interface": "10ge1/0/2",
- "statistics_direction": [],
- "type": "null"
- }
- ],
- "vxlan_record": [
- "test"
- ]}
-end_state:
- description: k/v pairs of configuration after module execution
- returned: verbose mode
- type: dict
- sample: {"flexible_statistic": [
- {
- "interface": "10ge1/0/2",
- "statistics_record": [],
- "type": "ip"
- },
- {
- "interface": "10ge1/0/2",
- "statistics_record": [
- "test"
- ],
- "type": "vxlan"
- }
- ],
- "index-switch": [
- {
- "index-switch": "16",
- "type": "ip"
- },
- {
- "index-switch": "16",
- "type": "vxlan"
- }
- ],
- "sampler": [
- {
- "interface": "all",
- "sampler_direction": "null",
- "sampler_interval": "null"
- }
- ],
- "statistic": [
- {
- "interface": "10ge1/0/2",
- "statistics_direction": [],
- "type": "null"
- }
- ]}
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: ["interface 10ge1/0/2",
- "netstream record test vxlan inner-ip"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import load_config
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_connection, rm_config_prefix
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE, ETH-TRUNK..."""
-
- if interface is None:
- return None
-
- iftype = None
-
- if interface.upper().startswith('GE'):
- iftype = 'ge'
- elif interface.upper().startswith('10GE'):
- iftype = '10ge'
- elif interface.upper().startswith('25GE'):
- iftype = '25ge'
- elif interface.upper().startswith('4X10GE'):
- iftype = '4x10ge'
- elif interface.upper().startswith('40GE'):
- iftype = '40ge'
- elif interface.upper().startswith('100GE'):
- iftype = '100ge'
- elif interface.upper().startswith('ETH-TRUNK'):
- iftype = 'eth-trunk'
- elif interface.upper().startswith('ALL'):
- iftype = 'all'
- else:
- return None
-
- return iftype.lower()
-
-
-def get_config(module, flags):
-
- """Retrieves the current config from the device or cache
- """
- time_stamp_regex = re.compile(r'\s*\d{4}-\d{1,2}-\d{1,2}\s+\d{2}\:\d{2}\:\d{2}\.\d+\s*')
- flags = [] if flags is None else flags
- if isinstance(flags, str):
- flags = [flags]
- elif not isinstance(flags, list):
- flags = []
-
- cmd = 'display current-configuration '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
- conn = get_connection(module)
- rc, out, err = conn.exec_command(cmd)
- if rc != 0:
- module.fail_json(msg=err)
- cfg = str(out).strip()
- # remove default configuration prefix '~'
- for flag in flags:
- if "include-default" in flag:
- cfg = rm_config_prefix(cfg)
- break
- lines = cfg.split('\n')
- lines = [l for l in lines if time_stamp_regex.match(l) is None]
- if cfg.startswith('display'):
- if len(lines) > 1:
- lines.pop(0)
- else:
- return ''
- return '\n'.join(lines)
-
-
-class NetStreamGlobal(object):
- """
- Manages netstream global parameters.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.type = self.module.params['type']
- self.interface = self.module.params['interface']
- self.sampler_interval = self.module.params['sampler_interval']
- self.sampler_direction = self.module.params['sampler_direction']
- self.statistics_direction = self.module.params['statistics_direction']
- self.statistics_record = self.module.params['statistics_record']
- self.index_switch = self.module.params['index_switch']
- self.state = self.module.params['state']
-
- # host info
- self.host = self.module.params['host']
- self.username = self.module.params['username']
- self.port = self.module.params['port']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.commands = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- # local parameters
- self.existing["sampler"] = list()
- self.existing["statistic"] = list()
- self.existing["flexible_statistic"] = list()
- self.existing["index-switch"] = list()
- self.existing["ip_record"] = list()
- self.existing["vxlan_record"] = list()
- self.end_state["sampler"] = list()
- self.end_state["statistic"] = list()
- self.end_state["flexible_statistic"] = list()
- self.end_state["index-switch"] = list()
- self.sampler_changed = False
- self.statistic_changed = False
- self.flexible_changed = False
- self.index_switch_changed = False
-
- def init_module(self):
- """init module"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def cli_load_config(self, commands):
- """load config by cli"""
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def cli_add_command(self, command, undo=False):
- """add command to self.update_cmd and self.commands"""
-
- if undo and command.lower() not in ["quit", "return"]:
- cmd = "undo " + command
- else:
- cmd = command
-
- self.commands.append(cmd)
- if command.lower() not in ["quit", "return"]:
- self.updates_cmd.append(cmd)
-
- def get_exist_sampler_interval(self):
- """get exist netstream sampler interval"""
-
- sampler_tmp = dict()
- sampler_tmp1 = dict()
- flags = list()
- exp = " | ignore-case include ^netstream sampler random-packets"
- flags.append(exp)
- config = get_config(self.module, flags)
- if not config:
- sampler_tmp["sampler_interval"] = "null"
- sampler_tmp["sampler_direction"] = "null"
- sampler_tmp["interface"] = "null"
- else:
- config_list = config.split(' ')
- config_num = len(config_list)
- sampler_tmp["sampler_direction"] = config_list[config_num - 1]
- sampler_tmp["sampler_interval"] = config_list[config_num - 2]
- sampler_tmp["interface"] = "all"
- self.existing["sampler"].append(sampler_tmp)
- if self.interface != "all":
- flags = list()
- exp = r" | ignore-case section include ^#\s+interface %s" \
- r" | include netstream sampler random-packets" % self.interface
- flags.append(exp)
- config = get_config(self.module, flags)
- if not config:
- sampler_tmp1["sampler_interval"] = "null"
- sampler_tmp1["sampler_direction"] = "null"
- else:
- config = config.lstrip()
- config_list = config.split('\n')
- for config_mem in config_list:
- sampler_tmp1 = dict()
- config_mem_list = config_mem.split(' ')
- config_num = len(config_mem_list)
- if config_num > 1:
- sampler_tmp1["sampler_direction"] = config_mem_list[
- config_num - 1]
- sampler_tmp1["sampler_interval"] = config_mem_list[
- config_num - 2]
- sampler_tmp1["interface"] = self.interface
- self.existing["sampler"].append(sampler_tmp1)
-
- def get_exist_statistic_record(self):
- """get exist netstream statistic record parameter"""
-
- if self.statistics_record and self.statistics_direction:
- self.module.fail_json(
- msg='Error: The statistic direction and record can not exist at the same time.')
- statistic_tmp = dict()
- statistic_tmp1 = dict()
- statistic_tmp["statistics_record"] = list()
- statistic_tmp["interface"] = self.interface
- statistic_tmp1["statistics_record"] = list()
- statistic_tmp1["interface"] = self.interface
- flags = list()
- exp = r" | ignore-case section include ^#\s+interface %s" \
- r" | include netstream record"\
- % (self.interface)
- flags.append(exp)
- config = get_config(self.module, flags)
- if not config:
- statistic_tmp["type"] = "ip"
- self.existing["flexible_statistic"].append(statistic_tmp)
- statistic_tmp1["type"] = "vxlan"
- self.existing["flexible_statistic"].append(statistic_tmp1)
- else:
- config = config.lstrip()
- config_list = config.split('\n')
- for config_mem in config_list:
- config_mem = config_mem.lstrip()
- statistic_tmp["statistics_record"] = list()
- config_mem_list = config_mem.split(' ')
- if len(config_mem_list) > 3 and str(config_mem_list[3]) == "ip":
- statistic_tmp["statistics_record"].append(
- str(config_mem_list[2]))
- statistic_tmp["type"] = "ip"
- self.existing["flexible_statistic"].append(statistic_tmp)
- for config_mem in config_list:
- statistic_tmp1["statistics_record"] = list()
- config_mem = config_mem.lstrip()
- config_mem_list = config_mem.split(' ')
- if len(config_mem_list) > 3 and str(config_mem_list[3]) == "vxlan":
- statistic_tmp1["statistics_record"].append(
- str(config_mem_list[2]))
- statistic_tmp1["type"] = "vxlan"
- self.existing["flexible_statistic"].append(statistic_tmp1)
-
- def get_exist_interface_statistic(self):
- """get exist netstream interface statistic parameter"""
-
- statistic_tmp1 = dict()
- statistic_tmp1["statistics_direction"] = list()
- flags = list()
- exp = r" | ignore-case section include ^#\s+interface %s" \
- r" | include netstream inbound|outbound"\
- % self.interface
- flags.append(exp)
- config = get_config(self.module, flags)
- if not config:
- statistic_tmp1["type"] = "null"
- else:
- statistic_tmp1["type"] = "ip"
- config = config.lstrip()
- config_list = config.split('\n')
- for config_mem in config_list:
- config_mem = config_mem.lstrip()
- config_mem_list = config_mem.split(' ')
- if len(config_mem_list) > 1:
- statistic_tmp1["statistics_direction"].append(
- str(config_mem_list[1]))
- statistic_tmp1["interface"] = self.interface
- self.existing["statistic"].append(statistic_tmp1)
-
- def get_exist_index_switch(self):
- """get exist netstream index-switch"""
-
- index_switch_tmp = dict()
- index_switch_tmp1 = dict()
- index_switch_tmp["index-switch"] = "16"
- index_switch_tmp["type"] = "ip"
- index_switch_tmp1["index-switch"] = "16"
- index_switch_tmp1["type"] = "vxlan"
- flags = list()
- exp = " | ignore-case include index-switch"
- flags.append(exp)
- config = get_config(self.module, flags)
- if not config:
- self.existing["index-switch"].append(index_switch_tmp)
- self.existing["index-switch"].append(index_switch_tmp1)
- else:
- config = config.lstrip()
- config_list = config.split('\n')
- for config_mem in config_list:
- config_mem_list = config_mem.split(' ')
- if len(config_mem_list) > 2 and str(config_mem_list[2]) == "ip":
- index_switch_tmp["index-switch"] = "32"
- index_switch_tmp["type"] = "ip"
- if len(config_mem_list) > 2 and str(config_mem_list[2]) == "vxlan":
- index_switch_tmp1["index-switch"] = "32"
- index_switch_tmp1["type"] = "vxlan"
- self.existing["index-switch"].append(index_switch_tmp)
- self.existing["index-switch"].append(index_switch_tmp1)
-
- def get_exist_record(self):
- """get exist netstream record"""
-
- flags = list()
- exp = " | ignore-case include netstream record"
- flags.append(exp)
- config = get_config(self.module, flags)
- if config:
- config = config.lstrip()
- config_list = config.split('\n')
- for config_mem in config_list:
- config_mem_list = config_mem.split(' ')
- if len(config_mem_list) > 3 and config_mem_list[3] == "ip":
- self.existing["ip_record"].append(config_mem_list[2])
- if len(config_mem_list) > 3 and config_mem_list[3] == "vxlan":
- self.existing["vxlan_record"].append(config_mem_list[2])
-
- def get_end_sampler_interval(self):
- """get end netstream sampler interval"""
-
- sampler_tmp = dict()
- sampler_tmp1 = dict()
- flags = list()
- exp = " | ignore-case include ^netstream sampler random-packets"
- flags.append(exp)
- config = get_config(self.module, flags)
- if not config:
- sampler_tmp["sampler_interval"] = "null"
- sampler_tmp["sampler_direction"] = "null"
- else:
- config_list = config.split(' ')
- config_num = len(config_list)
- if config_num > 1:
- sampler_tmp["sampler_direction"] = config_list[config_num - 1]
- sampler_tmp["sampler_interval"] = config_list[config_num - 2]
- sampler_tmp["interface"] = "all"
- self.end_state["sampler"].append(sampler_tmp)
- if self.interface != "all":
- flags = list()
- exp = r" | ignore-case section include ^#\s+interface %s" \
- r" | include netstream sampler random-packets" % self.interface
- flags.append(exp)
- config = get_config(self.module, flags)
- if not config:
- sampler_tmp1["sampler_interval"] = "null"
- sampler_tmp1["sampler_direction"] = "null"
- else:
- config = config.lstrip()
- config_list = config.split('\n')
- for config_mem in config_list:
- sampler_tmp1 = dict()
- config_mem_list = config_mem.split(' ')
- config_num = len(config_mem_list)
- if config_num > 1:
- sampler_tmp1["sampler_direction"] = config_mem_list[
- config_num - 1]
- sampler_tmp1["sampler_interval"] = config_mem_list[
- config_num - 2]
- sampler_tmp1["interface"] = self.interface
- self.end_state["sampler"].append(sampler_tmp1)
-
- def get_end_statistic_record(self):
- """get end netstream statistic record parameter"""
-
- if self.statistics_record and self.statistics_direction:
- self.module.fail_json(
- msg='Error: The statistic direction and record can not exist at the same time.')
- statistic_tmp = dict()
- statistic_tmp1 = dict()
- statistic_tmp["statistics_record"] = list()
- statistic_tmp["interface"] = self.interface
- statistic_tmp1["statistics_record"] = list()
- statistic_tmp1["interface"] = self.interface
- flags = list()
- exp = r" | ignore-case section include ^#\s+interface %s" \
- r" | include netstream record"\
- % (self.interface)
- flags.append(exp)
- config = get_config(self.module, flags)
- if not config:
- statistic_tmp["type"] = "ip"
- self.end_state["flexible_statistic"].append(statistic_tmp)
- statistic_tmp1["type"] = "vxlan"
- self.end_state["flexible_statistic"].append(statistic_tmp1)
- else:
- config = config.lstrip()
- config_list = config.split('\n')
- for config_mem in config_list:
- config_mem = config_mem.lstrip()
- statistic_tmp["statistics_record"] = list()
- config_mem_list = config_mem.split(' ')
- if len(config_mem_list) > 3 and str(config_mem_list[3]) == "ip":
- statistic_tmp["statistics_record"].append(
- str(config_mem_list[2]))
- statistic_tmp["type"] = "ip"
- self.end_state["flexible_statistic"].append(statistic_tmp)
- for config_mem in config_list:
- statistic_tmp1["statistics_record"] = list()
- config_mem = config_mem.lstrip()
- config_mem_list = config_mem.split(' ')
- if len(config_mem_list) > 3 and str(config_mem_list[3]) == "vxlan":
- statistic_tmp1["statistics_record"].append(
- str(config_mem_list[2]))
- statistic_tmp1["type"] = "vxlan"
- self.end_state["flexible_statistic"].append(statistic_tmp1)
-
- def get_end_interface_statistic(self):
- """get end netstream interface statistic parameters"""
-
- statistic_tmp1 = dict()
- statistic_tmp1["statistics_direction"] = list()
- flags = list()
- exp = r" | ignore-case section include ^#\s+interface %s" \
- r" | include netstream inbound|outbound"\
- % self.interface
- flags.append(exp)
- config = get_config(self.module, flags)
- if not config:
- statistic_tmp1["type"] = "null"
- else:
- statistic_tmp1["type"] = "ip"
- config = config.lstrip()
- config_list = config.split('\n')
- for config_mem in config_list:
- config_mem = config_mem.lstrip()
- config_mem_list = config_mem.split(' ')
- if len(config_mem_list) > 1:
- statistic_tmp1["statistics_direction"].append(
- str(config_mem_list[1]))
- statistic_tmp1["interface"] = self.interface
- self.end_state["statistic"].append(statistic_tmp1)
-
- def get_end_index_switch(self):
- """get end netstream index switch"""
-
- index_switch_tmp = dict()
- index_switch_tmp1 = dict()
- index_switch_tmp["index-switch"] = "16"
- index_switch_tmp["type"] = "ip"
- index_switch_tmp1["index-switch"] = "16"
- index_switch_tmp1["type"] = "vxlan"
- flags = list()
- exp = " | ignore-case include index-switch"
- flags.append(exp)
- config = get_config(self.module, flags)
- if not config:
- self.end_state["index-switch"].append(index_switch_tmp)
- self.end_state["index-switch"].append(index_switch_tmp1)
- else:
- config = config.lstrip()
- config_list = config.split('\n')
- for config_mem in config_list:
- config_mem_list = config_mem.split(' ')
- if len(config_mem_list) > 2 and str(config_mem_list[2]) == "ip":
- index_switch_tmp["index-switch"] = "32"
- index_switch_tmp["type"] = "ip"
- if len(config_mem_list) > 2 and str(config_mem_list[2]) == "vxlan":
- index_switch_tmp1["index-switch"] = "32"
- index_switch_tmp1["type"] = "vxlan"
- self.end_state["index-switch"].append(index_switch_tmp)
- self.end_state["index-switch"].append(index_switch_tmp1)
-
- def check_params(self):
- """check all input params"""
-
- # netstream parameters check
- if not get_interface_type(self.interface):
- self.module.fail_json(
- msg='Error: Interface name of %s is error.' % self.interface)
- if self.sampler_interval:
- if not str(self.sampler_interval).isdigit():
- self.module.fail_json(
- msg='Error: Active interval should be numerical.')
- if int(self.sampler_interval) < 1 or int(self.sampler_interval) > 65535:
- self.module.fail_json(
- msg="Error: Sampler interval should between 1 - 65535.")
- if self.statistics_record:
- if len(self.statistics_record) < 1 or len(self.statistics_record) > 32:
- self.module.fail_json(
- msg="Error: Statistic record length should between 1 - 32.")
- if self.interface == "all":
- if self.statistics_record or self.statistics_direction:
- self.module.fail_json(
- msg="Error: Statistic function should be used at interface.")
- if self.statistics_direction:
- if self.type == "vxlan":
- self.module.fail_json(
- msg="Error: Vxlan do not support inbound or outbound statistic.")
- if (self.sampler_interval and not self.sampler_direction) \
- or (self.sampler_direction and not self.sampler_interval):
- self.module.fail_json(
- msg="Error: Sampler interval and direction must be set at the same time.")
-
- if self.statistics_record and not self.type:
- self.module.fail_json(
- msg="Error: Statistic type and record must be set at the same time.")
-
- self.get_exist_record()
- if self.statistics_record:
- if self.type == "ip":
- if self.statistics_record not in self.existing["ip_record"]:
- self.module.fail_json(
- msg="Error: The statistic record is not exist.")
- if self.type == "vxlan":
- if self.statistics_record not in self.existing["vxlan_record"]:
- self.module.fail_json(
- msg="Error: The statistic record is not exist.")
-
- def get_proposed(self):
- """get proposed info"""
-
- if self.type:
- self.proposed["type"] = self.type
- if self.interface:
- self.proposed["interface"] = self.interface
- if self.sampler_interval:
- self.proposed["sampler_interval"] = self.sampler_interval
- if self.sampler_direction:
- self.proposed["sampler_direction"] = self.sampler_direction
- if self.statistics_direction:
- self.proposed["statistics_direction"] = self.statistics_direction
- if self.statistics_record:
- self.proposed["statistics_record"] = self.statistics_record
- if self.index_switch:
- self.proposed["index_switch"] = self.index_switch
- if self.state:
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
- sampler_tmp = dict()
- statistic_tmp = dict()
- statistic_tmp1 = dict()
- index_tmp = dict()
- temp = False
-
- self.get_exist_sampler_interval()
- self.get_exist_interface_statistic()
- self.get_exist_statistic_record()
- self.get_exist_index_switch()
-
- if self.state == "present":
- for sampler_tmp in self.existing["sampler"]:
- if self.interface == str(sampler_tmp["interface"]):
- temp = True
- if (self.sampler_interval and str(sampler_tmp["sampler_interval"]) != self.sampler_interval) \
- or (self.sampler_direction and
- str(sampler_tmp["sampler_direction"]) != self.sampler_direction):
- self.sampler_changed = True
- if not temp:
- if self.sampler_direction or self.sampler_interval:
- self.sampler_changed = True
- for statistic_tmp in self.existing["statistic"]:
- if str(statistic_tmp["interface"]) == self.interface and self.interface != "all":
- if self.type == "vxlan":
- if statistic_tmp["statistics_direction"] \
- and 'outbound' in statistic_tmp["statistics_direction"]:
- self.module.fail_json(
- msg='Error: The NetStream record vxlan '
- 'cannot be configured because the port has been configured NetStream outbound ip.')
- if statistic_tmp["statistics_direction"] and self.statistics_direction:
- if self.statistics_direction not in statistic_tmp["statistics_direction"]:
- self.statistic_changed = True
- else:
- if self.statistics_direction:
- self.statistic_changed = True
- for statistic_tmp1 in self.existing["flexible_statistic"]:
- if self.interface != "all" \
- and self.type == str(statistic_tmp1["type"]) \
- and self.interface == str(statistic_tmp1["interface"]):
- if statistic_tmp1["statistics_record"] and self.statistics_record:
- if self.statistics_record not in statistic_tmp1["statistics_record"]:
- self.flexible_changed = True
- else:
- if self.statistics_record:
- self.flexible_changed = True
- for index_tmp in self.existing["index-switch"]:
- if self.type == str(index_tmp["type"]):
- if self.index_switch != str(index_tmp["index-switch"]):
- self.index_switch_changed = True
- else:
- for sampler_tmp in self.existing["sampler"]:
- if self.interface == str(sampler_tmp["interface"]):
- if (self.sampler_interval and str(sampler_tmp["sampler_interval"]) == self.sampler_interval) \
- and (self.sampler_direction and str(sampler_tmp["sampler_direction"]) == self.sampler_direction):
- self.sampler_changed = True
- for statistic_tmp in self.existing["statistic"]:
- if str(statistic_tmp["interface"]) == self.interface and self.interface != "all":
- if len(statistic_tmp["statistics_direction"]) and self.statistics_direction:
- if self.statistics_direction in statistic_tmp["statistics_direction"]:
- self.statistic_changed = True
- for statistic_tmp1 in self.existing["flexible_statistic"]:
- if self.interface != "all" \
- and self.type == str(statistic_tmp1["type"]) \
- and self.interface == str(statistic_tmp1["interface"]):
- if len(statistic_tmp1["statistics_record"]) and self.statistics_record:
- if self.statistics_record in statistic_tmp1["statistics_record"]:
- self.flexible_changed = True
- for index_tmp in self.existing["index-switch"]:
- if self.type == str(index_tmp["type"]):
- if self.index_switch == str(index_tmp["index-switch"]):
- if self.index_switch != "16":
- self.index_switch_changed = True
-
- def operate_ns_gloabl(self):
- """configure netstream global parameters"""
-
- cmd = ""
- if not self.sampler_changed and not self.statistic_changed \
- and not self.flexible_changed and not self.index_switch_changed:
- self.changed = False
- return
-
- if self.sampler_changed is True:
- if self.type == "vxlan":
- self.module.fail_json(
- msg="Error: Netstream do not support vxlan sampler.")
- if self.interface != "all":
- cmd = "interface %s" % self.interface
- self.cli_add_command(cmd)
- cmd = "netstream sampler random-packets %s %s" % (
- self.sampler_interval, self.sampler_direction)
- if self.state == "present":
- self.cli_add_command(cmd)
- else:
- self.cli_add_command(cmd, undo=True)
- if self.interface != "all":
- cmd = "quit"
- self.cli_add_command(cmd)
- if self.statistic_changed is True:
- if self.interface != "all":
- cmd = "interface %s" % self.interface
- self.cli_add_command(cmd)
- cmd = "netstream %s ip" % self.statistics_direction
- if self.state == "present":
- self.cli_add_command(cmd)
- else:
- self.cli_add_command(cmd, undo=True)
- if self.interface != "all":
- cmd = "quit"
- self.cli_add_command(cmd)
- if self.flexible_changed is True:
- if self.interface != "all":
- cmd = "interface %s" % self.interface
- self.cli_add_command(cmd)
- if self.state == "present":
- for statistic_tmp in self.existing["flexible_statistic"]:
- tmp_list = statistic_tmp["statistics_record"]
- if self.type == statistic_tmp["type"]:
- if self.type == "ip":
- if len(tmp_list) > 0:
- cmd = "netstream record %s ip" % tmp_list[0]
- self.cli_add_command(cmd, undo=True)
- cmd = "netstream record %s ip" % self.statistics_record
- self.cli_add_command(cmd)
- if self.type == "vxlan":
- if len(tmp_list) > 0:
- cmd = "netstream record %s vxlan inner-ip" % tmp_list[
- 0]
- self.cli_add_command(cmd, undo=True)
- cmd = "netstream record %s vxlan inner-ip" % self.statistics_record
- self.cli_add_command(cmd)
- else:
- if self.type == "ip":
- cmd = "netstream record %s ip" % self.statistics_record
- self.cli_add_command(cmd, undo=True)
- if self.type == "vxlan":
- cmd = "netstream record %s vxlan inner-ip" % self.statistics_record
- self.cli_add_command(cmd, undo=True)
- if self.interface != "all":
- cmd = "quit"
- self.cli_add_command(cmd)
- if self.index_switch_changed is True:
- if self.interface != "all":
- self.module.fail_json(
- msg="Error: Index-switch function should be used globally.")
- if self.type == "ip":
- cmd = "netstream export ip index-switch %s" % self.index_switch
- else:
- cmd = "netstream export vxlan inner-ip index-switch %s" % self.index_switch
- if self.state == "present":
- self.cli_add_command(cmd)
- else:
- self.cli_add_command(cmd, undo=True)
-
- if self.commands:
- self.cli_load_config(self.commands)
- self.changed = True
-
- def get_end_state(self):
- """get end state info"""
-
- self.get_end_sampler_interval()
- self.get_end_interface_statistic()
- self.get_end_statistic_record()
- self.get_end_index_switch()
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.get_existing()
- self.get_proposed()
- self.operate_ns_gloabl()
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- type=dict(required=False, choices=['ip', 'vxlan'], default='ip'),
- interface=dict(required=True, type='str'),
- sampler_interval=dict(required=False, type='str'),
- sampler_direction=dict(required=False, choices=['inbound', 'outbound']),
- statistics_direction=dict(required=False, choices=['inbound', 'outbound']),
- statistics_record=dict(required=False, type='str'),
- index_switch=dict(required=False, choices=['16', '32'], default='16'),
- state=dict(required=False, choices=['present', 'absent'], default='present'),
- )
- argument_spec.update(ce_argument_spec)
- module = NetStreamGlobal(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_netstream_template.py b/plugins/modules/network/cloudengine/ce_netstream_template.py
deleted file mode 100644
index 5ea943fa6e..0000000000
--- a/plugins/modules/network/cloudengine/ce_netstream_template.py
+++ /dev/null
@@ -1,498 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_netstream_template
-short_description: Manages NetStream template configuration on HUAWEI CloudEngine switches.
-description:
- - Manages NetStream template configuration on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- state:
- description:
- - Specify desired state of the resource.
- default: present
- choices: ['present', 'absent']
- type:
- description:
- - Configure the type of netstream record.
- required: true
- choices: ['ip', 'vxlan']
- record_name:
- description:
- - Configure the name of netstream record.
- The value is a string of 1 to 32 case-insensitive characters.
- match:
- description:
- - Configure flexible flow statistics template keywords.
- choices: ['destination-address', 'destination-port', 'tos', 'protocol', 'source-address', 'source-port']
- collect_counter:
- description:
- - Configure the number of packets and bytes that are included in the flexible flow statistics sent to NSC.
- choices: ['bytes', 'packets']
- collect_interface:
- description:
- - Configure the input or output interface that are included in the flexible flow statistics sent to NSC.
- choices: ['input', 'output']
- description:
- description:
- - Configure the description of netstream record.
- The value is a string of 1 to 80 case-insensitive characters.
-'''
-
-EXAMPLES = '''
-- name: netstream template module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Config ipv4 netstream record
- ce_netstream_template:
- state: present
- type: ip
- record_name: test
- provider: "{{ cli }}"
- - name: Undo ipv4 netstream record
- ce_netstream_template:
- state: absent
- type: ip
- record_name: test
- provider: "{{ cli }}"
- - name: Config ipv4 netstream record collect_counter
- ce_netstream_template:
- state: present
- type: ip
- record_name: test
- collect_counter: bytes
- provider: "{{ cli }}"
- - name: Undo ipv4 netstream record collect_counter
- ce_netstream_template:
- state: absent
- type: ip
- record_name: test
- collect_counter: bytes
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"record_name": "test",
- "type": "ip",
- "state": "present"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"record_name": "test",
- "type": "ip"}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["netstream record test ip"]
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import load_config
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_connection, rm_config_prefix
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec
-
-
-def get_config(module, flags):
-
- """Retrieves the current config from the device or cache
- """
- flags = [] if flags is None else flags
- if isinstance(flags, str):
- flags = [flags]
- elif not isinstance(flags, list):
- flags = []
-
- cmd = 'display current-configuration '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
- conn = get_connection(module)
- rc, out, err = conn.exec_command(cmd)
- if rc != 0:
- module.fail_json(msg=err)
- cfg = str(out).strip()
- # remove default configuration prefix '~'
- for flag in flags:
- if "include-default" in flag:
- cfg = rm_config_prefix(cfg)
- break
- if cfg.startswith('display'):
- lines = cfg.split('\n')
- if len(lines) > 1:
- return '\n'.join(lines[1:])
- else:
- return ''
- return cfg
-
-
-class NetstreamTemplate(object):
- """ Manages netstream template configuration """
-
- def __init__(self, **kwargs):
- """ Netstream template module init """
-
- # module
- argument_spec = kwargs["argument_spec"]
- self.spec = argument_spec
- self.module = AnsibleModule(argument_spec=self.spec, supports_check_mode=True)
-
- # netstream config
- self.netstream_cfg = None
-
- # module args
- self.state = self.module.params['state'] or None
- self.type = self.module.params['type'] or None
- self.record_name = self.module.params['record_name'] or None
- self.match = self.module.params['match'] or None
- self.collect_counter = self.module.params['collect_counter'] or None
- self.collect_interface = self.module.params['collect_interface'] or None
- self.description = self.module.params['description'] or None
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def cli_load_config(self, commands):
- """ Cli load configuration """
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def cli_get_netstream_config(self):
- """ Cli get netstream configuration """
-
- if self.type == "ip":
- cmd = "netstream record %s ip" % self.record_name
- else:
- cmd = "netstream record %s vxlan inner-ip" % self.record_name
- flags = list()
- regular = "| section include %s" % cmd
- flags.append(regular)
- self.netstream_cfg = get_config(self.module, flags)
-
- def check_args(self):
- """ Check module args """
-
- if not self.type or not self.record_name:
- self.module.fail_json(
- msg='Error: Please input type and record_name.')
-
- if self.record_name:
- if len(self.record_name) < 1 or len(self.record_name) > 32:
- self.module.fail_json(
- msg='Error: The len of record_name is out of [1 - 32].')
-
- if self.description:
- if len(self.description) < 1 or len(self.description) > 80:
- self.module.fail_json(
- msg='Error: The len of description is out of [1 - 80].')
-
- def get_proposed(self):
- """ Get module proposed """
-
- self.proposed["state"] = self.state
-
- if self.type:
- self.proposed["type"] = self.type
- if self.record_name:
- self.proposed["record_name"] = self.record_name
- if self.match:
- self.proposed["match"] = self.match
- if self.collect_counter:
- self.proposed["collect_counter"] = self.collect_counter
- if self.collect_interface:
- self.proposed["collect_interface"] = self.collect_interface
- if self.description:
- self.proposed["description"] = self.description
-
- def get_existing(self):
- """ Get existing configuration """
-
- self.cli_get_netstream_config()
-
- if self.netstream_cfg is not None and "netstream record" in self.netstream_cfg:
- self.existing["type"] = self.type
- self.existing["record_name"] = self.record_name
-
- if self.description:
- tmp_value = re.findall(r'description (.*)', self.netstream_cfg)
- if tmp_value is not None and len(tmp_value) > 0:
- self.existing["description"] = tmp_value[0]
-
- if self.match:
- if self.type == "ip":
- tmp_value = re.findall(r'match ip (.*)', self.netstream_cfg)
- else:
- tmp_value = re.findall(r'match inner-ip (.*)', self.netstream_cfg)
-
- if tmp_value:
- self.existing["match"] = tmp_value
-
- if self.collect_counter:
- tmp_value = re.findall(r'collect counter (.*)', self.netstream_cfg)
- if tmp_value:
- self.existing["collect_counter"] = tmp_value
-
- if self.collect_interface:
- tmp_value = re.findall(r'collect interface (.*)', self.netstream_cfg)
- if tmp_value:
- self.existing["collect_interface"] = tmp_value
-
- def get_end_state(self):
- """ Get end state """
-
- self.cli_get_netstream_config()
-
- if self.netstream_cfg is not None and "netstream record" in self.netstream_cfg:
- self.end_state["type"] = self.type
- self.end_state["record_name"] = self.record_name
-
- if self.description:
- tmp_value = re.findall(r'description (.*)', self.netstream_cfg)
- if tmp_value is not None and len(tmp_value) > 0:
- self.end_state["description"] = tmp_value[0]
-
- if self.match:
- if self.type == "ip":
- tmp_value = re.findall(r'match ip (.*)', self.netstream_cfg)
- else:
- tmp_value = re.findall(r'match inner-ip (.*)', self.netstream_cfg)
-
- if tmp_value:
- self.end_state["match"] = tmp_value
-
- if self.collect_counter:
- tmp_value = re.findall(r'collect counter (.*)', self.netstream_cfg)
- if tmp_value:
- self.end_state["collect_counter"] = tmp_value
-
- if self.collect_interface:
- tmp_value = re.findall(r'collect interface (.*)', self.netstream_cfg)
- if tmp_value:
- self.end_state["collect_interface"] = tmp_value
- if self.end_state == self.existing:
- self.changed = False
- self.updates_cmd = list()
-
- def present_netstream(self):
- """ Present netstream configuration """
-
- cmds = list()
- need_create_record = False
-
- if self.type == "ip":
- cmd = "netstream record %s ip" % self.record_name
- else:
- cmd = "netstream record %s vxlan inner-ip" % self.record_name
- cmds.append(cmd)
-
- if self.existing.get('record_name') != self.record_name:
- self.updates_cmd.append(cmd)
- need_create_record = True
-
- if self.description:
- cmd = "description %s" % self.description.strip()
- if need_create_record or not self.netstream_cfg or cmd not in self.netstream_cfg:
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.match:
- if self.type == "ip":
- cmd = "match ip %s" % self.match
- cfg = "match ip"
- else:
- cmd = "match inner-ip %s" % self.match
- cfg = "match inner-ip"
-
- if need_create_record or cfg not in self.netstream_cfg or self.match != self.existing["match"][0]:
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.collect_counter:
- cmd = "collect counter %s" % self.collect_counter
- if need_create_record or cmd not in self.netstream_cfg:
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.collect_interface:
- cmd = "collect interface %s" % self.collect_interface
- if need_create_record or cmd not in self.netstream_cfg:
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if cmds:
- self.cli_load_config(cmds)
- self.changed = True
-
- def absent_netstream(self):
- """ Absent netstream configuration """
-
- cmds = list()
- absent_netstream_attr = False
-
- if not self.netstream_cfg:
- return
-
- if self.description or self.match or self.collect_counter or self.collect_interface:
- absent_netstream_attr = True
-
- if absent_netstream_attr:
- if self.type == "ip":
- cmd = "netstream record %s ip" % self.record_name
- else:
- cmd = "netstream record %s vxlan inner-ip" % self.record_name
-
- cmds.append(cmd)
-
- if self.description:
- cfg = "description %s" % self.description
- if self.netstream_cfg and cfg in self.netstream_cfg:
- cmd = "undo description %s" % self.description
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.match:
- if self.type == "ip":
- cfg = "match ip %s" % self.match
- else:
- cfg = "match inner-ip %s" % self.match
- if self.netstream_cfg and cfg in self.netstream_cfg:
- if self.type == "ip":
- cmd = "undo match ip %s" % self.match
- else:
- cmd = "undo match inner-ip %s" % self.match
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.collect_counter:
- cfg = "collect counter %s" % self.collect_counter
- if self.netstream_cfg and cfg in self.netstream_cfg:
- cmd = "undo collect counter %s" % self.collect_counter
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.collect_interface:
- cfg = "collect interface %s" % self.collect_interface
- if self.netstream_cfg and cfg in self.netstream_cfg:
- cmd = "undo collect interface %s" % self.collect_interface
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if len(cmds) > 1:
- self.cli_load_config(cmds)
- self.changed = True
-
- else:
- if self.type == "ip":
- cmd = "undo netstream record %s ip" % self.record_name
- else:
- cmd = "undo netstream record %s vxlan inner-ip" % self.record_name
-
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- self.cli_load_config(cmds)
- self.changed = True
-
- def work(self):
- """ Work function """
-
- self.check_args()
- self.get_proposed()
- self.get_existing()
-
- if self.state == "present":
- self.present_netstream()
- else:
- self.absent_netstream()
-
- self.get_end_state()
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- self.results['updates'] = self.updates_cmd
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- type=dict(choices=['ip', 'vxlan'], required=True),
- record_name=dict(type='str'),
- match=dict(choices=['destination-address', 'destination-port',
- 'tos', 'protocol', 'source-address', 'source-port']),
- collect_counter=dict(choices=['bytes', 'packets']),
- collect_interface=dict(choices=['input', 'output']),
- description=dict(type='str')
- )
- argument_spec.update(ce_argument_spec)
- module = NetstreamTemplate(argument_spec=argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_ntp.py b/plugins/modules/network/cloudengine/ce_ntp.py
deleted file mode 100644
index bc4a5a966c..0000000000
--- a/plugins/modules/network/cloudengine/ce_ntp.py
+++ /dev/null
@@ -1,619 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_ntp
-short_description: Manages core NTP configuration on HUAWEI CloudEngine switches.
-description:
- - Manages core NTP configuration on HUAWEI CloudEngine switches.
-author:
- - Zhijin Zhou (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- server:
- description:
- - Network address of NTP server.
- peer:
- description:
- - Network address of NTP peer.
- key_id:
- description:
- - Authentication key identifier to use with given NTP server or peer.
- is_preferred:
- description:
- - Makes given NTP server or peer the preferred NTP server or peer for the device.
- choices: ['enable', 'disable']
- vpn_name:
- description:
- - Makes the device communicate with the given
- NTP server or peer over a specific vpn.
- default: '_public_'
- source_int:
- description:
- - Local source interface from which NTP messages are sent.
- Must be fully qualified interface name, i.e. C(40GE1/0/22), C(vlanif10).
- Interface types, such as C(10GE), C(40GE), C(100GE), C(Eth-Trunk), C(LoopBack),
- C(MEth), C(NULL), C(Tunnel), C(Vlanif).
- state:
- description:
- - Manage the state of the resource.
- default: present
- choices: ['present','absent']
-'''
-
-EXAMPLES = '''
-- name: NTP test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Set NTP Server with parameters"
- ce_ntp:
- server: 192.8.2.6
- vpn_name: js
- source_int: vlanif4001
- is_preferred: enable
- key_id: 32
- provider: "{{ cli }}"
-
- - name: "Set NTP Peer with parameters"
- ce_ntp:
- peer: 192.8.2.6
- vpn_name: js
- source_int: vlanif4001
- is_preferred: enable
- key_id: 32
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"server": "2.2.2.2", "key_id": "48",
- "is_preferred": "enable", "vpn_name":"js",
- "source_int": "vlanif4002", "state":"present"}
-existing:
- description: k/v pairs of existing ntp server/peer
- returned: always
- type: dict
- sample: {"server": "2.2.2.2", "key_id": "32",
- "is_preferred": "disable", "vpn_name":"js",
- "source_int": "vlanif4002"}
-end_state:
- description: k/v pairs of ntp info after module execution
- returned: always
- type: dict
- sample: {"server": "2.2.2.2", "key_id": "48",
- "is_preferred": "enable", "vpn_name":"js",
- "source_int": "vlanif4002"}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["ntp server 2.2.2.2 authentication-keyid 48 source-interface vlanif4002 vpn-instance js preferred"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import re
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec, get_nc_config, set_nc_config
-
-CE_NC_GET_NTP_CONFIG = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_NTP_CONFIG = """
-
-
-
-
- %s
- %s
- %s
- %s
- %s
- %s
- %s
- %s
- 0-0
-
-
-
-
-"""
-
-CE_NC_DELETE_NTP_CONFIG = """
-
-
-
-
- %s
- %s
- %s
- %s
- %s
- 0-0
-
-
-
-
-"""
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- iftype = None
-
- if interface.upper().startswith('GE'):
- iftype = 'ge'
- elif interface.upper().startswith('10GE'):
- iftype = '10ge'
- elif interface.upper().startswith('25GE'):
- iftype = '25ge'
- elif interface.upper().startswith('4X10GE'):
- iftype = '4x10ge'
- elif interface.upper().startswith('40GE'):
- iftype = '40ge'
- elif interface.upper().startswith('100GE'):
- iftype = '100ge'
- elif interface.upper().startswith('VLANIF'):
- iftype = 'vlanif'
- elif interface.upper().startswith('LOOPBACK'):
- iftype = 'loopback'
- elif interface.upper().startswith('METH'):
- iftype = 'meth'
- elif interface.upper().startswith('ETH-TRUNK'):
- iftype = 'eth-trunk'
- elif interface.upper().startswith('VBDIF'):
- iftype = 'vbdif'
- elif interface.upper().startswith('NVE'):
- iftype = 'nve'
- elif interface.upper().startswith('TUNNEL'):
- iftype = 'tunnel'
- elif interface.upper().startswith('ETHERNET'):
- iftype = 'ethernet'
- elif interface.upper().startswith('FCOE-PORT'):
- iftype = 'fcoe-port'
- elif interface.upper().startswith('FABRIC-PORT'):
- iftype = 'fabric-port'
- elif interface.upper().startswith('STACK-PORT'):
- iftype = 'stack-Port'
- elif interface.upper().startswith('NULL'):
- iftype = 'null'
- else:
- return None
-
- return iftype.lower()
-
-
-class Ntp(object):
- """Ntp class"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.mutually_exclusive = [('server', 'peer')]
- self.init_module()
-
- # ntp configuration info
- self.server = self.module.params['server'] or None
- self.peer = self.module.params['peer'] or None
- self.key_id = self.module.params['key_id']
- self.is_preferred = self.module.params['is_preferred']
- self.vpn_name = self.module.params['vpn_name']
- self.interface = self.module.params['source_int'] or ""
- self.state = self.module.params['state']
- self.ntp_conf = dict()
- self.conf_exsit = False
- self.ip_ver = 'IPv4'
-
- if self.server:
- self.peer_type = 'Server'
- self.address = self.server
- elif self.peer:
- self.peer_type = 'Peer'
- self.address = self.peer
- else:
- self.peer_type = None
- self.address = None
-
- self.check_params()
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = list()
- self.end_state = list()
-
- self.init_data()
-
- def init_data(self):
- """Init data"""
-
- if self.interface is not None:
- self.interface = self.interface.lower()
-
- if not self.key_id:
- self.key_id = ""
-
- if not self.is_preferred:
- self.is_preferred = 'disable'
-
- def init_module(self):
- """Init module"""
-
- required_one_of = [("server", "peer")]
- self.module = AnsibleModule(
- argument_spec=self.spec,
- supports_check_mode=True,
- required_one_of=required_one_of,
- mutually_exclusive=self.mutually_exclusive
- )
-
- def check_ipaddr_validate(self):
- """Check ipaddress validate"""
-
- rule1 = r'(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.'
- rule2 = r'(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])'
- ipv4_regex = '%s%s%s%s%s%s' % ('^', rule1, rule1, rule1, rule2, '$')
- ipv6_regex = '^(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4}$'
-
- flag = False
- if bool(re.match(ipv4_regex, self.address)):
- flag = True
- self.ip_ver = "IPv4"
- if not self.ntp_ucast_ipv4_validate():
- flag = False
- elif bool(re.match(ipv6_regex, self.address)):
- flag = True
- self.ip_ver = "IPv6"
- else:
- flag = True
- self.ip_ver = "IPv6"
-
- if not flag:
- if self.peer_type == "Server":
- self.module.fail_json(msg='Error: Illegal server ip-address.')
- else:
- self.module.fail_json(msg='Error: Illegal peer ip-address.')
-
- def ntp_ucast_ipv4_validate(self):
- """Check ntp ucast ipv4 address"""
-
- addr_list = re.findall(r'(.*)\.(.*)\.(.*)\.(.*)', self.address)
- if not addr_list:
- self.module.fail_json(msg='Error: Match ip-address fail.')
-
- value = ((int(addr_list[0][0])) * 0x1000000) + (int(addr_list[0][1]) * 0x10000) + \
- (int(addr_list[0][2]) * 0x100) + (int(addr_list[0][3]))
- if (value & (0xff000000) == 0x7f000000) or (value & (0xF0000000) == 0xF0000000) \
- or (value & (0xF0000000) == 0xE0000000) or (value == 0):
- return False
- return True
-
- def check_params(self):
- """Check all input params"""
-
- # check interface type
- if self.interface:
- intf_type = get_interface_type(self.interface)
- if not intf_type:
- self.module.fail_json(
- msg='Error: Interface name of %s '
- 'is error.' % self.interface)
-
- if self.vpn_name:
- if (len(self.vpn_name) < 1) or (len(self.vpn_name) > 31):
- self.module.fail_json(
- msg='Error: VPN name length is between 1 and 31.')
-
- if self.address:
- self.check_ipaddr_validate()
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def set_ntp(self, *args):
- """Configure ntp parameters"""
-
- if self.state == 'present':
- if self.ip_ver == 'IPv4':
- xml_str = CE_NC_MERGE_NTP_CONFIG % (
- args[0], args[1], '::', args[2], args[3], args[4], args[5], args[6])
- elif self.ip_ver == 'IPv6':
- xml_str = CE_NC_MERGE_NTP_CONFIG % (
- args[0], '0.0.0.0', args[1], args[2], args[3], args[4], args[5], args[6])
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "NTP_CORE_CONFIG")
- else:
- if self.ip_ver == 'IPv4':
- xml_str = CE_NC_DELETE_NTP_CONFIG % (
- args[0], args[1], '::', args[2], args[3])
- elif self.ip_ver == 'IPv6':
- xml_str = CE_NC_DELETE_NTP_CONFIG % (
- args[0], '0.0.0.0', args[1], args[2], args[3])
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "UNDO_NTP_CORE_CONFIG")
-
- def config_ntp(self):
- """Config ntp"""
-
- if self.state == "present":
- if self.address and not self.conf_exsit:
- if self.is_preferred == 'enable':
- is_preferred = 'true'
- else:
- is_preferred = 'false'
- self.set_ntp(self.ip_ver, self.address, self.peer_type,
- self.vpn_name, self.key_id, is_preferred, self.interface)
- self.changed = True
- else:
- if self.address:
- self.set_ntp(self.ip_ver, self.address,
- self.peer_type, self.vpn_name, '', '', '')
- self.changed = True
-
- def show_result(self):
- """Show result"""
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
- def get_ntp_exist_config(self):
- """Get ntp existed configure"""
-
- ntp_config = list()
- conf_str = CE_NC_GET_NTP_CONFIG
- con_obj = get_nc_config(self.module, conf_str)
- if "" in con_obj:
- return ntp_config
-
- xml_str = con_obj.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get all ntp config info
- root = ElementTree.fromstring(xml_str)
- ntpsite = root.findall("ntp/ntpUCastCfgs/ntpUCastCfg")
- for nexthop in ntpsite:
- ntp_dict = dict()
- for ele in nexthop:
- if ele.tag in ["addrFamily", "vpnName", "ifName", "ipv4Addr",
- "ipv6Addr", "type", "isPreferred", "keyId"]:
- ntp_dict[ele.tag] = ele.text
-
- ip_addr = ntp_dict['ipv6Addr']
- if ntp_dict['addrFamily'] == "IPv4":
- ip_addr = ntp_dict['ipv4Addr']
- if ntp_dict['ifName'] is None:
- ntp_dict['ifName'] = ""
- if ntp_dict['isPreferred'] == 'true':
- is_preferred = 'enable'
- else:
- is_preferred = 'disable'
-
- if self.state == "present":
- key_id = ntp_dict['keyId'] or ""
- cur_ntp_cfg = dict(vpn_name=ntp_dict['vpnName'], source_int=ntp_dict['ifName'].lower(), address=ip_addr,
- peer_type=ntp_dict['type'], prefer=is_preferred, key_id=key_id)
- exp_ntp_cfg = dict(vpn_name=self.vpn_name, source_int=self.interface.lower(), address=self.address,
- peer_type=self.peer_type, prefer=self.is_preferred, key_id=self.key_id)
- if cur_ntp_cfg == exp_ntp_cfg:
- self.conf_exsit = True
-
- vpn_name = ntp_dict['vpnName']
- if ntp_dict['vpnName'] == "_public_":
- vpn_name = None
-
- if_name = ntp_dict['ifName']
- if if_name == "":
- if_name = None
- if self.peer_type == 'Server':
- ntp_config.append(dict(vpn_name=vpn_name,
- source_int=if_name, server=ip_addr,
- is_preferred=is_preferred, key_id=ntp_dict['keyId']))
- else:
- ntp_config.append(dict(vpn_name=vpn_name,
- source_int=if_name, peer=ip_addr,
- is_preferred=is_preferred, key_id=ntp_dict['keyId']))
-
- return ntp_config
-
- def get_existing(self):
- """Get existing info"""
-
- if self.address:
- self.existing = self.get_ntp_exist_config()
-
- def get_proposed(self):
- """Get proposed info"""
-
- if self.address:
- vpn_name = self.vpn_name
- if vpn_name == "_public_":
- vpn_name = None
-
- if_name = self.interface
- if if_name == "":
- if_name = None
-
- key_id = self.key_id
- if key_id == "":
- key_id = None
- if self.peer_type == 'Server':
- self.proposed = dict(state=self.state, vpn_name=vpn_name,
- source_int=if_name, server=self.address,
- is_preferred=self.is_preferred, key_id=key_id)
- else:
- self.proposed = dict(state=self.state, vpn_name=vpn_name,
- source_int=if_name, peer=self.address,
- is_preferred=self.is_preferred, key_id=key_id)
-
- def get_end_state(self):
- """Get end state info"""
-
- if self.address:
- self.end_state = self.get_ntp_exist_config()
-
- def get_update_cmd(self):
- """Get updated commands"""
-
- if self.conf_exsit:
- return
-
- cli_str = ""
- if self.state == "present":
- if self.address:
- if self.peer_type == 'Server':
- if self.ip_ver == "IPv4":
- cli_str = "%s %s" % (
- "ntp unicast-server", self.address)
- else:
- cli_str = "%s %s" % (
- "ntp unicast-server ipv6", self.address)
- elif self.peer_type == 'Peer':
- if self.ip_ver == "IPv4":
- cli_str = "%s %s" % ("ntp unicast-peer", self.address)
- else:
- cli_str = "%s %s" % (
- "ntp unicast-peer ipv6", self.address)
-
- if self.key_id:
- cli_str = "%s %s %s" % (
- cli_str, "authentication-keyid", self.key_id)
- if self.interface:
- cli_str = "%s %s %s" % (
- cli_str, "source-interface", self.interface)
- if (self.vpn_name) and (self.vpn_name != '_public_'):
- cli_str = "%s %s %s" % (
- cli_str, "vpn-instance", self.vpn_name)
- if self.is_preferred == "enable":
- cli_str = "%s %s" % (cli_str, "preferred")
- else:
- if self.address:
- if self.peer_type == 'Server':
- if self.ip_ver == "IPv4":
- cli_str = "%s %s" % (
- "undo ntp unicast-server", self.address)
- else:
- cli_str = "%s %s" % (
- "undo ntp unicast-server ipv6", self.address)
- elif self.peer_type == 'Peer':
- if self.ip_ver == "IPv4":
- cli_str = "%s %s" % (
- "undo ntp unicast-peer", self.address)
- else:
- cli_str = "%s %s" % (
- "undo ntp unicast-peer ipv6", self.address)
- if (self.vpn_name) and (self.vpn_name != '_public_'):
- cli_str = "%s %s %s" % (
- cli_str, "vpn-instance", self.vpn_name)
-
- self.updates_cmd.append(cli_str)
-
- def work(self):
- """Execute task"""
-
- self.get_existing()
- self.get_proposed()
-
- self.config_ntp()
-
- self.get_update_cmd()
- self.get_end_state()
- self.show_result()
-
-
-def main():
- """Main function entry"""
-
- argument_spec = dict(
- server=dict(type='str'),
- peer=dict(type='str'),
- key_id=dict(type='str'),
- is_preferred=dict(type='str', choices=['enable', 'disable']),
- vpn_name=dict(type='str', default='_public_'),
- source_int=dict(type='str'),
- state=dict(choices=['absent', 'present'], default='present'),
- )
- argument_spec.update(ce_argument_spec)
- ntp_obj = Ntp(argument_spec)
- ntp_obj.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_ntp_auth.py b/plugins/modules/network/cloudengine/ce_ntp_auth.py
deleted file mode 100644
index c7aa6ecd07..0000000000
--- a/plugins/modules/network/cloudengine/ce_ntp_auth.py
+++ /dev/null
@@ -1,520 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-
-module: ce_ntp_auth
-short_description: Manages NTP authentication configuration on HUAWEI CloudEngine switches.
-description:
- - Manages NTP authentication configuration on HUAWEI CloudEngine switches.
-author:
- - Zhijin Zhou (@QijunPan)
-notes:
- - If C(state=absent), the module will attempt to remove the given key configuration.
- If a matching key configuration isn't found on the device, the module will fail.
- - If C(state=absent) and C(authentication=on), authentication will be turned on.
- - If C(state=absent) and C(authentication=off), authentication will be turned off.
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- key_id:
- description:
- - Authentication key identifier (numeric).
- required: true
- auth_pwd:
- description:
- - Plain text with length of 1 to 255, encrypted text with length of 20 to 392.
- auth_mode:
- description:
- - Specify authentication algorithm.
- choices: ['hmac-sha256', 'md5']
- auth_type:
- description:
- - Whether the given password is in cleartext or
- has been encrypted. If in cleartext, the device
- will encrypt it before storing it.
- default: encrypt
- choices: ['text', 'encrypt']
- trusted_key:
- description:
- - Whether the given key is required to be supplied by a time source
- for the device to synchronize to the time source.
- default: 'disable'
- choices: ['enable', 'disable']
- authentication:
- description:
- - Configure ntp authentication enable or unconfigure ntp authentication enable.
- choices: ['enable', 'disable']
- state:
- description:
- - Manage the state of the resource.
- default: present
- choices: ['present','absent']
-'''
-
-EXAMPLES = '''
-- name: NTP AUTH test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Configure ntp authentication key-id"
- ce_ntp_auth:
- key_id: 32
- auth_mode: md5
- auth_pwd: 11111111111111111111111
- provider: "{{ cli }}"
-
- - name: "Configure ntp authentication key-id and trusted authentication keyid"
- ce_ntp_auth:
- key_id: 32
- auth_mode: md5
- auth_pwd: 11111111111111111111111
- trusted_key: enable
- provider: "{{ cli }}"
-
- - name: "Configure ntp authentication key-id and authentication enable"
- ce_ntp_auth:
- key_id: 32
- auth_mode: md5
- auth_pwd: 11111111111111111111111
- authentication: enable
- provider: "{{ cli }}"
-
- - name: "Unconfigure ntp authentication key-id and trusted authentication keyid"
- ce_ntp_auth:
- key_id: 32
- state: absent
- provider: "{{ cli }}"
-
- - name: "Unconfigure ntp authentication key-id and authentication enable"
- ce_ntp_auth:
- key_id: 32
- authentication: enable
- state: absent
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "auth_type": "text",
- "authentication": "enable",
- "key_id": "32",
- "auth_pwd": "1111",
- "auth_mode": "md5",
- "trusted_key": "enable",
- "state": "present"
- }
-existing:
- description: k/v pairs of existing ntp authentication
- returned: always
- type: dict
- sample: {
- "authentication": "off",
- "authentication-keyid": [
- {
- "auth_mode": "md5",
- "key_id": "1",
- "trusted_key": "disable"
- }
- ]
- }
-end_state:
- description: k/v pairs of ntp authentication after module execution
- returned: always
- type: dict
- sample: {
- "authentication": "off",
- "authentication-keyid": [
- {
- "auth_mode": "md5",
- "key_id": "1",
- "trusted_key": "disable"
- },
- {
- "auth_mode": "md5",
- "key_id": "32",
- "trusted_key": "enable"
- }
- ]
- }
-state:
- description: state as sent in from the playbook
- returned: always
- type: str
- sample: "present"
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: [
- "ntp authentication-key 32 md5 1111",
- "ntp trusted-key 32",
- "ntp authentication enable"
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import copy
-import re
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec, load_config
-from ansible.module_utils.connection import exec_command
-
-
-class NtpAuth(object):
- """Manage ntp authentication"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # ntp_auth configuration info
- self.key_id = self.module.params['key_id']
- self.password = self.module.params['auth_pwd'] or None
- self.auth_mode = self.module.params['auth_mode'] or None
- self.auth_type = self.module.params['auth_type']
- self.trusted_key = self.module.params['trusted_key']
- self.authentication = self.module.params['authentication'] or None
- self.state = self.module.params['state']
- self.check_params()
-
- self.ntp_auth_conf = dict()
- self.key_id_exist = False
- self.cur_trusted_key = 'disable'
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = list()
- self.end_state = list()
-
- self.get_ntp_auth_exist_config()
-
- def check_params(self):
- """Check all input params"""
-
- if not self.key_id.isdigit():
- self.module.fail_json(
- msg='Error: key_id is not digit.')
-
- if (int(self.key_id) < 1) or (int(self.key_id) > 4294967295):
- self.module.fail_json(
- msg='Error: The length of key_id is between 1 and 4294967295.')
- if self.state == "present" and not self.password:
- self.module.fail_json(
- msg='Error: The password cannot be empty.')
- if self.state == "present" and self.password:
- if (self.auth_type == 'encrypt') and\
- ((len(self.password) < 20) or (len(self.password) > 392)):
- self.module.fail_json(
- msg='Error: The length of encrypted password is between 20 and 392.')
- elif (self.auth_type == 'text') and\
- ((len(self.password) < 1) or (len(self.password) > 255)):
- self.module.fail_json(
- msg='Error: The length of text password is between 1 and 255.')
-
- def init_module(self):
- """Init module object"""
-
- required_if = [("state", "present", ("auth_pwd", "auth_mode"))]
- self.module = AnsibleModule(
- argument_spec=self.spec,
- required_if=required_if,
- supports_check_mode=True
- )
-
- def get_config(self, flags=None):
- """Retrieves the current config from the device or cache
- """
- flags = [] if flags is None else flags
-
- cmd = 'display current-configuration '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- cfg = str(out).strip()
-
- return cfg
-
- def get_ntp_auth_enable(self):
- """Get ntp authentication enable state"""
-
- flags = list()
- exp = "| exclude undo | include ntp authentication"
- flags.append(exp)
- config = self.get_config(flags)
- auth_en = re.findall(
- r'.*ntp\s*authentication\s*enable.*', config)
- if auth_en:
- self.ntp_auth_conf['authentication'] = 'enable'
- else:
- self.ntp_auth_conf['authentication'] = 'disable'
-
- def get_ntp_all_auth_keyid(self):
- """Get all authentication keyid info"""
-
- ntp_auth_conf = list()
-
- flags = list()
- exp = "| include authentication-keyid %s" % self.key_id
- flags.append(exp)
- config = self.get_config(flags)
- ntp_config_list = config.split('\n')
- if not ntp_config_list:
- self.ntp_auth_conf["authentication-keyid"] = "None"
- return ntp_auth_conf
-
- self.key_id_exist = True
- cur_auth_mode = ""
- cur_auth_pwd = ""
- for ntp_config in ntp_config_list:
- ntp_auth_mode = re.findall(r'.*authentication-mode(\s\S*)\s\S*\s(\S*)', ntp_config)
- ntp_auth_trust = re.findall(r'.*trusted.*', ntp_config)
- if ntp_auth_trust:
- self.cur_trusted_key = 'enable'
- if ntp_auth_mode:
- cur_auth_mode = ntp_auth_mode[0][0].strip()
- cur_auth_pwd = ntp_auth_mode[0][1].strip()
- ntp_auth_conf.append(dict(key_id=self.key_id,
- auth_mode=cur_auth_mode,
- auth_pwd=cur_auth_pwd,
- trusted_key=self.cur_trusted_key))
- self.ntp_auth_conf["authentication-keyid"] = ntp_auth_conf
-
- return ntp_auth_conf
-
- def get_ntp_auth_exist_config(self):
- """Get ntp authentication existed configure"""
-
- self.get_ntp_auth_enable()
- self.get_ntp_all_auth_keyid()
-
- def config_ntp_auth_keyid(self):
- """Config ntp authentication keyid"""
-
- commands = list()
- if self.auth_type == 'encrypt':
- config_cli = "ntp authentication-keyid %s authentication-mode %s cipher %s" % (
- self.key_id, self.auth_mode, self.password)
- else:
- config_cli = "ntp authentication-keyid %s authentication-mode %s %s" % (
- self.key_id, self.auth_mode, self.password)
-
- commands.append(config_cli)
-
- if self.trusted_key != self.cur_trusted_key:
- if self.trusted_key == 'enable':
- config_cli_trust = "ntp trusted authentication-keyid %s" % (self.key_id)
- commands.append(config_cli_trust)
- else:
- config_cli_trust = "undo ntp trusted authentication-keyid %s" % (self.key_id)
- commands.append(config_cli_trust)
-
- self.cli_load_config(commands)
-
- def config_ntp_auth_enable(self):
- """Config ntp authentication enable"""
-
- commands = list()
- if self.ntp_auth_conf['authentication'] != self.authentication:
- if self.authentication == 'enable':
- config_cli = "ntp authentication enable"
- else:
- config_cli = "undo ntp authentication enable"
- commands.append(config_cli)
-
- self.cli_load_config(commands)
-
- def undo_config_ntp_auth_keyid(self):
- """Undo ntp authentication key-id"""
-
- commands = list()
- config_cli = "undo ntp authentication-keyid %s" % self.key_id
- commands.append(config_cli)
-
- self.cli_load_config(commands)
-
- def cli_load_config(self, commands):
- """Load config by cli"""
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def config_ntp_auth(self):
- """Config ntp authentication"""
-
- if self.state == "present":
- self.config_ntp_auth_keyid()
- else:
- if not self.key_id_exist:
- self.module.fail_json(
- msg='Error: The Authentication-keyid does not exist.')
- self.undo_config_ntp_auth_keyid()
-
- if self.authentication:
- self.config_ntp_auth_enable()
-
- self.changed = True
-
- def get_existing(self):
- """Get existing info"""
-
- self.existing = copy.deepcopy(self.ntp_auth_conf)
-
- def get_proposed(self):
- """Get proposed result"""
-
- auth_type = self.auth_type
- trusted_key = self.trusted_key
- if self.state == 'absent':
- auth_type = None
- trusted_key = None
- self.proposed = dict(key_id=self.key_id, auth_pwd=self.password,
- auth_mode=self.auth_mode, auth_type=auth_type,
- trusted_key=trusted_key, authentication=self.authentication,
- state=self.state)
-
- def get_update_cmd(self):
- """Get updated commands"""
-
- cli_str = ""
- if self.state == "present":
- cli_str = "ntp authentication-keyid %s authentication-mode %s " % (
- self.key_id, self.auth_mode)
- if self.auth_type == 'encrypt':
- cli_str = "%s cipher %s" % (cli_str, self.password)
- else:
- cli_str = "%s %s" % (cli_str, self.password)
- else:
- cli_str = "undo ntp authentication-keyid %s" % self.key_id
-
- self.updates_cmd.append(cli_str)
-
- if self.authentication:
- cli_str = ""
-
- if self.ntp_auth_conf['authentication'] != self.authentication:
- if self.authentication == 'enable':
- cli_str = "ntp authentication enable"
- else:
- cli_str = "undo ntp authentication enable"
-
- if cli_str != "":
- self.updates_cmd.append(cli_str)
-
- cli_str = ""
- if self.state == "present":
- if self.trusted_key != self.cur_trusted_key:
- if self.trusted_key == 'enable':
- cli_str = "ntp trusted authentication-keyid %s" % self.key_id
- else:
- cli_str = "undo ntp trusted authentication-keyid %s" % self.key_id
- else:
- cli_str = "undo ntp trusted authentication-keyid %s" % self.key_id
-
- if cli_str != "":
- self.updates_cmd.append(cli_str)
-
- def get_end_state(self):
- """Get end state info"""
-
- self.ntp_auth_conf = dict()
- self.get_ntp_auth_exist_config()
- self.end_state = copy.deepcopy(self.ntp_auth_conf)
- if self.end_state == self.existing:
- self.changed = False
-
- def show_result(self):
- """Show result"""
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
- def work(self):
- """Execute task"""
-
- self.get_existing()
- self.get_proposed()
- self.get_update_cmd()
-
- self.config_ntp_auth()
-
- self.get_end_state()
- self.show_result()
-
-
-def main():
- """Main function entry"""
-
- argument_spec = dict(
- key_id=dict(required=True, type='str'),
- auth_pwd=dict(type='str', no_log=True),
- auth_mode=dict(choices=['md5', 'hmac-sha256'], type='str'),
- auth_type=dict(choices=['text', 'encrypt'], default='encrypt'),
- trusted_key=dict(choices=['enable', 'disable'], default='disable'),
- authentication=dict(choices=['enable', 'disable']),
- state=dict(choices=['absent', 'present'], default='present'),
- )
- argument_spec.update(ce_argument_spec)
- ntp_auth_obj = NtpAuth(argument_spec)
- ntp_auth_obj.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_ospf.py b/plugins/modules/network/cloudengine/ce_ospf.py
deleted file mode 100644
index c5af33b219..0000000000
--- a/plugins/modules/network/cloudengine/ce_ospf.py
+++ /dev/null
@@ -1,972 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_ospf
-short_description: Manages configuration of an OSPF instance on HUAWEI CloudEngine switches.
-description:
- - Manages configuration of an OSPF instance on HUAWEI CloudEngine switches.
-author: QijunPan (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- process_id:
- description:
- - Specifies a process ID.
- The value is an integer ranging from 1 to 4294967295.
- required: true
- area:
- description:
- - Specifies the area ID. The area with the area-id being 0 is a backbone area.
- Valid values are a string, formatted as an IP address
- (i.e. "0.0.0.0") or as an integer between 1 and 4294967295.
- addr:
- description:
- - Specifies the address of the network segment where the interface resides.
- The value is in dotted decimal notation.
- mask:
- description:
- - IP network wildcard bits in decimal format between 0 and 32.
- auth_mode:
- description:
- - Specifies the authentication type.
- choices: ['none', 'hmac-sha256', 'md5', 'hmac-md5', 'simple']
- auth_text_simple:
- description:
- - Specifies a password for simple authentication.
- The value is a string of 1 to 8 characters.
- auth_key_id:
- description:
- - Authentication key id when C(auth_mode) is 'hmac-sha256', 'md5' or 'hmac-md5.
- Valid value is an integer is in the range from 1 to 255.
- auth_text_md5:
- description:
- - Specifies a password for MD5, HMAC-MD5, or HMAC-SHA256 authentication.
- The value is a string of 1 to 255 case-sensitive characters, spaces not supported.
- nexthop_addr:
- description:
- - IPv4 address for configure next-hop address's weight.
- Valid values are a string, formatted as an IP address.
- nexthop_weight:
- description:
- - Indicates the weight of the next hop.
- The smaller the value is, the higher the preference of the route is.
- It is an integer that ranges from 1 to 254.
- max_load_balance:
- description:
- - The maximum number of paths for forward packets over multiple paths.
- Valid value is an integer in the range from 1 to 64.
- state:
- description:
- - Determines whether the config should be present or not
- on the device.
- default: present
- choices: ['present','absent']
-'''
-
-EXAMPLES = '''
-- name: ospf module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Configure ospf
- ce_ospf:
- process_id: 1
- area: 100
- state: present
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: verbose mode
- type: dict
- sample: {"process_id": "1", "area": "100"}
-existing:
- description: k/v pairs of existing configuration
- returned: verbose mode
- type: dict
- sample: {"process_id": "1", "areas": [], "nexthops":[], "max_load_balance": "32"}
-end_state:
- description: k/v pairs of configuration after module execution
- returned: verbose mode
- type: dict
- sample: {"process_id": "1",
- "areas": [{"areaId": "0.0.0.100", "areaType": "Normal"}],
- "nexthops":[], "max_load_balance": "32"}
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: ["ospf 1", "area 0.0.0.100"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-CE_NC_GET_OSPF = """
-
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_CREATE_PROCESS = """
-
-
-
-
-
- %s
-
-
-
-
-
-"""
-
-CE_NC_DELETE_PROCESS = """
-
-
-
-
-
- %s
-
-
-
-
-
-"""
-
-CE_NC_XML_BUILD_MERGE_PROCESS = """
-
-
-
-
-
- %s
- %s
-
-
-
-
-
-"""
-
-CE_NC_XML_BUILD_PROCESS = """
-
-
-
-
-
- %s
- %s
-
-
-
-
-
-"""
-
-CE_NC_XML_BUILD_MERGE_AREA = """
-
-
- %s
- %s
-
-
-"""
-
-CE_NC_XML_BUILD_DELETE_AREA = """
-
-
- %s
- %s
-
-
-"""
-
-CE_NC_XML_BUILD_AREA = """
-
-
- %s
- %s
-
-
-"""
-
-CE_NC_XML_SET_AUTH_MODE = """
- %s
-"""
-CE_NC_XML_SET_AUTH_TEXT_SIMPLE = """
- %s
-"""
-
-CE_NC_XML_SET_AUTH_MD5 = """
- %s
- %s
-"""
-
-
-CE_NC_XML_MERGE_NETWORKS = """
-
-
- %s
- %s
-
-
-"""
-
-CE_NC_XML_DELETE_NETWORKS = """
-
-
- %s
- %s
-
-
-"""
-
-CE_NC_XML_SET_LB = """
- %s
-"""
-
-
-CE_NC_XML_BUILD_MERGE_TOPO = """
-
-
- base
- %s
-
-
-
-"""
-
-CE_NC_XML_BUILD_TOPO = """
-
-
- base
- %s
-
-
-
-"""
-
-CE_NC_XML_MERGE_NEXTHOP = """
-
-
- %s
- %s
-
-
-"""
-
-CE_NC_XML_DELETE_NEXTHOP = """
-
-
- %s
-
-
-"""
-
-
-class OSPF(object):
- """
- Manages configuration of an ospf instance.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.process_id = self.module.params['process_id']
- self.area = self.module.params['area']
- self.addr = self.module.params['addr']
- self.mask = self.module.params['mask']
- self.auth_mode = self.module.params['auth_mode']
- self.auth_text_simple = self.module.params['auth_text_simple']
- self.auth_key_id = self.module.params['auth_key_id']
- self.auth_text_md5 = self.module.params['auth_text_md5']
- self.nexthop_addr = self.module.params['nexthop_addr']
- self.nexthop_weight = self.module.params['nexthop_weight']
- self.max_load_balance = self.module.params['max_load_balance']
- self.state = self.module.params['state']
-
- # ospf info
- self.ospf_info = dict()
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def init_module(self):
- """ init module """
-
- required_together = [
- ("addr", "mask"),
- ("auth_key_id", "auth_text_md5"),
- ("nexthop_addr", "nexthop_weight")
- ]
- self.module = AnsibleModule(
- argument_spec=self.spec, required_together=required_together, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_wildcard_mask(self):
- """convert mask length to ip address wildcard mask, i.e. 24 to 0.0.0.255"""
-
- mask_int = ["255"] * 4
- length = int(self.mask)
-
- if length > 32:
- self.module.fail_json(msg='IPv4 ipaddress mask length is invalid')
- if length < 8:
- mask_int[0] = str(int(~(0xFF << (8 - length % 8)) & 0xFF))
- if length >= 8:
- mask_int[0] = '0'
- mask_int[1] = str(int(~(0xFF << (16 - (length % 16))) & 0xFF))
- if length >= 16:
- mask_int[1] = '0'
- mask_int[2] = str(int(~(0xFF << (24 - (length % 24))) & 0xFF))
- if length >= 24:
- mask_int[2] = '0'
- mask_int[3] = str(int(~(0xFF << (32 - (length % 32))) & 0xFF))
- if length == 32:
- mask_int[3] = '0'
-
- return '.'.join(mask_int)
-
- def get_area_ip(self):
- """convert integer to ip address"""
-
- if not self.area.isdigit():
- return self.area
-
- addr_int = ['0'] * 4
- addr_int[0] = str(((int(self.area) & 0xFF000000) >> 24) & 0xFF)
- addr_int[1] = str(((int(self.area) & 0x00FF0000) >> 16) & 0xFF)
- addr_int[2] = str(((int(self.area) & 0x0000FF00) >> 8) & 0XFF)
- addr_int[3] = str(int(self.area) & 0xFF)
-
- return '.'.join(addr_int)
-
- def get_ospf_dict(self, process_id):
- """ get one ospf attributes dict."""
-
- ospf_info = dict()
- conf_str = CE_NC_GET_OSPF % process_id
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return ospf_info
-
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get process base info
- root = ElementTree.fromstring(xml_str)
- ospfsite = root.find("ospfv2/ospfv2comm/ospfSites/ospfSite")
- if ospfsite:
- for site in ospfsite:
- if site.tag in ["processId", "routerId", "vrfName"]:
- ospf_info[site.tag] = site.text
-
- # get Topology info
- topo = root.find(
- "ospfv2/ospfv2comm/ospfSites/ospfSite/ProcessTopologys/ProcessTopology")
- if topo:
- for eles in topo:
- if eles.tag in ["maxLoadBalancing"]:
- ospf_info[eles.tag] = eles.text
-
- # get nexthop info
- ospf_info["nexthops"] = list()
- nexthops = root.findall(
- "ospfv2/ospfv2comm/ospfSites/ospfSite/ProcessTopologys/ProcessTopology/nexthopMTs/nexthopMT")
- if nexthops:
- for nexthop in nexthops:
- nh_dict = dict()
- for ele in nexthop:
- if ele.tag in ["ipAddress", "weight"]:
- nh_dict[ele.tag] = ele.text
- ospf_info["nexthops"].append(nh_dict)
-
- # get areas info
- ospf_info["areas"] = list()
- areas = root.findall(
- "ospfv2/ospfv2comm/ospfSites/ospfSite/areas/area")
- if areas:
- for area in areas:
- area_dict = dict()
- for ele in area:
- if ele.tag in ["areaId", "authTextSimple", "areaType",
- "authenticationMode", "keyId", "authTextMd5"]:
- area_dict[ele.tag] = ele.text
- if ele.tag == "networks":
- # get networks info
- area_dict["networks"] = list()
- for net in ele:
- net_dict = dict()
- for net_ele in net:
- if net_ele.tag in ["ipAddress", "wildcardMask"]:
- net_dict[net_ele.tag] = net_ele.text
- area_dict["networks"].append(net_dict)
-
- ospf_info["areas"].append(area_dict)
- return ospf_info
-
- def is_area_exist(self):
- """is ospf area exist"""
- if not self.ospf_info:
- return False
- for area in self.ospf_info["areas"]:
- if area["areaId"] == self.get_area_ip():
- return True
-
- return False
-
- def is_network_exist(self):
- """is ospf area network exist"""
- if not self.ospf_info:
- return False
-
- for area in self.ospf_info["areas"]:
- if area["areaId"] == self.get_area_ip():
- if not area.get("networks"):
- return False
- for network in area.get("networks"):
- if network["ipAddress"] == self.addr and network["wildcardMask"] == self.get_wildcard_mask():
- return True
- return False
-
- def is_nexthop_exist(self):
- """is ospf nexthop exist"""
-
- if not self.ospf_info:
- return False
- for nexthop in self.ospf_info["nexthops"]:
- if nexthop["ipAddress"] == self.nexthop_addr:
- return True
-
- return False
-
- def is_nexthop_change(self):
- """is ospf nexthop change"""
- if not self.ospf_info:
- return True
-
- for nexthop in self.ospf_info["nexthops"]:
- if nexthop["ipAddress"] == self.nexthop_addr:
- if nexthop["weight"] == self.nexthop_weight:
- return False
- else:
- return True
-
- return True
-
- def create_process(self):
- """Create ospf process"""
-
- xml_area = ""
- self.updates_cmd.append("ospf %s" % self.process_id)
- xml_create = CE_NC_CREATE_PROCESS % self.process_id
- set_nc_config(self.module, xml_create)
-
- # nexthop weight
- xml_nh = ""
- if self.nexthop_addr:
- xml_nh = CE_NC_XML_MERGE_NEXTHOP % (
- self.nexthop_addr, self.nexthop_weight)
- self.updates_cmd.append("nexthop %s weight %s" % (
- self.nexthop_addr, self.nexthop_weight))
-
- # max load balance
- xml_lb = ""
- if self.max_load_balance:
- xml_lb = CE_NC_XML_SET_LB % self.max_load_balance
- self.updates_cmd.append(
- "maximum load-balancing %s" % self.max_load_balance)
-
- xml_topo = ""
- if xml_lb or xml_nh:
- xml_topo = CE_NC_XML_BUILD_TOPO % (xml_nh + xml_lb)
-
- if self.area:
- self.updates_cmd.append("area %s" % self.get_area_ip())
- xml_auth = ""
- xml_network = ""
-
- # networks
- if self.addr and self.mask:
- xml_network = CE_NC_XML_MERGE_NETWORKS % (
- self.addr, self.get_wildcard_mask())
- self.updates_cmd.append("network %s %s" % (
- self.addr, self.get_wildcard_mask()))
-
- # authentication mode
- if self.auth_mode:
- xml_auth += CE_NC_XML_SET_AUTH_MODE % self.auth_mode
- if self.auth_mode == "none":
- self.updates_cmd.append("undo authentication-mode")
- else:
- self.updates_cmd.append(
- "authentication-mode %s" % self.auth_mode)
- if self.auth_mode == "simple" and self.auth_text_simple:
- xml_auth += CE_NC_XML_SET_AUTH_TEXT_SIMPLE % self.auth_text_simple
- self.updates_cmd.pop()
- self.updates_cmd.append(
- "authentication-mode %s %s" % (self.auth_mode, self.auth_text_simple))
- if self.auth_mode in ["hmac-sha256", "hmac-sha256", "md5"]:
- if self.auth_key_id and self.auth_text_md5:
- xml_auth += CE_NC_XML_SET_AUTH_MD5 % (
- self.auth_key_id, self.auth_text_md5)
- self.updates_cmd.pop()
- self.updates_cmd.append(
- "authentication-mode %s %s %s" % (self.auth_mode, self.auth_key_id, self.auth_text_md5))
- if xml_network or xml_auth or not self.is_area_exist():
- xml_area += CE_NC_XML_BUILD_MERGE_AREA % (
- self.get_area_ip(), xml_network + xml_auth)
-
- xml_str = CE_NC_XML_BUILD_MERGE_PROCESS % (
- self.process_id, xml_topo + xml_area)
- recv_xml = set_nc_config(self.module, xml_str)
- self.check_response(recv_xml, "CREATE_PROCESS")
- self.changed = True
-
- def delete_process(self):
- """Delete ospf process"""
-
- xml_str = CE_NC_DELETE_PROCESS % self.process_id
- recv_xml = set_nc_config(self.module, xml_str)
- self.check_response(recv_xml, "DELETE_PROCESS")
- self.updates_cmd.append("undo ospf %s" % self.process_id)
- self.changed = True
-
- def merge_process(self):
- """merge ospf process"""
-
- xml_area = ""
- xml_str = ""
- self.updates_cmd.append("ospf %s" % self.process_id)
-
- # nexthop weight
- xml_nh = ""
- if self.nexthop_addr and self.is_nexthop_change():
- xml_nh = CE_NC_XML_MERGE_NEXTHOP % (
- self.nexthop_addr, self.nexthop_weight)
- self.updates_cmd.append("nexthop %s weight %s" % (
- self.nexthop_addr, self.nexthop_weight))
-
- # max load balance
- xml_lb = ""
- if self.max_load_balance and self.ospf_info.get("maxLoadBalancing") != self.max_load_balance:
- xml_lb = CE_NC_XML_SET_LB % self.max_load_balance
- self.updates_cmd.append(
- "maximum load-balancing %s" % self.max_load_balance)
-
- xml_topo = ""
- if xml_lb or xml_nh:
- xml_topo = CE_NC_XML_BUILD_MERGE_TOPO % (xml_nh + xml_lb)
-
- if self.area:
- self.updates_cmd.append("area %s" % self.get_area_ip())
- xml_network = ""
- xml_auth = ""
- if self.addr and self.mask:
- if not self.is_network_exist():
- xml_network += CE_NC_XML_MERGE_NETWORKS % (
- self.addr, self.get_wildcard_mask())
- self.updates_cmd.append("network %s %s" % (
- self.addr, self.get_wildcard_mask()))
-
- # NOTE: for security, authentication config will always be update
- if self.auth_mode:
- xml_auth += CE_NC_XML_SET_AUTH_MODE % self.auth_mode
- if self.auth_mode == "none":
- self.updates_cmd.append("undo authentication-mode")
- else:
- self.updates_cmd.append(
- "authentication-mode %s" % self.auth_mode)
- if self.auth_mode == "simple" and self.auth_text_simple:
- xml_auth += CE_NC_XML_SET_AUTH_TEXT_SIMPLE % self.auth_text_simple
- self.updates_cmd.pop()
- self.updates_cmd.append(
- "authentication-mode %s %s" % (self.auth_mode, self.auth_text_simple))
- if self.auth_mode in ["hmac-sha256", "hmac-sha256", "md5"]:
- if self.auth_key_id and self.auth_text_md5:
- xml_auth += CE_NC_XML_SET_AUTH_MD5 % (
- self.auth_key_id, self.auth_text_md5)
- self.updates_cmd.pop()
- self.updates_cmd.append(
- "authentication-mode %s %s %s" % (self.auth_mode, self.auth_key_id, self.auth_text_md5))
- if xml_network or xml_auth or not self.is_area_exist():
- xml_area += CE_NC_XML_BUILD_MERGE_AREA % (
- self.get_area_ip(), xml_network + xml_auth)
- elif self.is_area_exist():
- self.updates_cmd.pop() # remove command: area
- else:
- pass
-
- if xml_area or xml_topo:
- xml_str = CE_NC_XML_BUILD_MERGE_PROCESS % (
- self.process_id, xml_topo + xml_area)
- recv_xml = set_nc_config(self.module, xml_str)
- self.check_response(recv_xml, "MERGE_PROCESS")
- self.changed = True
-
- def remove_area_network(self):
- """remvoe ospf area network"""
-
- if not self.is_network_exist():
- return
-
- xml_network = CE_NC_XML_DELETE_NETWORKS % (
- self.addr, self.get_wildcard_mask())
- xml_area = CE_NC_XML_BUILD_AREA % (self.get_area_ip(), xml_network)
- xml_str = CE_NC_XML_BUILD_PROCESS % (self.process_id, xml_area)
- recv_xml = set_nc_config(self.module, xml_str)
- self.check_response(recv_xml, "DELETE_AREA_NETWORK")
- self.updates_cmd.append("ospf %s" % self.process_id)
- self.updates_cmd.append("area %s" % self.get_area_ip())
- self.updates_cmd.append("undo network %s %s" %
- (self.addr, self.get_wildcard_mask()))
- self.changed = True
-
- def remove_area(self):
- """remove ospf area"""
-
- if not self.is_area_exist():
- return
-
- xml_area = CE_NC_XML_BUILD_DELETE_AREA % (self.get_area_ip(), "")
- xml_str = CE_NC_XML_BUILD_PROCESS % (self.process_id, xml_area)
- recv_xml = set_nc_config(self.module, xml_str)
- self.check_response(recv_xml, "DELETE_AREA")
- self.updates_cmd.append("ospf %s" % self.process_id)
- self.updates_cmd.append("undo area %s" % self.get_area_ip())
- self.changed = True
-
- def remove_nexthop(self):
- """remove ospf nexthop weight"""
-
- if not self.is_nexthop_exist():
- return
-
- xml_nh = CE_NC_XML_DELETE_NEXTHOP % self.nexthop_addr
- xml_topo = CE_NC_XML_BUILD_TOPO % xml_nh
- xml_str = CE_NC_XML_BUILD_PROCESS % (self.process_id, xml_topo)
- recv_xml = set_nc_config(self.module, xml_str)
- self.check_response(recv_xml, "DELETE_NEXTHOP_WEIGHT")
- self.updates_cmd.append("ospf %s" % self.process_id)
- self.updates_cmd.append("undo nexthop %s" % self.nexthop_addr)
- self.changed = True
-
- def is_valid_v4addr(self, addr):
- """check is ipv4 addr is valid"""
-
- if addr.find('.') != -1:
- addr_list = addr.split('.')
- if len(addr_list) != 4:
- return False
- for each_num in addr_list:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- return True
-
- return False
-
- def convert_ip_to_network(self):
- """convert ip to subnet address"""
-
- ip_list = self.addr.split('.')
- mask_list = self.get_wildcard_mask().split('.')
-
- for i in range(len(ip_list)):
- ip_list[i] = str((int(ip_list[i]) & (~int(mask_list[i]))) & 0xff)
-
- self.addr = '.'.join(ip_list)
-
- def check_params(self):
- """Check all input params"""
-
- # process_id check
- if not self.process_id.isdigit():
- self.module.fail_json(msg="Error: process_id is not digit.")
- if int(self.process_id) < 1 or int(self.process_id) > 4294967295:
- self.module.fail_json(
- msg="Error: process_id must be an integer between 1 and 4294967295.")
-
- if self.area:
- # area check
- if self.area.isdigit():
- if int(self.area) < 0 or int(self.area) > 4294967295:
- self.module.fail_json(
- msg="Error: area id (Integer) must be between 0 and 4294967295.")
-
- else:
- if not self.is_valid_v4addr(self.area):
- self.module.fail_json(msg="Error: area id is invalid.")
-
- # area network check
- if self.addr:
- if not self.is_valid_v4addr(self.addr):
- self.module.fail_json(
- msg="Error: network addr is invalid.")
- if not self.mask.isdigit():
- self.module.fail_json(
- msg="Error: network mask is not digit.")
- if int(self.mask) < 0 or int(self.mask) > 32:
- self.module.fail_json(
- msg="Error: network mask is invalid.")
-
- # area authentication check
- if self.state == "present" and self.auth_mode:
- if self.auth_mode == "simple":
- if self.auth_text_simple and len(self.auth_text_simple) > 8:
- self.module.fail_json(
- msg="Error: auth_text_simple is not in the range from 1 to 8.")
- if self.auth_mode in ["hmac-sha256", "hmac-sha256", "md5"]:
- if self.auth_key_id:
- if not self.auth_key_id.isdigit():
- self.module.fail_json(
- msg="Error: auth_key_id is not digit.")
- if int(self.auth_key_id) < 1 or int(self.auth_key_id) > 255:
- self.module.fail_json(
- msg="Error: auth_key_id is not in the range from 1 to 255.")
- if self.auth_text_md5 and len(self.auth_text_md5) > 255:
- self.module.fail_json(
- msg="Error: auth_text_md5 is not in the range from 1 to 255.")
-
- # process max load balance check
- if self.state == "present" and self.max_load_balance:
- if not self.max_load_balance.isdigit():
- self.module.fail_json(
- msg="Error: max_load_balance is not digit.")
- if int(self.max_load_balance) < 1 or int(self.max_load_balance) > 64:
- self.module.fail_json(
- msg="Error: max_load_balance is not in the range from 1 to 64.")
-
- # process nexthop weight check
- if self.nexthop_addr:
- if not self.is_valid_v4addr(self.nexthop_addr):
- self.module.fail_json(msg="Error: nexthop_addr is invalid.")
- if not self.nexthop_weight.isdigit():
- self.module.fail_json(
- msg="Error: nexthop_weight is not digit.")
- if int(self.nexthop_weight) < 1 or int(self.nexthop_weight) > 254:
- self.module.fail_json(
- msg="Error: nexthop_weight is not in the range from 1 to 254.")
-
- if self.addr:
- self.convert_ip_to_network()
-
- def get_proposed(self):
- """get proposed info"""
-
- self.proposed["process_id"] = self.process_id
- self.proposed["area"] = self.area
- if self.area:
- self.proposed["addr"] = self.addr
- self.proposed["mask"] = self.mask
- if self.auth_mode:
- self.proposed["auth_mode"] = self.auth_mode
- if self.auth_mode == "simple":
- self.proposed["auth_text_simple"] = self.auth_text_simple
- if self.auth_mode in ["hmac-sha256", "hmac-sha256", "md5"]:
- self.proposed["auth_key_id"] = self.auth_key_id
- self.proposed["auth_text_md5"] = self.auth_text_md5
-
- if self.nexthop_addr:
- self.proposed["nexthop_addr"] = self.nexthop_addr
- self.proposed["nexthop_weight"] = self.nexthop_weight
- self.proposed["max_load_balance"] = self.max_load_balance
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- if not self.ospf_info:
- return
-
- self.existing["process_id"] = self.process_id
- self.existing["areas"] = self.ospf_info["areas"]
- self.existing["nexthops"] = self.ospf_info["nexthops"]
- self.existing["max_load_balance"] = self.ospf_info.get(
- "maxLoadBalancing")
-
- def get_end_state(self):
- """get end state info"""
-
- ospf_info = self.get_ospf_dict(self.process_id)
-
- if not ospf_info:
- return
-
- self.end_state["process_id"] = self.process_id
- self.end_state["areas"] = ospf_info["areas"]
- self.end_state["nexthops"] = ospf_info["nexthops"]
- self.end_state["max_load_balance"] = ospf_info.get("maxLoadBalancing")
-
- if self.end_state == self.existing:
- if not self.auth_text_simple and not self.auth_text_md5:
- self.changed = False
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.ospf_info = self.get_ospf_dict(self.process_id)
- self.get_existing()
- self.get_proposed()
-
- # deal present or absent
- if self.state == "present":
- if not self.ospf_info:
- # create ospf process
- self.create_process()
- else:
- # merge ospf
- self.merge_process()
- else:
- if self.ospf_info:
- if self.area:
- if self.addr:
- # remove ospf area network
- self.remove_area_network()
- else:
- # remove ospf area
- self.remove_area()
- if self.nexthop_addr:
- # remove ospf nexthop weight
- self.remove_nexthop()
-
- if not self.area and not self.nexthop_addr:
- # remove ospf process
- self.delete_process()
- else:
- self.module.fail_json(msg='Error: ospf process does not exist')
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- process_id=dict(required=True, type='str'),
- area=dict(required=False, type='str'),
- addr=dict(required=False, type='str'),
- mask=dict(required=False, type='str'),
- auth_mode=dict(required=False,
- choices=['none', 'hmac-sha256', 'md5', 'hmac-md5', 'simple'], type='str'),
- auth_text_simple=dict(required=False, type='str', no_log=True),
- auth_key_id=dict(required=False, type='str'),
- auth_text_md5=dict(required=False, type='str', no_log=True),
- nexthop_addr=dict(required=False, type='str'),
- nexthop_weight=dict(required=False, type='str'),
- max_load_balance=dict(required=False, type='str'),
- state=dict(required=False, default='present',
- choices=['present', 'absent'])
- )
- argument_spec.update(ce_argument_spec)
- module = OSPF(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_ospf_vrf.py b/plugins/modules/network/cloudengine/ce_ospf_vrf.py
deleted file mode 100644
index e1b1b721a8..0000000000
--- a/plugins/modules/network/cloudengine/ce_ospf_vrf.py
+++ /dev/null
@@ -1,1623 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_ospf_vrf
-short_description: Manages configuration of an OSPF VPN instance on HUAWEI CloudEngine switches.
-description:
- - Manages configuration of an OSPF VPN instance on HUAWEI CloudEngine switches.
-author: Yang yang (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- ospf:
- description:
- - The ID of the ospf process.
- Valid values are an integer, 1 - 4294967295, the default value is 1.
- required: true
- route_id:
- description:
- - Specifies the ospf private route id,.
- Valid values are a string, formatted as an IP address
- (i.e. "10.1.1.1") the length is 0 - 20.
- vrf:
- description:
- - Specifies the vpn instance which use ospf,length is 1 - 31.
- Valid values are a string.
- default: _public_
- description:
- description:
- - Specifies the description information of ospf process.
- bandwidth:
- description:
- - Specifies the reference bandwidth used to assign ospf cost.
- Valid values are an integer, in Mbps, 1 - 2147483648, the default value is 100.
- lsaalflag:
- description:
- - Specifies the mode of timer to calculate interval of arrive LSA.
- If set the parameter but not specifies value, the default will be used.
- If true use general timer.
- If false use intelligent timer.
- type: bool
- default: 'no'
- lsaainterval:
- description:
- - Specifies the interval of arrive LSA when use the general timer.
- Valid value is an integer, in millisecond, from 0 to 10000.
- lsaamaxinterval:
- description:
- - Specifies the max interval of arrive LSA when use the intelligent timer.
- Valid value is an integer, in millisecond, from 0 to 10000, the default value is 1000.
- lsaastartinterval:
- description:
- - Specifies the start interval of arrive LSA when use the intelligent timer.
- Valid value is an integer, in millisecond, from 0 to 10000, the default value is 500.
- lsaaholdinterval:
- description:
- - Specifies the hold interval of arrive LSA when use the intelligent timer.
- Valid value is an integer, in millisecond, from 0 to 10000, the default value is 500.
- lsaointervalflag:
- description:
- - Specifies whether cancel the interval of LSA originate or not.
- If set the parameter but noe specifies value, the default will be used.
- true:cancel the interval of LSA originate, the interval is 0.
- false:do not cancel the interval of LSA originate.
- type: bool
- default: 'no'
- lsaointerval:
- description:
- - Specifies the interval of originate LSA .
- Valid value is an integer, in second, from 0 to 10, the default value is 5.
- lsaomaxinterval:
- description:
- - Specifies the max interval of originate LSA .
- Valid value is an integer, in millisecond, from 1 to 10000, the default value is 5000.
- lsaostartinterval:
- description:
- - Specifies the start interval of originate LSA .
- Valid value is an integer, in millisecond, from 0 to 1000, the default value is 500.
- lsaoholdinterval:
- description:
- - Specifies the hold interval of originate LSA .
- Valid value is an integer, in millisecond, from 0 to 5000, the default value is 1000.
- spfintervaltype:
- description:
- - Specifies the mode of timer which used to calculate SPF.
- If set the parameter but noe specifies value, the default will be used.
- If is intelligent-timer, then use intelligent timer.
- If is timer, then use second level timer.
- If is millisecond, then use millisecond level timer.
- choices: ['intelligent-timer','timer','millisecond']
- default: intelligent-timer
- spfinterval:
- description:
- - Specifies the interval to calculate SPF when use second level timer.
- Valid value is an integer, in second, from 1 to 10.
- spfintervalmi:
- description:
- - Specifies the interval to calculate SPF when use millisecond level timer.
- Valid value is an integer, in millisecond, from 1 to 10000.
- spfmaxinterval:
- description:
- - Specifies the max interval to calculate SPF when use intelligent timer.
- Valid value is an integer, in millisecond, from 1 to 20000, the default value is 5000.
- spfstartinterval:
- description:
- - Specifies the start interval to calculate SPF when use intelligent timer.
- Valid value is an integer, in millisecond, from 1 to 1000, the default value is 50.
- spfholdinterval:
- description:
- - Specifies the hold interval to calculate SPF when use intelligent timer.
- Valid value is an integer, in millisecond, from 1 to 5000, the default value is 200.
- state:
- description:
- - Specify desired state of the resource.
- choices: ['present', 'absent']
- default: present
-'''
-
-EXAMPLES = '''
-- name: ospf vrf module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Configure ospf route id
- ce_ospf_vrf:
- ospf: 2
- route_id: 2.2.2.2
- lsaointervalflag: False
- lsaointerval: 2
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: verbose mode
- type: dict
- sample: {
- "bandwidth": "100",
- "description": null,
- "lsaaholdinterval": "500",
- "lsaainterval": null,
- "lsaamaxinterval": "1000",
- "lsaastartinterval": "500",
- "lsaalflag": "False",
- "lsaoholdinterval": "1000",
- "lsaointerval": "2",
- "lsaointervalflag": "False",
- "lsaomaxinterval": "5000",
- "lsaostartinterval": "500",
- "process_id": "2",
- "route_id": "2.2.2.2",
- "spfholdinterval": "1000",
- "spfinterval": null,
- "spfintervalmi": null,
- "spfintervaltype": "intelligent-timer",
- "spfmaxinterval": "10000",
- "spfstartinterval": "500",
- "vrf": "_public_"
- }
-existing:
- description: k/v pairs of existing configuration
- returned: verbose mode
- type: dict
- sample: {
- "bandwidthReference": "100",
- "description": null,
- "lsaArrivalFlag": "false",
- "lsaArrivalHoldInterval": "500",
- "lsaArrivalInterval": null,
- "lsaArrivalMaxInterval": "1000",
- "lsaArrivalStartInterval": "500",
- "lsaOriginateHoldInterval": "1000",
- "lsaOriginateInterval": "2",
- "lsaOriginateIntervalFlag": "false",
- "lsaOriginateMaxInterval": "5000",
- "lsaOriginateStartInterval": "500",
- "processId": "2",
- "routerId": "2.2.2.2",
- "spfScheduleHoldInterval": "1000",
- "spfScheduleInterval": null,
- "spfScheduleIntervalMillisecond": null,
- "spfScheduleIntervalType": "intelligent-timer",
- "spfScheduleMaxInterval": "10000",
- "spfScheduleStartInterval": "500",
- "vrfName": "_public_"
- }
-end_state:
- description: k/v pairs of configuration after module execution
- returned: verbose mode
- type: dict
- sample: {
- "bandwidthReference": "100",
- "description": null,
- "lsaArrivalFlag": "false",
- "lsaArrivalHoldInterval": "500",
- "lsaArrivalInterval": null,
- "lsaArrivalMaxInterval": "1000",
- "lsaArrivalStartInterval": "500",
- "lsaOriginateHoldInterval": "1000",
- "lsaOriginateInterval": "2",
- "lsaOriginateIntervalFlag": "false",
- "lsaOriginateMaxInterval": "5000",
- "lsaOriginateStartInterval": "500",
- "processId": "2",
- "routerId": "2.2.2.2",
- "spfScheduleHoldInterval": "1000",
- "spfScheduleInterval": null,
- "spfScheduleIntervalMillisecond": null,
- "spfScheduleIntervalType": "intelligent-timer",
- "spfScheduleMaxInterval": "10000",
- "spfScheduleStartInterval": "500",
- "vrfName": "_public_"
- }
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: ["ospf 2"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: False
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-CE_NC_GET_OSPF_VRF = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_CREATE_OSPF_VRF = """
-
-
-
-
- %s
-%s
- %s
- %s
- %s
- %s
- %s
- %s
- %s
- %s
- %s
- %s
- %s
- %s
- %s
- %s
- %s
- %s
- %s
- %s
- %s
-
-
-
-
-"""
-CE_NC_CREATE_ROUTE_ID = """
- %s
-"""
-
-CE_NC_DELETE_OSPF = """
-
-
-
-
- %s
- %s
- %s
-
-
-
-
-"""
-
-
-def build_config_xml(xmlstr):
- """build_config_xml"""
-
- return ' ' + xmlstr + ' '
-
-
-class OspfVrf(object):
- """
- Manages configuration of an ospf instance.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.ospf = self.module.params['ospf']
- self.route_id = self.module.params['route_id']
- self.vrf = self.module.params['vrf']
- self.description = self.module.params['description']
- self.bandwidth = self.module.params['bandwidth']
- self.lsaalflag = self.module.params['lsaalflag']
- self.lsaainterval = self.module.params['lsaainterval']
- self.lsaamaxinterval = self.module.params['lsaamaxinterval']
- self.lsaastartinterval = self.module.params['lsaastartinterval']
- self.lsaaholdinterval = self.module.params['lsaaholdinterval']
- self.lsaointervalflag = self.module.params['lsaointervalflag']
- self.lsaointerval = self.module.params['lsaointerval']
- self.lsaomaxinterval = self.module.params['lsaomaxinterval']
- self.lsaostartinterval = self.module.params['lsaostartinterval']
- self.lsaoholdinterval = self.module.params['lsaoholdinterval']
- self.spfintervaltype = self.module.params['spfintervaltype']
- self.spfinterval = self.module.params['spfinterval']
- self.spfintervalmi = self.module.params['spfintervalmi']
- self.spfmaxinterval = self.module.params['spfmaxinterval']
- self.spfstartinterval = self.module.params['spfstartinterval']
- self.spfholdinterval = self.module.params['spfholdinterval']
- self.state = self.module.params['state']
-
- # ospf info
- self.ospf_info = dict()
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
- self.lsa_arrival_changed = False
- self.lsa_originate_changed = False
- self.spf_changed = False
- self.route_id_changed = False
- self.bandwidth_changed = False
- self.description_changed = False
- self.vrf_changed = False
-
- def init_module(self):
- """" init module """
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def is_valid_ospf_process_id(self):
- """check whether the input ospf process id is valid"""
-
- if not self.ospf.isdigit():
- return False
- if int(self.ospf) > 4294967295 or int(self.ospf) < 1:
- return False
- return True
-
- def is_valid_ospf_route_id(self):
- """check is ipv4 addr is valid"""
-
- if self.route_id.find('.') != -1:
- addr_list = self.route_id.split('.')
- if len(addr_list) != 4:
- return False
- for each_num in addr_list:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- return True
- return False
-
- def is_valid_vrf_name(self):
- """check whether the input ospf vrf name is valid"""
-
- if len(self.vrf) > 31 or len(self.vrf) < 1:
- return False
- if self.vrf.find('?') != -1:
- return False
- if self.vrf.find(' ') != -1:
- return False
- return True
-
- def is_valid_description(self):
- """check whether the input ospf description is valid"""
-
- if len(self.description) > 80 or len(self.description) < 1:
- return False
- if self.description.find('?') != -1:
- return False
- return True
-
- def is_valid_bandwidth(self):
- """check whether the input ospf bandwidth reference is valid"""
-
- if not self.bandwidth.isdigit():
- return False
- if int(self.bandwidth) > 2147483648 or int(self.bandwidth) < 1:
- return False
- return True
-
- def is_valid_lsa_arrival_interval(self):
- """check whether the input ospf lsa arrival interval is valid"""
-
- if self.lsaainterval is None:
- return False
- if not self.lsaainterval.isdigit():
- return False
- if int(self.lsaainterval) > 10000 or int(self.lsaainterval) < 0:
- return False
- return True
-
- def isvalidlsamaxarrivalinterval(self):
- """check whether the input ospf lsa max arrival interval is valid"""
-
- if not self.lsaamaxinterval.isdigit():
- return False
- if int(self.lsaamaxinterval) > 10000 or int(self.lsaamaxinterval) < 1:
- return False
- return True
-
- def isvalidlsastartarrivalinterval(self):
- """check whether the input ospf lsa start arrival interval is valid"""
-
- if not self.lsaastartinterval.isdigit():
- return False
- if int(self.lsaastartinterval) > 1000 or int(self.lsaastartinterval) < 0:
- return False
- return True
-
- def isvalidlsaholdarrivalinterval(self):
- """check whether the input ospf lsa hold arrival interval is valid"""
-
- if not self.lsaaholdinterval.isdigit():
- return False
- if int(self.lsaaholdinterval) > 5000 or int(self.lsaaholdinterval) < 0:
- return False
- return True
-
- def is_valid_lsa_originate_interval(self):
- """check whether the input ospf lsa originate interval is valid"""
-
- if not self.lsaointerval.isdigit():
- return False
- if int(self.lsaointerval) > 10 or int(self.lsaointerval) < 0:
- return False
- return True
-
- def isvalidlsaoriginatemaxinterval(self):
- """check whether the input ospf lsa originate max interval is valid"""
-
- if not self.lsaomaxinterval.isdigit():
- return False
- if int(self.lsaomaxinterval) > 10000 or int(self.lsaomaxinterval) < 1:
- return False
- return True
-
- def isvalidlsaostartinterval(self):
- """check whether the input ospf lsa originate start interval is valid"""
-
- if not self.lsaostartinterval.isdigit():
- return False
- if int(self.lsaostartinterval) > 1000 or int(self.lsaostartinterval) < 0:
- return False
- return True
-
- def isvalidlsaoholdinterval(self):
- """check whether the input ospf lsa originate hold interval is valid"""
-
- if not self.lsaoholdinterval.isdigit():
- return False
- if int(self.lsaoholdinterval) > 5000 or int(self.lsaoholdinterval) < 1:
- return False
- return True
-
- def is_valid_spf_interval(self):
- """check whether the input ospf spf interval is valid"""
-
- if not self.spfinterval.isdigit():
- return False
- if int(self.spfinterval) > 10 or int(self.spfinterval) < 1:
- return False
- return True
-
- def is_valid_spf_milli_interval(self):
- """check whether the input ospf spf millisecond level interval is valid"""
-
- if not self.spfintervalmi.isdigit():
- return False
- if int(self.spfintervalmi) > 10000 or int(self.spfintervalmi) < 1:
- return False
- return True
-
- def is_valid_spf_max_interval(self):
- """check whether the input ospf spf intelligent timer max interval is valid"""
-
- if not self.spfmaxinterval.isdigit():
- return False
- if int(self.spfmaxinterval) > 20000 or int(self.spfmaxinterval) < 1:
- return False
- return True
-
- def is_valid_spf_start_interval(self):
- """check whether the input ospf spf intelligent timer start interval is valid"""
-
- if not self.spfstartinterval.isdigit():
- return False
- if int(self.spfstartinterval) > 1000 or int(self.spfstartinterval) < 1:
- return False
- return True
-
- def is_valid_spf_hold_interval(self):
- """check whether the input ospf spf intelligent timer hold interval is valid"""
-
- if not self.spfholdinterval.isdigit():
- return False
- if int(self.spfholdinterval) > 5000 or int(self.spfholdinterval) < 1:
- return False
- return True
-
- def is_route_id_exist(self):
- """is route id exist"""
-
- if not self.ospf_info:
- return False
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] != self.ospf:
- continue
- if ospf_site["routerId"] == self.route_id:
- return True
- else:
- continue
- return False
-
- def get_exist_ospf_id(self):
- """get exist ospf process id"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["processId"]
- else:
- continue
- return None
-
- def get_exist_route(self):
- """get exist route id"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["routerId"]
- else:
- continue
- return None
-
- def get_exist_vrf(self):
- """get exist vrf"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["vrfName"]
- else:
- continue
- return None
-
- def get_exist_bandwidth(self):
- """get exist bandwidth"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["bandwidthReference"]
- else:
- continue
- return None
-
- def get_exist_lsa_a_interval(self):
- """get exist lsa arrival interval"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["lsaArrivalInterval"]
- else:
- continue
- return None
-
- def get_exist_lsa_a_interval_flag(self):
- """get exist lsa arrival interval flag"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["lsaArrivalFlag"]
- else:
- continue
- return None
-
- def get_exist_lsa_a_max_interval(self):
- """get exist lsa arrival max interval"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["lsaArrivalMaxInterval"]
- else:
- continue
- return None
-
- def get_exist_lsa_a_start_interval(self):
- """get exist lsa arrival start interval"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["lsaArrivalStartInterval"]
- else:
- continue
- return None
-
- def get_exist_lsa_a_hold_interval(self):
- """get exist lsa arrival hold interval"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["lsaArrivalHoldInterval"]
- else:
- continue
- return None
-
- def getexistlsaointerval(self):
- """get exist lsa originate interval"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["lsaOriginateInterval"]
- else:
- continue
- return None
-
- def getexistlsaointerval_flag(self):
- """get exist lsa originate interval flag"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["lsaOriginateIntervalFlag"]
- else:
- continue
- return None
-
- def getexistlsaomaxinterval(self):
- """get exist lsa originate max interval"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["lsaOriginateMaxInterval"]
- else:
- continue
- return None
-
- def getexistlsaostartinterval(self):
- """get exist lsa originate start interval"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["lsaOriginateStartInterval"]
- else:
- continue
- return None
-
- def getexistlsaoholdinterval(self):
- """get exist lsa originate hold interval"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["lsaOriginateHoldInterval"]
- else:
- continue
- return None
-
- def get_exist_spf_interval(self):
- """get exist spf second level timer interval"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["spfScheduleInterval"]
- else:
- continue
- return None
-
- def get_exist_spf_milli_interval(self):
- """get exist spf millisecond level timer interval"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["spfScheduleIntervalMillisecond"]
- else:
- continue
- return None
-
- def get_exist_spf_max_interval(self):
- """get exist spf max interval"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["spfScheduleMaxInterval"]
- else:
- continue
- return None
-
- def get_exist_spf_start_interval(self):
- """get exist spf start interval"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["spfScheduleStartInterval"]
- else:
- continue
- return None
-
- def get_exist_spf_hold_interval(self):
- """get exist spf hold interval"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["spfScheduleHoldInterval"]
- else:
- continue
- return None
-
- def get_exist_spf_interval_type(self):
- """get exist spf hold interval"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["spfScheduleIntervalType"]
- else:
- continue
- return None
-
- def is_ospf_exist(self):
- """is ospf exist"""
-
- if not self.ospf_info:
- return False
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return True
- else:
- continue
- return False
-
- def get_exist_description(self):
- """is description exist"""
-
- if not self.ospf_info:
- return None
-
- for ospf_site in self.ospf_info["ospfsite"]:
- if ospf_site["processId"] == self.ospf:
- return ospf_site["description"]
- else:
- continue
- return None
-
- def check_params(self):
- """Check all input params"""
-
- if self.ospf == '':
- self.module.fail_json(
- msg='Error: The ospf process id should not be null.')
- if self.ospf:
- if not self.is_valid_ospf_process_id():
- self.module.fail_json(
- msg='Error: The ospf process id should between 1 - 4294967295.')
- if self.route_id == '':
- self.module.fail_json(
- msg='Error: The ospf route id length should not be null.')
- if self.route_id:
- if not self.is_valid_ospf_route_id():
- self.module.fail_json(
- msg='Error: The ospf route id length should between 0 - 20,i.e.10.1.1.1.')
- if self.vrf == '':
- self.module.fail_json(
- msg='Error: The ospf vpn instance length should not be null.')
- if self.vrf:
- if not self.is_valid_vrf_name():
- self.module.fail_json(
- msg='Error: The ospf vpn instance length should between 0 - 31,but can not contain " " or "?".')
- if self.description == '':
- self.module.fail_json(
- msg='Error: The ospf description should not be null.')
- if self.description:
- if not self.is_valid_description():
- self.module.fail_json(
- msg='Error: The ospf description length should between 1 - 80,but can not contain "?".')
- if self.bandwidth == '':
- self.module.fail_json(
- msg='Error: The ospf bandwidth reference should not be null.')
- if self.bandwidth:
- if not self.is_valid_bandwidth():
- self.module.fail_json(
- msg='Error: The ospf bandwidth reference should between 1 - 2147483648.')
- if self.lsaalflag is True:
- if not self.is_valid_lsa_arrival_interval():
- self.module.fail_json(
- msg='Error: The ospf lsa arrival interval should between 0 - 10000.')
- if self.lsaamaxinterval or self.lsaastartinterval or self.lsaaholdinterval:
- self.module.fail_json(
- msg='Error: Non-Intelligent Timer and Intelligent Timer Interval of '
- 'lsa-arrival-interval can not configured at the same time.')
- if self.lsaalflag is False:
- if self.lsaainterval:
- self.module.fail_json(
- msg='Error: The parameter of lsa arrival interval command is invalid, '
- 'because LSA arrival interval can not be config when the LSA arrival flag is not set.')
- if self.lsaamaxinterval == '' or self.lsaastartinterval == '' or self.lsaaholdinterval == '':
- self.module.fail_json(
- msg='Error: The ospf lsa arrival intervals should not be null.')
- if self.lsaamaxinterval:
- if not self.isvalidlsamaxarrivalinterval():
- self.module.fail_json(
- msg='Error: The ospf lsa arrival max interval should between 1 - 10000.')
- if self.lsaastartinterval:
- if not self.isvalidlsastartarrivalinterval():
- self.module.fail_json(
- msg='Error: The ospf lsa arrival start interval should between 1 - 1000.')
- if self.lsaaholdinterval:
- if not self.isvalidlsaholdarrivalinterval():
- self.module.fail_json(
- msg='Error: The ospf lsa arrival hold interval should between 1 - 5000.')
- if self.lsaointervalflag is True:
- if self.lsaointerval or self.lsaomaxinterval \
- or self.lsaostartinterval or self.lsaoholdinterval:
- self.module.fail_json(
- msg='Error: Interval for other-type and Instantly Flag '
- 'of lsa-originate-interval can not configured at the same time.')
- if self.lsaointerval == '':
- self.module.fail_json(
- msg='Error: The ospf lsa originate interval should should not be null.')
- if self.lsaointerval:
- if not self.is_valid_lsa_originate_interval():
- self.module.fail_json(
- msg='Error: The ospf lsa originate interval should between 0 - 10 s.')
- if self.lsaomaxinterval == '' or self.lsaostartinterval == '' or self.lsaoholdinterval == '':
- self.module.fail_json(
- msg='Error: The ospf lsa originate intelligent intervals should should not be null.')
- if self.lsaomaxinterval:
- if not self.isvalidlsaoriginatemaxinterval():
- self.module.fail_json(
- msg='Error: The ospf lsa originate max interval should between 1 - 10000 ms.')
- if self.lsaostartinterval:
- if not self.isvalidlsaostartinterval():
- self.module.fail_json(
- msg='Error: The ospf lsa originate start interval should between 0 - 1000 ms.')
- if self.lsaoholdinterval:
- if not self.isvalidlsaoholdinterval():
- self.module.fail_json(
- msg='Error: The ospf lsa originate hold interval should between 1 - 5000 ms.')
- if self.spfintervaltype == '':
- self.module.fail_json(
- msg='Error: The ospf spf interval type should should not be null.')
- if self.spfintervaltype == 'intelligent-timer':
- if self.spfinterval is not None or self.spfintervalmi is not None:
- self.module.fail_json(
- msg='Error: Interval second and interval millisecond '
- 'of spf-schedule-interval can not configured if use intelligent timer.')
- if self.spfmaxinterval == '' or self.spfstartinterval == '' or self.spfholdinterval == '':
- self.module.fail_json(
- msg='Error: The ospf spf intelligent timer intervals should should not be null.')
- if self.spfmaxinterval and not self.is_valid_spf_max_interval():
- self.module.fail_json(
- msg='Error: The ospf spf max interval of intelligent timer should between 1 - 20000 ms.')
- if self.spfstartinterval and not self.is_valid_spf_start_interval():
- self.module.fail_json(
- msg='Error: The ospf spf start interval of intelligent timer should between 1 - 1000 ms.')
- if self.spfholdinterval and not self.is_valid_spf_hold_interval():
- self.module.fail_json(
- msg='Error: The ospf spf hold interval of intelligent timer should between 1 - 5000 ms.')
- if self.spfintervaltype == 'timer':
- if self.spfintervalmi is not None:
- self.module.fail_json(
- msg='Error: Interval second and interval millisecond '
- 'of spf-schedule-interval can not configured at the same time.')
- if self.spfmaxinterval or self.spfstartinterval or self.spfholdinterval:
- self.module.fail_json(
- msg='Error: Interval second and interval intelligent '
- 'of spf-schedule-interval can not configured at the same time.')
- if self.spfinterval == '' or self.spfinterval is None:
- self.module.fail_json(
- msg='Error: The ospf spf timer intervals should should not be null.')
- if not self.is_valid_spf_interval():
- self.module.fail_json(
- msg='Error: Interval second should between 1 - 10 s.')
- if self.spfintervaltype == 'millisecond':
- if self.spfinterval is not None:
- self.module.fail_json(
- msg='Error: Interval millisecond and interval second '
- 'of spf-schedule-interval can not configured at the same time.')
- if self.spfmaxinterval or self.spfstartinterval or self.spfholdinterval:
- self.module.fail_json(
- msg='Error: Interval millisecond and interval intelligent '
- 'of spf-schedule-interval can not configured at the same time.')
- if self.spfintervalmi == '' or self.spfintervalmi is None:
- self.module.fail_json(
- msg='Error: The ospf spf millisecond intervals should should not be null.')
- if not self.is_valid_spf_milli_interval():
- self.module.fail_json(
- msg='Error: Interval millisecond should between 1 - 10000 ms.')
-
- def get_ospf_info(self):
- """ get the detail information of ospf """
-
- self.ospf_info["ospfsite"] = list()
-
- getxmlstr = CE_NC_GET_OSPF_VRF
- xml_str = get_nc_config(self.module, getxmlstr)
- if 'data/' in xml_str:
- return
-
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
-
- # get the vpn address family and RD text
- ospf_sites = root.findall(
- "ospfv2/ospfv2comm/ospfSites/ospfSite")
- if ospf_sites:
- for ospf_site in ospf_sites:
- ospf_ele_info = dict()
- for ospf_site_ele in ospf_site:
- if ospf_site_ele.tag in ["processId", "routerId", "vrfName", "bandwidthReference",
- "description", "lsaArrivalInterval", "lsaArrivalMaxInterval",
- "lsaArrivalStartInterval", "lsaArrivalHoldInterval", "lsaArrivalFlag",
- "lsaOriginateInterval", "lsaOriginateMaxInterval",
- "lsaOriginateStartInterval", "lsaOriginateHoldInterval",
- "lsaOriginateIntervalFlag", "spfScheduleInterval",
- "spfScheduleIntervalMillisecond", "spfScheduleMaxInterval",
- "spfScheduleStartInterval", "spfScheduleHoldInterval",
- "spfScheduleIntervalType"]:
- ospf_ele_info[
- ospf_site_ele.tag] = ospf_site_ele.text
- if ospf_ele_info["processId"] == self.ospf:
- self.ospf_info["ospfsite"].append(ospf_ele_info)
-
- def get_proposed(self):
- """get proposed info"""
-
- self.proposed["process_id"] = self.ospf
- self.proposed["route_id"] = self.route_id
- self.proposed["vrf"] = self.vrf
- self.proposed["description"] = self.description
- self.proposed["bandwidth"] = self.bandwidth
- self.proposed["lsaalflag"] = self.lsaalflag
- self.proposed["lsaainterval"] = self.lsaainterval
- self.proposed["lsaamaxinterval"] = self.lsaamaxinterval
- self.proposed["lsaastartinterval"] = self.lsaastartinterval
- self.proposed["lsaaholdinterval"] = self.lsaaholdinterval
- self.proposed["lsaointervalflag"] = self.lsaointervalflag
- self.proposed["lsaointerval"] = self.lsaointerval
- self.proposed["lsaomaxinterval"] = self.lsaomaxinterval
- self.proposed["lsaostartinterval"] = self.lsaostartinterval
- self.proposed["lsaoholdinterval"] = self.lsaoholdinterval
- self.proposed["spfintervaltype"] = self.spfintervaltype
- self.proposed["spfinterval"] = self.spfinterval
- self.proposed["spfintervalmi"] = self.spfintervalmi
- self.proposed["spfmaxinterval"] = self.spfmaxinterval
- self.proposed["spfstartinterval"] = self.spfstartinterval
- self.proposed["spfholdinterval"] = self.spfholdinterval
-
- def operate_ospf_info(self):
- """operate ospf info"""
-
- config_route_id_xml = ''
- vrf = self.get_exist_vrf()
- if vrf is None:
- vrf = '_public_'
- description = self.get_exist_description()
- if description is None:
- description = ''
- bandwidth_reference = self.get_exist_bandwidth()
- if bandwidth_reference is None:
- bandwidth_reference = '100'
- lsa_in_interval = self.get_exist_lsa_a_interval()
- if lsa_in_interval is None:
- lsa_in_interval = ''
- lsa_arrival_max_interval = self.get_exist_lsa_a_max_interval()
- if lsa_arrival_max_interval is None:
- lsa_arrival_max_interval = '1000'
- lsa_arrival_start_interval = self.get_exist_lsa_a_start_interval()
- if lsa_arrival_start_interval is None:
- lsa_arrival_start_interval = '500'
- lsa_arrival_hold_interval = self.get_exist_lsa_a_hold_interval()
- if lsa_arrival_hold_interval is None:
- lsa_arrival_hold_interval = '500'
- lsa_originate_interval = self.getexistlsaointerval()
- if lsa_originate_interval is None:
- lsa_originate_interval = '5'
- lsa_originate_max_interval = self.getexistlsaomaxinterval()
- if lsa_originate_max_interval is None:
- lsa_originate_max_interval = '5000'
- lsa_originate_start_interval = self.getexistlsaostartinterval()
- if lsa_originate_start_interval is None:
- lsa_originate_start_interval = '500'
- lsa_originate_hold_interval = self.getexistlsaoholdinterval()
- if lsa_originate_hold_interval is None:
- lsa_originate_hold_interval = '1000'
- spf_interval = self.get_exist_spf_interval()
- if spf_interval is None:
- spf_interval = ''
- spf_interval_milli = self.get_exist_spf_milli_interval()
- if spf_interval_milli is None:
- spf_interval_milli = ''
- spf_max_interval = self.get_exist_spf_max_interval()
- if spf_max_interval is None:
- spf_max_interval = '5000'
- spf_start_interval = self.get_exist_spf_start_interval()
- if spf_start_interval is None:
- spf_start_interval = '50'
- spf_hold_interval = self.get_exist_spf_hold_interval()
- if spf_hold_interval is None:
- spf_hold_interval = '200'
-
- if self.route_id:
- if self.state == 'present':
- if self.route_id != self.get_exist_route():
- self.route_id_changed = True
- config_route_id_xml = CE_NC_CREATE_ROUTE_ID % self.route_id
- else:
- if self.route_id != self.get_exist_route():
- self.module.fail_json(
- msg='Error: The route id %s is not exist.' % self.route_id)
- self.route_id_changed = True
- configxmlstr = CE_NC_DELETE_OSPF % (
- self.ospf, self.get_exist_route(), self.get_exist_vrf())
- conf_str = build_config_xml(configxmlstr)
-
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "OPERATE_VRF_AF")
- self.changed = True
- return
- if self.vrf != '_public_':
- if self.state == 'present':
- if self.vrf != self.get_exist_vrf():
- self.vrf_changed = True
- vrf = self.vrf
- else:
- if self.vrf != self.get_exist_vrf():
- self.module.fail_json(
- msg='Error: The vrf %s is not exist.' % self.vrf)
- self.vrf_changed = True
- configxmlstr = CE_NC_DELETE_OSPF % (
- self.ospf, self.get_exist_route(), self.get_exist_vrf())
- conf_str = build_config_xml(configxmlstr)
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "OPERATE_VRF_AF")
- self.changed = True
- return
- if self.bandwidth:
- if self.state == 'present':
- if self.bandwidth != self.get_exist_bandwidth():
- self.bandwidth_changed = True
- bandwidth_reference = self.bandwidth
- else:
- if self.bandwidth != self.get_exist_bandwidth():
- self.module.fail_json(
- msg='Error: The bandwidth %s is not exist.' % self.bandwidth)
- if self.get_exist_bandwidth() != '100':
- self.bandwidth_changed = True
- bandwidth_reference = '100'
- if self.description:
- if self.state == 'present':
- if self.description != self.get_exist_description():
- self.description_changed = True
- description = self.description
- else:
- if self.description != self.get_exist_description():
- self.module.fail_json(
- msg='Error: The description %s is not exist.' % self.description)
- self.description_changed = True
- description = ''
-
- if self.lsaalflag is False:
- lsa_in_interval = ''
- if self.state == 'present':
- if self.lsaamaxinterval:
- if self.lsaamaxinterval != self.get_exist_lsa_a_max_interval():
- self.lsa_arrival_changed = True
- lsa_arrival_max_interval = self.lsaamaxinterval
- if self.lsaastartinterval:
- if self.lsaastartinterval != self.get_exist_lsa_a_start_interval():
- self.lsa_arrival_changed = True
- lsa_arrival_start_interval = self.lsaastartinterval
- if self.lsaaholdinterval:
- if self.lsaaholdinterval != self.get_exist_lsa_a_hold_interval():
- self.lsa_arrival_changed = True
- lsa_arrival_hold_interval = self.lsaaholdinterval
- else:
- if self.lsaamaxinterval:
- if self.lsaamaxinterval != self.get_exist_lsa_a_max_interval():
- self.module.fail_json(
- msg='Error: The lsaamaxinterval %s is not exist.' % self.lsaamaxinterval)
- if self.get_exist_lsa_a_max_interval() != '1000':
- lsa_arrival_max_interval = '1000'
- self.lsa_arrival_changed = True
- if self.lsaastartinterval:
- if self.lsaastartinterval != self.get_exist_lsa_a_start_interval():
- self.module.fail_json(
- msg='Error: The lsaastartinterval %s is not exist.' % self.lsaastartinterval)
- if self.get_exist_lsa_a_start_interval() != '500':
- lsa_arrival_start_interval = '500'
- self.lsa_arrival_changed = True
- if self.lsaaholdinterval:
- if self.lsaaholdinterval != self.get_exist_lsa_a_hold_interval():
- self.module.fail_json(
- msg='Error: The lsaaholdinterval %s is not exist.' % self.lsaaholdinterval)
- if self.get_exist_lsa_a_hold_interval() != '500':
- lsa_arrival_hold_interval = '500'
- self.lsa_arrival_changed = True
- else:
- if self.state == 'present':
- lsaalflag = "false"
- if self.lsaalflag is True:
- lsaalflag = "true"
- if lsaalflag != self.get_exist_lsa_a_interval_flag():
- self.lsa_arrival_changed = True
- if self.lsaainterval is None:
- self.module.fail_json(
- msg='Error: The lsaainterval is not supplied.')
- else:
- lsa_in_interval = self.lsaainterval
- else:
- if self.lsaainterval:
- if self.lsaainterval != self.get_exist_lsa_a_interval():
- self.lsa_arrival_changed = True
- lsa_in_interval = self.lsaainterval
- else:
- if self.lsaainterval:
- if self.lsaainterval != self.get_exist_lsa_a_interval():
- self.module.fail_json(
- msg='Error: The lsaainterval %s is not exist.' % self.lsaainterval)
- self.lsaalflag = False
- lsa_in_interval = ''
- self.lsa_arrival_changed = True
-
- if self.lsaointervalflag is False:
- if self.state == 'present':
- if self.lsaomaxinterval:
- if self.lsaomaxinterval != self.getexistlsaomaxinterval():
- self.lsa_originate_changed = True
- lsa_originate_max_interval = self.lsaomaxinterval
- if self.lsaostartinterval:
- if self.lsaostartinterval != self.getexistlsaostartinterval():
- self.lsa_originate_changed = True
- lsa_originate_start_interval = self.lsaostartinterval
- if self.lsaoholdinterval:
- if self.lsaoholdinterval != self.getexistlsaoholdinterval():
- self.lsa_originate_changed = True
- lsa_originate_hold_interval = self.lsaoholdinterval
- if self.lsaointerval:
- if self.lsaointerval != self.getexistlsaointerval():
- self.lsa_originate_changed = True
- lsa_originate_interval = self.lsaointerval
- else:
- if self.lsaomaxinterval:
- if self.lsaomaxinterval != self.getexistlsaomaxinterval():
- self.module.fail_json(
- msg='Error: The lsaomaxinterval %s is not exist.' % self.lsaomaxinterval)
- if self.getexistlsaomaxinterval() != '5000':
- lsa_originate_max_interval = '5000'
- self.lsa_originate_changed = True
- if self.lsaostartinterval:
- if self.lsaostartinterval != self.getexistlsaostartinterval():
- self.module.fail_json(
- msg='Error: The lsaostartinterval %s is not exist.' % self.lsaostartinterval)
- if self.getexistlsaostartinterval() != '500':
- lsa_originate_start_interval = '500'
- self.lsa_originate_changed = True
- if self.lsaoholdinterval:
- if self.lsaoholdinterval != self.getexistlsaoholdinterval():
- self.module.fail_json(
- msg='Error: The lsaoholdinterval %s is not exist.' % self.lsaoholdinterval)
- if self.getexistlsaoholdinterval() != '1000':
- lsa_originate_hold_interval = '1000'
- self.lsa_originate_changed = True
- if self.lsaointerval:
- if self.lsaointerval != self.getexistlsaointerval():
- self.module.fail_json(
- msg='Error: The lsaointerval %s is not exist.' % self.lsaointerval)
- if self.getexistlsaointerval() != '5':
- lsa_originate_interval = '5'
- self.lsa_originate_changed = True
- else:
- if self.state == 'present':
- if self.getexistlsaointerval_flag() != 'true':
- self.lsa_originate_changed = True
- lsa_originate_interval = '5'
- lsa_originate_max_interval = '5000'
- lsa_originate_start_interval = '500'
- lsa_originate_hold_interval = '1000'
- else:
- if self.getexistlsaointerval_flag() == 'true':
- self.lsaointervalflag = False
- self.lsa_originate_changed = True
- if self.spfintervaltype != self.get_exist_spf_interval_type():
- self.spf_changed = True
- if self.spfintervaltype == 'timer':
- if self.spfinterval:
- if self.state == 'present':
- if self.spfinterval != self.get_exist_spf_interval():
- self.spf_changed = True
- spf_interval = self.spfinterval
- spf_interval_milli = ''
- else:
- if self.spfinterval != self.get_exist_spf_interval():
- self.module.fail_json(
- msg='Error: The spfinterval %s is not exist.' % self.spfinterval)
- self.spfintervaltype = 'intelligent-timer'
- spf_interval = ''
- self.spf_changed = True
- if self.spfintervaltype == 'millisecond':
- if self.spfintervalmi:
- if self.state == 'present':
- if self.spfintervalmi != self.get_exist_spf_milli_interval():
- self.spf_changed = True
- spf_interval_milli = self.spfintervalmi
- spf_interval = ''
- else:
- if self.spfintervalmi != self.get_exist_spf_milli_interval():
- self.module.fail_json(
- msg='Error: The spfintervalmi %s is not exist.' % self.spfintervalmi)
- self.spfintervaltype = 'intelligent-timer'
- spf_interval_milli = ''
- self.spf_changed = True
- if self.spfintervaltype == 'intelligent-timer':
- spf_interval = ''
- spf_interval_milli = ''
- if self.spfmaxinterval:
- if self.state == 'present':
- if self.spfmaxinterval != self.get_exist_spf_max_interval():
- self.spf_changed = True
- spf_max_interval = self.spfmaxinterval
- else:
- if self.spfmaxinterval != self.get_exist_spf_max_interval():
- self.module.fail_json(
- msg='Error: The spfmaxinterval %s is not exist.' % self.spfmaxinterval)
- if self.get_exist_spf_max_interval() != '5000':
- self.spf_changed = True
- spf_max_interval = '5000'
- if self.spfstartinterval:
- if self.state == 'present':
- if self.spfstartinterval != self.get_exist_spf_start_interval():
- self.spf_changed = True
- spf_start_interval = self.spfstartinterval
- else:
- if self.spfstartinterval != self.get_exist_spf_start_interval():
- self.module.fail_json(
- msg='Error: The spfstartinterval %s is not exist.' % self.spfstartinterval)
- if self.get_exist_spf_start_interval() != '50':
- self.spf_changed = True
- spf_start_interval = '50'
- if self.spfholdinterval:
- if self.state == 'present':
- if self.spfholdinterval != self.get_exist_spf_hold_interval():
- self.spf_changed = True
- spf_hold_interval = self.spfholdinterval
- else:
- if self.spfholdinterval != self.get_exist_spf_hold_interval():
- self.module.fail_json(
- msg='Error: The spfholdinterval %s is not exist.' % self.spfholdinterval)
- if self.get_exist_spf_hold_interval() != '200':
- self.spf_changed = True
- spf_hold_interval = '200'
-
- if not self.description_changed and not self.vrf_changed and not self.lsa_arrival_changed \
- and not self.lsa_originate_changed and not self.spf_changed \
- and not self.route_id_changed and not self.bandwidth_changed:
- self.changed = False
- return
- else:
- self.changed = True
- lsaointervalflag = "false"
- lsaalflag = "false"
- if self.lsaointervalflag is True:
- lsaointervalflag = "true"
- if self.lsaalflag is True:
- lsaalflag = "true"
- configxmlstr = CE_NC_CREATE_OSPF_VRF % (
- self.ospf, config_route_id_xml, vrf,
- description, bandwidth_reference, lsaalflag,
- lsa_in_interval, lsa_arrival_max_interval, lsa_arrival_start_interval,
- lsa_arrival_hold_interval, lsaointervalflag, lsa_originate_interval,
- lsa_originate_max_interval, lsa_originate_start_interval, lsa_originate_hold_interval,
- self.spfintervaltype, spf_interval, spf_interval_milli,
- spf_max_interval, spf_start_interval, spf_hold_interval)
-
- conf_str = build_config_xml(configxmlstr)
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "OPERATE_VRF_AF")
-
- def get_existing(self):
- """get existing info"""
-
- self.get_ospf_info()
- self.existing['ospf_info'] = self.ospf_info["ospfsite"]
-
- def set_update_cmd(self):
- """ set update command"""
- if not self.changed:
- return
-
- if self.state == 'present':
- if self.vrf_changed:
- if self.vrf != '_public_':
- if self.route_id_changed:
- self.updates_cmd.append(
- 'ospf %s router-id %s vpn-instance %s' % (self.ospf, self.route_id, self.vrf))
- else:
- self.updates_cmd.append(
- 'ospf %s vpn-instance %s ' % (self.ospf, self.vrf))
- else:
- if self.route_id_changed:
- self.updates_cmd.append(
- 'ospf %s router-id %s' % (self.ospf, self.route_id))
- else:
- if self.route_id_changed:
- if self.vrf != '_public_':
- self.updates_cmd.append(
- 'ospf %s router-id %s vpn-instance %s' % (self.ospf, self.route_id, self.get_exist_vrf()))
- else:
- self.updates_cmd.append(
- 'ospf %s router-id %s' % (self.ospf, self.route_id))
- else:
- if self.route_id_changed:
- self.updates_cmd.append('undo ospf %s' % self.ospf)
- return
-
- self.updates_cmd.append('ospf %s' % self.ospf)
-
- if self.description:
- if self.state == 'present':
- if self.description_changed:
- self.updates_cmd.append(
- 'description %s' % self.description)
- else:
- if self.description_changed:
- self.updates_cmd.append('undo description')
- if self.bandwidth_changed:
- if self.state == 'present':
- if self.get_exist_bandwidth() != '100':
- self.updates_cmd.append(
- 'bandwidth-reference %s' % (self.get_exist_bandwidth()))
- else:
- self.updates_cmd.append('undo bandwidth-reference')
- if self.lsaalflag is True:
- if self.lsa_arrival_changed:
- if self.state == 'present':
- self.updates_cmd.append(
- 'lsa-arrival-interval %s' % (self.get_exist_lsa_a_interval()))
- else:
- self.updates_cmd.append(
- 'undo lsa-arrival-interval')
-
- if self.lsaalflag is False:
- if self.lsa_arrival_changed:
- if self.state == 'present':
- if self.get_exist_lsa_a_max_interval() != '1000' \
- or self.get_exist_lsa_a_start_interval() != '500'\
- or self.get_exist_lsa_a_hold_interval() != '500':
- self.updates_cmd.append('lsa-arrival-interval intelligent-timer %s %s %s'
- % (self.get_exist_lsa_a_max_interval(),
- self.get_exist_lsa_a_start_interval(),
- self.get_exist_lsa_a_hold_interval()))
- else:
- if self.get_exist_lsa_a_max_interval() == '1000' \
- and self.get_exist_lsa_a_start_interval() == '500'\
- and self.get_exist_lsa_a_hold_interval() == '500':
- self.updates_cmd.append(
- 'undo lsa-arrival-interval')
- if self.lsaointervalflag is False:
- if self.lsa_originate_changed:
- if self.state == 'present':
- if self.getexistlsaointerval() != '5' \
- or self.getexistlsaomaxinterval() != '5000' \
- or self.getexistlsaostartinterval() != '500' \
- or self.getexistlsaoholdinterval() != '1000':
- self.updates_cmd.append('lsa-originate-interval other-type %s intelligent-timer %s %s %s'
- % (self.getexistlsaointerval(),
- self.getexistlsaomaxinterval(),
- self.getexistlsaostartinterval(),
- self.getexistlsaoholdinterval()))
- else:
- self.updates_cmd.append(
- 'undo lsa-originate-interval')
- if self.lsaointervalflag is True:
- if self.lsa_originate_changed:
- if self.state == 'present':
- self.updates_cmd.append('lsa-originate-interval 0 ')
- else:
- self.updates_cmd.append(
- 'undo lsa-originate-interval')
- if self.spfintervaltype == 'millisecond':
- if self.spf_changed:
- if self.state == 'present':
- self.updates_cmd.append(
- 'spf-schedule-interval millisecond %s' % self.get_exist_spf_milli_interval())
- else:
- self.updates_cmd.append(
- 'undo spf-schedule-interval')
- if self.spfintervaltype == 'timer':
- if self.spf_changed:
- if self.state == 'present':
- self.updates_cmd.append(
- 'spf-schedule-interval %s' % self.get_exist_spf_interval())
- else:
- self.updates_cmd.append(
- 'undo spf-schedule-interval')
- if self.spfintervaltype == 'intelligent-timer':
- if self.spf_changed:
- if self.state == 'present':
- if self.get_exist_spf_max_interval() != '5000' \
- or self.get_exist_spf_start_interval() != '50' \
- or self.get_exist_spf_hold_interval() != '200':
- self.updates_cmd.append('spf-schedule-interval intelligent-timer %s %s %s'
- % (self.get_exist_spf_max_interval(),
- self.get_exist_spf_start_interval(),
- self.get_exist_spf_hold_interval()))
- else:
- self.updates_cmd.append(
- 'undo spf-schedule-interval')
-
- def get_end_state(self):
- """get end state info"""
-
- self.get_ospf_info()
- self.end_state['ospf_info'] = self.ospf_info["ospfsite"]
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.get_existing()
- self.get_proposed()
- self.operate_ospf_info()
- self.get_end_state()
- self.set_update_cmd()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- ospf=dict(required=True, type='str'),
- route_id=dict(required=False, type='str'),
- vrf=dict(required=False, type='str', default='_public_'),
- description=dict(required=False, type='str'),
- bandwidth=dict(required=False, type='str'),
- lsaalflag=dict(type='bool', default=False),
- lsaainterval=dict(required=False, type='str'),
- lsaamaxinterval=dict(required=False, type='str'),
- lsaastartinterval=dict(required=False, type='str'),
- lsaaholdinterval=dict(required=False, type='str'),
- lsaointervalflag=dict(type='bool', default=False),
- lsaointerval=dict(required=False, type='str'),
- lsaomaxinterval=dict(required=False, type='str'),
- lsaostartinterval=dict(required=False, type='str'),
- lsaoholdinterval=dict(required=False, type='str'),
- spfintervaltype=dict(required=False, default='intelligent-timer',
- choices=['intelligent-timer', 'timer', 'millisecond']),
- spfinterval=dict(required=False, type='str'),
- spfintervalmi=dict(required=False, type='str'),
- spfmaxinterval=dict(required=False, type='str'),
- spfstartinterval=dict(required=False, type='str'),
- spfholdinterval=dict(required=False, type='str'),
- state=dict(required=False, choices=['present', 'absent'], default='present'),
- )
-
- argument_spec.update(ce_argument_spec)
- module = OspfVrf(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_reboot.py b/plugins/modules/network/cloudengine/ce_reboot.py
deleted file mode 100644
index 289c67a43e..0000000000
--- a/plugins/modules/network/cloudengine/ce_reboot.py
+++ /dev/null
@@ -1,169 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_reboot
-short_description: Reboot a HUAWEI CloudEngine switches.
-description:
- - Reboot a HUAWEI CloudEngine switches.
-author: Gong Jianjun (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-requirements: ["ncclient"]
-options:
- confirm:
- description:
- - Safeguard boolean. Set to true if you're sure you want to reboot.
- type: bool
- required: true
- save_config:
- description:
- - Flag indicating whether to save the configuration.
- required: false
- type: bool
- default: false
-'''
-
-EXAMPLES = '''
-- name: reboot module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
- - name: Reboot the device
- ce_reboot:
- confirm: true
- save_config: true
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-rebooted:
- description: Whether the device was instructed to reboot.
- returned: success
- type: bool
- sample: true
-'''
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import execute_nc_action, ce_argument_spec
-
-try:
- from ncclient.operations.errors import TimeoutExpiredError
- HAS_NCCLIENT = True
-except ImportError:
- HAS_NCCLIENT = False
-
-CE_NC_XML_EXECUTE_REBOOT = """
-
-
-
- %s
-
-
-
-"""
-
-
-class Reboot(object):
- """ Reboot a network device """
-
- def __init__(self, **kwargs):
- """ __init___ """
-
- self.network_module = None
- self.netconf = None
- self.init_network_module(**kwargs)
-
- self.confirm = self.network_module.params['confirm']
- self.save_config = self.network_module.params['save_config']
-
- def init_network_module(self, **kwargs):
- """ init network module """
-
- self.network_module = AnsibleModule(**kwargs)
-
- def netconf_set_action(self, xml_str):
- """ netconf execute action """
-
- try:
- execute_nc_action(self.network_module, xml_str)
- except TimeoutExpiredError:
- pass
-
- def work(self):
- """ start to work """
-
- if not self.confirm:
- self.network_module.fail_json(
- msg='Error: Confirm must be set to true for this module to work.')
-
- xml_str = CE_NC_XML_EXECUTE_REBOOT % str(self.save_config).lower()
- self.netconf_set_action(xml_str)
-
-
-def main():
- """ main """
-
- argument_spec = dict(
- confirm=dict(required=True, type='bool'),
- save_config=dict(default=False, type='bool')
- )
-
- argument_spec.update(ce_argument_spec)
- module = Reboot(argument_spec=argument_spec, supports_check_mode=True)
-
- if not HAS_NCCLIENT:
- module.network_module.fail_json(msg='Error: The ncclient library is required.')
-
- changed = False
- rebooted = False
-
- module.work()
-
- changed = True
- rebooted = True
-
- results = dict()
- results['changed'] = changed
- results['rebooted'] = rebooted
-
- module.network_module.exit_json(**results)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_rollback.py b/plugins/modules/network/cloudengine/ce_rollback.py
deleted file mode 100644
index 428b32ddf2..0000000000
--- a/plugins/modules/network/cloudengine/ce_rollback.py
+++ /dev/null
@@ -1,453 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_rollback
-short_description: Set a checkpoint or rollback to a checkpoint on HUAWEI CloudEngine switches.
-description:
- - This module offers the ability to set a configuration checkpoint
- file or rollback to a configuration checkpoint file on HUAWEI CloudEngine switches.
-author:
- - Li Yanfeng (@QijunPan)
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- commit_id:
- description:
- - Specifies the label of the configuration rollback point to which system configurations are
- expected to roll back.
- The value is an integer that the system generates automatically.
- label:
- description:
- - Specifies a user label for a configuration rollback point.
- The value is a string of 1 to 256 case-sensitive ASCII characters, spaces not supported.
- The value must start with a letter and cannot be presented in a single hyphen (-).
- filename:
- description:
- - Specifies a configuration file for configuration rollback.
- The value is a string of 5 to 64 case-sensitive characters in the format of *.zip, *.cfg, or *.dat,
- spaces not supported.
- last:
- description:
- - Specifies the number of configuration rollback points.
- The value is an integer that ranges from 1 to 80.
- oldest:
- description:
- - Specifies the number of configuration rollback points.
- The value is an integer that ranges from 1 to 80.
- action:
- description:
- - The operation of configuration rollback.
- required: true
- choices: ['rollback','clear','set','display','commit']
-'''
-EXAMPLES = '''
-- name: rollback module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
-- name: Ensure commit_id is exist, and specifies the label of the configuration rollback point to
- which system configurations are expected to roll back.
- ce_rollback:
- commit_id: 1000000748
- action: rollback
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: sometimes
- type: dict
- sample: {"commit_id": "1000000748", "action": "rollback"}
-existing:
- description: k/v pairs of existing rollback
- returned: sometimes
- type: dict
- sample: {"commitId": "1000000748", "userLabel": "abc"}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["rollback configuration to file a.cfg",
- "set configuration commit 1000000783 label ddd",
- "clear configuration commit 1000000783 label",
- "display configuration commit list"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-end_state:
- description: k/v pairs of configuration after module execution
- returned: always
- type: dict
- sample: {"commitId": "1000000748", "userLabel": "abc"}
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec, exec_command, run_commands
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ComplexList
-
-
-class RollBack(object):
- """
- Manages rolls back the system from the current configuration state to a historical configuration state.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = AnsibleModule(argument_spec=self.spec, supports_check_mode=True)
- self.commands = list()
- # module input info
- self.commit_id = self.module.params['commit_id']
- self.label = self.module.params['label']
- self.filename = self.module.params['filename']
- self.last = self.module.params['last']
- self.oldest = self.module.params['oldest']
- self.action = self.module.params['action']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.existing = dict()
- self.proposed = dict()
- self.end_state = dict()
-
- # configuration rollback points info
- self.rollback_info = None
- self.init_module()
-
- def init_module(self):
- """ init module """
-
- required_if = [('action', 'set', ['commit_id', 'label']), ('action', 'commit', ['label'])]
- mutually_exclusive = None
- required_one_of = None
- if self.action == "rollback":
- required_one_of = [['commit_id', 'label', 'filename', 'last']]
- elif self.action == "clear":
- required_one_of = [['commit_id', 'oldest']]
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True, required_if=required_if, mutually_exclusive=mutually_exclusive, required_one_of=required_one_of)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def cli_add_command(self, command, undo=False):
- """add command to self.update_cmd and self.commands"""
- self.commands.append("return")
- self.commands.append("mmi-mode enable")
-
- if self.action == "commit":
- self.commands.append("sys")
-
- self.commands.append(command)
- self.updates_cmd.append(command)
-
- def cli_load_config(self, commands):
- """load config by cli"""
-
- if not self.module.check_mode:
- run_commands(self.module, commands)
-
- def get_config(self, flags=None):
- """Retrieves the current config from the device or cache
- """
- flags = [] if flags is None else flags
-
- cmd = 'display configuration '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- cfg = str(out).strip()
-
- return cfg
-
- def get_rollback_dict(self):
- """ get rollback attributes dict."""
-
- rollback_info = dict()
- rollback_info["RollBackInfos"] = list()
-
- flags = list()
- exp = "commit list"
- flags.append(exp)
- cfg_info = self.get_config(flags)
- if not cfg_info:
- return rollback_info
-
- cfg_line = cfg_info.split("\n")
- for cfg in cfg_line:
- if re.findall(r'^\d', cfg):
- pre_rollback_info = cfg.split()
- rollback_info["RollBackInfos"].append(dict(commitId=pre_rollback_info[1], userLabel=pre_rollback_info[2]))
-
- return rollback_info
-
- def get_filename_type(self, filename):
- """Gets the type of filename, such as cfg, zip, dat..."""
-
- if filename is None:
- return None
- if ' ' in filename:
- self.module.fail_json(
- msg='Error: Configuration file name include spaces.')
-
- iftype = None
-
- if filename.endswith('.cfg'):
- iftype = 'cfg'
- elif filename.endswith('.zip'):
- iftype = 'zip'
- elif filename.endswith('.dat'):
- iftype = 'dat'
- else:
- return None
- return iftype.lower()
-
- def set_config(self):
-
- if self.action == "rollback":
- if self.commit_id:
- cmd = "rollback configuration to commit-id %s" % self.commit_id
- self.cli_add_command(cmd)
- if self.label:
- cmd = "rollback configuration to label %s" % self.label
- self.cli_add_command(cmd)
- if self.filename:
- cmd = "rollback configuration to file %s" % self.filename
- self.cli_add_command(cmd)
- if self.last:
- cmd = "rollback configuration last %s" % self.last
- self.cli_add_command(cmd)
- elif self.action == "set":
- if self.commit_id and self.label:
- cmd = "set configuration commit %s label %s" % (self.commit_id, self.label)
- self.cli_add_command(cmd)
- elif self.action == "clear":
- if self.commit_id:
- cmd = "clear configuration commit %s label" % self.commit_id
- self.cli_add_command(cmd)
- if self.oldest:
- cmd = "clear configuration commit oldest %s" % self.oldest
- self.cli_add_command(cmd)
- elif self.action == "commit":
- if self.label:
- cmd = "commit label %s" % self.label
- self.cli_add_command(cmd)
-
- elif self.action == "display":
- self.rollback_info = self.get_rollback_dict()
- if self.commands:
- self.commands.append('return')
- self.commands.append('undo mmi-mode enable')
- self.cli_load_config(self.commands)
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- # commit_id check
- rollback_info = self.rollback_info["RollBackInfos"]
- if self.commit_id:
- if not self.commit_id.isdigit():
- self.module.fail_json(
- msg='Error: The parameter of commit_id is invalid.')
-
- info_bool = False
- for info in rollback_info:
- if info.get("commitId") == self.commit_id:
- info_bool = True
- if not info_bool:
- self.module.fail_json(
- msg='Error: The parameter of commit_id is not exist.')
-
- if self.action == "clear":
- info_bool = False
- for info in rollback_info:
- if info.get("commitId") == self.commit_id:
- if info.get("userLabel") == "-":
- info_bool = True
- if info_bool:
- self.module.fail_json(
- msg='Error: This commit_id does not have a label.')
-
- # filename check
- if self.filename:
- if not self.get_filename_type(self.filename):
- self.module.fail_json(
- msg='Error: Invalid file name or file name extension ( *.cfg, *.zip, *.dat ).')
- # last check
- if self.last:
- if not self.last.isdigit():
- self.module.fail_json(
- msg='Error: Number of configuration checkpoints is not digit.')
- if int(self.last) <= 0 or int(self.last) > 80:
- self.module.fail_json(
- msg='Error: Number of configuration checkpoints is not in the range from 1 to 80.')
-
- # oldest check
- if self.oldest:
- if not self.oldest.isdigit():
- self.module.fail_json(
- msg='Error: Number of configuration checkpoints is not digit.')
- if int(self.oldest) <= 0 or int(self.oldest) > 80:
- self.module.fail_json(
- msg='Error: Number of configuration checkpoints is not in the range from 1 to 80.')
-
- # label check
- if self.label:
- if self.label[0].isdigit():
- self.module.fail_json(
- msg='Error: Commit label which should not start with a number.')
- if len(self.label.replace(' ', '')) == 1:
- if self.label == '-':
- self.module.fail_json(
- msg='Error: Commit label which should not be "-"')
- if len(self.label.replace(' ', '')) < 1 or len(self.label) > 256:
- self.module.fail_json(
- msg='Error: Label of configuration checkpoints is a string of 1 to 256 characters.')
-
- if self.action == "rollback":
- info_bool = False
- for info in rollback_info:
- if info.get("userLabel") == self.label:
- info_bool = True
- if not info_bool:
- self.module.fail_json(
- msg='Error: The parameter of userLabel is not exist.')
-
- if self.action == "commit":
- info_bool = False
- for info in rollback_info:
- if info.get("userLabel") == self.label:
- info_bool = True
- if info_bool:
- self.module.fail_json(
- msg='Error: The parameter of userLabel is existing.')
-
- if self.action == "set":
- info_bool = False
- for info in rollback_info:
- if info.get("commitId") == self.commit_id:
- if info.get("userLabel") != "-":
- info_bool = True
- if info_bool:
- self.module.fail_json(
- msg='Error: The userLabel of this commitid is present and can be reset after deletion.')
-
- def get_proposed(self):
- """get proposed info"""
-
- if self.commit_id:
- self.proposed["commit_id"] = self.commit_id
- if self.label:
- self.proposed["label"] = self.label
- if self.filename:
- self.proposed["filename"] = self.filename
- if self.last:
- self.proposed["last"] = self.last
- if self.oldest:
- self.proposed["oldest"] = self.oldest
-
- def get_existing(self):
- """get existing info"""
- if not self.rollback_info:
- self.existing["RollBackInfos"] = None
- else:
- self.existing["RollBackInfos"] = self.rollback_info["RollBackInfos"]
-
- def get_end_state(self):
- """get end state info"""
-
- rollback_info = self.get_rollback_dict()
- if not rollback_info:
- self.end_state["RollBackInfos"] = None
- else:
- self.end_state["RollBackInfos"] = rollback_info["RollBackInfos"]
-
- def work(self):
- """worker"""
-
- self.rollback_info = self.get_rollback_dict()
- self.check_params()
- self.get_proposed()
-
- self.set_config()
-
- self.get_existing()
- self.get_end_state()
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- commit_id=dict(required=False),
- label=dict(required=False, type='str'),
- filename=dict(required=False, type='str'),
- last=dict(required=False, type='str'),
- oldest=dict(required=False, type='str'),
- action=dict(required=False, type='str', choices=[
- 'rollback', 'clear', 'set', 'commit', 'display']),
- )
- argument_spec.update(ce_argument_spec)
- module = RollBack(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_sflow.py b/plugins/modules/network/cloudengine/ce_sflow.py
deleted file mode 100644
index ddd179e4bd..0000000000
--- a/plugins/modules/network/cloudengine/ce_sflow.py
+++ /dev/null
@@ -1,1167 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_sflow
-short_description: Manages sFlow configuration on HUAWEI CloudEngine switches.
-description:
- - Configure Sampled Flow (sFlow) to monitor traffic on an interface in real time,
- detect abnormal traffic, and locate the source of attack traffic,
- ensuring stable running of the network.
-author: QijunPan (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- agent_ip:
- description:
- - Specifies the IPv4/IPv6 address of an sFlow agent.
- source_ip:
- description:
- - Specifies the source IPv4/IPv6 address of sFlow packets.
- collector_id:
- description:
- - Specifies the ID of an sFlow collector. This ID is used when you specify
- the collector in subsequent sFlow configuration.
- choices: ['1', '2']
- collector_ip:
- description:
- - Specifies the IPv4/IPv6 address of the sFlow collector.
- collector_ip_vpn:
- description:
- - Specifies the name of a VPN instance.
- The value is a string of 1 to 31 case-sensitive characters, spaces not supported.
- When double quotation marks are used around the string, spaces are allowed in the string.
- The value C(_public_) is reserved and cannot be used as the VPN instance name.
- collector_datagram_size:
- description:
- - Specifies the maximum length of sFlow packets sent from an sFlow agent to an sFlow collector.
- The value is an integer, in bytes. It ranges from 1024 to 8100. The default value is 1400.
- collector_udp_port:
- description:
- - Specifies the UDP destination port number of sFlow packets.
- The value is an integer that ranges from 1 to 65535. The default value is 6343.
- collector_meth:
- description:
- - Configures the device to send sFlow packets through service interfaces,
- enhancing the sFlow packet forwarding capability.
- The enhanced parameter is optional. No matter whether you configure the enhanced mode,
- the switch determines to send sFlow packets through service cards or management port
- based on the routing information on the collector.
- When the value is meth, the device forwards sFlow packets at the control plane.
- When the value is enhanced, the device forwards sFlow packets at the forwarding plane to
- enhance the sFlow packet forwarding capacity.
- choices: ['meth', 'enhanced']
- collector_description:
- description:
- - Specifies the description of an sFlow collector.
- The value is a string of 1 to 255 case-sensitive characters without spaces.
- sflow_interface:
- description:
- - Full name of interface for Flow Sampling or Counter.
- It must be a physical interface, Eth-Trunk, or Layer 2 subinterface.
- sample_collector:
- description:
- - Indicates the ID list of the collector.
- sample_rate:
- description:
- - Specifies the flow sampling rate in the format 1/rate.
- The value is an integer and ranges from 1 to 4294967295. The default value is 8192.
- sample_length:
- description:
- - Specifies the maximum length of sampled packets.
- The value is an integer and ranges from 18 to 512, in bytes. The default value is 128.
- sample_direction:
- description:
- - Enables flow sampling in the inbound or outbound direction.
- choices: ['inbound', 'outbound', 'both']
- counter_collector:
- description:
- - Indicates the ID list of the counter collector.
- counter_interval:
- description:
- - Indicates the counter sampling interval.
- The value is an integer that ranges from 10 to 4294967295, in seconds. The default value is 20.
- export_route:
- description:
- - Configures the sFlow packets sent by the switch not to carry routing information.
- choices: ['enable', 'disable']
- rate_limit:
- description:
- - Specifies the rate of sFlow packets sent from a card to the control plane.
- The value is an integer that ranges from 100 to 1500, in pps.
- type: str
- rate_limit_slot:
- description:
- - Specifies the slot where the rate of output sFlow packets is limited.
- If this parameter is not specified, the rate of sFlow packets sent from
- all cards to the control plane is limited.
- The value is an integer or a string of characters.
- type: str
- forward_enp_slot:
- description:
- - Enable the Embedded Network Processor (ENP) chip function.
- The switch uses the ENP chip to perform sFlow sampling,
- and the maximum sFlow sampling interval is 65535.
- If you set the sampling interval to be larger than 65535,
- the switch automatically restores it to 65535.
- The value is an integer or 'all'.
- type: str
- state:
- description:
- - Determines whether the config should be present or not
- on the device.
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = '''
----
-
-- name: sflow module test
- hosts: ce128
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
- - name: Configuring sFlow Agent
- ce_sflow:
- agent_ip: 6.6.6.6
- provider: '{{ cli }}'
-
- - name: Configuring sFlow Collector
- ce_sflow:
- collector_id: 1
- collector_ip: 7.7.7.7
- collector_ip_vpn: vpn1
- collector_description: Collector1
- provider: '{{ cli }}'
-
- - name: Configure flow sampling.
- ce_sflow:
- sflow_interface: 10GE2/0/2
- sample_collector: 1
- sample_direction: inbound
- provider: '{{ cli }}'
-
- - name: Configure counter sampling.
- ce_sflow:
- sflow_interface: 10GE2/0/2
- counter_collector: 1
- counter_interval: 1000
- provider: '{{ cli }}'
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: verbose mode
- type: dict
- sample: {"agent_ip": "6.6.6.6", "state": "present"}
-existing:
- description: k/v pairs of existing configuration
- returned: verbose mode
- type: dict
- sample: {"agent": {}}
-end_state:
- description: k/v pairs of configuration after module execution
- returned: verbose mode
- type: dict
- sample: {"agent": {"family": "ipv4", "ipv4Addr": "1.2.3.4", "ipv6Addr": null}}
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: ["sflow agent ip 6.6.6.6"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import re
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec, check_ip_addr
-
-CE_NC_GET_SFLOW = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- %s
-
-
-
-
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-
-def is_config_exist(cmp_cfg, test_cfg):
- """is configuration exist?"""
-
- if not cmp_cfg or not test_cfg:
- return False
-
- return bool(test_cfg in cmp_cfg)
-
-
-def is_valid_ip_vpn(vpname):
- """check ip vpn"""
-
- if not vpname:
- return False
-
- if vpname == "_public_":
- return False
-
- if len(vpname) < 1 or len(vpname) > 31:
- return False
-
- return True
-
-
-def get_ip_version(address):
- """get ip version fast"""
-
- if not address:
- return None
-
- if address.count(':') >= 2 and address.count(":") <= 7:
- return "ipv6"
- elif address.count('.') == 3:
- return "ipv4"
- else:
- return None
-
-
-def get_interface_type(interface):
- """get the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- if interface.upper().startswith('GE'):
- iftype = 'ge'
- elif interface.upper().startswith('10GE'):
- iftype = '10ge'
- elif interface.upper().startswith('25GE'):
- iftype = '25ge'
- elif interface.upper().startswith('4X10GE'):
- iftype = '4x10ge'
- elif interface.upper().startswith('40GE'):
- iftype = '40ge'
- elif interface.upper().startswith('100GE'):
- iftype = '100ge'
- elif interface.upper().startswith('VLANIF'):
- iftype = 'vlanif'
- elif interface.upper().startswith('LOOPBACK'):
- iftype = 'loopback'
- elif interface.upper().startswith('METH'):
- iftype = 'meth'
- elif interface.upper().startswith('ETH-TRUNK'):
- iftype = 'eth-trunk'
- elif interface.upper().startswith('VBDIF'):
- iftype = 'vbdif'
- elif interface.upper().startswith('NVE'):
- iftype = 'nve'
- elif interface.upper().startswith('TUNNEL'):
- iftype = 'tunnel'
- elif interface.upper().startswith('ETHERNET'):
- iftype = 'ethernet'
- elif interface.upper().startswith('FCOE-PORT'):
- iftype = 'fcoe-port'
- elif interface.upper().startswith('FABRIC-PORT'):
- iftype = 'fabric-port'
- elif interface.upper().startswith('STACK-PORT'):
- iftype = 'stack-port'
- elif interface.upper().startswith('NULL'):
- iftype = 'null'
- else:
- return None
-
- return iftype.lower()
-
-
-class Sflow(object):
- """Manages sFlow"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.__init_module__()
-
- # module input info
- self.agent_ip = self.module.params['agent_ip']
- self.agent_version = None
- self.source_ip = self.module.params['source_ip']
- self.source_version = None
- self.export_route = self.module.params['export_route']
- self.rate_limit = self.module.params['rate_limit']
- self.rate_limit_slot = self.module.params['rate_limit_slot']
- self.forward_enp_slot = self.module.params['forward_enp_slot']
- self.collector_id = self.module.params['collector_id']
- self.collector_ip = self.module.params['collector_ip']
- self.collector_version = None
- self.collector_ip_vpn = self.module.params['collector_ip_vpn']
- self.collector_datagram_size = self.module.params['collector_datagram_size']
- self.collector_udp_port = self.module.params['collector_udp_port']
- self.collector_meth = self.module.params['collector_meth']
- self.collector_description = self.module.params['collector_description']
- self.sflow_interface = self.module.params['sflow_interface']
- self.sample_collector = self.module.params['sample_collector'] or list()
- self.sample_rate = self.module.params['sample_rate']
- self.sample_length = self.module.params['sample_length']
- self.sample_direction = self.module.params['sample_direction']
- self.counter_collector = self.module.params['counter_collector'] or list()
- self.counter_interval = self.module.params['counter_interval']
- self.state = self.module.params['state']
-
- # state
- self.config = "" # current config
- self.sflow_dict = dict()
- self.changed = False
- self.updates_cmd = list()
- self.commands = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def __init_module__(self):
- """init module"""
-
- required_together = [("collector_id", "collector_ip")]
- self.module = AnsibleModule(
- argument_spec=self.spec, required_together=required_together, supports_check_mode=True)
-
- def check_response(self, con_obj, xml_name):
- """Check if response message is already succeed"""
-
- xml_str = con_obj.xml
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def netconf_set_config(self, xml_str, xml_name):
- """netconf set config"""
-
- rcv_xml = set_nc_config(self.module, xml_str)
- if "" not in rcv_xml:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_sflow_dict(self):
- """ sflow config dict"""
-
- sflow_dict = dict(source=list(), agent=dict(), collector=list(),
- sampling=dict(), counter=dict(), export=dict())
- conf_str = CE_NC_GET_SFLOW % (
- self.sflow_interface, self.sflow_interface)
-
- if not self.collector_meth:
- conf_str = conf_str.replace("", "")
-
- rcv_xml = get_nc_config(self.module, conf_str)
-
- if "" in rcv_xml:
- return sflow_dict
-
- xml_str = rcv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
-
- # get source info
- srcs = root.findall("sflow/sources/source")
- if srcs:
- for src in srcs:
- attrs = dict()
- for attr in src:
- if attr.tag in ["family", "ipv4Addr", "ipv6Addr"]:
- attrs[attr.tag] = attr.text
- sflow_dict["source"].append(attrs)
-
- # get agent info
- agent = root.find("sflow/agents/agent")
- if agent:
- for attr in agent:
- if attr.tag in ["family", "ipv4Addr", "ipv6Addr"]:
- sflow_dict["agent"][attr.tag] = attr.text
-
- # get collector info
- collectors = root.findall("sflow/collectors/collector")
- if collectors:
- for collector in collectors:
- attrs = dict()
- for attr in collector:
- if attr.tag in ["collectorID", "family", "ipv4Addr", "ipv6Addr",
- "vrfName", "datagramSize", "port", "description", "meth"]:
- attrs[attr.tag] = attr.text
- sflow_dict["collector"].append(attrs)
-
- # get sampling info
- sample = root.find("sflow/samplings/sampling")
- if sample:
- for attr in sample:
- if attr.tag in ["ifName", "collectorID", "direction", "length", "rate"]:
- sflow_dict["sampling"][attr.tag] = attr.text
-
- # get counter info
- counter = root.find("sflow/counters/counter")
- if counter:
- for attr in counter:
- if attr.tag in ["ifName", "collectorID", "interval"]:
- sflow_dict["counter"][attr.tag] = attr.text
-
- # get export info
- export = root.find("sflow/exports/export")
- if export:
- for attr in export:
- if attr.tag == "ExportRoute":
- sflow_dict["export"][attr.tag] = attr.text
-
- return sflow_dict
-
- def config_agent(self):
- """configures sFlow agent"""
-
- xml_str = ''
- if not self.agent_ip:
- return xml_str
-
- self.agent_version = get_ip_version(self.agent_ip)
- if not self.agent_version:
- self.module.fail_json(msg="Error: agent_ip is invalid.")
-
- if self.state == "present":
- if self.agent_ip != self.sflow_dict["agent"].get("ipv4Addr") \
- and self.agent_ip != self.sflow_dict["agent"].get("ipv6Addr"):
- xml_str += ''
- xml_str += '%s' % self.agent_version
- if self.agent_version == "ipv4":
- xml_str += '%s' % self.agent_ip
- self.updates_cmd.append("sflow agent ip %s" % self.agent_ip)
- else:
- xml_str += '%s' % self.agent_ip
- self.updates_cmd.append("sflow agent ipv6 %s" % self.agent_ip)
- xml_str += ''
-
- else:
- if self.agent_ip == self.sflow_dict["agent"].get("ipv4Addr") \
- or self.agent_ip == self.sflow_dict["agent"].get("ipv6Addr"):
- xml_str += ''
- self.updates_cmd.append("undo sflow agent")
-
- return xml_str
-
- def config_source(self):
- """configures the source IP address for sFlow packets"""
-
- xml_str = ''
- if not self.source_ip:
- return xml_str
-
- self.source_version = get_ip_version(self.source_ip)
- if not self.source_version:
- self.module.fail_json(msg="Error: source_ip is invalid.")
-
- src_dict = dict()
- for src in self.sflow_dict["source"]:
- if src.get("family") == self.source_version:
- src_dict = src
- break
-
- if self.state == "present":
- if self.source_ip != src_dict.get("ipv4Addr") \
- and self.source_ip != src_dict.get("ipv6Addr"):
- xml_str += ''
- else:
- if self.source_ip == src_dict.get("ipv4Addr"):
- xml_str += ''
- self.updates_cmd.append("undo sflow source ip %s" % self.source_ip)
- elif self.source_ip == src_dict.get("ipv6Addr"):
- xml_str += ''
- self.updates_cmd.append("undo sflow source ipv6 %s" % self.source_ip)
-
- return xml_str
-
- def config_collector(self):
- """creates an sFlow collector and sets or modifies optional parameters for the sFlow collector"""
-
- xml_str = ''
- if not self.collector_id:
- return xml_str
-
- if self.state == "present" and not self.collector_ip:
- return xml_str
-
- if self.collector_ip:
- self.collector_version = get_ip_version(self.collector_ip)
- if not self.collector_version:
- self.module.fail_json(msg="Error: collector_ip is invalid.")
-
- # get collector dict
- exist_dict = dict()
- for collector in self.sflow_dict["collector"]:
- if collector.get("collectorID") == self.collector_id:
- exist_dict = collector
- break
-
- change = False
- if self.state == "present":
- if not exist_dict:
- change = True
- elif self.collector_version != exist_dict.get("family"):
- change = True
- elif self.collector_version == "ipv4" and self.collector_ip != exist_dict.get("ipv4Addr"):
- change = True
- elif self.collector_version == "ipv6" and self.collector_ip != exist_dict.get("ipv6Addr"):
- change = True
- elif self.collector_ip_vpn and self.collector_ip_vpn != exist_dict.get("vrfName"):
- change = True
- elif not self.collector_ip_vpn and exist_dict.get("vrfName") != "_public_":
- change = True
- elif self.collector_udp_port and self.collector_udp_port != exist_dict.get("port"):
- change = True
- elif not self.collector_udp_port and exist_dict.get("port") != "6343":
- change = True
- elif self.collector_datagram_size and self.collector_datagram_size != exist_dict.get("datagramSize"):
- change = True
- elif not self.collector_datagram_size and exist_dict.get("datagramSize") != "1400":
- change = True
- elif self.collector_meth and self.collector_meth != exist_dict.get("meth"):
- change = True
- elif not self.collector_meth and exist_dict.get("meth") and exist_dict.get("meth") != "meth":
- change = True
- elif self.collector_description and self.collector_description != exist_dict.get("description"):
- change = True
- elif not self.collector_description and exist_dict.get("description"):
- change = True
- else:
- pass
- else: # absent
- # collector not exist
- if not exist_dict:
- return xml_str
- if self.collector_version and self.collector_version != exist_dict.get("family"):
- return xml_str
- if self.collector_version == "ipv4" and self.collector_ip != exist_dict.get("ipv4Addr"):
- return xml_str
- if self.collector_version == "ipv6" and self.collector_ip != exist_dict.get("ipv6Addr"):
- return xml_str
- if self.collector_ip_vpn and self.collector_ip_vpn != exist_dict.get("vrfName"):
- return xml_str
- if self.collector_udp_port and self.collector_udp_port != exist_dict.get("port"):
- return xml_str
- if self.collector_datagram_size and self.collector_datagram_size != exist_dict.get("datagramSize"):
- return xml_str
- if self.collector_meth and self.collector_meth != exist_dict.get("meth"):
- return xml_str
- if self.collector_description and self.collector_description != exist_dict.get("description"):
- return xml_str
- change = True
-
- if not change:
- return xml_str
-
- # update or delete
- if self.state == "absent":
- xml_str += '%s' % self.collector_id
- self.updates_cmd.append("undo collector %s" % self.collector_id)
- else:
- xml_str += '%s' % self.collector_id
- cmd = "sflow collector %s" % self.collector_id
- xml_str += '%s' % self.collector_version
- if self.collector_version == "ipv4":
- cmd += " ip %s" % self.collector_ip
- xml_str += '%s' % self.collector_ip
- else:
- cmd += " ipv6 %s" % self.collector_ip
- xml_str += '%s' % self.collector_ip
- if self.collector_ip_vpn:
- cmd += " vpn-instance %s" % self.collector_ip_vpn
- xml_str += '%s' % self.collector_ip_vpn
- if self.collector_datagram_size:
- cmd += " length %s" % self.collector_datagram_size
- xml_str += '%s' % self.collector_datagram_size
- if self.collector_udp_port:
- cmd += " udp-port %s" % self.collector_udp_port
- xml_str += '%s' % self.collector_udp_port
- if self.collector_description:
- cmd += " description %s" % self.collector_description
- xml_str += '%s' % self.collector_description
- else:
- xml_str += ''
- if self.collector_meth:
- if self.collector_meth == "enhanced":
- cmd += " enhanced"
- xml_str += '%s' % self.collector_meth
- self.updates_cmd.append(cmd)
-
- xml_str += ""
-
- return xml_str
-
- def config_sampling(self):
- """configure sflow sampling on an interface"""
-
- xml_str = ''
- if not self.sflow_interface:
- return xml_str
-
- if not self.sflow_dict["sampling"] and self.state == "absent":
- return xml_str
-
- self.updates_cmd.append("interface %s" % self.sflow_interface)
- if self.state == "present":
- xml_str += '%s' % self.sflow_interface
- else:
- xml_str += '%s' % self.sflow_interface
-
- # sample_collector
- if self.sample_collector:
- if self.sflow_dict["sampling"].get("collectorID") \
- and self.sflow_dict["sampling"].get("collectorID") != "invalid":
- existing = self.sflow_dict["sampling"].get("collectorID").split(',')
- else:
- existing = list()
-
- if self.state == "present":
- diff = list(set(self.sample_collector) - set(existing))
- if diff:
- self.updates_cmd.append(
- "sflow sampling collector %s" % ' '.join(diff))
- new_set = list(self.sample_collector + existing)
- xml_str += '%s' % ','.join(list(set(new_set)))
- else:
- same = list(set(self.sample_collector) & set(existing))
- if same:
- self.updates_cmd.append(
- "undo sflow sampling collector %s" % ' '.join(same))
- xml_str += '%s' % ','.join(list(set(same)))
-
- # sample_rate
- if self.sample_rate:
- exist = bool(self.sample_rate == self.sflow_dict["sampling"].get("rate"))
- if self.state == "present" and not exist:
- self.updates_cmd.append(
- "sflow sampling rate %s" % self.sample_rate)
- xml_str += '%s' % self.sample_rate
- elif self.state == "absent" and exist:
- self.updates_cmd.append(
- "undo sflow sampling rate %s" % self.sample_rate)
- xml_str += '%s' % self.sample_rate
-
- # sample_length
- if self.sample_length:
- exist = bool(self.sample_length == self.sflow_dict["sampling"].get("length"))
- if self.state == "present" and not exist:
- self.updates_cmd.append(
- "sflow sampling length %s" % self.sample_length)
- xml_str += '%s' % self.sample_length
- elif self.state == "absent" and exist:
- self.updates_cmd.append(
- "undo sflow sampling length %s" % self.sample_length)
- xml_str += '%s' % self.sample_length
-
- # sample_direction
- if self.sample_direction:
- direction = list()
- if self.sample_direction == "both":
- direction = ["inbound", "outbound"]
- else:
- direction.append(self.sample_direction)
- existing = list()
- if self.sflow_dict["sampling"].get("direction"):
- if self.sflow_dict["sampling"].get("direction") == "both":
- existing = ["inbound", "outbound"]
- else:
- existing.append(
- self.sflow_dict["sampling"].get("direction"))
-
- if self.state == "present":
- diff = list(set(direction) - set(existing))
- if diff:
- new_set = list(set(direction + existing))
- self.updates_cmd.append(
- "sflow sampling %s" % ' '.join(diff))
- if len(new_set) > 1:
- new_dir = "both"
- else:
- new_dir = new_set[0]
- xml_str += '%s' % new_dir
- else:
- same = list(set(existing) & set(direction))
- if same:
- self.updates_cmd.append("undo sflow sampling %s" % ' '.join(same))
- if len(same) > 1:
- del_dir = "both"
- else:
- del_dir = same[0]
- xml_str += '%s' % del_dir
-
- if xml_str.endswith(""):
- self.updates_cmd.pop()
- return ""
-
- xml_str += ''
-
- return xml_str
-
- def config_counter(self):
- """configures sflow counter on an interface"""
-
- xml_str = ''
- if not self.sflow_interface:
- return xml_str
-
- if not self.sflow_dict["counter"] and self.state == "absent":
- return xml_str
-
- self.updates_cmd.append("interface %s" % self.sflow_interface)
- if self.state == "present":
- xml_str += '%s' % self.sflow_interface
- else:
- xml_str += '%s' % self.sflow_interface
-
- # counter_collector
- if self.counter_collector:
- if self.sflow_dict["counter"].get("collectorID") \
- and self.sflow_dict["counter"].get("collectorID") != "invalid":
- existing = self.sflow_dict["counter"].get("collectorID").split(',')
- else:
- existing = list()
-
- if self.state == "present":
- diff = list(set(self.counter_collector) - set(existing))
- if diff:
- self.updates_cmd.append("sflow counter collector %s" % ' '.join(diff))
- new_set = list(self.counter_collector + existing)
- xml_str += '%s' % ','.join(list(set(new_set)))
- else:
- same = list(set(self.counter_collector) & set(existing))
- if same:
- self.updates_cmd.append(
- "undo sflow counter collector %s" % ' '.join(same))
- xml_str += '%s' % ','.join(list(set(same)))
-
- # counter_interval
- if self.counter_interval:
- exist = bool(self.counter_interval == self.sflow_dict["counter"].get("interval"))
- if self.state == "present" and not exist:
- self.updates_cmd.append(
- "sflow counter interval %s" % self.counter_interval)
- xml_str += '%s' % self.counter_interval
- elif self.state == "absent" and exist:
- self.updates_cmd.append(
- "undo sflow counter interval %s" % self.counter_interval)
- xml_str += '%s' % self.counter_interval
-
- if xml_str.endswith(""):
- self.updates_cmd.pop()
- return ""
-
- xml_str += ''
-
- return xml_str
-
- def config_export(self):
- """configure sflow export"""
-
- xml_str = ''
- if not self.export_route:
- return xml_str
-
- if self.export_route == "enable":
- if self.sflow_dict["export"] and self.sflow_dict["export"].get("ExportRoute") == "disable":
- xml_str = 'disable'
- self.updates_cmd.append("undo sflow export extended-route-data disable")
- else: # disable
- if not self.sflow_dict["export"] or self.sflow_dict["export"].get("ExportRoute") != "disable":
- xml_str = 'disable'
- self.updates_cmd.append("sflow export extended-route-data disable")
-
- return xml_str
-
- def netconf_load_config(self, xml_str):
- """load sflow config by netconf"""
-
- if not xml_str:
- return
-
- xml_cfg = """
-
-
- %s
-
- """ % xml_str
-
- self.netconf_set_config(xml_cfg, "SET_SFLOW")
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- # check agent_ip
- if self.agent_ip:
- self.agent_ip = self.agent_ip.upper()
- if not check_ip_addr(self.agent_ip):
- self.module.fail_json(msg="Error: agent_ip is invalid.")
-
- # check source_ip
- if self.source_ip:
- self.source_ip = self.source_ip.upper()
- if not check_ip_addr(self.source_ip):
- self.module.fail_json(msg="Error: source_ip is invalid.")
-
- # check collector
- if self.collector_id:
- # check collector_ip and collector_ip_vpn
- if self.collector_ip:
- self.collector_ip = self.collector_ip.upper()
- if not check_ip_addr(self.collector_ip):
- self.module.fail_json(
- msg="Error: collector_ip is invalid.")
- if self.collector_ip_vpn and not is_valid_ip_vpn(self.collector_ip_vpn):
- self.module.fail_json(
- msg="Error: collector_ip_vpn is invalid.")
-
- # check collector_datagram_size ranges from 1024 to 8100
- if self.collector_datagram_size:
- if not self.collector_datagram_size.isdigit():
- self.module.fail_json(
- msg="Error: collector_datagram_size is not digit.")
- if int(self.collector_datagram_size) < 1024 or int(self.collector_datagram_size) > 8100:
- self.module.fail_json(
- msg="Error: collector_datagram_size is not ranges from 1024 to 8100.")
-
- # check collector_udp_port ranges from 1 to 65535
- if self.collector_udp_port:
- if not self.collector_udp_port.isdigit():
- self.module.fail_json(
- msg="Error: collector_udp_port is not digit.")
- if int(self.collector_udp_port) < 1 or int(self.collector_udp_port) > 65535:
- self.module.fail_json(
- msg="Error: collector_udp_port is not ranges from 1 to 65535.")
-
- # check collector_description 1 to 255 case-sensitive characters
- if self.collector_description:
- if self.collector_description.count(" "):
- self.module.fail_json(
- msg="Error: collector_description should without spaces.")
- if len(self.collector_description) < 1 or len(self.collector_description) > 255:
- self.module.fail_json(
- msg="Error: collector_description is not ranges from 1 to 255.")
-
- # check sflow_interface
- if self.sflow_interface:
- intf_type = get_interface_type(self.sflow_interface)
- if not intf_type:
- self.module.fail_json(msg="Error: intf_type is invalid.")
- if intf_type not in ['ge', '10ge', '25ge', '4x10ge', '40ge', '100ge', 'eth-trunk']:
- self.module.fail_json(
- msg="Error: interface %s is not support sFlow." % self.sflow_interface)
-
- # check sample_collector
- if self.sample_collector:
- self.sample_collector.sort()
- if self.sample_collector not in [["1"], ["2"], ["1", "2"]]:
- self.module.fail_json(
- msg="Error: sample_collector is invalid.")
-
- # check sample_rate ranges from 1 to 4294967295
- if self.sample_rate:
- if not self.sample_rate.isdigit():
- self.module.fail_json(
- msg="Error: sample_rate is not digit.")
- if int(self.sample_rate) < 1 or int(self.sample_rate) > 4294967295:
- self.module.fail_json(
- msg="Error: sample_rate is not ranges from 1 to 4294967295.")
-
- # check sample_length ranges from 18 to 512
- if self.sample_length:
- if not self.sample_length.isdigit():
- self.module.fail_json(
- msg="Error: sample_rate is not digit.")
- if int(self.sample_length) < 18 or int(self.sample_length) > 512:
- self.module.fail_json(
- msg="Error: sample_length is not ranges from 18 to 512.")
-
- # check counter_collector
- if self.counter_collector:
- self.counter_collector.sort()
- if self.counter_collector not in [["1"], ["2"], ["1", "2"]]:
- self.module.fail_json(
- msg="Error: counter_collector is invalid.")
-
- # counter_interval ranges from 10 to 4294967295
- if self.counter_interval:
- if not self.counter_interval.isdigit():
- self.module.fail_json(
- msg="Error: counter_interval is not digit.")
- if int(self.counter_interval) < 10 or int(self.counter_interval) > 4294967295:
- self.module.fail_json(
- msg="Error: sample_length is not ranges from 10 to 4294967295.")
-
- if self.rate_limit or self.rate_limit_slot or self.forward_enp_slot:
- self.module.fail_json(msg="Error: The following parameters cannot be configured"
- "because XML mode is not supported:rate_limit,rate_limit_slot,forward_enp_slot.")
-
- def get_proposed(self):
- """get proposed info"""
-
- # base config
- if self.agent_ip:
- self.proposed["agent_ip"] = self.agent_ip
- if self.source_ip:
- self.proposed["source_ip"] = self.source_ip
- if self.export_route:
- self.proposed["export_route"] = self.export_route
- if self.rate_limit:
- self.proposed["rate_limit"] = self.rate_limit
- self.proposed["rate_limit_slot"] = self.rate_limit_slot
- if self.forward_enp_slot:
- self.proposed["forward_enp_slot"] = self.forward_enp_slot
- if self.collector_id:
- self.proposed["collector_id"] = self.collector_id
- if self.collector_ip:
- self.proposed["collector_ip"] = self.collector_ip
- self.proposed["collector_ip_vpn"] = self.collector_ip_vpn
- if self.collector_datagram_size:
- self.proposed[
- "collector_datagram_size"] = self.collector_datagram_size
- if self.collector_udp_port:
- self.proposed["collector_udp_port"] = self.collector_udp_port
- if self.collector_meth:
- self.proposed["collector_meth"] = self.collector_meth
- if self.collector_description:
- self.proposed[
- "collector_description"] = self.collector_description
-
- # sample and counter config
- if self.sflow_interface:
- self.proposed["sflow_interface"] = self.sflow_interface
- if self.sample_collector:
- self.proposed["sample_collector"] = self.sample_collector
- if self.sample_rate:
- self.proposed["sample_rate"] = self.sample_rate
- if self.sample_length:
- self.proposed["sample_length"] = self.sample_length
- if self.sample_direction:
- self.proposed["sample_direction"] = self.sample_direction
- if self.counter_collector:
- self.proposed["counter_collector"] = self.counter_collector
- if self.counter_interval:
- self.proposed["counter_interval"] = self.counter_interval
-
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- if not self.sflow_dict:
- return
-
- if self.agent_ip:
- self.existing["agent"] = self.sflow_dict["agent"]
- if self.source_ip:
- self.existing["source"] = self.sflow_dict["source"]
- if self.collector_id:
- self.existing["collector"] = self.sflow_dict["collector"]
- if self.export_route:
- self.existing["export"] = self.sflow_dict["export"]
-
- if self.sflow_interface:
- self.existing["sampling"] = self.sflow_dict["sampling"]
- self.existing["counter"] = self.sflow_dict["counter"]
-
- def get_end_state(self):
- """get end state info"""
-
- sflow_dict = self.get_sflow_dict()
- if not sflow_dict:
- return
-
- if self.agent_ip:
- self.end_state["agent"] = sflow_dict["agent"]
- if self.source_ip:
- self.end_state["source"] = sflow_dict["source"]
- if self.collector_id:
- self.end_state["collector"] = sflow_dict["collector"]
- if self.export_route:
- self.end_state["export"] = sflow_dict["export"]
-
- if self.sflow_interface:
- self.end_state["sampling"] = sflow_dict["sampling"]
- self.end_state["counter"] = sflow_dict["counter"]
- if self.existing == self.end_state:
- self.changed = False
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.sflow_dict = self.get_sflow_dict()
- self.get_existing()
- self.get_proposed()
-
- # deal present or absent
- xml_str = ''
- if self.export_route:
- xml_str += self.config_export()
- if self.agent_ip:
- xml_str += self.config_agent()
- if self.source_ip:
- xml_str += self.config_source()
-
- if self.state == "present":
- if self.collector_id and self.collector_ip:
- xml_str += self.config_collector()
- if self.sflow_interface:
- xml_str += self.config_sampling()
- xml_str += self.config_counter()
- else:
- if self.sflow_interface:
- xml_str += self.config_sampling()
- xml_str += self.config_counter()
- if self.collector_id:
- xml_str += self.config_collector()
-
- if xml_str:
- self.netconf_load_config(xml_str)
- self.changed = True
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- agent_ip=dict(required=False, type='str'),
- source_ip=dict(required=False, type='str'),
- export_route=dict(required=False, type='str',
- choices=['enable', 'disable']),
- rate_limit=dict(required=False, removed_in_version=2.13, type='str'),
- rate_limit_slot=dict(required=False, removed_in_version=2.13, type='str'),
- forward_enp_slot=dict(required=False, removed_in_version=2.13, type='str'),
- collector_id=dict(required=False, type='str', choices=['1', '2']),
- collector_ip=dict(required=False, type='str'),
- collector_ip_vpn=dict(required=False, type='str'),
- collector_datagram_size=dict(required=False, type='str'),
- collector_udp_port=dict(required=False, type='str'),
- collector_meth=dict(required=False, type='str',
- choices=['meth', 'enhanced']),
- collector_description=dict(required=False, type='str'),
- sflow_interface=dict(required=False, type='str'),
- sample_collector=dict(required=False, type='list'),
- sample_rate=dict(required=False, type='str'),
- sample_length=dict(required=False, type='str'),
- sample_direction=dict(required=False, type='str',
- choices=['inbound', 'outbound', 'both']),
- counter_collector=dict(required=False, type='list'),
- counter_interval=dict(required=False, type='str'),
- state=dict(required=False, default='present',
- choices=['present', 'absent'])
- )
-
- argument_spec.update(ce_argument_spec)
- module = Sflow(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_snmp_community.py b/plugins/modules/network/cloudengine/ce_snmp_community.py
deleted file mode 100644
index be0557c41a..0000000000
--- a/plugins/modules/network/cloudengine/ce_snmp_community.py
+++ /dev/null
@@ -1,979 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_snmp_community
-short_description: Manages SNMP community configuration on HUAWEI CloudEngine switches.
-description:
- - Manages SNMP community configuration on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- acl_number:
- description:
- - Access control list number.
- community_name:
- description:
- - Unique name to identify the community.
- access_right:
- description:
- - Access right read or write.
- choices: ['read','write']
- community_mib_view:
- description:
- - Mib view name.
- group_name:
- description:
- - Unique name to identify the SNMPv3 group.
- security_level:
- description:
- - Security level indicating whether to use authentication and encryption.
- choices: ['noAuthNoPriv', 'authentication', 'privacy']
- read_view:
- description:
- - Mib view name for read.
- write_view:
- description:
- - Mib view name for write.
- notify_view:
- description:
- - Mib view name for notification.
- state:
- description:
- - Manage the state of the resource.
- default: present
- choices: ['present','absent']
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine snmp community test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Config SNMP community"
- ce_snmp_community:
- state: present
- community_name: Wdz123456789
- access_right: write
- provider: "{{ cli }}"
-
- - name: "Undo SNMP community"
- ce_snmp_community:
- state: absent
- community_name: Wdz123456789
- access_right: write
- provider: "{{ cli }}"
-
- - name: "Config SNMP group"
- ce_snmp_community:
- state: present
- group_name: wdz_group
- security_level: noAuthNoPriv
- acl_number: 2000
- provider: "{{ cli }}"
-
- - name: "Undo SNMP group"
- ce_snmp_community:
- state: absent
- group_name: wdz_group
- security_level: noAuthNoPriv
- acl_number: 2000
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"acl_number": "2000", "group_name": "wdz_group",
- "security_level": "noAuthNoPriv", "state": "present"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"snmp v3 group": {"snmp_group": ["wdz_group", "noAuthNoPriv", "2000"]}}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["snmp-agent group v3 wdz_group noauthentication acl 2000"]
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-
-# get snmp community
-CE_GET_SNMP_COMMUNITY_HEADER = """
-
-
-
-
-
-
-"""
-CE_GET_SNMP_COMMUNITY_TAIL = """
-
-
-
-
-"""
-# merge snmp community
-CE_MERGE_SNMP_COMMUNITY_HEADER = """
-
-
-
-
- %s
- %s
-"""
-CE_MERGE_SNMP_COMMUNITY_TAIL = """
-
-
-
-
-"""
-# create snmp community
-CE_CREATE_SNMP_COMMUNITY_HEADER = """
-
-
-
-
- %s
- %s
-"""
-CE_CREATE_SNMP_COMMUNITY_TAIL = """
-
-
-
-
-"""
-# delete snmp community
-CE_DELETE_SNMP_COMMUNITY_HEADER = """
-
-
-
-
- %s
- %s
-"""
-CE_DELETE_SNMP_COMMUNITY_TAIL = """
-
-
-
-
-"""
-
-# get snmp v3 group
-CE_GET_SNMP_V3_GROUP_HEADER = """
-
-
-
-
-
-
-"""
-CE_GET_SNMP_V3_GROUP_TAIL = """
-
-
-
-
-"""
-# merge snmp v3 group
-CE_MERGE_SNMP_V3_GROUP_HEADER = """
-
-
-
-
- %s
- %s
-"""
-CE_MERGE_SNMP_V3_GROUP_TAIL = """
-
-
-
-
-"""
-# create snmp v3 group
-CE_CREATE_SNMP_V3_GROUP_HEADER = """
-
-
-
-
- %s
- %s
-"""
-CE_CREATE_SNMP_V3_GROUP_TAIL = """
-
-
-
-
-"""
-# delete snmp v3 group
-CE_DELETE_SNMP_V3_GROUP_HEADER = """
-
-
-
-
- %s
- %s
-"""
-CE_DELETE_SNMP_V3_GROUP_TAIL = """
-
-
-
-
-"""
-
-
-class SnmpCommunity(object):
- """ Manages SNMP community configuration """
-
- def netconf_get_config(self, **kwargs):
- """ Get configure through netconf """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- xml_str = get_nc_config(module, conf_str)
-
- return xml_str
-
- def netconf_set_config(self, **kwargs):
- """ Set configure through netconf """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- xml_str = set_nc_config(module, conf_str)
-
- return xml_str
-
- def check_snmp_community_args(self, **kwargs):
- """ Check snmp community args """
-
- module = kwargs["module"]
- result = dict()
- need_cfg = False
- result["community_info"] = []
- state = module.params['state']
- community_name = module.params['community_name']
- access_right = module.params['access_right']
- acl_number = module.params['acl_number']
- community_mib_view = module.params['community_mib_view']
-
- if community_name and access_right:
- if len(community_name) > 32 or len(community_name) == 0:
- module.fail_json(
- msg='Error: The len of community_name %s is out of [1 - 32].' % community_name)
-
- if acl_number:
- if acl_number.isdigit():
- if int(acl_number) > 2999 or int(acl_number) < 2000:
- module.fail_json(
- msg='Error: The value of acl_number %s is out of [2000 - 2999].' % acl_number)
- else:
- if not acl_number[0].isalpha() or len(acl_number) > 32 or len(acl_number) < 1:
- module.fail_json(
- msg='Error: The len of acl_number %s is out of [1 - 32] or is invalid.' % acl_number)
-
- if community_mib_view:
- if len(community_mib_view) > 32 or len(community_mib_view) == 0:
- module.fail_json(
- msg='Error: The len of community_mib_view %s is out of [1 - 32].' % community_mib_view)
-
- conf_str = CE_GET_SNMP_COMMUNITY_HEADER
- if acl_number:
- conf_str += ""
- if community_mib_view:
- conf_str += ""
-
- conf_str += CE_GET_SNMP_COMMUNITY_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- if state == "present":
- need_cfg = True
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- community_info = root.findall("snmp/communitys/community")
- if community_info:
- for tmp in community_info:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["communityName", "accessRight", "aclNumber", "mibViewName"]:
- tmp_dict[site.tag] = site.text
-
- result["community_info"].append(tmp_dict)
-
- if result["community_info"]:
- community_name_list = list()
- for tmp in result["community_info"]:
- if "communityName" in tmp.keys():
- community_name_list.append(tmp["communityName"])
-
- if community_name not in community_name_list:
- need_cfg = True
- else:
- need_cfg_bool = True
-
- for tmp in result["community_info"]:
- if tmp["communityName"] == community_name:
-
- cfg_bool_list = list()
-
- if access_right:
- if "accessRight" in tmp.keys():
- need_cfg_access = False
- if tmp["accessRight"] != access_right:
- need_cfg_access = True
- else:
- need_cfg_access = True
-
- cfg_bool_list.append(need_cfg_access)
-
- if acl_number:
- if "aclNumber" in tmp.keys():
- need_cfg_acl = False
- if tmp["aclNumber"] != acl_number:
- need_cfg_acl = True
- else:
- need_cfg_acl = True
-
- cfg_bool_list.append(need_cfg_acl)
-
- if community_mib_view:
- if "mibViewName" in tmp.keys():
- need_cfg_mib = False
- if tmp["mibViewName"] != community_mib_view:
- need_cfg_mib = True
- else:
- need_cfg_mib = True
- cfg_bool_list.append(need_cfg_mib)
-
- if True not in cfg_bool_list:
- need_cfg_bool = False
-
- if state == "present":
- if not need_cfg_bool:
- need_cfg = False
- else:
- need_cfg = True
- else:
- if not need_cfg_bool:
- need_cfg = True
- else:
- need_cfg = False
-
- result["need_cfg"] = need_cfg
- return result
-
- def check_snmp_v3_group_args(self, **kwargs):
- """ Check snmp v3 group args """
-
- module = kwargs["module"]
- result = dict()
- need_cfg = False
- result["group_info"] = []
- state = module.params['state']
- group_name = module.params['group_name']
- security_level = module.params['security_level']
- acl_number = module.params['acl_number']
- read_view = module.params['read_view']
- write_view = module.params['write_view']
- notify_view = module.params['notify_view']
-
- community_name = module.params['community_name']
- access_right = module.params['access_right']
-
- if group_name and security_level:
-
- if community_name and access_right:
- module.fail_json(
- msg='Error: Community is used for v1/v2c, group_name is used for v3, do not '
- 'input at the same time.')
-
- if len(group_name) > 32 or len(group_name) == 0:
- module.fail_json(
- msg='Error: The len of group_name %s is out of [1 - 32].' % group_name)
-
- if acl_number:
- if acl_number.isdigit():
- if int(acl_number) > 2999 or int(acl_number) < 2000:
- module.fail_json(
- msg='Error: The value of acl_number %s is out of [2000 - 2999].' % acl_number)
- else:
- if not acl_number[0].isalpha() or len(acl_number) > 32 or len(acl_number) < 1:
- module.fail_json(
- msg='Error: The len of acl_number %s is out of [1 - 32] or is invalid.' % acl_number)
-
- if read_view:
- if len(read_view) > 32 or len(read_view) < 1:
- module.fail_json(
- msg='Error: The len of read_view %s is out of [1 - 32].' % read_view)
-
- if write_view:
- if len(write_view) > 32 or len(write_view) < 1:
- module.fail_json(
- msg='Error: The len of write_view %s is out of [1 - 32].' % write_view)
-
- if notify_view:
- if len(notify_view) > 32 or len(notify_view) < 1:
- module.fail_json(
- msg='Error: The len of notify_view %s is out of [1 - 32].' % notify_view)
-
- conf_str = CE_GET_SNMP_V3_GROUP_HEADER
- if acl_number:
- conf_str += ""
- if read_view:
- conf_str += ""
- if write_view:
- conf_str += ""
- if notify_view:
- conf_str += ""
-
- conf_str += CE_GET_SNMP_V3_GROUP_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- if state == "present":
- need_cfg = True
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- group_info = root.findall("snmp/snmpv3Groups/snmpv3Group")
- if group_info:
- for tmp in group_info:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["groupName", "securityLevel", "readViewName", "writeViewName",
- "notifyViewName", "aclNumber"]:
- tmp_dict[site.tag] = site.text
-
- result["group_info"].append(tmp_dict)
-
- if result["group_info"]:
- group_name_list = list()
-
- for tmp in result["group_info"]:
- if "groupName" in tmp.keys():
- group_name_list.append(tmp["groupName"])
- if group_name not in group_name_list:
- if state == "present":
- need_cfg = True
- else:
- need_cfg = False
- else:
- need_cfg_bool = True
- for tmp in result["group_info"]:
- if tmp["groupName"] == group_name:
-
- cfg_bool_list = list()
-
- if security_level:
- if "securityLevel" in tmp.keys():
- need_cfg_group = False
- if tmp["securityLevel"] != security_level:
- need_cfg_group = True
- else:
- need_cfg_group = True
-
- cfg_bool_list.append(need_cfg_group)
-
- if acl_number:
- if "aclNumber" in tmp.keys():
- need_cfg_acl = False
- if tmp["aclNumber"] != acl_number:
- need_cfg_acl = True
- else:
- need_cfg_acl = True
-
- cfg_bool_list.append(need_cfg_acl)
-
- if read_view:
- if "readViewName" in tmp.keys():
- need_cfg_read = False
- if tmp["readViewName"] != read_view:
- need_cfg_read = True
- else:
- need_cfg_read = True
- cfg_bool_list.append(need_cfg_read)
-
- if write_view:
- if "writeViewName" in tmp.keys():
- need_cfg_write = False
- if tmp["writeViewName"] != write_view:
- need_cfg_write = True
- else:
- need_cfg_write = True
- cfg_bool_list.append(need_cfg_write)
-
- if notify_view:
- if "notifyViewName" in tmp.keys():
- need_cfg_notify = False
- if tmp["notifyViewName"] != notify_view:
- need_cfg_notify = True
- else:
- need_cfg_notify = True
- cfg_bool_list.append(need_cfg_notify)
-
- if True not in cfg_bool_list:
- need_cfg_bool = False
-
- if state == "present":
- if not need_cfg_bool:
- need_cfg = False
- else:
- need_cfg = True
- else:
- if not need_cfg_bool:
- need_cfg = True
- else:
- need_cfg = False
-
- result["need_cfg"] = need_cfg
- return result
-
- def merge_snmp_community(self, **kwargs):
- """ Merge snmp community operation """
-
- module = kwargs["module"]
- community_name = module.params['community_name']
- access_right = module.params['access_right']
- acl_number = module.params['acl_number']
- community_mib_view = module.params['community_mib_view']
-
- conf_str = CE_MERGE_SNMP_COMMUNITY_HEADER % (
- community_name, access_right)
- if acl_number:
- conf_str += "%s" % acl_number
- if community_mib_view:
- conf_str += "%s" % community_mib_view
-
- conf_str += CE_MERGE_SNMP_COMMUNITY_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge snmp community failed.')
-
- community_safe_name = "******"
-
- cmd = "snmp-agent community %s %s" % (access_right, community_safe_name)
-
- if acl_number:
- cmd += " acl %s" % acl_number
- if community_mib_view:
- cmd += " mib-view %s" % community_mib_view
-
- return cmd
-
- def create_snmp_community(self, **kwargs):
- """ Create snmp community operation """
-
- module = kwargs["module"]
- community_name = module.params['community_name']
- access_right = module.params['access_right']
- acl_number = module.params['acl_number']
- community_mib_view = module.params['community_mib_view']
-
- conf_str = CE_CREATE_SNMP_COMMUNITY_HEADER % (
- community_name, access_right)
- if acl_number:
- conf_str += "%s" % acl_number
- if community_mib_view:
- conf_str += "%s" % community_mib_view
-
- conf_str += CE_CREATE_SNMP_COMMUNITY_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Create snmp community failed.')
-
- community_safe_name = "******"
-
- cmd = "snmp-agent community %s %s" % (access_right, community_safe_name)
-
- if acl_number:
- cmd += " acl %s" % acl_number
- if community_mib_view:
- cmd += " mib-view %s" % community_mib_view
-
- return cmd
-
- def delete_snmp_community(self, **kwargs):
- """ Delete snmp community operation """
-
- module = kwargs["module"]
- community_name = module.params['community_name']
- access_right = module.params['access_right']
- acl_number = module.params['acl_number']
- community_mib_view = module.params['community_mib_view']
-
- conf_str = CE_DELETE_SNMP_COMMUNITY_HEADER % (
- community_name, access_right)
- if acl_number:
- conf_str += "%s" % acl_number
- if community_mib_view:
- conf_str += "%s" % community_mib_view
-
- conf_str += CE_DELETE_SNMP_COMMUNITY_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Create snmp community failed.')
-
- community_safe_name = "******"
- cmd = "undo snmp-agent community %s %s" % (
- access_right, community_safe_name)
-
- return cmd
-
- def merge_snmp_v3_group(self, **kwargs):
- """ Merge snmp v3 group operation """
-
- module = kwargs["module"]
- group_name = module.params['group_name']
- security_level = module.params['security_level']
- acl_number = module.params['acl_number']
- read_view = module.params['read_view']
- write_view = module.params['write_view']
- notify_view = module.params['notify_view']
-
- conf_str = CE_MERGE_SNMP_V3_GROUP_HEADER % (group_name, security_level)
- if acl_number:
- conf_str += "%s" % acl_number
- if read_view:
- conf_str += "%s" % read_view
- if write_view:
- conf_str += "%s" % write_view
- if notify_view:
- conf_str += "%s" % notify_view
- conf_str += CE_MERGE_SNMP_V3_GROUP_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge snmp v3 group failed.')
-
- if security_level == "noAuthNoPriv":
- security_level_cli = "noauthentication"
- elif security_level == "authentication":
- security_level_cli = "authentication"
- elif security_level == "privacy":
- security_level_cli = "privacy"
-
- cmd = "snmp-agent group v3 %s %s" % (group_name, security_level_cli)
-
- if read_view:
- cmd += " read-view %s" % read_view
- if write_view:
- cmd += " write-view %s" % write_view
- if notify_view:
- cmd += " notify-view %s" % notify_view
- if acl_number:
- cmd += " acl %s" % acl_number
-
- return cmd
-
- def create_snmp_v3_group(self, **kwargs):
- """ Create snmp v3 group operation """
-
- module = kwargs["module"]
- group_name = module.params['group_name']
- security_level = module.params['security_level']
- acl_number = module.params['acl_number']
- read_view = module.params['read_view']
- write_view = module.params['write_view']
- notify_view = module.params['notify_view']
-
- conf_str = CE_CREATE_SNMP_V3_GROUP_HEADER % (
- group_name, security_level)
- if acl_number:
- conf_str += "%s" % acl_number
- if read_view:
- conf_str += "%s" % read_view
- if write_view:
- conf_str += "%s" % write_view
- if notify_view:
- conf_str += "%s" % notify_view
- conf_str += CE_CREATE_SNMP_V3_GROUP_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Create snmp v3 group failed.')
-
- if security_level == "noAuthNoPriv":
- security_level_cli = "noauthentication"
- elif security_level == "authentication":
- security_level_cli = "authentication"
- elif security_level == "privacy":
- security_level_cli = "privacy"
-
- cmd = "snmp-agent group v3 %s %s" % (group_name, security_level_cli)
-
- if read_view:
- cmd += " read-view %s" % read_view
- if write_view:
- cmd += " write-view %s" % write_view
- if notify_view:
- cmd += " notify-view %s" % notify_view
- if acl_number:
- cmd += " acl %s" % acl_number
-
- return cmd
-
- def delete_snmp_v3_group(self, **kwargs):
- """ Delete snmp v3 group operation """
-
- module = kwargs["module"]
- group_name = module.params['group_name']
- security_level = module.params['security_level']
- acl_number = module.params['acl_number']
- read_view = module.params['read_view']
- write_view = module.params['write_view']
- notify_view = module.params['notify_view']
-
- conf_str = CE_DELETE_SNMP_V3_GROUP_HEADER % (
- group_name, security_level)
- if acl_number:
- conf_str += "%s" % acl_number
- if read_view:
- conf_str += "%s" % read_view
- if write_view:
- conf_str += "%s" % write_view
- if notify_view:
- conf_str += "%s" % notify_view
- conf_str += CE_DELETE_SNMP_V3_GROUP_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Delete snmp v3 group failed.')
-
- if security_level == "noAuthNoPriv":
- security_level_cli = "noauthentication"
- elif security_level == "authentication":
- security_level_cli = "authentication"
- elif security_level == "privacy":
- security_level_cli = "privacy"
-
- cmd = "undo snmp-agent group v3 %s %s" % (
- group_name, security_level_cli)
-
- return cmd
-
-
-def main():
- """ main function """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- acl_number=dict(type='str'),
- community_name=dict(type='str', no_log=True),
- access_right=dict(choices=['read', 'write']),
- community_mib_view=dict(type='str'),
- group_name=dict(type='str'),
- security_level=dict(
- choices=['noAuthNoPriv', 'authentication', 'privacy']),
- read_view=dict(type='str'),
- write_view=dict(type='str'),
- notify_view=dict(type='str')
- )
-
- argument_spec.update(ce_argument_spec)
- required_together = [("community_name", "access_right"), ("security_level", "group_name")]
- module = AnsibleModule(
- argument_spec=argument_spec,
- required_together=required_together,
- supports_check_mode=True
- )
-
- changed = False
- proposed = dict()
- existing = dict()
- end_state = dict()
- updates = []
-
- state = module.params['state']
- acl_number = module.params['acl_number']
- community_name = module.params['community_name']
- community_mib_view = module.params['community_mib_view']
- access_right = module.params['access_right']
- group_name = module.params['group_name']
- security_level = module.params['security_level']
- read_view = module.params['read_view']
- write_view = module.params['write_view']
- notify_view = module.params['notify_view']
-
- snmp_community_obj = SnmpCommunity()
-
- if not snmp_community_obj:
- module.fail_json(msg='Error: Init module failed.')
-
- snmp_community_rst = snmp_community_obj.check_snmp_community_args(
- module=module)
- snmp_v3_group_rst = snmp_community_obj.check_snmp_v3_group_args(
- module=module)
-
- # get proposed
- proposed["state"] = state
- if acl_number:
- proposed["acl_number"] = acl_number
- if community_name:
- proposed["community_name"] = community_name
- if community_mib_view:
- proposed["community_mib_view"] = community_mib_view
- if access_right:
- proposed["access_right"] = access_right
- if group_name:
- proposed["group_name"] = group_name
- if security_level:
- proposed["security_level"] = security_level
- if read_view:
- proposed["read_view"] = read_view
- if write_view:
- proposed["write_view"] = write_view
- if notify_view:
- proposed["notify_view"] = notify_view
-
- # state exist snmp community config
- exist_tmp = dict()
- for item in snmp_community_rst:
- if item != "need_cfg":
- exist_tmp[item] = snmp_community_rst[item]
-
- if exist_tmp:
- existing["snmp community"] = exist_tmp
- # state exist snmp v3 group config
- exist_tmp = dict()
- for item in snmp_v3_group_rst:
- if item != "need_cfg":
- exist_tmp[item] = snmp_v3_group_rst[item]
-
- if exist_tmp:
- existing["snmp v3 group"] = exist_tmp
-
- if state == "present":
- if snmp_community_rst["need_cfg"]:
- if len(snmp_community_rst["community_info"]) != 0:
- cmd = snmp_community_obj.merge_snmp_community(module=module)
- changed = True
- updates.append(cmd)
- else:
- cmd = snmp_community_obj.create_snmp_community(module=module)
- changed = True
- updates.append(cmd)
-
- if snmp_v3_group_rst["need_cfg"]:
- if len(snmp_v3_group_rst["group_info"]):
- cmd = snmp_community_obj.merge_snmp_v3_group(module=module)
- changed = True
- updates.append(cmd)
- else:
- cmd = snmp_community_obj.create_snmp_v3_group(module=module)
- changed = True
- updates.append(cmd)
-
- else:
- if snmp_community_rst["need_cfg"]:
- cmd = snmp_community_obj.delete_snmp_community(module=module)
- changed = True
- updates.append(cmd)
- if snmp_v3_group_rst["need_cfg"]:
- cmd = snmp_community_obj.delete_snmp_v3_group(module=module)
- changed = True
- updates.append(cmd)
-
- # state end snmp community config
- snmp_community_rst = snmp_community_obj.check_snmp_community_args(
- module=module)
- end_tmp = dict()
- for item in snmp_community_rst:
- if item != "need_cfg":
- end_tmp[item] = snmp_community_rst[item]
- end_tmp[item] = snmp_community_rst[item]
- if end_tmp:
- end_state["snmp community"] = end_tmp
- # state end snmp v3 group config
- snmp_v3_group_rst = snmp_community_obj.check_snmp_v3_group_args(
- module=module)
- end_tmp = dict()
- for item in snmp_v3_group_rst:
- if item != "need_cfg":
- end_tmp[item] = snmp_v3_group_rst[item]
- if end_tmp:
- end_state["snmp v3 group"] = end_tmp
-
- results = dict()
- results['proposed'] = proposed
- results['existing'] = existing
- results['changed'] = changed
- results['end_state'] = end_state
- results['updates'] = updates
-
- module.exit_json(**results)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_snmp_contact.py b/plugins/modules/network/cloudengine/ce_snmp_contact.py
deleted file mode 100644
index 52f9616230..0000000000
--- a/plugins/modules/network/cloudengine/ce_snmp_contact.py
+++ /dev/null
@@ -1,272 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_snmp_contact
-short_description: Manages SNMP contact configuration on HUAWEI CloudEngine switches.
-description:
- - Manages SNMP contact configurations on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- contact:
- description:
- - Contact information.
- required: true
- state:
- description:
- - Manage the state of the resource.
- default: present
- choices: ['present','absent']
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine snmp contact test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Config SNMP contact"
- ce_snmp_contact:
- state: present
- contact: call Operator at 010-99999999
- provider: "{{ cli }}"
-
- - name: "Undo SNMP contact"
- ce_snmp_contact:
- state: absent
- contact: call Operator at 010-99999999
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"contact": "call Operator at 010-99999999",
- "state": "present"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"contact": "call Operator at 010-99999999"}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["snmp-agent sys-info contact call Operator at 010-99999999"]
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import exec_command, load_config, ce_argument_spec
-
-
-class SnmpContact(object):
- """ Manages SNMP contact configuration """
-
- def __init__(self, **kwargs):
- """ Class init """
-
- # module
- argument_spec = kwargs["argument_spec"]
- self.spec = argument_spec
- self.module = AnsibleModule(argument_spec=self.spec, supports_check_mode=True)
-
- # config
- self.cur_cfg = dict()
-
- # module args
- self.state = self.module.params['state']
- self.contact = self.module.params['contact']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def check_args(self):
- """ Check invalid args """
-
- if self.contact:
- if len(self.contact) > 255 or len(self.contact) < 1:
- self.module.fail_json(
- msg='Error: The len of contact %s is out of [1 - 255].' % self.contact)
- else:
- self.module.fail_json(
- msg='Error: The len of contact is 0.')
-
- def get_config(self, flags=None):
- """Retrieves the current config from the device or cache
- """
- flags = [] if flags is None else flags
-
- cmd = 'display current-configuration '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- cfg = str(out).strip()
-
- return cfg
-
- def get_proposed(self):
- """ Get proposed state """
-
- self.proposed["state"] = self.state
-
- if self.contact:
- self.proposed["contact"] = self.contact
-
- def get_existing(self):
- """ Get existing state """
-
- tmp_cfg = self.cli_get_config()
- if tmp_cfg:
- temp_data = tmp_cfg.split(r"contact ")
- if len(temp_data) > 1:
- self.cur_cfg["contact"] = temp_data[1]
- self.existing["contact"] = temp_data[1]
-
- def get_end_state(self):
- """ Get end state """
-
- tmp_cfg = self.cli_get_config()
- if tmp_cfg:
- temp_data = tmp_cfg.split(r"contact ")
- if len(temp_data) > 1:
- self.end_state["contact"] = temp_data[1]
-
- def cli_load_config(self, commands):
- """ Load configure by cli """
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def cli_get_config(self):
- """ Get configure by cli """
-
- regular = "| include snmp | include contact"
- flags = list()
- flags.append(regular)
- tmp_cfg = self.get_config(flags)
-
- return tmp_cfg
-
- def set_config(self):
- """ Set configure by cli """
-
- cmd = "snmp-agent sys-info contact %s" % self.contact
- self.updates_cmd.append(cmd)
-
- cmds = list()
- cmds.append(cmd)
-
- self.cli_load_config(cmds)
- self.changed = True
-
- def undo_config(self):
- """ Undo configure by cli """
-
- cmd = "undo snmp-agent sys-info contact"
- self.updates_cmd.append(cmd)
-
- cmds = list()
- cmds.append(cmd)
-
- self.cli_load_config(cmds)
- self.changed = True
-
- def work(self):
- """ Main work function """
-
- self.check_args()
- self.get_proposed()
- self.get_existing()
-
- if self.state == "present":
- if "contact" in self.cur_cfg.keys() and self.contact == self.cur_cfg["contact"]:
- pass
- else:
- self.set_config()
- else:
- if "contact" in self.cur_cfg.keys() and self.contact == self.cur_cfg["contact"]:
- self.undo_config()
-
- self.get_end_state()
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- self.results['updates'] = self.updates_cmd
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- contact=dict(type='str', required=True)
- )
-
- argument_spec.update(ce_argument_spec)
- module = SnmpContact(argument_spec=argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_snmp_location.py b/plugins/modules/network/cloudengine/ce_snmp_location.py
deleted file mode 100644
index 3187ddeb78..0000000000
--- a/plugins/modules/network/cloudengine/ce_snmp_location.py
+++ /dev/null
@@ -1,273 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_snmp_location
-short_description: Manages SNMP location configuration on HUAWEI CloudEngine switches.
-description:
- - Manages SNMP location configurations on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- location:
- description:
- - Location information.
- required: true
- state:
- description:
- - Manage the state of the resource.
- default: present
- choices: ['present','absent']
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine snmp location test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Config SNMP location"
- ce_snmp_location:
- state: present
- location: nanjing China
- provider: "{{ cli }}"
-
- - name: "Remove SNMP location"
- ce_snmp_location:
- state: absent
- location: nanjing China
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"location": "nanjing China",
- "state": "present"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"location": "nanjing China"}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["snmp-agent sys-info location nanjing China"]
-'''
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import exec_command, load_config, ce_argument_spec
-
-
-class SnmpLocation(object):
- """ Manages SNMP location configuration """
-
- def __init__(self, **kwargs):
- """ Class init """
-
- # module
- argument_spec = kwargs["argument_spec"]
- self.spec = argument_spec
- self.module = AnsibleModule(argument_spec=self.spec, supports_check_mode=True)
-
- # config
- self.cur_cfg = dict()
-
- # module args
- self.state = self.module.params['state']
- self.location = self.module.params['location']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def check_args(self):
- """ Check invalid args """
-
- if self.location:
- if len(self.location) > 255 or len(self.location) < 1:
- self.module.fail_json(
- msg='Error: The len of location %s is out of [1 - 255].' % self.location)
- else:
- self.module.fail_json(
- msg='Error: The len of location is 0.')
-
- def get_config(self, flags=None):
- """Retrieves the current config from the device or cache
- """
- flags = [] if flags is None else flags
-
- cmd = 'display current-configuration '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- cfg = str(out).strip()
-
- return cfg
-
- def get_proposed(self):
- """ Get proposed state """
-
- self.proposed["state"] = self.state
-
- if self.location:
- self.proposed["location"] = self.location
-
- def get_existing(self):
- """ Get existing state """
-
- tmp_cfg = self.cli_get_config()
- if tmp_cfg:
- temp_data = tmp_cfg.split(r"location ")
- if len(temp_data) > 1:
- self.cur_cfg["location"] = temp_data[1]
- self.existing["location"] = temp_data[1]
-
- def get_end_state(self):
- """ Get end state """
-
- tmp_cfg = self.cli_get_config()
- if tmp_cfg:
- temp_data = tmp_cfg.split(r"location ")
- if len(temp_data) > 1:
- self.end_state["location"] = temp_data[1]
-
- def cli_load_config(self, commands):
- """ Load config by cli """
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def cli_get_config(self):
- """ Get config by cli """
-
- regular = "| include snmp | include location"
- flags = list()
- flags.append(regular)
- tmp_cfg = self.get_config(flags)
-
- return tmp_cfg
-
- def set_config(self):
- """ Set configure by cli """
-
- cmd = "snmp-agent sys-info location %s" % self.location
- self.updates_cmd.append(cmd)
-
- cmds = list()
- cmds.append(cmd)
-
- self.cli_load_config(cmds)
- self.changed = True
-
- def undo_config(self):
- """ Undo configure by cli """
-
- cmd = "undo snmp-agent sys-info location"
- self.updates_cmd.append(cmd)
-
- cmds = list()
- cmds.append(cmd)
-
- self.cli_load_config(cmds)
- self.changed = True
-
- def work(self):
- """ Main work function """
-
- self.check_args()
- self.get_proposed()
- self.get_existing()
-
- if self.state == "present":
- if "location" in self.cur_cfg.keys() and self.location == self.cur_cfg["location"]:
- pass
- else:
- self.set_config()
- else:
- if "location" in self.cur_cfg.keys() and self.location == self.cur_cfg["location"]:
- self.undo_config()
-
- self.get_end_state()
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- self.results['updates'] = self.updates_cmd
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- location=dict(type='str', required=True)
- )
-
- argument_spec.update(ce_argument_spec)
- module = SnmpLocation(argument_spec=argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_snmp_target_host.py b/plugins/modules/network/cloudengine/ce_snmp_target_host.py
deleted file mode 100644
index 037cdd54f7..0000000000
--- a/plugins/modules/network/cloudengine/ce_snmp_target_host.py
+++ /dev/null
@@ -1,944 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_snmp_target_host
-short_description: Manages SNMP target host configuration on HUAWEI CloudEngine switches.
-description:
- - Manages SNMP target host configurations on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- version:
- description:
- - Version(s) Supported by SNMP Engine.
- choices: ['none', 'v1', 'v2c', 'v3', 'v1v2c', 'v1v3', 'v2cv3', 'all']
- connect_port:
- description:
- - Udp port used by SNMP agent to connect the Network management.
- host_name:
- description:
- - Unique name to identify target host entry.
- address:
- description:
- - Network Address.
- notify_type:
- description:
- - To configure notify type as trap or inform.
- choices: ['trap','inform']
- vpn_name:
- description:
- - VPN instance Name.
- recv_port:
- description:
- - UDP Port number used by network management to receive alarm messages.
- security_model:
- description:
- - Security Model.
- choices: ['v1','v2c', 'v3']
- security_name:
- description:
- - Security Name.
- security_name_v3:
- description:
- - Security Name V3.
- security_level:
- description:
- - Security level indicating whether to use authentication and encryption.
- choices: ['noAuthNoPriv','authentication', 'privacy']
- is_public_net:
- description:
- - To enable or disable Public Net-manager for target Host.
- default: no_use
- choices: ['no_use','true','false']
- interface_name:
- description:
- - Name of the interface to send the trap message.
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine snmp target host test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Config SNMP version"
- ce_snmp_target_host:
- state: present
- version: v2cv3
- provider: "{{ cli }}"
-
- - name: "Config SNMP target host"
- ce_snmp_target_host:
- state: present
- host_name: test1
- address: 1.1.1.1
- notify_type: trap
- vpn_name: js
- security_model: v2c
- security_name: wdz
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"address": "10.135.182.158", "host_name": "test2",
- "notify_type": "trap", "security_level": "authentication",
- "security_model": "v3", "security_name_v3": "wdz",
- "state": "present", "vpn_name": "js"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"target host info": [{"address": "10.135.182.158", "domain": "snmpUDPDomain",
- "nmsName": "test2", "notifyType": "trap",
- "securityLevel": "authentication", "securityModel": "v3",
- "securityNameV3": "wdz", "vpnInstanceName": "js"}]}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["snmp-agent target-host host-name test2 trap address udp-domain 10.135.182.158 vpn-instance js params securityname wdz v3 authentication"]
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, \
- ce_argument_spec, load_config, check_ip_addr
-
-# get snmp version
-CE_GET_SNMP_VERSION = """
-
-
-
-
-
-
-
-"""
-# merge snmp version
-CE_MERGE_SNMP_VERSION = """
-
-
-
- %s
-
-
-
-"""
-
-# get snmp target host
-CE_GET_SNMP_TARGET_HOST_HEADER = """
-
-
-
-
-
-"""
-CE_GET_SNMP_TARGET_HOST_TAIL = """
-
-
-
-
-"""
-
-# merge snmp target host
-CE_MERGE_SNMP_TARGET_HOST_HEADER = """
-
-
-
-
- %s
-"""
-CE_MERGE_SNMP_TARGET_HOST_TAIL = """
-
-
-
-
-"""
-
-# create snmp target host
-CE_CREATE_SNMP_TARGET_HOST_HEADER = """
-
-
-
-
- %s
-"""
-CE_CREATE_SNMP_TARGET_HOST_TAIL = """
-
-
-
-
-"""
-
-# delete snmp target host
-CE_DELETE_SNMP_TARGET_HOST_HEADER = """
-
-
-
-
- %s
-"""
-CE_DELETE_SNMP_TARGET_HOST_TAIL = """
-
-
-
-
-"""
-
-# get snmp listen port
-CE_GET_SNMP_PORT = """
-
-
-
-
-
-
-
-"""
-
-# merge snmp listen port
-CE_MERGE_SNMP_PORT = """
-
-
-
- %s
-
-
-
-"""
-
-
-INTERFACE_TYPE = ['ethernet', 'eth-trunk', 'tunnel', 'null', 'loopback',
- 'vlanif', '100ge', '40ge', 'mtunnel', '10ge', 'ge', 'meth', 'vbdif', 'nve']
-
-
-class SnmpTargetHost(object):
- """ Manages SNMP target host configuration """
-
- def __init__(self, **kwargs):
- """ Class init """
-
- # module
- argument_spec = kwargs["argument_spec"]
- self.spec = argument_spec
- required_together = [("address", "notify_type"), ("address", "notify_type")]
- required_if = [
- ["security_model", "v1", ["security_name"]],
- ["security_model", "v2c", ["security_name"]],
- ["security_model", "v3", ["security_name_v3"]]
- ]
- self.module = AnsibleModule(
- argument_spec=argument_spec,
- required_together=required_together,
- required_if=required_if,
- supports_check_mode=True
- )
-
- # module args
- self.state = self.module.params['state']
- self.version = self.module.params['version']
- self.connect_port = self.module.params['connect_port']
- self.host_name = self.module.params['host_name']
- self.domain = "snmpUDPDomain"
- self.address = self.module.params['address']
- self.notify_type = self.module.params['notify_type']
- self.vpn_name = self.module.params['vpn_name']
- self.recv_port = self.module.params['recv_port']
- self.security_model = self.module.params['security_model']
- self.security_name = self.module.params['security_name']
- self.security_name_v3 = self.module.params['security_name_v3']
- self.security_level = self.module.params['security_level']
- self.is_public_net = self.module.params['is_public_net']
- self.interface_name = self.module.params['interface_name']
-
- # config
- self.cur_cli_cfg = dict()
- self.cur_netconf_cfg = dict()
- self.end_netconf_cfg = dict()
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def netconf_get_config(self, conf_str):
- """ Get configure by netconf """
-
- xml_str = get_nc_config(self.module, conf_str)
-
- return xml_str
-
- def netconf_set_config(self, conf_str):
- """ Set configure by netconf """
-
- xml_str = set_nc_config(self.module, conf_str)
-
- return xml_str
-
- def check_cli_args(self):
- """ Check invalid cli args """
-
- if self.connect_port:
- if int(self.connect_port) != 161 and (int(self.connect_port) > 65535 or int(self.connect_port) < 1025):
- self.module.fail_json(
- msg='Error: The value of connect_port %s is out of [161, 1025 - 65535].' % self.connect_port)
-
- def check_netconf_args(self, result):
- """ Check invalid netconf args """
-
- need_cfg = True
- same_flag = True
- delete_flag = False
- result["target_host_info"] = []
-
- if self.host_name:
-
- if len(self.host_name) > 32 or len(self.host_name) < 1:
- self.module.fail_json(
- msg='Error: The len of host_name is out of [1 - 32].')
-
- if self.vpn_name and self.is_public_net != 'no_use':
- if self.is_public_net == "true":
- self.module.fail_json(
- msg='Error: Do not support vpn_name and is_public_net at the same time.')
-
- conf_str = CE_GET_SNMP_TARGET_HOST_HEADER
-
- if self.domain:
- conf_str += ""
-
- if self.address:
- if not check_ip_addr(ipaddr=self.address):
- self.module.fail_json(
- msg='Error: The host address [%s] is invalid.' % self.address)
- conf_str += ""
-
- if self.notify_type:
- conf_str += ""
-
- if self.vpn_name:
- if len(self.vpn_name) > 31 or len(self.vpn_name) < 1:
- self.module.fail_json(
- msg='Error: The len of vpn_name is out of [1 - 31].')
- conf_str += ""
-
- if self.recv_port:
- if int(self.recv_port) > 65535 or int(self.recv_port) < 0:
- self.module.fail_json(
- msg='Error: The value of recv_port is out of [0 - 65535].')
- conf_str += ""
-
- if self.security_model:
- conf_str += ""
-
- if self.security_name:
- if len(self.security_name) > 32 or len(self.security_name) < 1:
- self.module.fail_json(
- msg='Error: The len of security_name is out of [1 - 32].')
- conf_str += ""
-
- if self.security_name_v3:
- if len(self.security_name_v3) > 32 or len(self.security_name_v3) < 1:
- self.module.fail_json(
- msg='Error: The len of security_name_v3 is out of [1 - 32].')
- conf_str += ""
-
- if self.security_level:
- conf_str += ""
-
- if self.is_public_net != 'no_use':
- conf_str += ""
-
- if self.interface_name:
- if len(self.interface_name) > 63 or len(self.interface_name) < 1:
- self.module.fail_json(
- msg='Error: The len of interface_name is out of [1 - 63].')
-
- find_flag = False
- for item in INTERFACE_TYPE:
- if item in self.interface_name.lower():
- find_flag = True
- break
- if not find_flag:
- self.module.fail_json(
- msg='Error: Please input full name of interface_name.')
-
- conf_str += ""
-
- conf_str += CE_GET_SNMP_TARGET_HOST_TAIL
- recv_xml = self.netconf_get_config(conf_str=conf_str)
-
- if "" in recv_xml:
- if self.state == "present":
- same_flag = False
- else:
- delete_flag = False
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- target_host_info = root.findall(
- "snmp/targetHosts/targetHost")
- if target_host_info:
- for tmp in target_host_info:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["nmsName", "domain", "address", "notifyType", "vpnInstanceName",
- "portNumber", "securityModel", "securityName", "securityNameV3",
- "securityLevel", "isPublicNet", "interface-name"]:
- tmp_dict[site.tag] = site.text
-
- result["target_host_info"].append(tmp_dict)
-
- if result["target_host_info"]:
- for tmp in result["target_host_info"]:
-
- same_flag = True
-
- if "nmsName" in tmp.keys():
- if tmp["nmsName"] != self.host_name:
- same_flag = False
- else:
- delete_flag = True
-
- if "domain" in tmp.keys():
- if tmp["domain"] != self.domain:
- same_flag = False
-
- if "address" in tmp.keys():
- if tmp["address"] != self.address:
- same_flag = False
-
- if "notifyType" in tmp.keys():
- if tmp["notifyType"] != self.notify_type:
- same_flag = False
-
- if "vpnInstanceName" in tmp.keys():
- if tmp["vpnInstanceName"] != self.vpn_name:
- same_flag = False
-
- if "portNumber" in tmp.keys():
- if tmp["portNumber"] != self.recv_port:
- same_flag = False
-
- if "securityModel" in tmp.keys():
- if tmp["securityModel"] != self.security_model:
- same_flag = False
-
- if "securityName" in tmp.keys():
- if tmp["securityName"] != self.security_name:
- same_flag = False
-
- if "securityNameV3" in tmp.keys():
- if tmp["securityNameV3"] != self.security_name_v3:
- same_flag = False
-
- if "securityLevel" in tmp.keys():
- if tmp["securityLevel"] != self.security_level:
- same_flag = False
-
- if "isPublicNet" in tmp.keys():
- if tmp["isPublicNet"] != self.is_public_net:
- same_flag = False
-
- if "interface-name" in tmp.keys():
- if tmp.get("interface-name") is not None:
- if tmp["interface-name"].lower() != self.interface_name.lower():
- same_flag = False
- else:
- same_flag = False
-
- if same_flag:
- break
-
- if self.state == "present":
- need_cfg = True
- if same_flag:
- need_cfg = False
- else:
- need_cfg = False
- if delete_flag:
- need_cfg = True
-
- result["need_cfg"] = need_cfg
-
- def cli_load_config(self, commands):
- """ Load configure by cli """
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def get_snmp_version(self):
- """ Get snmp version """
-
- version = None
- conf_str = CE_GET_SNMP_VERSION
- recv_xml = self.netconf_get_config(conf_str=conf_str)
-
- if "" in recv_xml:
- pass
-
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- version_info = root.find("snmp/engine")
- if version_info:
- for site in version_info:
- if site.tag in ["version"]:
- version = site.text
-
- return version
-
- def xml_get_connect_port(self):
- """ Get connect port by xml """
- tmp_cfg = None
- conf_str = CE_GET_SNMP_PORT
- recv_xml = self.netconf_get_config(conf_str=conf_str)
- if "" in recv_xml:
- pass
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- snmp_port_info = root.findall("snmp/systemCfg/snmpListenPort")
-
- if snmp_port_info:
- tmp_cfg = snmp_port_info[0].text
- return tmp_cfg
-
- def get_proposed(self):
- """ Get proposed state """
-
- self.proposed["state"] = self.state
-
- if self.version:
- self.proposed["version"] = self.version
- if self.connect_port:
- self.proposed["connect_port"] = self.connect_port
- if self.host_name:
- self.proposed["host_name"] = self.host_name
- if self.address:
- self.proposed["address"] = self.address
- if self.notify_type:
- self.proposed["notify_type"] = self.notify_type
- if self.vpn_name:
- self.proposed["vpn_name"] = self.vpn_name
- if self.recv_port:
- self.proposed["recv_port"] = self.recv_port
- if self.security_model:
- self.proposed["security_model"] = self.security_model
- if self.security_name:
- self.proposed["security_name"] = "******"
- if self.security_name_v3:
- self.proposed["security_name_v3"] = self.security_name_v3
- if self.security_level:
- self.proposed["security_level"] = self.security_level
- if self.is_public_net != 'no_use':
- self.proposed["is_public_net"] = self.is_public_net
- if self.interface_name:
- self.proposed["interface_name"] = self.interface_name
-
- def get_existing(self):
- """ Get existing state """
-
- if self.version:
- version = self.get_snmp_version()
- if version:
- self.cur_cli_cfg["version"] = version
- self.existing["version"] = version
-
- if self.connect_port:
- tmp_cfg = self.xml_get_connect_port()
- if tmp_cfg:
- self.cur_cli_cfg["connect port"] = tmp_cfg
- self.existing["connect port"] = tmp_cfg
-
- if self.host_name:
- self.existing["target host info"] = self.cur_netconf_cfg[
- "target_host_info"]
-
- def get_end_state(self):
- """ Get end state """
-
- if self.version:
- version = self.get_snmp_version()
- if version:
- self.end_state["version"] = version
-
- if self.connect_port:
- tmp_cfg = self.xml_get_connect_port()
- if tmp_cfg:
- self.end_state["connect port"] = tmp_cfg
-
- if self.host_name:
- self.end_state["target host info"] = self.end_netconf_cfg[
- "target_host_info"]
- if self.existing == self.end_state:
- self.changed = False
- self.updates_cmd = list()
-
- def config_version_cli(self):
- """ Config version by cli """
-
- if "disable" in self.cur_cli_cfg["version"]:
- cmd = "snmp-agent sys-info version %s" % self.version
- self.updates_cmd.append(cmd)
-
- cmds = list()
- cmds.append(cmd)
-
- self.cli_load_config(cmds)
- self.changed = True
-
- else:
- if self.version != self.cur_cli_cfg["version"]:
- cmd = "snmp-agent sys-info version %s disable" % self.cur_cli_cfg[
- "version"]
- self.updates_cmd.append(cmd)
- cmd = "snmp-agent sys-info version %s" % self.version
- self.updates_cmd.append(cmd)
-
- cmds = list()
- cmds.append(cmd)
-
- self.cli_load_config(cmds)
- self.changed = True
-
- def undo_config_version_cli(self):
- """ Undo config version by cli """
-
- if "disable" in self.cur_cli_cfg["version"]:
- pass
- else:
- cmd = "snmp-agent sys-info version %s disable" % self.cur_cli_cfg[
- "version"]
-
- cmds = list()
- cmds.append(cmd)
-
- self.updates_cmd.append(cmd)
- self.cli_load_config(cmds)
- self.changed = True
-
- def config_connect_port_xml(self):
- """ Config connect port by xml """
-
- if "connect port" in self.cur_cli_cfg.keys():
- if self.cur_cli_cfg["connect port"] == self.connect_port:
- pass
- else:
- cmd = "snmp-agent udp-port %s" % self.connect_port
-
- cmds = list()
- cmds.append(cmd)
-
- self.updates_cmd.append(cmd)
- conf_str = CE_MERGE_SNMP_PORT % self.connect_port
- self.netconf_set_config(conf_str=conf_str)
- self.changed = True
- else:
- cmd = "snmp-agent udp-port %s" % self.connect_port
-
- cmds = list()
- cmds.append(cmd)
-
- self.updates_cmd.append(cmd)
- conf_str = CE_MERGE_SNMP_PORT % self.connect_port
- self.netconf_set_config(conf_str=conf_str)
- self.changed = True
-
- def undo_config_connect_port_cli(self):
- """ Undo config connect port by cli """
-
- if "connect port" in self.cur_cli_cfg.keys():
- if not self.cur_cli_cfg["connect port"]:
- pass
- else:
- cmd = "undo snmp-agent udp-port"
-
- cmds = list()
- cmds.append(cmd)
-
- self.updates_cmd.append(cmd)
- connect_port = "161"
- conf_str = CE_MERGE_SNMP_PORT % connect_port
- self.netconf_set_config(conf_str=conf_str)
- self.changed = True
-
- def merge_snmp_target_host(self):
- """ Merge snmp target host operation """
-
- conf_str = CE_MERGE_SNMP_TARGET_HOST_HEADER % self.host_name
-
- if self.domain:
- conf_str += "%s" % self.domain
- if self.address:
- conf_str += "%s" % self.address
- if self.notify_type:
- conf_str += "%s" % self.notify_type
- if self.vpn_name:
- conf_str += "%s" % self.vpn_name
- if self.recv_port:
- conf_str += "%s" % self.recv_port
- if self.security_model:
- conf_str += "%s" % self.security_model
- if self.security_name:
- conf_str += "%s" % self.security_name
- if self.security_name_v3:
- conf_str += "%s" % self.security_name_v3
- if self.security_level:
- conf_str += "%s" % self.security_level
- if self.is_public_net != 'no_use':
- conf_str += "%s" % self.is_public_net
- if self.interface_name:
- conf_str += "%s" % self.interface_name
-
- conf_str += CE_MERGE_SNMP_TARGET_HOST_TAIL
-
- recv_xml = self.netconf_set_config(conf_str=conf_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Merge snmp target host failed.')
-
- cmd = "snmp-agent target-host host-name %s " % self.host_name
- cmd += "%s " % self.notify_type
- cmd += "address udp-domain %s " % self.address
-
- if self.recv_port:
- cmd += "udp-port %s " % self.recv_port
- if self.interface_name:
- cmd += "source %s " % self.interface_name
- if self.vpn_name:
- cmd += "vpn-instance %s " % self.vpn_name
- if self.is_public_net == "true":
- cmd += "public-net "
- if self.security_model in ["v1", "v2c"] and self.security_name:
- cmd += "params securityname %s %s " % (
- "******", self.security_model)
- if self.security_model == "v3" and self.security_name_v3:
- cmd += "params securityname %s %s " % (
- self.security_name_v3, self.security_model)
- if self.security_level and self.security_level in ["authentication", "privacy"]:
- cmd += "%s" % self.security_level
-
- self.changed = True
- self.updates_cmd.append(cmd)
-
- def delete_snmp_target_host(self):
- """ Delete snmp target host operation """
-
- conf_str = CE_DELETE_SNMP_TARGET_HOST_HEADER % self.host_name
-
- if self.domain:
- conf_str += "%s" % self.domain
- if self.address:
- conf_str += "%s" % self.address
- if self.notify_type:
- conf_str += "%s" % self.notify_type
- if self.vpn_name:
- conf_str += "%s" % self.vpn_name
- if self.recv_port:
- conf_str += "%s" % self.recv_port
- if self.security_model:
- conf_str += "%s" % self.security_model
- if self.security_name:
- conf_str += "%s" % self.security_name
- if self.security_name_v3:
- conf_str += "%s" % self.security_name_v3
- if self.security_level:
- conf_str += "%s" % self.security_level
- if self.is_public_net != 'no_use':
- conf_str += "%s" % self.is_public_net
- if self.interface_name:
- conf_str += "%s" % self.interface_name
-
- conf_str += CE_DELETE_SNMP_TARGET_HOST_TAIL
-
- recv_xml = self.netconf_set_config(conf_str=conf_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Delete snmp target host failed.')
-
- if not self.address:
- cmd = "undo snmp-agent target-host host-name %s " % self.host_name
- else:
- if self.notify_type == "trap":
- cmd = "undo snmp-agent target-host trap address udp-domain %s " % self.address
- else:
- cmd = "undo snmp-agent target-host inform address udp-domain %s " % self.address
- if self.recv_port:
- cmd += "udp-port %s " % self.recv_port
- if self.interface_name:
- cmd += "source %s " % self.interface_name
- if self.vpn_name:
- cmd += "vpn-instance %s " % self.vpn_name
- if self.is_public_net == "true":
- cmd += "public-net "
- if self.security_model in ["v1", "v2c"] and self.security_name:
- cmd += "params securityname %s" % "******"
- if self.security_model == "v3" and self.security_name_v3:
- cmd += "params securityname %s" % self.security_name_v3
-
- self.changed = True
- self.updates_cmd.append(cmd)
-
- def merge_snmp_version(self):
- """ Merge snmp version operation """
-
- conf_str = CE_MERGE_SNMP_VERSION % self.version
- recv_xml = self.netconf_set_config(conf_str=conf_str)
-
- if "" not in recv_xml:
- self.module.fail_json(msg='Error: Merge snmp version failed.')
-
- if self.version == "none":
- cmd = "snmp-agent sys-info version %s disable" % self.cur_cli_cfg[
- "version"]
- self.updates_cmd.append(cmd)
- elif self.version == "v1v2c":
- cmd = "snmp-agent sys-info version v1"
- self.updates_cmd.append(cmd)
- cmd = "snmp-agent sys-info version v2c"
- self.updates_cmd.append(cmd)
- elif self.version == "v1v3":
- cmd = "snmp-agent sys-info version v1"
- self.updates_cmd.append(cmd)
- cmd = "snmp-agent sys-info version v3"
- self.updates_cmd.append(cmd)
- elif self.version == "v2cv3":
- cmd = "snmp-agent sys-info version v2c"
- self.updates_cmd.append(cmd)
- cmd = "snmp-agent sys-info version v3"
- self.updates_cmd.append(cmd)
- else:
- cmd = "snmp-agent sys-info version %s" % self.version
- self.updates_cmd.append(cmd)
-
- self.changed = True
-
- def work(self):
- """ Main work function """
-
- self.check_cli_args()
- self.check_netconf_args(self.cur_netconf_cfg)
- self.get_proposed()
- self.get_existing()
-
- if self.state == "present":
- if self.version:
- if self.version != self.cur_cli_cfg["version"]:
- self.merge_snmp_version()
- if self.connect_port:
- self.config_connect_port_xml()
- if self.cur_netconf_cfg["need_cfg"]:
- self.merge_snmp_target_host()
-
- else:
- if self.connect_port:
- self.undo_config_connect_port_cli()
- if self.cur_netconf_cfg["need_cfg"]:
- self.delete_snmp_target_host()
-
- self.check_netconf_args(self.end_netconf_cfg)
- self.get_end_state()
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- self.results['updates'] = self.updates_cmd
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- version=dict(choices=['none', 'v1', 'v2c', 'v3',
- 'v1v2c', 'v1v3', 'v2cv3', 'all']),
- connect_port=dict(type='str'),
- host_name=dict(type='str'),
- address=dict(type='str'),
- notify_type=dict(choices=['trap', 'inform']),
- vpn_name=dict(type='str'),
- recv_port=dict(type='str'),
- security_model=dict(choices=['v1', 'v2c', 'v3']),
- security_name=dict(type='str', no_log=True),
- security_name_v3=dict(type='str'),
- security_level=dict(
- choices=['noAuthNoPriv', 'authentication', 'privacy']),
- is_public_net=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
- interface_name=dict(type='str')
- )
-
- argument_spec.update(ce_argument_spec)
- module = SnmpTargetHost(argument_spec=argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_snmp_traps.py b/plugins/modules/network/cloudengine/ce_snmp_traps.py
deleted file mode 100644
index ec40b8f00c..0000000000
--- a/plugins/modules/network/cloudengine/ce_snmp_traps.py
+++ /dev/null
@@ -1,563 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_snmp_traps
-short_description: Manages SNMP traps configuration on HUAWEI CloudEngine switches.
-description:
- - Manages SNMP traps configurations on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- feature_name:
- description:
- - Alarm feature name.
- choices: ['aaa', 'arp', 'bfd', 'bgp', 'cfg', 'configuration', 'dad', 'devm',
- 'dhcpsnp', 'dldp', 'driver', 'efm', 'erps', 'error-down', 'fcoe',
- 'fei', 'fei_comm', 'fm', 'ifnet', 'info', 'ipsg', 'ipv6', 'isis',
- 'l3vpn', 'lacp', 'lcs', 'ldm', 'ldp', 'ldt', 'lldp', 'mpls_lspm',
- 'msdp', 'mstp', 'nd', 'netconf', 'nqa', 'nvo3', 'openflow', 'ospf',
- 'ospfv3', 'pim', 'pim-std', 'qos', 'radius', 'rm', 'rmon', 'securitytrap',
- 'smlktrap', 'snmp', 'ssh', 'stackmng', 'sysclock', 'sysom', 'system',
- 'tcp', 'telnet', 'trill', 'trunk', 'tty', 'vbst', 'vfs', 'virtual-perception',
- 'vrrp', 'vstm', 'all']
- trap_name:
- description:
- - Alarm trap name.
- interface_type:
- description:
- - Interface type.
- choices: ['Ethernet', 'Eth-Trunk', 'Tunnel', 'NULL', 'LoopBack', 'Vlanif', '100GE',
- '40GE', 'MTunnel', '10GE', 'GE', 'MEth', 'Vbdif', 'Nve']
- interface_number:
- description:
- - Interface number.
- port_number:
- description:
- - Source port number.
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine snmp traps test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Config SNMP trap all enable"
- ce_snmp_traps:
- state: present
- feature_name: all
- provider: "{{ cli }}"
-
- - name: "Config SNMP trap interface"
- ce_snmp_traps:
- state: present
- interface_type: 40GE
- interface_number: 2/0/1
- provider: "{{ cli }}"
-
- - name: "Config SNMP trap port"
- ce_snmp_traps:
- state: present
- port_number: 2222
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"feature_name": "all",
- "state": "present"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {"snmp-agent trap": [],
- "undo snmp-agent trap": []}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"snmp-agent trap": ["enable"],
- "undo snmp-agent trap": []}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["snmp-agent trap enable"]
-'''
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import load_config, ce_argument_spec, run_commands
-from ansible.module_utils.connection import exec_command
-
-
-class SnmpTraps(object):
- """ Manages SNMP trap configuration """
-
- def __init__(self, **kwargs):
- """ Class init """
-
- # module
- argument_spec = kwargs["argument_spec"]
- self.spec = argument_spec
- self.module = AnsibleModule(
- argument_spec=self.spec,
- required_together=[("interface_type", "interface_number")],
- supports_check_mode=True
- )
-
- # config
- self.cur_cfg = dict()
- self.cur_cfg["snmp-agent trap"] = []
- self.cur_cfg["undo snmp-agent trap"] = []
-
- # module args
- self.state = self.module.params['state']
- self.feature_name = self.module.params['feature_name']
- self.trap_name = self.module.params['trap_name']
- self.interface_type = self.module.params['interface_type']
- self.interface_number = self.module.params['interface_number']
- self.port_number = self.module.params['port_number']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.existing["snmp-agent trap"] = []
- self.existing["undo snmp-agent trap"] = []
- self.end_state = dict()
- self.end_state["snmp-agent trap"] = []
- self.end_state["undo snmp-agent trap"] = []
-
- commands = list()
- cmd1 = 'display interface brief'
- commands.append(cmd1)
- self.interface = run_commands(self.module, commands)
-
- def get_config(self, flags=None):
- """Retrieves the current config from the device or cache
- """
- flags = [] if flags is None else flags
-
- cmd = 'display current-configuration '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- cfg = str(out).strip()
-
- return cfg
-
- def check_args(self):
- """ Check invalid args """
-
- if self.port_number:
- if self.port_number.isdigit():
- if int(self.port_number) < 1025 or int(self.port_number) > 65535:
- self.module.fail_json(
- msg='Error: The value of port_number is out of [1025 - 65535].')
- else:
- self.module.fail_json(
- msg='Error: The port_number is not digit.')
-
- if self.interface_type and self.interface_number:
- tmp_interface = self.interface_type + self.interface_number
- if tmp_interface not in self.interface[0]:
- self.module.fail_json(
- msg='Error: The interface %s is not in the device.' % tmp_interface)
-
- def get_proposed(self):
- """ Get proposed state """
-
- self.proposed["state"] = self.state
-
- if self.feature_name:
- self.proposed["feature_name"] = self.feature_name
-
- if self.trap_name:
- self.proposed["trap_name"] = self.trap_name
-
- if self.interface_type:
- self.proposed["interface_type"] = self.interface_type
-
- if self.interface_number:
- self.proposed["interface_number"] = self.interface_number
-
- if self.port_number:
- self.proposed["port_number"] = self.port_number
-
- def get_existing(self):
- """ Get existing state """
-
- tmp_cfg = self.cli_get_config()
- if tmp_cfg:
- temp_cfg_lower = tmp_cfg.lower()
- temp_data = tmp_cfg.split("\n")
- temp_data_lower = temp_cfg_lower.split("\n")
-
- for item in temp_data:
- if "snmp-agent trap source-port " in item:
- if self.port_number:
- item_tmp = item.split("snmp-agent trap source-port ")
- self.cur_cfg["trap source-port"] = item_tmp[1]
- self.existing["trap source-port"] = item_tmp[1]
- elif "snmp-agent trap source " in item:
- if self.interface_type:
- item_tmp = item.split("snmp-agent trap source ")
- self.cur_cfg["trap source interface"] = item_tmp[1]
- self.existing["trap source interface"] = item_tmp[1]
-
- if self.feature_name:
- for item in temp_data_lower:
- if item == "snmp-agent trap enable":
- self.cur_cfg["snmp-agent trap"].append("enable")
- self.existing["snmp-agent trap"].append("enable")
- elif item == "snmp-agent trap disable":
- self.cur_cfg["snmp-agent trap"].append("disable")
- self.existing["snmp-agent trap"].append("disable")
- elif "undo snmp-agent trap enable " in item:
- item_tmp = item.split("undo snmp-agent trap enable ")
- self.cur_cfg[
- "undo snmp-agent trap"].append(item_tmp[1])
- self.existing[
- "undo snmp-agent trap"].append(item_tmp[1])
- elif "snmp-agent trap enable " in item:
- item_tmp = item.split("snmp-agent trap enable ")
- self.cur_cfg["snmp-agent trap"].append(item_tmp[1])
- self.existing["snmp-agent trap"].append(item_tmp[1])
- else:
- del self.existing["snmp-agent trap"]
- del self.existing["undo snmp-agent trap"]
-
- def get_end_state(self):
- """ Get end_state state """
-
- tmp_cfg = self.cli_get_config()
- if tmp_cfg:
- temp_cfg_lower = tmp_cfg.lower()
- temp_data = tmp_cfg.split("\n")
- temp_data_lower = temp_cfg_lower.split("\n")
-
- for item in temp_data:
- if "snmp-agent trap source-port " in item:
- if self.port_number:
- item_tmp = item.split("snmp-agent trap source-port ")
- self.end_state["trap source-port"] = item_tmp[1]
- elif "snmp-agent trap source " in item:
- if self.interface_type:
- item_tmp = item.split("snmp-agent trap source ")
- self.end_state["trap source interface"] = item_tmp[1]
-
- if self.feature_name:
- for item in temp_data_lower:
- if item == "snmp-agent trap enable":
- self.end_state["snmp-agent trap"].append("enable")
- elif item == "snmp-agent trap disable":
- self.end_state["snmp-agent trap"].append("disable")
- elif "undo snmp-agent trap enable " in item:
- item_tmp = item.split("undo snmp-agent trap enable ")
- self.end_state[
- "undo snmp-agent trap"].append(item_tmp[1])
- elif "snmp-agent trap enable " in item:
- item_tmp = item.split("snmp-agent trap enable ")
- self.end_state["snmp-agent trap"].append(item_tmp[1])
- else:
- del self.end_state["snmp-agent trap"]
- del self.end_state["undo snmp-agent trap"]
- if self.end_state == self.existing:
- self.changed = False
- self.updates_cmd = list()
-
- def cli_load_config(self, commands):
- """ Load configure through cli """
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def cli_get_config(self):
- """ Get configure through cli """
-
- regular = "| include snmp | include trap"
- flags = list()
- flags.append(regular)
- tmp_cfg = self.get_config(flags)
-
- return tmp_cfg
-
- def set_trap_feature_name(self):
- """ Set feature name for trap """
-
- if self.feature_name == "all":
- cmd = "snmp-agent trap enable"
- else:
- cmd = "snmp-agent trap enable feature-name %s" % self.feature_name
- if self.trap_name:
- cmd += " trap-name %s" % self.trap_name
-
- self.updates_cmd.append(cmd)
-
- cmds = list()
- cmds.append(cmd)
-
- self.cli_load_config(cmds)
- self.changed = True
-
- def undo_trap_feature_name(self):
- """ Undo feature name for trap """
-
- if self.feature_name == "all":
- cmd = "undo snmp-agent trap enable"
- else:
- cmd = "undo snmp-agent trap enable feature-name %s" % self.feature_name
- if self.trap_name:
- cmd += " trap-name %s" % self.trap_name
-
- self.updates_cmd.append(cmd)
-
- cmds = list()
- cmds.append(cmd)
-
- self.cli_load_config(cmds)
- self.changed = True
-
- def set_trap_source_interface(self):
- """ Set source interface for trap """
-
- cmd = "snmp-agent trap source %s %s" % (
- self.interface_type, self.interface_number)
- self.updates_cmd.append(cmd)
-
- cmds = list()
- cmds.append(cmd)
-
- self.cli_load_config(cmds)
- self.changed = True
-
- def undo_trap_source_interface(self):
- """ Undo source interface for trap """
-
- cmd = "undo snmp-agent trap source"
- self.updates_cmd.append(cmd)
-
- cmds = list()
- cmds.append(cmd)
-
- self.cli_load_config(cmds)
- self.changed = True
-
- def set_trap_source_port(self):
- """ Set source port for trap """
-
- cmd = "snmp-agent trap source-port %s" % self.port_number
- self.updates_cmd.append(cmd)
-
- cmds = list()
- cmds.append(cmd)
-
- self.cli_load_config(cmds)
- self.changed = True
-
- def undo_trap_source_port(self):
- """ Undo source port for trap """
-
- cmd = "undo snmp-agent trap source-port"
- self.updates_cmd.append(cmd)
-
- cmds = list()
- cmds.append(cmd)
-
- self.cli_load_config(cmds)
- self.changed = True
-
- def work(self):
- """ The work function """
-
- self.check_args()
- self.get_proposed()
- self.get_existing()
-
- find_flag = False
- find_undo_flag = False
- tmp_interface = None
-
- if self.state == "present":
- if self.feature_name:
- if self.trap_name:
- tmp_cfg = "feature-name %s trap-name %s" % (
- self.feature_name, self.trap_name.lower())
- else:
- tmp_cfg = "feature-name %s" % self.feature_name
-
- find_undo_flag = False
- if self.cur_cfg["undo snmp-agent trap"]:
- for item in self.cur_cfg["undo snmp-agent trap"]:
- if item == tmp_cfg:
- find_undo_flag = True
- elif tmp_cfg in item:
- find_undo_flag = True
- elif self.feature_name == "all":
- find_undo_flag = True
- if find_undo_flag:
- self.set_trap_feature_name()
-
- if not find_undo_flag:
- find_flag = False
- if self.cur_cfg["snmp-agent trap"]:
- for item in self.cur_cfg["snmp-agent trap"]:
- if item == "enable":
- find_flag = True
- elif item == tmp_cfg:
- find_flag = True
- if not find_flag:
- self.set_trap_feature_name()
-
- if self.interface_type:
- find_flag = False
- tmp_interface = self.interface_type + self.interface_number
-
- if "trap source interface" in self.cur_cfg.keys():
- if self.cur_cfg["trap source interface"] == tmp_interface:
- find_flag = True
-
- if not find_flag:
- self.set_trap_source_interface()
-
- if self.port_number:
- find_flag = False
-
- if "trap source-port" in self.cur_cfg.keys():
- if self.cur_cfg["trap source-port"] == self.port_number:
- find_flag = True
-
- if not find_flag:
- self.set_trap_source_port()
-
- else:
- if self.feature_name:
- if self.trap_name:
- tmp_cfg = "feature-name %s trap-name %s" % (
- self.feature_name, self.trap_name.lower())
- else:
- tmp_cfg = "feature-name %s" % self.feature_name
-
- find_flag = False
- if self.cur_cfg["snmp-agent trap"]:
- for item in self.cur_cfg["snmp-agent trap"]:
- if item == tmp_cfg:
- find_flag = True
- elif item == "enable":
- find_flag = True
- elif tmp_cfg in item:
- find_flag = True
- else:
- find_flag = True
-
- find_undo_flag = False
- if self.cur_cfg["undo snmp-agent trap"]:
- for item in self.cur_cfg["undo snmp-agent trap"]:
- if item == tmp_cfg:
- find_undo_flag = True
- elif tmp_cfg in item:
- find_undo_flag = True
-
- if find_undo_flag:
- pass
- elif find_flag:
- self.undo_trap_feature_name()
-
- if self.interface_type:
- if "trap source interface" in self.cur_cfg.keys():
- self.undo_trap_source_interface()
-
- if self.port_number:
- if "trap source-port" in self.cur_cfg.keys():
- self.undo_trap_source_port()
-
- self.get_end_state()
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- self.results['updates'] = self.updates_cmd
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- feature_name=dict(choices=['aaa', 'arp', 'bfd', 'bgp', 'cfg', 'configuration', 'dad',
- 'devm', 'dhcpsnp', 'dldp', 'driver', 'efm', 'erps', 'error-down',
- 'fcoe', 'fei', 'fei_comm', 'fm', 'ifnet', 'info', 'ipsg', 'ipv6',
- 'isis', 'l3vpn', 'lacp', 'lcs', 'ldm', 'ldp', 'ldt', 'lldp',
- 'mpls_lspm', 'msdp', 'mstp', 'nd', 'netconf', 'nqa', 'nvo3',
- 'openflow', 'ospf', 'ospfv3', 'pim', 'pim-std', 'qos', 'radius',
- 'rm', 'rmon', 'securitytrap', 'smlktrap', 'snmp', 'ssh', 'stackmng',
- 'sysclock', 'sysom', 'system', 'tcp', 'telnet', 'trill', 'trunk',
- 'tty', 'vbst', 'vfs', 'virtual-perception', 'vrrp', 'vstm', 'all']),
- trap_name=dict(type='str'),
- interface_type=dict(choices=['Ethernet', 'Eth-Trunk', 'Tunnel', 'NULL', 'LoopBack', 'Vlanif',
- '100GE', '40GE', 'MTunnel', '10GE', 'GE', 'MEth', 'Vbdif', 'Nve']),
- interface_number=dict(type='str'),
- port_number=dict(type='str')
- )
-
- argument_spec.update(ce_argument_spec)
- module = SnmpTraps(argument_spec=argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_snmp_user.py b/plugins/modules/network/cloudengine/ce_snmp_user.py
deleted file mode 100644
index 5358b8926f..0000000000
--- a/plugins/modules/network/cloudengine/ce_snmp_user.py
+++ /dev/null
@@ -1,1048 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_snmp_user
-short_description: Manages SNMP user configuration on HUAWEI CloudEngine switches.
-description:
- - Manages SNMP user configurations on CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- acl_number:
- description:
- - Access control list number.
- usm_user_name:
- description:
- - Unique name to identify the USM user.
- aaa_local_user:
- description:
- - Unique name to identify the local user.
- remote_engine_id:
- description:
- - Remote engine id of the USM user.
- user_group:
- description:
- - Name of the group where user belongs to.
- auth_protocol:
- description:
- - Authentication protocol.
- choices: ['noAuth', 'md5', 'sha']
- auth_key:
- description:
- - The authentication password. Password length, 8-255 characters.
- priv_protocol:
- description:
- - Encryption protocol.
- choices: ['noPriv', 'des56', '3des168', 'aes128', 'aes192', 'aes256']
- priv_key:
- description:
- - The encryption password. Password length 8-255 characters.
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine snmp user test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Config SNMP usm user"
- ce_snmp_user:
- state: present
- usm_user_name: wdz_snmp
- remote_engine_id: 800007DB03389222111200
- acl_number: 2000
- user_group: wdz_group
- provider: "{{ cli }}"
-
- - name: "Undo SNMP usm user"
- ce_snmp_user:
- state: absent
- usm_user_name: wdz_snmp
- remote_engine_id: 800007DB03389222111200
- acl_number: 2000
- user_group: wdz_group
- provider: "{{ cli }}"
-
- - name: "Config SNMP local user"
- ce_snmp_user:
- state: present
- aaa_local_user: wdz_user
- auth_protocol: md5
- auth_key: huawei123
- priv_protocol: des56
- priv_key: huawei123
- provider: "{{ cli }}"
-
- - name: "Config SNMP local user"
- ce_snmp_user:
- state: absent
- aaa_local_user: wdz_user
- auth_protocol: md5
- auth_key: huawei123
- priv_protocol: des56
- priv_key: huawei123
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"acl_number": "2000", "remote_engine_id": "800007DB03389222111200",
- "state": "present", "user_group": "wdz_group",
- "usm_user_name": "wdz_snmp"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {"snmp local user": {"local_user_info": []},
- "snmp usm user": {"usm_user_info": []}}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"snmp local user": {"local_user_info": []},
- "snmp usm user": {"usm_user_info": [{"aclNumber": "2000", "engineID": "800007DB03389222111200",
- "groupName": "wdz_group", "userName": "wdz_snmp"}]}}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["snmp-agent remote-engineid 800007DB03389222111200 usm-user v3 wdz_snmp wdz_group acl 2000"]
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec
-
-# get snmp v3 USM user
-CE_GET_SNMP_V3_USM_USER_HEADER = """
-
-
-
-
-
-
-
-"""
-CE_GET_SNMP_V3_USM_USER_TAIL = """
-
-
-
-
-"""
-# merge snmp v3 USM user
-CE_MERGE_SNMP_V3_USM_USER_HEADER = """
-
-
-
-
- %s
- %s
- %s
-"""
-CE_MERGE_SNMP_V3_USM_USER_TAIL = """
-
-
-
-
-"""
-# create snmp v3 USM user
-CE_CREATE_SNMP_V3_USM_USER_HEADER = """
-
-
-
-
- %s
- %s
- %s
-"""
-CE_CREATE_SNMP_V3_USM_USER_TAIL = """
-
-
-
-
-"""
-# delete snmp v3 USM user
-CE_DELETE_SNMP_V3_USM_USER_HEADER = """
-
-
-
-
- %s
- %s
- %s
-"""
-CE_DELETE_SNMP_V3_USM_USER_TAIL = """
-
-
-
-
-"""
-
-# get snmp v3 aaa local user
-CE_GET_SNMP_V3_LOCAL_USER = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-# merge snmp v3 aaa local user
-CE_MERGE_SNMP_V3_LOCAL_USER = """
-
-
-
-
- %s
- %s
- %s
- %s
- %s
-
-
-
-
-"""
-# create snmp v3 aaa local user
-CE_CREATE_SNMP_V3_LOCAL_USER = """
-
-
-
-
- %s
- %s
- %s
- %s
- %s
-
-
-
-
-"""
-# delete snmp v3 aaa local user
-CE_DELETE_SNMP_V3_LOCAL_USER = """
-
-
-
-
- %s
- %s
- %s
- %s
- %s
-
-
-
-
-"""
-# display info
-GET_SNMP_LOCAL_ENGINE = """
-
-
-
-
-
-
-
-"""
-
-
-class SnmpUser(object):
- """ Manages SNMP user configuration """
-
- def netconf_get_config(self, **kwargs):
- """ Get configure by netconf """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- xml_str = get_nc_config(module, conf_str)
-
- return xml_str
-
- def netconf_set_config(self, **kwargs):
- """ Set configure by netconf """
-
- module = kwargs["module"]
- conf_str = kwargs["conf_str"]
-
- xml_str = set_nc_config(module, conf_str)
-
- return xml_str
-
- def check_snmp_v3_usm_user_args(self, **kwargs):
- """ Check snmp v3 usm user invalid args """
-
- module = kwargs["module"]
- result = dict()
- need_cfg = False
- state = module.params['state']
- usm_user_name = module.params['usm_user_name']
- remote_engine_id = module.params['remote_engine_id']
-
- acl_number = module.params['acl_number']
- user_group = module.params['user_group']
- auth_protocol = module.params['auth_protocol']
- auth_key = module.params['auth_key']
- priv_protocol = module.params['priv_protocol']
- priv_key = module.params['priv_key']
-
- local_user_name = module.params['aaa_local_user']
-
- if usm_user_name:
- if len(usm_user_name) > 32 or len(usm_user_name) == 0:
- module.fail_json(
- msg='Error: The length of usm_user_name %s is out of [1 - 32].' % usm_user_name)
- if remote_engine_id:
- if len(remote_engine_id) > 64 or len(remote_engine_id) < 10:
- module.fail_json(
- msg='Error: The length of remote_engine_id %s is out of [10 - 64].' % remote_engine_id)
-
- conf_str = CE_GET_SNMP_V3_USM_USER_HEADER
-
- if acl_number:
- if acl_number.isdigit():
- if int(acl_number) > 2999 or int(acl_number) < 2000:
- module.fail_json(
- msg='Error: The value of acl_number %s is out of [2000 - 2999].' % acl_number)
- else:
- if not acl_number[0].isalpha() or len(acl_number) > 32 or len(acl_number) < 1:
- module.fail_json(
- msg='Error: The length of acl_number %s is out of [1 - 32].' % acl_number)
-
- conf_str += ""
-
- if user_group:
- if len(user_group) > 32 or len(user_group) == 0:
- module.fail_json(
- msg='Error: The length of user_group %s is out of [1 - 32].' % user_group)
-
- conf_str += ""
-
- if auth_protocol:
- conf_str += ""
-
- if auth_key:
- if len(auth_key) > 255 or len(auth_key) == 0:
- module.fail_json(
- msg='Error: The length of auth_key %s is out of [1 - 255].' % auth_key)
-
- conf_str += ""
-
- if priv_protocol:
- if not auth_protocol:
- module.fail_json(
- msg='Error: Please input auth_protocol at the same time.')
-
- conf_str += ""
-
- if priv_key:
- if len(priv_key) > 255 or len(priv_key) == 0:
- module.fail_json(
- msg='Error: The length of priv_key %s is out of [1 - 255].' % priv_key)
- conf_str += ""
-
- result["usm_user_info"] = []
-
- conf_str += CE_GET_SNMP_V3_USM_USER_TAIL
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- if state == "present":
- need_cfg = True
-
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- usm_user_info = root.findall("snmp/usmUsers/usmUser")
- if usm_user_info:
- for tmp in usm_user_info:
- tmp_dict = dict()
- tmp_dict["remoteEngineID"] = None
- for site in tmp:
- if site.tag in ["userName", "remoteEngineID", "engineID", "groupName", "authProtocol",
- "authKey", "privProtocol", "privKey", "aclNumber"]:
- tmp_dict[site.tag] = site.text
-
- result["usm_user_info"].append(tmp_dict)
-
- cur_cfg = dict()
- if usm_user_name:
- cur_cfg["userName"] = usm_user_name
- if user_group:
- cur_cfg["groupName"] = user_group
- if auth_protocol:
- cur_cfg["authProtocol"] = auth_protocol
- if auth_key:
- cur_cfg["authKey"] = auth_key
- if priv_protocol:
- cur_cfg["privProtocol"] = priv_protocol
- if priv_key:
- cur_cfg["privKey"] = priv_key
- if acl_number:
- cur_cfg["aclNumber"] = acl_number
-
- if remote_engine_id:
- cur_cfg["engineID"] = remote_engine_id
- cur_cfg["remoteEngineID"] = "true"
- else:
- cur_cfg["engineID"] = self.local_engine_id
- cur_cfg["remoteEngineID"] = "false"
-
- if result["usm_user_info"]:
- num = 0
- for tmp in result["usm_user_info"]:
- if cur_cfg == tmp:
- num += 1
-
- if num == 0:
- if state == "present":
- need_cfg = True
- else:
- need_cfg = False
- else:
- if state == "present":
- need_cfg = False
- else:
- need_cfg = True
-
- else:
- if state == "present":
- need_cfg = True
- else:
- need_cfg = False
-
- result["need_cfg"] = need_cfg
- return result
-
- def check_snmp_v3_local_user_args(self, **kwargs):
- """ Check snmp v3 local user invalid args """
-
- module = kwargs["module"]
- result = dict()
-
- need_cfg = False
- state = module.params['state']
- local_user_name = module.params['aaa_local_user']
- auth_protocol = module.params['auth_protocol']
- auth_key = module.params['auth_key']
- priv_protocol = module.params['priv_protocol']
- priv_key = module.params['priv_key']
-
- usm_user_name = module.params['usm_user_name']
-
- if local_user_name:
-
- if usm_user_name:
- module.fail_json(
- msg='Error: Please do not input usm_user_name and local_user_name at the same time.')
-
- if not auth_protocol or not auth_key or not priv_protocol or not priv_key:
- module.fail_json(
- msg='Error: Please input auth_protocol auth_key priv_protocol priv_key for local user.')
-
- if len(local_user_name) > 32 or len(local_user_name) == 0:
- module.fail_json(
- msg='Error: The length of local_user_name %s is out of [1 - 32].' % local_user_name)
-
- if len(auth_key) > 255 or len(auth_key) == 0:
- module.fail_json(
- msg='Error: The length of auth_key %s is out of [1 - 255].' % auth_key)
-
- if len(priv_key) > 255 or len(priv_key) == 0:
- module.fail_json(
- msg='Error: The length of priv_key %s is out of [1 - 255].' % priv_key)
-
- result["local_user_info"] = []
-
- conf_str = CE_GET_SNMP_V3_LOCAL_USER
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
-
- if "" in recv_xml:
- if state == "present":
- need_cfg = True
-
- else:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- local_user_info = root.findall(
- "snmp/localUsers/localUser")
- if local_user_info:
- for tmp in local_user_info:
- tmp_dict = dict()
- for site in tmp:
- if site.tag in ["userName", "authProtocol", "authKey", "privProtocol", "privKey"]:
- tmp_dict[site.tag] = site.text
-
- result["local_user_info"].append(tmp_dict)
-
- if result["local_user_info"]:
- for tmp in result["local_user_info"]:
- if "userName" in tmp.keys():
- if state == "present":
- if tmp["userName"] != local_user_name:
- need_cfg = True
- else:
- if tmp["userName"] == local_user_name:
- need_cfg = True
- if auth_protocol:
- if "authProtocol" in tmp.keys():
- if state == "present":
- if tmp["authProtocol"] != auth_protocol:
- need_cfg = True
- else:
- if tmp["authProtocol"] == auth_protocol:
- need_cfg = True
- if auth_key:
- if "authKey" in tmp.keys():
- if state == "present":
- if tmp["authKey"] != auth_key:
- need_cfg = True
- else:
- if tmp["authKey"] == auth_key:
- need_cfg = True
- if priv_protocol:
- if "privProtocol" in tmp.keys():
- if state == "present":
- if tmp["privProtocol"] != priv_protocol:
- need_cfg = True
- else:
- if tmp["privProtocol"] == priv_protocol:
- need_cfg = True
- if priv_key:
- if "privKey" in tmp.keys():
- if state == "present":
- if tmp["privKey"] != priv_key:
- need_cfg = True
- else:
- if tmp["privKey"] == priv_key:
- need_cfg = True
-
- result["need_cfg"] = need_cfg
- return result
-
- def merge_snmp_v3_usm_user(self, **kwargs):
- """ Merge snmp v3 usm user operation """
-
- module = kwargs["module"]
- usm_user_name = module.params['usm_user_name']
- remote_engine_id = module.params['remote_engine_id']
- acl_number = module.params['acl_number']
- user_group = module.params['user_group']
- auth_protocol = module.params['auth_protocol']
- auth_key = module.params['auth_key']
- priv_protocol = module.params['priv_protocol']
- priv_key = module.params['priv_key']
-
- cmds = []
-
- if remote_engine_id:
- conf_str = CE_MERGE_SNMP_V3_USM_USER_HEADER % (
- usm_user_name, "true", remote_engine_id)
- cmd = "snmp-agent remote-engineid %s usm-user v3 %s" % (
- remote_engine_id, usm_user_name)
- else:
- if not self.local_engine_id:
- module.fail_json(
- msg='Error: The local engine id is null, please input remote_engine_id.')
-
- conf_str = CE_MERGE_SNMP_V3_USM_USER_HEADER % (
- usm_user_name, "false", self.local_engine_id)
- cmd = "snmp-agent usm-user v3 %s" % usm_user_name
-
- if user_group:
- conf_str += "%s" % user_group
- cmd += " %s" % user_group
-
- if acl_number:
- conf_str += "%s" % acl_number
- cmd += " acl %s" % acl_number
-
- cmds.append(cmd)
-
- if remote_engine_id:
- cmd = "snmp-agent remote-engineid %s usm-user v3 %s" % (
- remote_engine_id, usm_user_name)
- else:
- cmd = "snmp-agent usm-user v3 %s" % usm_user_name
-
- if auth_protocol:
- conf_str += "%s" % auth_protocol
-
- if auth_protocol != "noAuth":
- cmd += " authentication-mode %s" % auth_protocol
-
- if auth_key:
- conf_str += "%s" % auth_key
-
- if auth_protocol != "noAuth":
- cmd += " cipher %s" % "******"
- if auth_protocol or auth_key:
- cmds.append(cmd)
-
- if remote_engine_id:
- cmd = "snmp-agent remote-engineid %s usm-user v3 %s" % (
- remote_engine_id, usm_user_name)
- else:
- cmd = "snmp-agent usm-user v3 %s" % usm_user_name
-
- if priv_protocol:
- conf_str += "%s" % priv_protocol
-
- if auth_protocol != "noAuth" and priv_protocol != "noPriv":
- cmd += " privacy-mode %s" % priv_protocol
-
- if priv_key:
- conf_str += "%s" % priv_key
-
- if auth_protocol != "noAuth" and priv_protocol != "noPriv":
- cmd += " cipher %s" % "******"
- if priv_key or priv_protocol:
- cmds.append(cmd)
-
- conf_str += CE_MERGE_SNMP_V3_USM_USER_TAIL
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge snmp v3 usm user failed.')
-
- return cmds
-
- def create_snmp_v3_usm_user(self, **kwargs):
- """ Create snmp v3 usm user operation """
-
- module = kwargs["module"]
- usm_user_name = module.params['usm_user_name']
- remote_engine_id = module.params['remote_engine_id']
- acl_number = module.params['acl_number']
- user_group = module.params['user_group']
- auth_protocol = module.params['auth_protocol']
- auth_key = module.params['auth_key']
- priv_protocol = module.params['priv_protocol']
- priv_key = module.params['priv_key']
-
- cmds = []
-
- if remote_engine_id:
- conf_str = CE_CREATE_SNMP_V3_USM_USER_HEADER % (
- usm_user_name, "true", remote_engine_id)
- cmd = "snmp-agent remote-engineid %s usm-user v3 %s" % (
- remote_engine_id, usm_user_name)
- else:
- if not self.local_engine_id:
- module.fail_json(
- msg='Error: The local engine id is null, please input remote_engine_id.')
-
- conf_str = CE_CREATE_SNMP_V3_USM_USER_HEADER % (
- usm_user_name, "false", self.local_engine_id)
- cmd = "snmp-agent usm-user v3 %s" % usm_user_name
-
- if user_group:
- conf_str += "%s" % user_group
- cmd += " %s" % user_group
-
- if acl_number:
- conf_str += "%s" % acl_number
- cmd += " acl %s" % acl_number
- cmds.append(cmd)
-
- if remote_engine_id:
- cmd = "snmp-agent remote-engineid %s usm-user v3 %s" % (
- remote_engine_id, usm_user_name)
- else:
- cmd = "snmp-agent usm-user v3 %s" % usm_user_name
-
- if auth_protocol:
- conf_str += "%s" % auth_protocol
-
- if auth_protocol != "noAuth":
- cmd += " authentication-mode %s" % auth_protocol
-
- if auth_key:
- conf_str += "%s" % auth_key
-
- if auth_protocol != "noAuth":
- cmd += " cipher %s" % "******"
-
- if auth_key or auth_protocol:
- cmds.append(cmd)
-
- if remote_engine_id:
- cmd = "snmp-agent remote-engineid %s usm-user v3 %s" % (
- remote_engine_id, usm_user_name)
- else:
- cmd = "snmp-agent usm-user v3 %s" % usm_user_name
-
- if priv_protocol:
- conf_str += "%s" % priv_protocol
-
- if auth_protocol != "noAuth" and priv_protocol != "noPriv":
- cmd += " privacy-mode %s" % priv_protocol
-
- if priv_key:
- conf_str += "%s" % priv_key
-
- if auth_protocol != "noAuth" and priv_protocol != "noPriv":
- cmd += " cipher %s" % "******"
-
- if priv_protocol or priv_key:
- cmds.append(cmd)
-
- conf_str += CE_CREATE_SNMP_V3_USM_USER_TAIL
-
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Create snmp v3 usm user failed.')
-
- return cmds
-
- def delete_snmp_v3_usm_user(self, **kwargs):
- """ Delete snmp v3 usm user operation """
-
- module = kwargs["module"]
- usm_user_name = module.params['usm_user_name']
- remote_engine_id = module.params['remote_engine_id']
- acl_number = module.params['acl_number']
- user_group = module.params['user_group']
- auth_protocol = module.params['auth_protocol']
- auth_key = module.params['auth_key']
- priv_protocol = module.params['priv_protocol']
- priv_key = module.params['priv_key']
-
- if remote_engine_id:
- conf_str = CE_DELETE_SNMP_V3_USM_USER_HEADER % (
- usm_user_name, "true", remote_engine_id)
- cmd = "undo snmp-agent remote-engineid %s usm-user v3 %s" % (
- remote_engine_id, usm_user_name)
- else:
- if not self.local_engine_id:
- module.fail_json(
- msg='Error: The local engine id is null, please input remote_engine_id.')
-
- conf_str = CE_DELETE_SNMP_V3_USM_USER_HEADER % (
- usm_user_name, "false", self.local_engine_id)
- cmd = "undo snmp-agent usm-user v3 %s" % usm_user_name
-
- if user_group:
- conf_str += "%s" % user_group
-
- if acl_number:
- conf_str += "%s" % acl_number
-
- if auth_protocol:
- conf_str += "%s" % auth_protocol
-
- if auth_key:
- conf_str += "%s" % auth_key
-
- if priv_protocol:
- conf_str += "%s" % priv_protocol
-
- if priv_key:
- conf_str += "%s" % priv_key
-
- conf_str += CE_DELETE_SNMP_V3_USM_USER_TAIL
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Delete snmp v3 usm user failed.')
-
- return cmd
-
- def merge_snmp_v3_local_user(self, **kwargs):
- """ Merge snmp v3 local user operation """
-
- module = kwargs["module"]
- local_user_name = module.params['aaa_local_user']
- auth_protocol = module.params['auth_protocol']
- auth_key = module.params['auth_key']
- priv_protocol = module.params['priv_protocol']
- priv_key = module.params['priv_key']
-
- conf_str = CE_MERGE_SNMP_V3_LOCAL_USER % (
- local_user_name, auth_protocol, auth_key, priv_protocol, priv_key)
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Merge snmp v3 local user failed.')
-
- cmd = "snmp-agent local-user v3 %s " % local_user_name + "authentication-mode %s " % auth_protocol + \
- "cipher ****** " + "privacy-mode %s " % priv_protocol + "cipher ******"
-
- return cmd
-
- def create_snmp_v3_local_user(self, **kwargs):
- """ Create snmp v3 local user operation """
-
- module = kwargs["module"]
- local_user_name = module.params['aaa_local_user']
- auth_protocol = module.params['auth_protocol']
- auth_key = module.params['auth_key']
- priv_protocol = module.params['priv_protocol']
- priv_key = module.params['priv_key']
-
- conf_str = CE_CREATE_SNMP_V3_LOCAL_USER % (
- local_user_name, auth_protocol, auth_key, priv_protocol, priv_key)
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Create snmp v3 local user failed.')
-
- cmd = "snmp-agent local-user v3 %s " % local_user_name + "authentication-mode %s " % auth_protocol + \
- "cipher ****** " + "privacy-mode %s " % priv_protocol + "cipher ******"
-
- return cmd
-
- def delete_snmp_v3_local_user(self, **kwargs):
- """ Delete snmp v3 local user operation """
-
- module = kwargs["module"]
- local_user_name = module.params['aaa_local_user']
- auth_protocol = module.params['auth_protocol']
- auth_key = module.params['auth_key']
- priv_protocol = module.params['priv_protocol']
- priv_key = module.params['priv_key']
-
- conf_str = CE_DELETE_SNMP_V3_LOCAL_USER % (
- local_user_name, auth_protocol, auth_key, priv_protocol, priv_key)
- recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
-
- if "" not in recv_xml:
- module.fail_json(msg='Error: Delete snmp v3 local user failed.')
-
- cmd = "undo snmp-agent local-user v3 %s" % local_user_name
-
- return cmd
-
- def get_snmp_local_engine(self, **kwargs):
- """ Get snmp local engine operation """
-
- module = kwargs["module"]
-
- conf_str = GET_SNMP_LOCAL_ENGINE
- recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
- if "
" in recv_xml:
- xml_str = recv_xml.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- local_engine_info = root.findall("snmp/engine/engineID")
- if local_engine_info:
- self.local_engine_id = local_engine_info[0].text
-
-
-def main():
- """ Module main function """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- acl_number=dict(type='str'),
- usm_user_name=dict(type='str'),
- remote_engine_id=dict(type='str'),
- user_group=dict(type='str'),
- auth_protocol=dict(choices=['noAuth', 'md5', 'sha']),
- auth_key=dict(type='str', no_log=True),
- priv_protocol=dict(
- choices=['noPriv', 'des56', '3des168', 'aes128', 'aes192', 'aes256']),
- priv_key=dict(type='str', no_log=True),
- aaa_local_user=dict(type='str')
- )
-
- mutually_exclusive = [("usm_user_name", "local_user_name")]
- argument_spec.update(ce_argument_spec)
- module = AnsibleModule(
- argument_spec=argument_spec,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True
- )
-
- changed = False
- proposed = dict()
- existing = dict()
- end_state = dict()
- updates = []
-
- state = module.params['state']
- acl_number = module.params['acl_number']
- usm_user_name = module.params['usm_user_name']
- remote_engine_id = module.params['remote_engine_id']
- user_group = module.params['user_group']
- auth_protocol = module.params['auth_protocol']
- auth_key = module.params['auth_key']
- priv_protocol = module.params['priv_protocol']
- priv_key = module.params['priv_key']
- aaa_local_user = module.params['aaa_local_user']
-
- snmp_user_obj = SnmpUser()
-
- if not snmp_user_obj:
- module.fail_json(msg='Error: Init module failed.')
-
- # get proposed
- proposed["state"] = state
- if acl_number:
- proposed["acl_number"] = acl_number
- if usm_user_name:
- proposed["usm_user_name"] = usm_user_name
- if remote_engine_id:
- proposed["remote_engine_id"] = remote_engine_id
- if user_group:
- proposed["user_group"] = user_group
- if auth_protocol:
- proposed["auth_protocol"] = auth_protocol
- if auth_key:
- proposed["auth_key"] = auth_key
- if priv_protocol:
- proposed["priv_protocol"] = priv_protocol
- if priv_key:
- proposed["priv_key"] = priv_key
- if aaa_local_user:
- proposed["aaa_local_user"] = aaa_local_user
-
- snmp_user_obj.get_snmp_local_engine(module=module)
- snmp_v3_usm_user_rst = snmp_user_obj.check_snmp_v3_usm_user_args(
- module=module)
- snmp_v3_local_user_rst = snmp_user_obj.check_snmp_v3_local_user_args(
- module=module)
-
- # state exist snmp v3 user config
- exist_tmp = dict()
- for item in snmp_v3_usm_user_rst:
- if item != "need_cfg":
- exist_tmp[item] = snmp_v3_usm_user_rst[item]
- if exist_tmp:
- existing["snmp usm user"] = exist_tmp
-
- exist_tmp = dict()
- for item in snmp_v3_local_user_rst:
- if item != "need_cfg":
- exist_tmp[item] = snmp_v3_local_user_rst[item]
- if exist_tmp:
- existing["snmp local user"] = exist_tmp
-
- if state == "present":
- if snmp_v3_usm_user_rst["need_cfg"]:
- if len(snmp_v3_usm_user_rst["usm_user_info"]) != 0:
- cmd = snmp_user_obj.merge_snmp_v3_usm_user(module=module)
- changed = True
- updates.append(cmd)
- else:
- cmd = snmp_user_obj.create_snmp_v3_usm_user(module=module)
- changed = True
- updates.append(cmd)
-
- if snmp_v3_local_user_rst["need_cfg"]:
- if len(snmp_v3_local_user_rst["local_user_info"]) != 0:
- cmd = snmp_user_obj.merge_snmp_v3_local_user(
- module=module)
- changed = True
- updates.append(cmd)
- else:
- cmd = snmp_user_obj.create_snmp_v3_local_user(
- module=module)
- changed = True
- updates.append(cmd)
-
- else:
- if snmp_v3_usm_user_rst["need_cfg"]:
- cmd = snmp_user_obj.delete_snmp_v3_usm_user(module=module)
- changed = True
- updates.append(cmd)
- if snmp_v3_local_user_rst["need_cfg"]:
- cmd = snmp_user_obj.delete_snmp_v3_local_user(module=module)
- changed = True
- updates.append(cmd)
-
- # state exist snmp v3 user config
- snmp_v3_usm_user_rst = snmp_user_obj.check_snmp_v3_usm_user_args(
- module=module)
- end_tmp = dict()
- for item in snmp_v3_usm_user_rst:
- if item != "need_cfg":
- end_tmp[item] = snmp_v3_usm_user_rst[item]
- if end_tmp:
- end_state["snmp usm user"] = end_tmp
-
- snmp_v3_local_user_rst = snmp_user_obj.check_snmp_v3_local_user_args(
- module=module)
- end_tmp = dict()
- for item in snmp_v3_local_user_rst:
- if item != "need_cfg":
- end_tmp[item] = snmp_v3_local_user_rst[item]
- if end_tmp:
- end_state["snmp local user"] = end_tmp
-
- results = dict()
- results['proposed'] = proposed
- results['existing'] = existing
- results['changed'] = changed
- results['end_state'] = end_state
- results['updates'] = updates
-
- module.exit_json(**results)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_startup.py b/plugins/modules/network/cloudengine/ce_startup.py
deleted file mode 100644
index 4311b68bce..0000000000
--- a/plugins/modules/network/cloudengine/ce_startup.py
+++ /dev/null
@@ -1,469 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_startup
-short_description: Manages a system startup information on HUAWEI CloudEngine switches.
-description:
- - Manages a system startup information on HUAWEI CloudEngine switches.
-author:
- - Li Yanfeng (@QijunPan)
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- cfg_file:
- description:
- - Name of the configuration file that is applied for the next startup.
- The value is a string of 5 to 255 characters.
- default: present
- software_file:
- description:
- - File name of the system software that is applied for the next startup.
- The value is a string of 5 to 255 characters.
- patch_file:
- description:
- - Name of the patch file that is applied for the next startup.
- slot:
- description:
- - Position of the device.The value is a string of 1 to 32 characters.
- The possible value of slot is all, slave-board, or the specific slotID.
- action:
- description:
- - Display the startup information.
- choices: ['display']
-
-'''
-
-EXAMPLES = '''
-- name: startup module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Display startup information
- ce_startup:
- action: display
- provider: "{{ cli }}"
-
- - name: Set startup patch file
- ce_startup:
- patch_file: 2.PAT
- slot: all
- provider: "{{ cli }}"
-
- - name: Set startup software file
- ce_startup:
- software_file: aa.cc
- slot: 1
- provider: "{{ cli }}"
-
- - name: Set startup cfg file
- ce_startup:
- cfg_file: 2.cfg
- slot: 1
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"patch_file": "2.PAT",
- "slot": "all"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {
- "configSysSoft": "flash:/CE12800-V200R002C20_issuB071.cc",
- "curentPatchFile": "NULL",
- "curentStartupFile": "NULL",
- "curentSysSoft": "flash:/CE12800-V200R002C20_issuB071.cc",
- "nextPatchFile": "flash:/1.PAT",
- "nextStartupFile": "flash:/1.cfg",
- "nextSysSoft": "flash:/CE12800-V200R002C20_issuB071.cc",
- "position": "5"
- }
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"StartupInfos": null}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: {"startup patch 2.PAT all"}
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec, run_commands
-from ansible.module_utils.connection import exec_command
-
-
-class StartUp(object):
- """
- Manages system startup information.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.cfg_file = self.module.params['cfg_file']
- self.software_file = self.module.params['software_file']
- self.patch_file = self.module.params['patch_file']
- self.slot = self.module.params['slot']
- self.action = self.module.params['action']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.existing = dict()
- self.proposed = dict()
- self.end_state = dict()
-
- # system startup info
- self.startup_info = None
-
- def init_module(self):
- """ init module """
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_startup_dict(self):
- """Retrieves the current config from the device or cache
- """
- cmd = 'display startup'
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- cfg = str(out).strip()
-
- startup_info = dict()
- startup_info["StartupInfos"] = list()
- if not cfg:
- return startup_info
- else:
- re_find = re.findall(r'(.*)\s*'
- r'\s*Configured\s*startup\s*system\s*software:\s*(.*)'
- r'\s*Startup\s*system\s*software:\s*(.*)'
- r'\s*Next\s*startup\s*system\s*software:\s*(.*)'
- r'\s*Startup\s*saved-configuration\s*file:\s*(.*)'
- r'\s*Next\s*startup\s*saved-configuration\s*file:\s*(.*)'
- r'\s*Startup\s*paf\s*file:\s*(.*)'
- r'\s*Next\s*startup\s*paf\s*file:\s*(.*)'
- r'\s*Startup\s*patch\s*package:\s*(.*)'
- r'\s*Next\s*startup\s*patch\s*package:\s*(.*)', cfg)
-
- if re_find:
- for mem in re_find:
- startup_info["StartupInfos"].append(
- dict(nextStartupFile=mem[5], configSysSoft=mem[1], curentSysSoft=mem[2],
- nextSysSoft=mem[3], curentStartupFile=mem[4], curentPatchFile=mem[8],
- nextPatchFile=mem[9], postion=mem[0]))
- return startup_info
- return startup_info
-
- def get_cfg_filename_type(self, filename):
- """Gets the type of cfg filename, such as cfg, zip, dat..."""
-
- if filename is None:
- return None
- if ' ' in filename:
- self.module.fail_json(
- msg='Error: Configuration file name include spaces.')
-
- iftype = None
-
- if filename.endswith('.cfg'):
- iftype = 'cfg'
- elif filename.endswith('.zip'):
- iftype = 'zip'
- elif filename.endswith('.dat'):
- iftype = 'dat'
- else:
- return None
- return iftype.lower()
-
- def get_pat_filename_type(self, filename):
- """Gets the type of patch filename, such as cfg, zip, dat..."""
-
- if filename is None:
- return None
- if ' ' in filename:
- self.module.fail_json(
- msg='Error: Patch file name include spaces.')
-
- iftype = None
-
- if filename.endswith('.PAT'):
- iftype = 'PAT'
- else:
- return None
- return iftype.upper()
-
- def get_software_filename_type(self, filename):
- """Gets the type of software filename, such as cfg, zip, dat..."""
-
- if filename is None:
- return None
- if ' ' in filename:
- self.module.fail_json(
- msg='Error: Software file name include spaces.')
-
- iftype = None
-
- if filename.endswith('.cc'):
- iftype = 'cc'
- else:
- return None
- return iftype.lower()
-
- def startup_next_cfg_file(self):
- """set next cfg file"""
- commands = list()
- cmd = {'output': None, 'command': ''}
- if self.slot:
- cmd['command'] = "startup saved-configuration %s slot %s" % (
- self.cfg_file, self.slot)
- commands.append(cmd)
- self.updates_cmd.append(
- "startup saved-configuration %s slot %s" % (self.cfg_file, self.slot))
- run_commands(self.module, commands)
- self.changed = True
- else:
- cmd['command'] = "startup saved-configuration %s" % self.cfg_file
- commands.append(cmd)
- self.updates_cmd.append(
- "startup saved-configuration %s" % self.cfg_file)
- run_commands(self.module, commands)
- self.changed = True
-
- def startup_next_software_file(self):
- """set next software file"""
- commands = list()
- cmd = {'output': None, 'command': ''}
- if self.slot:
- if self.slot == "all" or self.slot == "slave-board":
- cmd['command'] = "startup system-software %s %s" % (
- self.software_file, self.slot)
- commands.append(cmd)
- self.updates_cmd.append(
- "startup system-software %s %s" % (self.software_file, self.slot))
- run_commands(self.module, commands)
- self.changed = True
- else:
- cmd['command'] = "startup system-software %s slot %s" % (
- self.software_file, self.slot)
- commands.append(cmd)
- self.updates_cmd.append(
- "startup system-software %s slot %s" % (self.software_file, self.slot))
- run_commands(self.module, commands)
- self.changed = True
-
- if not self.slot:
- cmd['command'] = "startup system-software %s" % self.software_file
- commands.append(cmd)
- self.updates_cmd.append(
- "startup system-software %s" % self.software_file)
- run_commands(self.module, commands)
- self.changed = True
-
- def startup_next_pat_file(self):
- """set next patch file"""
-
- commands = list()
- cmd = {'output': None, 'command': ''}
- if self.slot:
- if self.slot == "all":
- cmd['command'] = "startup patch %s %s" % (
- self.patch_file, self.slot)
- commands.append(cmd)
- self.updates_cmd.append(
- "startup patch %s %s" % (self.patch_file, self.slot))
- run_commands(self.module, commands)
- self.changed = True
- else:
- cmd['command'] = "startup patch %s slot %s" % (
- self.patch_file, self.slot)
- commands.append(cmd)
- self.updates_cmd.append(
- "startup patch %s slot %s" % (self.patch_file, self.slot))
- run_commands(self.module, commands)
- self.changed = True
-
- if not self.slot:
- cmd['command'] = "startup patch %s" % self.patch_file
- commands.append(cmd)
- self.updates_cmd.append(
- "startup patch %s" % self.patch_file)
- run_commands(self.module, commands)
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- # cfg_file check
- if self.cfg_file:
- if not self.get_cfg_filename_type(self.cfg_file):
- self.module.fail_json(
- msg='Error: Invalid cfg file name or cfg file name extension ( *.cfg, *.zip, *.dat ).')
-
- # software_file check
- if self.software_file:
- if not self.get_software_filename_type(self.software_file):
- self.module.fail_json(
- msg='Error: Invalid software file name or software file name extension ( *.cc).')
-
- # patch_file check
- if self.patch_file:
- if not self.get_pat_filename_type(self.patch_file):
- self.module.fail_json(
- msg='Error: Invalid patch file name or patch file name extension ( *.PAT ).')
-
- # slot check
- if self.slot:
- if self.slot.isdigit():
- if int(self.slot) <= 0 or int(self.slot) > 16:
- self.module.fail_json(
- msg='Error: The number of slot is not in the range from 1 to 16.')
- else:
- if len(self.slot) <= 0 or len(self.slot) > 32:
- self.module.fail_json(
- msg='Error: The length of slot is not in the range from 1 to 32.')
-
- def get_proposed(self):
- """get proposed info"""
-
- if self.cfg_file:
- self.proposed["cfg_file"] = self.cfg_file
- if self.software_file:
- self.proposed["system_file"] = self.software_file
- if self.patch_file:
- self.proposed["patch_file"] = self.patch_file
- if self.slot:
- self.proposed["slot"] = self.slot
-
- def get_existing(self):
- """get existing info"""
-
- if not self.startup_info:
- self.existing["StartupInfos"] = None
- else:
- self.existing["StartupInfos"] = self.startup_info["StartupInfos"]
-
- def get_end_state(self):
- """get end state info"""
- if not self.startup_info:
- self.end_state["StartupInfos"] = None
- else:
- self.end_state["StartupInfos"] = self.startup_info["StartupInfos"]
- if self.end_state == self.existing:
- self.changed = False
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.get_proposed()
-
- self.startup_info = self.get_startup_dict()
- self.get_existing()
-
- startup_info = self.startup_info["StartupInfos"][0]
- if self.cfg_file:
- if self.cfg_file != startup_info["nextStartupFile"]:
- self.startup_next_cfg_file()
-
- if self.software_file:
- if self.software_file != startup_info["nextSysSoft"]:
- self.startup_next_software_file()
- if self.patch_file:
- if self.patch_file != startup_info["nextPatchFile"]:
- self.startup_next_pat_file()
- if self.action == "display":
- self.startup_info = self.get_startup_dict()
-
- self.startup_info = self.get_startup_dict()
- self.get_end_state()
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- cfg_file=dict(type='str'),
- software_file=dict(type='str'),
- patch_file=dict(type='str'),
- slot=dict(type='str'),
- action=dict(type='str', choices=['display'])
- )
- argument_spec.update(ce_argument_spec)
- module = StartUp(argument_spec=argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_static_route.py b/plugins/modules/network/cloudengine/ce_static_route.py
deleted file mode 100644
index 7a8ea88206..0000000000
--- a/plugins/modules/network/cloudengine/ce_static_route.py
+++ /dev/null
@@ -1,833 +0,0 @@
-#!/usr/bin/python
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_static_route
-short_description: Manages static route configuration on HUAWEI CloudEngine switches.
-description:
- - Manages the static routes on HUAWEI CloudEngine switches.
-author: Yang yang (@QijunPan)
-notes:
- - If no vrf is supplied, vrf is set to default.
- - If I(state=absent), the route will be removed, regardless of the non-required parameters.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- prefix:
- description:
- - Destination ip address of static route.
- required: true
- mask:
- description:
- - Destination ip mask of static route.
- required: true
- aftype:
- description:
- - Destination ip address family type of static route.
- required: true
- choices: ['v4','v6']
- next_hop:
- description:
- - Next hop address of static route.
- nhp_interface:
- description:
- - Next hop interface full name of static route.
- vrf:
- description:
- - VPN instance of destination ip address.
- destvrf:
- description:
- - VPN instance of next hop ip address.
- tag:
- description:
- - Route tag value (numeric).
- description:
- description:
- - Name of the route. Used with the name parameter on the CLI.
- pref:
- description:
- - Preference or administrative difference of route (range 1-255).
- state:
- description:
- - Specify desired state of the resource.
- choices: ['present','absent']
- default: present
-'''
-
-EXAMPLES = '''
-- name: static route module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Config a ipv4 static route, next hop is an address and that it has the proper description
- ce_static_route:
- prefix: 2.1.1.2
- mask: 24
- next_hop: 3.1.1.2
- description: 'Configured by Ansible'
- aftype: v4
- provider: "{{ cli }}"
- - name: Config a ipv4 static route ,next hop is an interface and that it has the proper description
- ce_static_route:
- prefix: 2.1.1.2
- mask: 24
- next_hop: 10GE1/0/1
- description: 'Configured by Ansible'
- aftype: v4
- provider: "{{ cli }}"
- - name: Config a ipv6 static route, next hop is an address and that it has the proper description
- ce_static_route:
- prefix: fc00:0:0:2001::1
- mask: 64
- next_hop: fc00:0:0:2004::1
- description: 'Configured by Ansible'
- aftype: v6
- provider: "{{ cli }}"
- - name: Config a ipv4 static route, next hop is an interface and that it has the proper description
- ce_static_route:
- prefix: fc00:0:0:2001::1
- mask: 64
- next_hop: 10GE1/0/1
- description: 'Configured by Ansible'
- aftype: v6
- provider: "{{ cli }}"
- - name: Config a VRF and set ipv4 static route, next hop is an address and that it has the proper description
- ce_static_route:
- vrf: vpna
- prefix: 2.1.1.2
- mask: 24
- next_hop: 3.1.1.2
- description: 'Configured by Ansible'
- aftype: v4
- provider: "{{ cli }}"
-'''
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"next_hop": "3.3.3.3", "pref": "100",
- "prefix": "192.168.20.642", "mask": "24", "description": "testing",
- "vrf": "_public_"}
-existing:
- description: k/v pairs of existing switchport
- returned: always
- type: dict
- sample: {}
-end_state:
- description: k/v pairs of switchport after module execution
- returned: always
- type: dict
- sample: {"next_hop": "3.3.3.3", "pref": "100",
- "prefix": "192.168.20.0", "mask": "24", "description": "testing",
- "tag" : "null"}
-updates:
- description: command list sent to the device
- returned: always
- type: list
- sample: ["ip route-static 192.168.20.0 255.255.255.0 3.3.3.3 preference 100 description testing"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-CE_NC_GET_STATIC_ROUTE = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_GET_STATIC_ROUTE_ABSENT = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_SET_STATIC_ROUTE = """
-
-
-
-
- %s
- %s
- base
- %s
- %s
- %s
- %s
- %s%s%s%s
-
-
-
-
-"""
-CE_NC_SET_DESCRIPTION = """
-%s
-"""
-
-CE_NC_SET_PREFERENCE = """
-%s
-"""
-
-CE_NC_SET_TAG = """
-%s
-"""
-
-CE_NC_DELETE_STATIC_ROUTE = """
-
-
-
-
- %s
- %s
- base
- %s
- %s
- %s
- %s
- %s
-
-
-
-
-"""
-
-
-def build_config_xml(xmlstr):
- """build config xml"""
-
- return ' ' + xmlstr + ' '
-
-
-def is_valid_v4addr(addr):
- """check if ipv4 addr is valid"""
- if addr.find('.') != -1:
- addr_list = addr.split('.')
- if len(addr_list) != 4:
- return False
- for each_num in addr_list:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- return True
- return False
-
-
-def is_valid_v6addr(addr):
- """check if ipv6 addr is valid"""
- if addr.find(':') != -1:
- addr_list = addr.split(':')
- # The IPv6 binary system has a length of 128 bits and is grouped by 16 bits.
- # Each group is separated by a colon ":" and can be divided into 8 groups, each group being represented by 4 hexadecimal
- if len(addr_list) > 8:
- return False
- # You can use a double colon "::" to represent a group of 0 or more consecutive 0s, but only once.
- if addr.count('::') > 1:
- return False
- # if do not use '::', the length of address should not be less than 8.
- if addr.count('::') == 0 and len(addr_list) < 8:
- return False
- for group in addr_list:
- if group.strip() == '':
- continue
- try:
- # Each group is represented in 4-digit hexadecimal
- int(group, base=16)
- except ValueError:
- return False
- return True
- return False
-
-
-def is_valid_tag(tag):
- """check if the tag is valid"""
-
- if not tag.isdigit():
- return False
-
- if int(tag) < 1 or int(tag) > 4294967295:
- return False
-
- return True
-
-
-def is_valid_preference(pref):
- """check if the preference is valid"""
- if pref.isdigit():
- return int(pref) > 0 and int(pref) < 256
- else:
- return False
-
-
-def is_valid_description(description):
- """check if the description is valid"""
- if description.find('?') != -1:
- return False
- if len(description) < 1 or len(description) > 255:
- return False
- return True
-
-
-class StaticRoute(object):
- """static route module"""
-
- def __init__(self, argument_spec, ):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # static route info
- self.prefix = self.module.params['prefix']
- self.mask = self.module.params['mask']
- self.aftype = self.module.params['aftype']
- self.next_hop = self.module.params['next_hop']
- self.nhp_interface = self.module.params['nhp_interface']
- if self.nhp_interface is None:
- self.nhp_interface = "Invalid0"
- self.tag = self.module.params['tag']
- self.description = self.module.params['description']
- self.state = self.module.params['state']
- self.pref = self.module.params['pref']
-
- # vpn instance info
- self.vrf = self.module.params['vrf']
- if self.vrf is None:
- self.vrf = "_public_"
- self.destvrf = self.module.params['destvrf']
- if self.destvrf is None:
- self.destvrf = "_public_"
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- self.static_routes_info = dict()
-
- def init_module(self):
- """init module"""
-
- required_one_of = [["next_hop", "nhp_interface"]]
- self.module = AnsibleModule(
- argument_spec=self.spec, required_one_of=required_one_of, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def convert_len_to_mask(self, masklen):
- """convert mask length to ip address mask, i.e. 24 to 255.255.255.0"""
-
- mask_int = ["0"] * 4
- length = int(masklen)
-
- if length > 32:
- self.module.fail_json(msg='IPv4 ipaddress mask length is invalid')
- if length < 8:
- mask_int[0] = str(int((0xFF << (8 - length % 8)) & 0xFF))
- if length >= 8:
- mask_int[0] = '255'
- mask_int[1] = str(int((0xFF << (16 - (length % 16))) & 0xFF))
- if length >= 16:
- mask_int[1] = '255'
- mask_int[2] = str(int((0xFF << (24 - (length % 24))) & 0xFF))
- if length >= 24:
- mask_int[2] = '255'
- mask_int[3] = str(int((0xFF << (32 - (length % 32))) & 0xFF))
- if length == 32:
- mask_int[3] = '255'
-
- return '.'.join(mask_int)
-
- def convert_ip_prefix(self):
- """convert prefix to real value i.e. 2.2.2.2/24 to 2.2.2.0/24"""
- if self.aftype == "v4":
- if self.prefix.find('.') == -1:
- return False
- if self.mask == '32':
- return True
- if self.mask == '0':
- self.prefix = '0.0.0.0'
- return True
- addr_list = self.prefix.split('.')
- length = len(addr_list)
- if length > 4:
- return False
- for each_num in addr_list:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- byte_len = 8
- ip_len = int(self.mask) // byte_len
- ip_bit = int(self.mask) % byte_len
- else:
- if self.prefix.find(':') == -1:
- return False
- if self.mask == '128':
- return True
- if self.mask == '0':
- self.prefix = '::'
- return True
- addr_list = self.prefix.split(':')
- length = len(addr_list)
- if length > 6:
- return False
- byte_len = 16
- ip_len = int(self.mask) // byte_len
- ip_bit = int(self.mask) % byte_len
-
- if self.aftype == "v4":
- for i in range(ip_len + 1, length):
- addr_list[i] = 0
- else:
- for i in range(length - ip_len, length):
- addr_list[i] = 0
- for j in range(0, byte_len - ip_bit):
- if self.aftype == "v4":
- addr_list[ip_len] = int(addr_list[ip_len]) & (0 << j)
- else:
- if addr_list[length - ip_len - 1] == "":
- continue
- addr_list[length - ip_len -
- 1] = '0x%s' % addr_list[length - ip_len - 1]
- addr_list[length - ip_len -
- 1] = int(addr_list[length - ip_len - 1], 16) & (0 << j)
-
- if self.aftype == "v4":
- self.prefix = '%s.%s.%s.%s' % (addr_list[0], addr_list[1], addr_list[2], addr_list[3])
- return True
- else:
- ipv6_addr_str = ""
- for num in range(0, length - ip_len):
- ipv6_addr_str += '%s:' % addr_list[num]
- self.prefix = ipv6_addr_str
- return True
-
- def set_update_cmd(self):
- """set update command"""
- if not self.changed:
- return
- if self.aftype == "v4":
- aftype = "ip"
- maskstr = self.convert_len_to_mask(self.mask)
- else:
- aftype = "ipv6"
- maskstr = self.mask
- if self.next_hop is None:
- next_hop = ''
- else:
- next_hop = self.next_hop
- if self.vrf == "_public_":
- vrf = ''
- else:
- vrf = self.vrf
- if self.destvrf == "_public_":
- destvrf = ''
- else:
- destvrf = self.destvrf
- if self.nhp_interface == "Invalid0":
- nhp_interface = ''
- else:
- nhp_interface = self.nhp_interface
- if self.state == "present":
- if self.vrf != "_public_":
- if self.destvrf != "_public_":
- self.updates_cmd.append('%s route-static vpn-instance %s %s %s vpn-instance %s %s'
- % (aftype, vrf, self.prefix, maskstr, destvrf, next_hop))
- else:
- self.updates_cmd.append('%s route-static vpn-instance %s %s %s %s %s'
- % (aftype, vrf, self.prefix, maskstr, nhp_interface, next_hop))
- elif self.destvrf != "_public_":
- self.updates_cmd.append('%s route-static %s %s vpn-instance %s %s'
- % (aftype, self.prefix, maskstr, self.destvrf, next_hop))
- else:
- self.updates_cmd.append('%s route-static %s %s %s %s'
- % (aftype, self.prefix, maskstr, nhp_interface, next_hop))
- if self.pref:
- self.updates_cmd[0] += ' preference %s' % (self.pref)
- if self.tag:
- self.updates_cmd[0] += ' tag %s' % (self.tag)
- if self.description:
- self.updates_cmd[0] += ' description %s' % (self.description)
-
- if self.state == "absent":
- if self.vrf != "_public_":
- if self.destvrf != "_public_":
- self.updates_cmd.append('undo %s route-static vpn-instance %s %s %s vpn-instance %s %s'
- % (aftype, vrf, self.prefix, maskstr, destvrf, next_hop))
- else:
- self.updates_cmd.append('undo %s route-static vpn-instance %s %s %s %s %s'
- % (aftype, vrf, self.prefix, maskstr, nhp_interface, next_hop))
- elif self.destvrf != "_public_":
- self.updates_cmd.append('undo %s route-static %s %s vpn-instance %s %s'
- % (aftype, self.prefix, maskstr, self.destvrf, self.next_hop))
- else:
- self.updates_cmd.append('undo %s route-static %s %s %s %s'
- % (aftype, self.prefix, maskstr, nhp_interface, next_hop))
-
- def operate_static_route(self, version, prefix, mask, nhp_interface, next_hop, vrf, destvrf, state):
- """operate ipv4 static route"""
-
- description_xml = """\n"""
- preference_xml = """\n"""
- tag_xml = """\n"""
- if next_hop is None:
- next_hop = '0.0.0.0'
- if nhp_interface is None:
- nhp_interface = "Invalid0"
-
- if vrf is None:
- vpn_instance = "_public_"
- else:
- vpn_instance = vrf
-
- if destvrf is None:
- dest_vpn_instance = "_public_"
- else:
- dest_vpn_instance = destvrf
- if self.description:
- description_xml = CE_NC_SET_DESCRIPTION % self.description
- if self.pref:
- preference_xml = CE_NC_SET_PREFERENCE % self.pref
- if self.tag:
- tag_xml = CE_NC_SET_TAG % self.tag
-
- if state == "present":
- configxmlstr = CE_NC_SET_STATIC_ROUTE % (
- vpn_instance, version, prefix, mask, nhp_interface,
- dest_vpn_instance, next_hop, description_xml, preference_xml, tag_xml)
- else:
- configxmlstr = CE_NC_DELETE_STATIC_ROUTE % (
- vpn_instance, version, prefix, mask, nhp_interface, dest_vpn_instance, next_hop)
-
- conf_str = build_config_xml(configxmlstr)
-
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "OPERATE_STATIC_ROUTE")
-
- def get_static_route(self, state):
- """get ipv4 static route"""
-
- self.static_routes_info["sroute"] = list()
-
- if state == 'absent':
- getxmlstr = CE_NC_GET_STATIC_ROUTE_ABSENT
- else:
- getxmlstr = CE_NC_GET_STATIC_ROUTE
-
- xml_str = get_nc_config(self.module, getxmlstr)
-
- if 'data/' in xml_str:
- return
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
- static_routes = root.findall(
- "staticrt/staticrtbase/srRoutes/srRoute")
-
- if static_routes:
- for static_route in static_routes:
- static_info = dict()
- for static_ele in static_route:
- if static_ele.tag in ["vrfName", "afType", "topologyName",
- "prefix", "maskLength", "destVrfName",
- "nexthop", "ifName", "preference", "description"]:
- static_info[
- static_ele.tag] = static_ele.text
- if static_ele.tag == "tag":
- if static_ele.text is not None:
- static_info["tag"] = static_ele.text
- else:
- static_info["tag"] = "None"
- self.static_routes_info["sroute"].append(static_info)
-
- def check_params(self):
- """check all input params"""
-
- # check prefix and mask
- if not self.mask.isdigit():
- self.module.fail_json(msg='Error: Mask is invalid.')
- # ipv4 check
- if self.aftype == "v4":
- if int(self.mask) > 32 or int(self.mask) < 0:
- self.module.fail_json(
- msg='Error: Ipv4 mask must be an integer between 1 and 32.')
- # next_hop check
- if self.next_hop:
- if not is_valid_v4addr(self.next_hop):
- self.module.fail_json(
- msg='Error: The %s is not a valid address' % self.next_hop)
- # ipv6 check
- if self.aftype == "v6":
- if int(self.mask) > 128 or int(self.mask) < 0:
- self.module.fail_json(
- msg='Error: Ipv6 mask must be an integer between 1 and 128.')
- if self.next_hop:
- if not is_valid_v6addr(self.next_hop):
- self.module.fail_json(
- msg='Error: The %s is not a valid address' % self.next_hop)
-
- # description check
- if self.description:
- if not is_valid_description(self.description):
- self.module.fail_json(
- msg='Error: Dsecription length should be 1 - 35, and can not contain "?".')
- # tag check
- if self.tag:
- if not is_valid_tag(self.tag):
- self.module.fail_json(
- msg='Error: Tag should be integer 1 - 4294967295.')
- # preference check
- if self.pref:
- if not is_valid_preference(self.pref):
- self.module.fail_json(
- msg='Error: Preference should be integer 1 - 255.')
- if self.nhp_interface != "Invalid0" and self.destvrf != "_public_":
- self.module.fail_json(
- msg='Error: Destination vrf dose no support next hop is interface.')
- # convert prefix
- if not self.convert_ip_prefix():
- self.module.fail_json(
- msg='Error: The %s is not a valid address' % self.prefix)
-
- def set_ip_static_route(self):
- """set ip static route"""
- if not self.changed:
- return
- version = None
- if self.aftype == "v4":
- version = "ipv4unicast"
- else:
- version = "ipv6unicast"
- self.operate_static_route(version, self.prefix, self.mask, self.nhp_interface,
- self.next_hop, self.vrf, self.destvrf, self.state)
-
- def is_prefix_exist(self, static_route, version):
- """is prefix mask nex_thop exist"""
- if static_route is None:
- return False
- if self.next_hop and self.nhp_interface:
- return static_route["prefix"].lower() == self.prefix.lower() \
- and static_route["maskLength"] == self.mask \
- and static_route["afType"] == version \
- and static_route["ifName"].lower() == self.nhp_interface.lower() \
- and static_route["nexthop"].lower() == self.next_hop.lower()
-
- if self.next_hop and not self.nhp_interface:
- return static_route["prefix"].lower() == self.prefix.lower() \
- and static_route["maskLength"] == self.mask \
- and static_route["afType"] == version \
- and static_route["nexthop"].lower() == self.next_hop.lower()
-
- if not self.next_hop and self.nhp_interface:
- return static_route["prefix"].lower() == self.prefix.lower() \
- and static_route["maskLength"] == self.mask \
- and static_route["afType"] == version \
- and static_route["ifName"].lower() == self.nhp_interface.lower()
-
- def get_ip_static_route(self):
- """get ip static route"""
-
- if self.aftype == "v4":
- version = "ipv4unicast"
- else:
- version = "ipv6unicast"
- change = False
- self.get_static_route(self.state)
- if self.state == 'present':
- for static_route in self.static_routes_info["sroute"]:
- if self.is_prefix_exist(static_route, version):
- if self.vrf:
- if static_route["vrfName"] != self.vrf:
- change = True
- if self.tag:
- if static_route["tag"] != self.tag:
- change = True
- if self.destvrf:
- if static_route["destVrfName"] != self.destvrf:
- change = True
- if self.description:
- if static_route["description"] != self.description:
- change = True
- if self.pref:
- if static_route["preference"] != self.pref:
- change = True
- if self.nhp_interface:
- if static_route["ifName"].lower() != self.nhp_interface.lower():
- change = True
- if self.next_hop:
- if static_route["nexthop"].lower() != self.next_hop.lower():
- change = True
- return change
- else:
- continue
- change = True
- else:
- for static_route in self.static_routes_info["sroute"]:
- if static_route["nexthop"] and self.next_hop:
- if static_route["prefix"].lower() == self.prefix.lower() \
- and static_route["maskLength"] == self.mask \
- and static_route["nexthop"].lower() == self.next_hop.lower() \
- and static_route["afType"] == version:
- change = True
- return change
- if static_route["ifName"] and self.nhp_interface:
- if static_route["prefix"].lower() == self.prefix.lower() \
- and static_route["maskLength"] == self.mask \
- and static_route["ifName"].lower() == self.nhp_interface.lower() \
- and static_route["afType"] == version:
- change = True
- return change
- else:
- continue
- change = False
- return change
-
- def get_proposed(self):
- """get proposed information"""
-
- self.proposed['prefix'] = self.prefix
- self.proposed['mask'] = self.mask
- self.proposed['afType'] = self.aftype
- self.proposed['next_hop'] = self.next_hop
- self.proposed['ifName'] = self.nhp_interface
- self.proposed['vrfName'] = self.vrf
- self.proposed['destVrfName'] = self.destvrf
- if self.tag:
- self.proposed['tag'] = self.tag
- if self.description:
- self.proposed['description'] = self.description
- if self.pref is None:
- self.proposed['preference'] = 60
- else:
- self.proposed['preference'] = self.pref
- self.proposed['state'] = self.state
-
- def get_existing(self):
- """get existing information"""
-
- change = self.get_ip_static_route()
- self.existing['sroute'] = self.static_routes_info["sroute"]
- self.changed = bool(change)
-
- def get_end_state(self):
- """get end state information"""
-
- self.get_static_route(self.state)
- self.end_state['sroute'] = self.static_routes_info["sroute"]
- if self.end_state == self.existing:
- self.changed = False
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.get_existing()
- self.get_proposed()
- self.set_ip_static_route()
- self.set_update_cmd()
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """main"""
-
- argument_spec = dict(
- prefix=dict(required=True, type='str'),
- mask=dict(required=True, type='str'),
- aftype=dict(choices=['v4', 'v6'], required=True),
- next_hop=dict(required=False, type='str'),
- nhp_interface=dict(required=False, type='str'),
- vrf=dict(required=False, type='str'),
- destvrf=dict(required=False, type='str'),
- tag=dict(required=False, type='str'),
- description=dict(required=False, type='str'),
- pref=dict(required=False, type='str'),
- state=dict(choices=['absent', 'present'],
- default='present', required=False),
- )
- argument_spec.update(ce_argument_spec)
- interface = StaticRoute(argument_spec)
- interface.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_static_route_bfd.py b/plugins/modules/network/cloudengine/ce_static_route_bfd.py
deleted file mode 100644
index 7cd571a2d3..0000000000
--- a/plugins/modules/network/cloudengine/ce_static_route_bfd.py
+++ /dev/null
@@ -1,1596 +0,0 @@
-#!/usr/bin/python
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_static_route_bfd
-short_description: Manages static route configuration on HUAWEI CloudEngine switches.
-description:
- - Manages the static routes on HUAWEI CloudEngine switches.
-author: xuxiaowei0512 (@CloudEngine-Ansible)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
- - If no vrf is supplied, vrf is set to default.
- - If I(state=absent), the route configuration will be removed, regardless of the non-required parameters.
-options:
- prefix:
- description:
- - Destination ip address of static route.
- required: true
- type: str
- mask:
- description:
- - Destination ip mask of static route.
- type: str
- aftype:
- description:
- - Destination ip address family type of static route.
- required: true
- type: str
- choices: ['v4','v6']
- next_hop:
- description:
- - Next hop address of static route.
- type: str
- nhp_interface:
- description:
- - Next hop interface full name of static route.
- type: str
- vrf:
- description:
- - VPN instance of destination ip address.
- type: str
- destvrf:
- description:
- - VPN instance of next hop ip address.
- type: str
- tag:
- description:
- - Route tag value (numeric).
- type: int
- description:
- description:
- - Name of the route. Used with the name parameter on the CLI.
- type: str
- pref:
- description:
- - Preference or administrative difference of route (range 1-255).
- type: int
- function_flag:
- description:
- - Used to distinguish between command line functions.
- required: true
- choices: ['globalBFD','singleBFD','dynamicBFD','staticBFD']
- type: str
- min_tx_interval:
- description:
- - Set the minimum BFD session sending interval (range 50-1000).
- type: int
- min_rx_interval:
- description:
- - Set the minimum BFD receive interval (range 50-1000).
- type: int
- detect_multiplier:
- description:
- - Configure the BFD multiplier (range 3-50).
- type: int
- bfd_session_name:
- description:
- - bfd name (range 1-15).
- type: str
- commands:
- description:
- - Incoming command line is used to send sys,undo ip route-static default-bfd,commit.
- type: list
- state:
- description:
- - Specify desired state of the resource.
- required: false
- choices: ['present','absent']
- type: str
- default: present
-'''
-
-EXAMPLES = '''
- #ip route-static bfd interface-type interface-number nexthop-address [ local-address address ]
- #[ min-rx-interval min-rx-interval | min-tx-interval min-tx-interval | detect-multiplier multiplier ]
- - name: Config an ip route-static bfd 10GE1/0/1 3.3.3.3 min-rx-interval 50 min-tx-interval 50 detect-multiplier 5
- ce_static_route_bfd:
- function_flag: 'singleBFD'
- nhp_interface: 10GE1/0/1
- next_hop: 3.3.3.3
- min_tx_interval: 50
- min_rx_interval: 50
- detect_multiplier: 5
- aftype: v4
- state: present
-
- #undo ip route-static bfd [ interface-type interface-number | vpn-instance vpn-instance-name ] nexthop-address
- - name: undo ip route-static bfd 10GE1/0/1 3.3.3.4
- ce_static_route_bfd:
- function_flag: 'singleBFD'
- nhp_interface: 10GE1/0/1
- next_hop: 3.3.3.4
- aftype: v4
- state: absent
-
- #ip route-static default-bfd { min-rx-interval {min-rx-interval} | min-tx-interval {min-tx-interval} | detect-multiplier {multiplier}}
- - name: Config an ip route-static default-bfd min-rx-interval 50 min-tx-interval 50 detect-multiplier 6
- ce_static_route_bfd:
- function_flag: 'globalBFD'
- min_tx_interval: 50
- min_rx_interval: 50
- detect_multiplier: 6
- aftype: v4
- state: present
-
- - name: undo ip route-static default-bfd
- ce_static_route_bfd:
- function_flag: 'globalBFD'
- aftype: v4
- state: absent
- commands: 'sys,undo ip route-static default-bfd,commit'
-
- - name: Config an ipv4 static route 2.2.2.0/24 2.2.2.1 preference 1 tag 2 description test for staticBFD
- ce_static_route_bfd:
- function_flag: 'staticBFD'
- prefix: 2.2.2.2
- mask: 24
- next_hop: 2.2.2.1
- tag: 2
- description: test
- pref: 1
- aftype: v4
- bfd_session_name: btoa
- state: present
-'''
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"function_flag": "staticBFD", "next_hop": "3.3.3.3", "pref": "100",
- "prefix": "192.168.20.642", "mask": "24", "description": "testing",
- "vrf": "_public_", "bfd_session_name": "btoa"}
-existing:
- description: k/v pairs of existing switchport
- returned: always
- type: dict
- sample: {"function_flag": "", "next_hop": "", "pref": "101",
- "prefix": "192.168.20.0", "mask": "24", "description": "testing",
- "tag" : "null", "bfd_session_name": "btoa"}
-end_state:
- description: k/v pairs of switchport after module execution
- returned: always
- type: dict
- sample: {"function_flag": "staticBFD", "next_hop": "3.3.3.3", "pref": "100",
- "prefix": "192.168.20.0", "mask": "24", "description": "testing",
- "tag" : "null", "bfd_session_name": "btoa"}
-updates:
- description: command list sent to the device
- returned: always
- type: list
- sample: ["ip route-static 192.168.20.0 255.255.255.0 3.3.3.3 preference 100 description testing"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.six import string_types
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config
-
-CE_NC_GET_STATIC_ROUTE_BFD_SESSIONNAME = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-# bfd enable
-CE_NC_GET_STATIC_ROUTE_BFD_ENABLE = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_GET_STATIC_ROUTE_BFD_ABSENT = """
-
-
-
-
-
- %s
- %s
- %s
- %s
-
-
-
-
-
-"""
-
-CE_NC_GET_STATIC_ROUTE_BFD = """
-
-
-
-
-
- %s
- %s
- %s
- %s
-
-
-
-
-
-
-
-
-
-"""
-CE_NC_GET_STATIC_ROUTE_IPV4_GLOBAL_BFD = """
-
-
-
-
-
-
-
-
-
-
-
-"""
-CE_NC_GET_STATIC_ROUTE_ABSENT = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_DELETE_STATIC_ROUTE_SINGLEBFD = """
-
-
-
-
- %s
- %s
- %s
- %s
-
-
-
-
-"""
-CE_NC_SET_STATIC_ROUTE_SINGLEBFD = """
-
-
-
-
- %s
- %s
- %s
- %s%s%s%s%s
-
-
-
-
-
-"""
-CE_NC_SET_STATIC_ROUTE_SINGLEBFD_LOCALADRESS = """
-%s
-"""
-CE_NC_SET_IPV4_STATIC_ROUTE_BFDCOMMON_MINTX = """
-%s
-"""
-CE_NC_SET_IPV4_STATIC_ROUTE_BFDCOMMON_MINRX = """
-%s
-"""
-CE_NC_SET_IPV4_STATIC_ROUTE_BFDCOMMON_MUL = """
-%s
-"""
-CE_NC_SET_IPV4_STATIC_ROUTE_GLOBALBFD = """
-
-
-
- %s%s%s
-
-
-
-"""
-
-CE_NC_SET_STATIC_ROUTE = """
-
-
-
-
- %s
- %s
- base
- %s
- %s
- %s
- %s
- %s%s%s%s%s
-
-
-
-
-"""
-CE_NC_SET_DESCRIPTION = """
-%s
-"""
-
-CE_NC_SET_PREFERENCE = """
-%s
-"""
-
-CE_NC_SET_TAG = """
-%s
-"""
-CE_NC_SET_BFDSESSIONNAME = """
-%s
-"""
-CE_NC_SET_BFDENABLE = """
-true
-"""
-CE_NC_DELETE_STATIC_ROUTE = """
-
-
-
-
- %s
- %s
- base
- %s
- %s
- %s
- %s
- %s
-
-
-
-
-"""
-
-
-def build_config_xml(xmlstr):
- """build config xml"""
-
- return ' ' + xmlstr + ' '
-
-
-def is_valid_v4addr(addr):
- """check if ipv4 addr is valid"""
- if addr.find('.') != -1:
- addr_list = addr.split('.')
- if len(addr_list) != 4:
- return False
- for each_num in addr_list:
-
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- return True
- return False
-
-
-def is_valid_v6addr(addr):
- """check if ipv6 addr is valid"""
- if addr.find(':') != -1:
- addr_list = addr.split(':')
- if len(addr_list) > 6:
- return False
- if addr_list[1] == "":
- return False
- return True
- return False
-
-
-def is_valid_tag(tag):
- """check if the tag is valid"""
-
- if int(tag) < 1 or int(tag) > 4294967295:
- return False
- return True
-
-
-def is_valid_bdf_interval(interval):
- """check if the min_tx_interva,min-rx-interval is valid"""
-
- if interval < 50 or interval > 1000:
- return False
- return True
-
-
-def is_valid_bdf_multiplier(multiplier):
- """check if the detect_multiplier is valid"""
-
- if multiplier < 3 or multiplier > 50:
- return False
- return True
-
-
-def is_valid_bdf_session_name(session_name):
- """check if the bfd_session_name is valid"""
- if session_name.find(' ') != -1:
- return False
- if len(session_name) < 1 or len(session_name) > 15:
- return False
- return True
-
-
-def is_valid_preference(pref):
- """check if the preference is valid"""
-
- if int(pref) > 0 and int(pref) < 256:
- return True
- return False
-
-
-def is_valid_description(description):
- """check if the description is valid"""
- if description.find('?') != -1:
- return False
- if len(description) < 1 or len(description) > 255:
- return False
- return True
-
-
-def compare_command(commands):
- """check if the commands is valid"""
- if len(commands) < 3:
- return True
- if commands[0] != 'sys' or commands[1] != 'undo ip route-static default-bfd' \
- or commands[2] != 'commit':
- return True
-
-
-def get_to_lines(stdout):
- """data conversion"""
- lines = list()
- for item in stdout:
- if isinstance(item, string_types):
- item = str(item).split('\n')
- lines.append(item)
- return lines
-
-
-def get_change_state(oldvalue, newvalue, change):
- """get change state"""
- if newvalue is not None:
- if oldvalue != str(newvalue):
- change = True
- else:
- if oldvalue != newvalue:
- change = True
- return change
-
-
-def get_xml(xml, value):
- """operate xml"""
- if value is None:
- value = ''
- else:
- value = value
- tempxml = xml % value
- return tempxml
-
-
-class StaticRouteBFD(object):
- """static route module"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self._initmodule_()
-
- # static route info
- self.function_flag = self.module.params['function_flag']
- self.aftype = self.module.params['aftype']
- self.state = self.module.params['state']
- if self.aftype == "v4":
- self.version = "ipv4unicast"
- else:
- self.version = "ipv6unicast"
- if self.function_flag != 'globalBFD':
- self.nhp_interface = self.module.params['nhp_interface']
- if self.nhp_interface is None:
- self.nhp_interface = "Invalid0"
-
- self.destvrf = self.module.params['destvrf']
- if self.destvrf is None:
- self.destvrf = "_public_"
-
- self.next_hop = self.module.params['next_hop']
- self.prefix = self.module.params['prefix']
-
- if self.function_flag != 'globalBFD' and self.function_flag != 'singleBFD':
- self.mask = self.module.params['mask']
- self.tag = self.module.params['tag']
- self.description = self.module.params['description']
- self.pref = self.module.params['pref']
- if self.pref is None:
- self.pref = 60
- # vpn instance info
- self.vrf = self.module.params['vrf']
- if self.vrf is None:
- self.vrf = "_public_"
- # bfd session name
- self.bfd_session_name = self.module.params['bfd_session_name']
-
- if self.function_flag == 'globalBFD' or self.function_flag == 'singleBFD':
- self.min_tx_interval = self.module.params['min_tx_interval']
- self.min_rx_interval = self.module.params['min_rx_interval']
- self.detect_multiplier = self.module.params['detect_multiplier']
- if self.function_flag == 'globalBFD' and self.state == 'absent':
- self.commands = self.module.params['commands']
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- self.static_routes_info = dict()
-
- def _initmodule_(self):
- """init module"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=False)
-
- def _checkresponse_(self, xml_str, xml_name):
- """check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def _convertlentomask_(self, masklen):
- """convert mask length to ip address mask, i.e. 24 to 255.255.255.0"""
-
- mask_int = ["0"] * 4
- length = int(masklen)
-
- if length > 32:
- self.module.fail_json(msg='IPv4 ipaddress mask length is invalid')
- if length < 8:
- mask_int[0] = str(int((0xFF << (8 - length % 8)) & 0xFF))
- if length >= 8:
- mask_int[0] = '255'
- mask_int[1] = str(int((0xFF << (16 - (length % 16))) & 0xFF))
- if length >= 16:
- mask_int[1] = '255'
- mask_int[2] = str(int((0xFF << (24 - (length % 24))) & 0xFF))
- if length >= 24:
- mask_int[2] = '255'
- mask_int[3] = str(int((0xFF << (32 - (length % 32))) & 0xFF))
- if length == 32:
- mask_int[3] = '255'
-
- return '.'.join(mask_int)
-
- def _convertipprefix_(self):
- """convert prefix to real value i.e. 2.2.2.2/24 to 2.2.2.0/24"""
- if self.function_flag == 'singleBFD':
- if self.aftype == "v4":
- if self.prefix.find('.') == -1:
- return False
- addr_list = self.prefix.split('.')
- length = len(addr_list)
- if length > 4:
- return False
- for each_num in addr_list:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- return True
- else:
- if self.prefix.find(':') == -1:
- return False
- else:
- if self.aftype == "v4":
- if self.prefix.find('.') == -1:
- return False
- if self.mask == '32':
- self.prefix = self.prefix
- return True
- if self.mask == '0':
- self.prefix = '0.0.0.0'
- return True
- addr_list = self.prefix.split('.')
- length = len(addr_list)
- if length > 4:
- return False
- for each_num in addr_list:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- byte_len = 8
- ip_len = int(self.mask) // byte_len
- ip_bit = int(self.mask) % byte_len
- else:
- if self.prefix.find(':') == -1:
- return False
- if self.mask == '128':
- self.prefix = self.prefix
- return True
- if self.mask == '0':
- self.prefix = '::'
- return True
- addr_list = self.prefix.split(':')
- length = len(addr_list)
- if length > 6:
- return False
- byte_len = 16
- ip_len = int(self.mask) // byte_len
- ip_bit = int(self.mask) % byte_len
-
- if self.aftype == "v4":
- for i in range(ip_len + 1, length):
- addr_list[i] = 0
- else:
- for i in range(length - ip_len, length):
- addr_list[i] = 0
- for j in range(0, byte_len - ip_bit):
- if self.aftype == "v4":
- addr_list[ip_len] = int(addr_list[ip_len]) & (0 << j)
- else:
- if addr_list[length - ip_len - 1] == "":
- continue
- addr_list[length - ip_len -
- 1] = '0x%s' % addr_list[length - ip_len - 1]
- addr_list[length - ip_len -
- 1] = int(addr_list[length - ip_len - 1], 16) & (0 << j)
-
- if self.aftype == "v4":
- self.prefix = '%s.%s.%s.%s' % (addr_list[0], addr_list[1], addr_list[2], addr_list[3])
- return True
- if self.aftype == "v6":
- ipv6_addr_str = ""
- for num in range(0, length - ip_len):
- ipv6_addr_str += '%s:' % addr_list[num]
- self.prefix = ipv6_addr_str
-
- return True
-
- def set_update_cmd_globalbfd(self):
- """set globalBFD update command"""
- if not self.changed:
- return
- if self.state == "present":
- self.updates_cmd.append('ip route-static default-bfd')
- if self.min_tx_interval:
- self.updates_cmd.append(' min-rx-interval %s' % (self.min_tx_interval))
- if self.min_rx_interval:
- self.updates_cmd.append(' min-tx-interval %s' % (self.min_rx_interval))
- if self.detect_multiplier:
- self.updates_cmd.append(' detect-multiplier %s' % (self.detect_multiplier))
- else:
- self.updates_cmd.append('undo ip route-static default-bfd')
-
- def set_update_cmd_singlebfd(self):
- """set singleBFD update command"""
- if not self.changed:
- return
- if self.next_hop is None:
- next_hop = ''
- else:
- next_hop = self.next_hop
-
- if self.destvrf == "_public_":
- destvrf = ''
- else:
- destvrf = self.destvrf
-
- if self.nhp_interface == "Invalid0":
- nhp_interface = ''
- else:
- nhp_interface = self.nhp_interface
- if self.prefix == "0.0.0.0":
- prefix = ''
- else:
- prefix = self.prefix
- if self.state == "present":
- if nhp_interface:
- self.updates_cmd.append('ip route-static bfd %s %s' % (nhp_interface, next_hop))
- elif destvrf:
- self.updates_cmd.append('ip route-static bfd vpn-instance %s %s' % (destvrf, next_hop))
- else:
- self.updates_cmd.append('ip route-static bfd %s' % (next_hop))
- if prefix:
- self.updates_cmd.append(' local-address %s' % (self.prefix))
- if self.min_tx_interval:
- self.updates_cmd.append(' min-rx-interval %s' % (self.min_tx_interval))
- if self.min_rx_interval:
- self.updates_cmd.append(' min-tx-interval %s' % (self.min_rx_interval))
- if self.detect_multiplier:
- self.updates_cmd.append(' detect-multiplier %s' % (self.detect_multiplier))
- else:
- if nhp_interface:
- self.updates_cmd.append('undo ip route-static bfd %s %s' % (nhp_interface, next_hop))
- elif destvrf:
- self.updates_cmd.append('undo ip route-static bfd vpn-instance %s %s' % (destvrf, next_hop))
- else:
- self.updates_cmd.append('undo ip route-static bfd %s' % (next_hop))
-
- def set_update_cmd(self):
- """set update command"""
- if not self.changed:
- return
-
- if self.aftype == "v4":
- maskstr = self._convertlentomask_(self.mask)
- else:
- maskstr = self.mask
- static_bfd_flag = True
- if self.bfd_session_name:
- static_bfd_flag = False
- if self.next_hop is None:
- next_hop = ''
- else:
- next_hop = self.next_hop
- if self.vrf == "_public_":
- vrf = ''
- else:
- vrf = self.vrf
- if self.destvrf == "_public_":
- destvrf = ''
- else:
- destvrf = self.destvrf
- if self.nhp_interface == "Invalid0":
- nhp_interface = ''
- else:
- nhp_interface = self.nhp_interface
- if self.state == "present":
- if self.vrf != "_public_":
- if self.destvrf != "_public_":
- self.updates_cmd.append('ip route-static vpn-instance %s %s %s vpn-instance %s %s'
- % (vrf, self.prefix, maskstr, destvrf, next_hop))
- else:
- self.updates_cmd.append('ip route-static vpn-instance %s %s %s %s %s'
- % (vrf, self.prefix, maskstr, nhp_interface, next_hop))
- elif self.destvrf != "_public_":
- self.updates_cmd.append('ip route-static %s %s vpn-instance %s %s'
- % (self.prefix, maskstr, self.destvrf, next_hop))
- else:
- self.updates_cmd.append('ip route-static %s %s %s %s'
- % (self.prefix, maskstr, nhp_interface, next_hop))
- if self.pref != 60:
- self.updates_cmd.append(' preference %s' % (self.pref))
- if self.tag:
- self.updates_cmd.append(' tag %s' % (self.tag))
- if not static_bfd_flag:
- self.updates_cmd.append(' track bfd-session %s' % (self.bfd_session_name))
- else:
- self.updates_cmd.append(' bfd enable')
- if self.description:
- self.updates_cmd.append(' description %s' % (self.description))
-
- if self.state == "absent":
- if self.vrf != "_public_":
- if self.destvrf != "_public_":
- self.updates_cmd.append('undo ip route-static vpn-instance %s %s %s vpn-instance %s %s'
- % (vrf, self.prefix, maskstr, destvrf, next_hop))
- else:
- self.updates_cmd.append('undo ip route-static vpn-instance %s %s %s %s %s'
- % (vrf, self.prefix, maskstr, nhp_interface, next_hop))
- elif self.destvrf != "_public_":
- self.updates_cmd.append('undo ip route-static %s %s vpn-instance %s %s'
- % (self.prefix, maskstr, self.destvrf, self.next_hop))
- else:
- self.updates_cmd.append('undo ip route-static %s %s %s %s'
- % (self.prefix, maskstr, nhp_interface, next_hop))
-
- def operate_static_route_globalbfd(self):
- """set globalbfd update command"""
- min_tx_interval = self.min_tx_interval
- min_rx_interval = self.min_rx_interval
- multiplier = self.detect_multiplier
- min_tx_interval_xml = """\n"""
- min_rx_interval_xml = """\n"""
- multiplier_xml = """\n"""
- if self.state == "present":
- if min_tx_interval is not None:
- min_tx_interval_xml = CE_NC_SET_IPV4_STATIC_ROUTE_BFDCOMMON_MINTX % min_tx_interval
- if min_rx_interval is not None:
- min_rx_interval_xml = CE_NC_SET_IPV4_STATIC_ROUTE_BFDCOMMON_MINRX % min_rx_interval
- if multiplier is not None:
- multiplier_xml = CE_NC_SET_IPV4_STATIC_ROUTE_BFDCOMMON_MUL % multiplier
-
- configxmlstr = CE_NC_SET_IPV4_STATIC_ROUTE_GLOBALBFD % (
- min_tx_interval_xml, min_rx_interval_xml, multiplier_xml)
- conf_str = build_config_xml(configxmlstr)
- recv_xml = set_nc_config(self.module, conf_str)
- self._checkresponse_(recv_xml, "OPERATE_STATIC_ROUTE_globalBFD")
-
- if self.state == "absent" and self.commands:
- min_tx_interval_xml = CE_NC_SET_IPV4_STATIC_ROUTE_BFDCOMMON_MINTX % 1000
- min_rx_interval_xml = CE_NC_SET_IPV4_STATIC_ROUTE_BFDCOMMON_MINRX % 1000
- multiplier_xml = CE_NC_SET_IPV4_STATIC_ROUTE_BFDCOMMON_MUL % 3
-
- configxmlstr = CE_NC_SET_IPV4_STATIC_ROUTE_GLOBALBFD % (
- min_tx_interval_xml, min_rx_interval_xml, multiplier_xml)
- conf_str = build_config_xml(configxmlstr)
- recv_xml = set_nc_config(self.module, conf_str)
- self._checkresponse_(recv_xml, "OPERATE_STATIC_ROUTE_globalBFD")
-
- def operate_static_route_singlebfd(self, version, prefix, nhp_interface, next_hop, destvrf, state):
- """operate ipv4 static route singleBFD"""
- min_tx_interval = self.min_tx_interval
- min_rx_interval = self.min_rx_interval
- multiplier = self.detect_multiplier
- min_tx_interval_xml = """\n"""
- min_rx_interval_xml = """\n"""
- multiplier_xml = """\n"""
- local_address_xml = """\n"""
- if next_hop is None:
- next_hop = '0.0.0.0'
-
- if destvrf is None:
- dest_vpn_instance = "_public_"
- else:
- dest_vpn_instance = destvrf
-
- if nhp_interface is None:
- nhp_interface = "Invalid0"
-
- if min_tx_interval is not None:
- min_tx_interval_xml = CE_NC_SET_IPV4_STATIC_ROUTE_BFDCOMMON_MINTX % min_tx_interval
- if min_rx_interval is not None:
- min_rx_interval_xml = CE_NC_SET_IPV4_STATIC_ROUTE_BFDCOMMON_MINRX % min_rx_interval
- if multiplier is not None:
- multiplier_xml = CE_NC_SET_IPV4_STATIC_ROUTE_BFDCOMMON_MUL % multiplier
-
- if prefix is not None:
- local_address_xml = CE_NC_SET_STATIC_ROUTE_SINGLEBFD_LOCALADRESS % prefix
-
- if state == "present":
- configxmlstr = CE_NC_SET_STATIC_ROUTE_SINGLEBFD % (
- version, nhp_interface, dest_vpn_instance,
- next_hop, local_address_xml, min_tx_interval_xml,
- min_rx_interval_xml, multiplier_xml)
-
- else:
- configxmlstr = CE_NC_DELETE_STATIC_ROUTE_SINGLEBFD % (
- version, nhp_interface, dest_vpn_instance, next_hop)
-
- conf_str = build_config_xml(configxmlstr)
-
- recv_xml = set_nc_config(self.module, conf_str)
- self._checkresponse_(recv_xml, "OPERATE_STATIC_ROUTE_singleBFD")
-
- def operate_static_route(self, version, prefix, mask, nhp_interface, next_hop, vrf, destvrf, state):
- """operate ipv4 static route"""
- description_xml = """\n"""
- preference_xml = """\n"""
- tag_xml = """\n"""
- bfd_xml = """\n"""
- if next_hop is None:
- next_hop = '0.0.0.0'
- if nhp_interface is None:
- nhp_interface = "Invalid0"
-
- if vrf is None:
- vpn_instance = "_public_"
- else:
- vpn_instance = vrf
-
- if destvrf is None:
- dest_vpn_instance = "_public_"
- else:
- dest_vpn_instance = destvrf
-
- description_xml = get_xml(CE_NC_SET_DESCRIPTION, self.description)
-
- preference_xml = get_xml(CE_NC_SET_PREFERENCE, self.pref)
-
- tag_xml = get_xml(CE_NC_SET_TAG, self.tag)
-
- if self.function_flag == 'staticBFD':
- if self.bfd_session_name:
- bfd_xml = CE_NC_SET_BFDSESSIONNAME % self.bfd_session_name
- else:
- bfd_xml = CE_NC_SET_BFDENABLE
- if state == "present":
- configxmlstr = CE_NC_SET_STATIC_ROUTE % (
- vpn_instance, version, prefix, mask, nhp_interface,
- dest_vpn_instance, next_hop, description_xml, preference_xml, tag_xml, bfd_xml)
-
- else:
- configxmlstr = CE_NC_DELETE_STATIC_ROUTE % (
- vpn_instance, version, prefix, mask, nhp_interface, dest_vpn_instance, next_hop)
-
- conf_str = build_config_xml(configxmlstr)
- recv_xml = set_nc_config(self.module, conf_str)
- self._checkresponse_(recv_xml, "OPERATE_STATIC_ROUTE")
-
- def get_change_state_global_bfd(self):
- """get ipv4 global bfd change state"""
-
- self.get_global_bfd(self.state)
- change = False
- if self.state == "present":
- if self.static_routes_info["sroute_global_bfd"]:
- for static_route in self.static_routes_info["sroute_global_bfd"]:
- if static_route is not None:
- if self.min_tx_interval is not None:
- if int(static_route["minTxInterval"]) != self.min_tx_interval:
- change = True
- if self.min_rx_interval is not None:
- if int(static_route["minRxInterval"]) != self.min_rx_interval:
- change = True
- if self.detect_multiplier is not None:
- if int(static_route["multiplier"]) != self.detect_multiplier:
- change = True
- return change
- else:
- continue
- else:
- change = True
- else:
- if self.commands:
- if self.static_routes_info["sroute_global_bfd"]:
- for static_route in self.static_routes_info["sroute_global_bfd"]:
- if static_route is not None:
- if int(static_route["minTxInterval"]) != 1000 or \
- int(static_route["minRxInterval"]) != 1000 or \
- int(static_route["multiplier"]) != 3:
- change = True
- return change
-
- def get_global_bfd(self, state):
- """get ipv4 global bfd"""
-
- self.static_routes_info["sroute_global_bfd"] = list()
-
- getglobalbfdxmlstr = None
- if self.aftype == 'v4':
- getglobalbfdxmlstr = CE_NC_GET_STATIC_ROUTE_IPV4_GLOBAL_BFD
-
- if getglobalbfdxmlstr is not None:
- xml_global_bfd_str = get_nc_config(self.module, getglobalbfdxmlstr)
-
- if 'data/' in xml_global_bfd_str:
- return
-
- xml_global_bfd_str = xml_global_bfd_str.replace('\r', '').replace('\n', ''). \
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', ""). \
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_global_bfd_str)
- static_routes_global_bfd = root.findall(
- "staticrt/staticrtbase/srIPv4StaticSite")
-
- if static_routes_global_bfd:
- for static_route in static_routes_global_bfd:
- static_info = dict()
- for static_ele in static_route:
- if static_ele.tag == "minTxInterval":
- if static_ele.text is not None:
- static_info["minTxInterval"] = static_ele.text
- if static_ele.tag == "minRxInterval":
- if static_ele.text is not None:
- static_info["minRxInterval"] = static_ele.text
- if static_ele.tag == "multiplier":
- if static_ele.text is not None:
- static_info["multiplier"] = static_ele.text
-
- self.static_routes_info["sroute_global_bfd"].append(static_info)
-
- def get_change_state_single_bfd(self):
- """get ipv4 single bfd change state"""
-
- self.get_single_bfd(self.state)
- change = False
- version = self.version
- if self.state == 'present':
- if self.static_routes_info["sroute_single_bfd"]:
- for static_route in self.static_routes_info["sroute_single_bfd"]:
- if static_route is not None and static_route['afType'] == version:
- if self.nhp_interface:
- if static_route["ifName"].lower() != self.nhp_interface.lower():
- change = True
- if self.destvrf:
- if static_route["destVrfName"].lower() != self.destvrf.lower():
- change = True
- if self.next_hop:
- if static_route["nexthop"].lower() != self.next_hop.lower():
- change = True
- if self.prefix:
- if static_route["localAddress"].lower() != self.prefix.lower():
- change = True
- if self.min_tx_interval:
- if int(static_route["minTxInterval"]) != self.min_tx_interval:
- change = True
- if self.min_rx_interval:
- if int(static_route["minRxInterval"]) != self.min_rx_interval:
- change = True
- if self.detect_multiplier:
- if int(static_route["multiplier"]) != self.detect_multiplier:
- change = True
- return change
-
- else:
- continue
- else:
- change = True
- else:
- for static_route in self.static_routes_info["sroute_single_bfd"]:
- # undo ip route-static bfd [ interface-type interface-number |
- # vpn-instance vpn-instance-name ] nexthop-address
-
- if static_route["ifName"] and self.nhp_interface:
- if static_route["ifName"].lower() == self.nhp_interface.lower() \
- and static_route["nexthop"].lower() == self.next_hop.lower() \
- and static_route["afType"] == version:
- change = True
- return change
-
- if static_route["destVrfName"] and self.destvrf:
- if static_route["destVrfName"].lower() == self.destvrf.lower() \
- and static_route["nexthop"].lower() == self.next_hop.lower() \
- and static_route["afType"] == version:
- change = True
- return change
-
- if static_route["nexthop"] and self.next_hop:
- if static_route["nexthop"].lower() == self.next_hop.lower() \
- and static_route["afType"] == version:
- change = True
- return change
- else:
- continue
- change = False
- return change
-
- def get_single_bfd(self, state):
- """get ipv4 sigle bfd"""
- self.static_routes_info["sroute_single_bfd"] = list()
- if self.aftype == "v4":
- version = "ipv4unicast"
- else:
- version = "ipv6unicast"
- if state == 'absent':
- getbfdxmlstr = CE_NC_GET_STATIC_ROUTE_BFD_ABSENT % (
- version, self.nhp_interface, self.destvrf, self.next_hop)
- else:
- getbfdxmlstr = CE_NC_GET_STATIC_ROUTE_BFD % (
- version, self.nhp_interface, self.destvrf, self.next_hop)
- xml_bfd_str = get_nc_config(self.module, getbfdxmlstr)
-
- if 'data/' in xml_bfd_str:
- return
- xml_bfd_str = xml_bfd_str.replace('\r', '').replace('\n', ''). \
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', ""). \
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_bfd_str)
- static_routes_bfd = root.findall(
- "staticrt/staticrtbase/srBfdParas/srBfdPara")
- if static_routes_bfd:
- for static_route in static_routes_bfd:
- static_info = dict()
- for static_ele in static_route:
- if static_ele.tag in ["afType", "destVrfName", "nexthop", "ifName"]:
- static_info[static_ele.tag] = static_ele.text
- if static_ele.tag == "localAddress":
- if static_ele.text is not None:
- static_info["localAddress"] = static_ele.text
- else:
- static_info["localAddress"] = "None"
- if static_ele.tag == "minTxInterval":
- if static_ele.text is not None:
- static_info["minTxInterval"] = static_ele.text
- if static_ele.tag == "minRxInterval":
- if static_ele.text is not None:
- static_info["minRxInterval"] = static_ele.text
- if static_ele.tag == "multiplier":
- if static_ele.text is not None:
- static_info["multiplier"] = static_ele.text
- self.static_routes_info["sroute_single_bfd"].append(static_info)
-
- def get_static_route(self, state):
- """get ipv4 static route about BFD"""
- self.static_routes_info["sroute"] = list()
- # Increase the parameter used to distinguish whether the incoming bfdSessionName
- static_bfd_flag = True
- if self.bfd_session_name:
- static_bfd_flag = False
-
- if state == 'absent':
- getxmlstr = CE_NC_GET_STATIC_ROUTE_ABSENT
- else:
- # self.static_bfd_flag is true
- if static_bfd_flag:
- getxmlstr = CE_NC_GET_STATIC_ROUTE_BFD_ENABLE
-
- else:
- getxmlstr = CE_NC_GET_STATIC_ROUTE_BFD_SESSIONNAME
- xml_str = get_nc_config(self.module, getxmlstr)
- if 'data/' in xml_str:
- return
- xml_str = xml_str.replace('\r', '').replace('\n', ''). \
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', ""). \
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- root = ElementTree.fromstring(xml_str)
- static_routes = root.findall(
- "staticrt/staticrtbase/srRoutes/srRoute")
-
- if static_routes:
- for static_route in static_routes:
- static_info = dict()
- for static_ele in static_route:
- if static_ele.tag in ["vrfName", "afType", "topologyName",
- "prefix", "maskLength", "destVrfName",
- "nexthop", "ifName", "preference", "description"]:
- static_info[static_ele.tag] = static_ele.text
- if static_ele.tag == "tag":
- if static_ele.text is not None:
- static_info["tag"] = static_ele.text
- else:
- static_info["tag"] = "None"
- if static_bfd_flag:
- if static_ele.tag == "bfdEnable":
- if static_ele.text is not None:
- static_info["bfdEnable"] = static_ele.text
- else:
- static_info["bfdEnable"] = "None"
- else:
- if static_ele.tag == "sessionName":
- if static_ele.text is not None:
- static_info["sessionName"] = static_ele.text
- else:
- static_info["sessionName"] = "None"
- self.static_routes_info["sroute"].append(static_info)
-
- def _checkparams_(self):
- """check all input params"""
- if self.function_flag == 'singleBFD':
- if not self.next_hop:
- self.module.fail_json(msg='Error: missing required argument: next_hop.')
- if self.state != 'absent':
- if self.nhp_interface == "Invalid0" and (not self.prefix or self.prefix == '0.0.0.0'):
- self.module.fail_json(msg='Error: If a nhp_interface is not configured, '
- 'the prefix must be configured.')
-
- if self.function_flag != 'globalBFD':
- if self.function_flag == 'dynamicBFD' or self.function_flag == 'staticBFD':
- if not self.mask:
- self.module.fail_json(msg='Error: missing required argument: mask.')
- # check prefix and mask
- if not self.mask.isdigit():
- self.module.fail_json(msg='Error: Mask is invalid.')
- if self.function_flag != 'singleBFD' or (self.function_flag == 'singleBFD' and self.destvrf != "_public_"):
- if not self.prefix:
- self.module.fail_json(msg='Error: missing required argument: prefix.')
- # convert prefix
- if not self._convertipprefix_():
- self.module.fail_json(msg='Error: The %s is not a valid address' % self.prefix)
-
- if self.nhp_interface != "Invalid0" and self.destvrf != "_public_":
- self.module.fail_json(msg='Error: Destination vrf dose not support next hop is interface.')
-
- if not self.next_hop and self.nhp_interface == "Invalid0":
- self.module.fail_json(msg='Error: one of the following is required: next_hop,nhp_interface.')
-
- if self.function_flag == 'dynamicBFD' or self.function_flag == 'staticBFD':
- # description check
- if self.description:
- if not is_valid_description(self.description):
- self.module.fail_json(
- msg='Error: Dsecription length should be 1 - 35, and can not contain "?".')
- # tag check
- if self.tag is not None:
- if not is_valid_tag(self.tag):
- self.module.fail_json(
- msg='Error: Tag should be integer 1 - 4294967295.')
- # preference check
- if self.pref is not None:
- if not is_valid_preference(self.pref):
- self.module.fail_json(
- msg='Error: Preference should be integer 1 - 255.')
-
- if self.function_flag == 'staticBFD':
- if self.bfd_session_name:
- if not is_valid_bdf_session_name(self.bfd_session_name):
- self.module.fail_json(
- msg='Error: bfd_session_name length should be 1 - 15, and can not contain Space.')
-
- # ipv4 check
- if self.aftype == "v4":
- if self.function_flag == 'dynamicBFD' or self.function_flag == 'staticBFD':
- if int(self.mask) > 32 or int(self.mask) < 0:
- self.module.fail_json(
- msg='Error: Ipv4 mask must be an integer between 1 and 32.')
- # next_hop check
- if self.function_flag != 'globalBFD':
- if self.next_hop:
- if not is_valid_v4addr(self.next_hop):
- self.module.fail_json(
- msg='Error: The %s is not a valid address.' % self.next_hop)
- # ipv6 check
- if self.aftype == "v6":
- if self.function_flag == 'dynamicBFD' or self.function_flag == 'staticBFD':
- if int(self.mask) > 128 or int(self.mask) < 0:
- self.module.fail_json(
- msg='Error: Ipv6 mask must be an integer between 1 and 128.')
- if self.function_flag != 'globalBFD':
- if self.next_hop:
- if not is_valid_v6addr(self.next_hop):
- self.module.fail_json(
- msg='Error: The %s is not a valid address.' % self.next_hop)
-
- if self.function_flag == 'globalBFD' or self.function_flag == 'singleBFD':
- # BFD prarams
- if self.min_tx_interval:
- if not is_valid_bdf_interval(self.min_tx_interval):
- self.module.fail_json(
- msg='Error: min_tx_interval should be integer 50 - 1000.')
- if self.min_rx_interval:
- if not is_valid_bdf_interval(self.min_rx_interval):
- self.module.fail_json(
- msg='Error: min_rx_interval should be integer 50 - 1000.')
- if self.detect_multiplier:
- if not is_valid_bdf_multiplier(self.detect_multiplier):
- self.module.fail_json(
- msg='Error: detect_multiplier should be integer 3 - 50.')
-
- if self.function_flag == 'globalBFD':
- if self.state != 'absent':
- if not self.min_tx_interval and not self.min_rx_interval and not self.detect_multiplier:
- self.module.fail_json(
- msg='Error: one of the following is required: min_tx_interval,'
- 'detect_multiplier,min_rx_interval.')
- else:
- if not self.commands:
- self.module.fail_json(
- msg='Error: missing required argument: command.')
- if compare_command(self.commands):
- self.module.fail_json(
- msg='Error: The command %s line is incorrect.' % (',').join(self.commands))
-
- def set_ip_static_route_globalbfd(self):
- """set ip static route globalBFD"""
- if not self.changed:
- return
- if self.aftype == "v4":
- self.operate_static_route_globalbfd()
-
- def set_ip_static_route_singlebfd(self):
- """set ip static route singleBFD"""
- if not self.changed:
- return
- version = None
- if self.aftype == "v4":
- version = "ipv4unicast"
- else:
- version = "ipv6unicast"
- self.operate_static_route_singlebfd(version, self.prefix, self.nhp_interface,
- self.next_hop, self.destvrf, self.state)
-
- def set_ip_static_route(self):
- """set ip static route"""
- if not self.changed:
- return
- version = None
- if self.aftype == "v4":
- version = "ipv4unicast"
- else:
- version = "ipv6unicast"
- self.operate_static_route(version, self.prefix, self.mask, self.nhp_interface,
- self.next_hop, self.vrf, self.destvrf, self.state)
-
- def is_prefix_exist(self, static_route, version):
- """is prefix mask nex_thop exist"""
- if static_route is None:
- return False
- if self.next_hop and self.nhp_interface:
- return static_route["prefix"].lower() == self.prefix.lower() \
- and static_route["maskLength"] == self.mask \
- and static_route["afType"] == version \
- and static_route["ifName"].lower() == self.nhp_interface.lower() \
- and static_route["nexthop"].lower() == self.next_hop.lower()
-
- if self.next_hop and not self.nhp_interface:
- return static_route["prefix"].lower() == self.prefix.lower() \
- and static_route["maskLength"] == self.mask \
- and static_route["afType"] == version \
- and static_route["nexthop"].lower() == self.next_hop.lower()
-
- if not self.next_hop and self.nhp_interface:
- return static_route["prefix"].lower() == self.prefix.lower() \
- and static_route["maskLength"] == self.mask \
- and static_route["afType"] == version \
- and static_route["ifName"].lower() == self.nhp_interface.lower()
-
- def get_ip_static_route(self):
- """get ip static route"""
- change = False
- version = self.version
- self.get_static_route(self.state)
- change_list = list()
- if self.state == 'present':
- for static_route in self.static_routes_info["sroute"]:
- if self.is_prefix_exist(static_route, self.version):
- info_dict = dict()
- exist_dict = dict()
- if self.vrf:
- info_dict["vrfName"] = self.vrf
- exist_dict["vrfName"] = static_route["vrfName"]
- if self.destvrf:
- info_dict["destVrfName"] = self.destvrf
- exist_dict["destVrfName"] = static_route["destVrfName"]
- if self.description:
- info_dict["description"] = self.description
- exist_dict["description"] = static_route["description"]
- if self.tag:
- info_dict["tag"] = self.tag
- exist_dict["tag"] = static_route["tag"]
- if self.pref:
- info_dict["preference"] = str(self.pref)
- exist_dict["preference"] = static_route["preference"]
- if self.nhp_interface:
- if self.nhp_interface.lower() == "invalid0":
- info_dict["ifName"] = "Invalid0"
- else:
- info_dict["ifName"] = "Invalid0"
- exist_dict["ifName"] = static_route["ifName"]
- if self.next_hop:
- info_dict["nexthop"] = self.next_hop
- exist_dict["nexthop"] = static_route["nexthop"]
-
- if self.bfd_session_name:
- info_dict["bfdEnable"] = 'true'
-
- else:
- info_dict["bfdEnable"] = 'false'
- exist_dict["bfdEnable"] = static_route["bfdEnable"]
-
- if exist_dict != info_dict:
- change = True
- else:
- change = False
- change_list.append(change)
-
- if False in change_list:
- change = False
- else:
- change = True
- return change
-
- else:
- for static_route in self.static_routes_info["sroute"]:
- if static_route["nexthop"] and self.next_hop:
- if static_route["prefix"].lower() == self.prefix.lower() \
- and static_route["maskLength"] == self.mask \
- and static_route["nexthop"].lower() == self.next_hop.lower() \
- and static_route["afType"] == version:
- change = True
- return change
- if static_route["ifName"] and self.nhp_interface:
- if static_route["prefix"].lower() == self.prefix.lower() \
- and static_route["maskLength"] == self.mask \
- and static_route["ifName"].lower() == self.nhp_interface.lower() \
- and static_route["afType"] == version:
- change = True
- return change
- else:
- continue
- change = False
- return change
-
- def get_proposed(self):
- """get proposed information"""
- self.proposed['afType'] = self.aftype
- self.proposed['state'] = self.state
- if self.function_flag != 'globalBFD':
- self.proposed['ifName'] = self.nhp_interface
- self.proposed['destVrfName'] = self.destvrf
- self.proposed['next_hop'] = self.next_hop
-
- if self.function_flag == 'singleBFD':
- if self.prefix:
- self.proposed['localAddress'] = self.prefix
-
- if self.function_flag == 'globalBFD' or self.function_flag == 'singleBFD':
- self.proposed['minTxInterval'] = self.min_tx_interval
- self.proposed['minRxInterval'] = self.min_rx_interval
- self.proposed['multiplier'] = self.detect_multiplier
-
- if self.function_flag != 'globalBFD' and self.function_flag != 'singleBFD':
- self.proposed['prefix'] = self.prefix
- self.proposed['mask'] = self.mask
- self.proposed['vrfName'] = self.vrf
- if self.tag:
- self.proposed['tag'] = self.tag
- if self.description:
- self.proposed['description'] = self.description
- if self.pref is None:
- self.proposed['preference'] = 60
- else:
- self.proposed['preference'] = self.pref
-
- static_bfd_flag = True
- if self.bfd_session_name:
- static_bfd_flag = False
- if not static_bfd_flag:
- self.proposed['sessionName'] = self.bfd_session_name
- else:
- self.proposed['bfdEnable'] = 'true'
-
- def get_existing(self):
- """get existing information"""
- # globalBFD
- if self.function_flag == 'globalBFD':
- change = self.get_change_state_global_bfd()
- self.existing['sroute_global_bfd'] = self.static_routes_info["sroute_global_bfd"]
- # singleBFD
- elif self.function_flag == 'singleBFD':
- change = self.get_change_state_single_bfd()
- self.existing['sroute_single_bfd'] = self.static_routes_info["sroute_single_bfd"]
- # dynamicBFD / staticBFD
- else:
- change = self.get_ip_static_route()
- self.existing['static_sroute'] = self.static_routes_info["sroute"]
- self.changed = bool(change)
-
- def get_end_state(self):
- """get end state information"""
-
- # globalBFD
- if self.function_flag == 'globalBFD':
- self.get_global_bfd(self.state)
- self.end_state['sroute_global_bfd'] = self.static_routes_info["sroute_global_bfd"]
- # singleBFD
- elif self.function_flag == 'singleBFD':
- self.static_routes_info["sroute_single_bfd"] = list()
- self.get_single_bfd(self.state)
- self.end_state['sroute_single_bfd'] = self.static_routes_info["sroute_single_bfd"]
- # dynamicBFD / staticBFD
- else:
- self.get_static_route(self.state)
- self.end_state['static_sroute'] = self.static_routes_info["sroute"]
-
- def work(self):
- """worker"""
- self._checkparams_()
- self.get_existing()
- self.get_proposed()
-
- if self.function_flag == 'globalBFD':
- self.set_ip_static_route_globalbfd()
- self.set_update_cmd_globalbfd()
- elif self.function_flag == 'singleBFD':
- self.set_ip_static_route_singlebfd()
- self.set_update_cmd_singlebfd()
- else:
- self.set_ip_static_route()
- self.set_update_cmd()
-
- self.get_end_state()
- if self.existing == self.end_state:
- self.changed = False
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """main"""
-
- argument_spec = dict(
- prefix=dict(type='str'),
- mask=dict(type='str'),
- aftype=dict(choices=['v4', 'v6'], required=True),
- next_hop=dict(type='str'),
- nhp_interface=dict(type='str'),
- vrf=dict(type='str'),
- destvrf=dict(type='str'),
- tag=dict(type='int'),
- description=dict(type='str'),
- pref=dict(type='int'),
- # bfd
- function_flag=dict(required=True, choices=['globalBFD', 'singleBFD', 'dynamicBFD', 'staticBFD']),
- min_tx_interval=dict(type='int'),
- min_rx_interval=dict(type='int'),
- detect_multiplier=dict(type='int'),
- # bfd session name
- bfd_session_name=dict(type='str'),
- commands=dict(type='list', required=False),
- state=dict(choices=['absent', 'present'], default='present', required=False),
- )
- interface = StaticRouteBFD(argument_spec)
- interface.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_stp.py b/plugins/modules/network/cloudengine/ce_stp.py
deleted file mode 100644
index a9c690305d..0000000000
--- a/plugins/modules/network/cloudengine/ce_stp.py
+++ /dev/null
@@ -1,973 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_stp
-short_description: Manages STP configuration on HUAWEI CloudEngine switches.
-description:
- - Manages STP configurations on HUAWEI CloudEngine switches.
-author:
- - wangdezhuang (@QijunPan)
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- state:
- description:
- - Specify desired state of the resource.
- default: present
- choices: ['present', 'absent']
- stp_mode:
- description:
- - Set an operation mode for the current MSTP process.
- The mode can be STP, RSTP, or MSTP.
- choices: ['stp', 'rstp', 'mstp']
- stp_enable:
- description:
- - Enable or disable STP on a switch.
- choices: ['enable', 'disable']
- stp_converge:
- description:
- - STP convergence mode.
- Fast means set STP aging mode to Fast.
- Normal means set STP aging mode to Normal.
- choices: ['fast', 'normal']
- bpdu_protection:
- description:
- - Configure BPDU protection on an edge port.
- This function prevents network flapping caused by attack packets.
- choices: ['enable', 'disable']
- tc_protection:
- description:
- - Configure the TC BPDU protection function for an MSTP process.
- choices: ['enable', 'disable']
- tc_protection_interval:
- description:
- - Set the time the MSTP device takes to handle the maximum number of TC BPDUs
- and immediately refresh forwarding entries.
- The value is an integer ranging from 1 to 600, in seconds.
- tc_protection_threshold:
- description:
- - Set the maximum number of TC BPDUs that the MSTP can handle.
- The value is an integer ranging from 1 to 255. The default value is 1 on the switch.
- interface:
- description:
- - Interface name.
- If the value is C(all), will apply configuration to all interfaces.
- if the value is a special name, only support input the full name.
- edged_port:
- description:
- - Set the current port as an edge port.
- choices: ['enable', 'disable']
- bpdu_filter:
- description:
- - Specify a port as a BPDU filter port.
- choices: ['enable', 'disable']
- cost:
- description:
- - Set the path cost of the current port.
- The default instance is 0.
- root_protection:
- description:
- - Enable root protection on the current port.
- choices: ['enable', 'disable']
- loop_protection:
- description:
- - Enable loop protection on the current port.
- choices: ['enable', 'disable']
-'''
-
-EXAMPLES = '''
-
-- name: CloudEngine stp test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Config stp mode"
- ce_stp:
- state: present
- stp_mode: stp
- provider: "{{ cli }}"
-
- - name: "Undo stp mode"
- ce_stp:
- state: absent
- stp_mode: stp
- provider: "{{ cli }}"
-
- - name: "Enable bpdu protection"
- ce_stp:
- state: present
- bpdu_protection: enable
- provider: "{{ cli }}"
-
- - name: "Disable bpdu protection"
- ce_stp:
- state: present
- bpdu_protection: disable
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"bpdu_protection": "enable",
- "state": "present"}
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {"bpdu_protection": "disable"}
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {"bpdu_protection": "enable"}
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["stp bpdu-protection"]
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import exec_command, load_config, ce_argument_spec
-
-
-def get_config(module, flags):
-
- """Retrieves the current config from the device or cache"""
-
- flags = [] if flags is None else flags
-
- cmd = 'display current-configuration '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- rc, out, err = exec_command(module, cmd)
- if rc != 0:
- module.fail_json(msg=err)
- config = str(out).strip()
- if config.startswith("display"):
- configs = config.split("\n")
- if len(configs) > 1:
- return "\n".join(configs[1:])
- else:
- return ""
- else:
- return config
-
-
-class Stp(object):
- """ Manages stp/rstp/mstp configuration """
-
- def __init__(self, **kwargs):
- """ Stp module init """
-
- # module
- argument_spec = kwargs["argument_spec"]
- self.spec = argument_spec
- self.module = AnsibleModule(argument_spec=self.spec, supports_check_mode=True)
-
- # config
- self.cur_cfg = dict()
- self.stp_cfg = None
- self.interface_stp_cfg = None
-
- # module args
- self.state = self.module.params['state'] or None
- self.stp_mode = self.module.params['stp_mode'] or None
- self.stp_enable = self.module.params['stp_enable'] or None
- self.stp_converge = self.module.params['stp_converge'] or None
- self.interface = self.module.params['interface'] or None
- self.edged_port = self.module.params['edged_port'] or None
- self.bpdu_filter = self.module.params['bpdu_filter'] or None
- self.cost = self.module.params['cost'] or None
- self.bpdu_protection = self.module.params['bpdu_protection'] or None
- self.tc_protection = self.module.params['tc_protection'] or None
- self.tc_protection_interval = self.module.params['tc_protection_interval'] or None
- self.tc_protection_threshold = self.module.params['tc_protection_threshold'] or None
- self.root_protection = self.module.params['root_protection'] or None
- self.loop_protection = self.module.params['loop_protection'] or None
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def cli_load_config(self, commands):
- """ Cli load configuration """
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def cli_get_stp_config(self):
- """ Cli get stp configuration """
-
- flags = [r"| section include #\s*\n\s*stp", r"| section exclude #\s*\n+\s*stp process \d+"]
- self.stp_cfg = get_config(self.module, flags)
-
- def cli_get_interface_stp_config(self):
- """ Cli get interface's stp configuration """
-
- if self.interface:
- regular = r"| ignore-case section include ^#\s+interface %s\s+" % self.interface.replace(" ", "")
- flags = list()
- flags.append(regular)
- tmp_cfg = get_config(self.module, flags)
-
- if not tmp_cfg:
- self.module.fail_json(
- msg='Error: The interface %s is not exist.' % self.interface)
-
- if "undo portswitch" in tmp_cfg:
- self.module.fail_json(
- msg='Error: The interface %s is not switch mode.' % self.interface)
-
- self.interface_stp_cfg = tmp_cfg
-
- def check_params(self):
- """ Check module params """
-
- if self.cost:
- if self.cost.isdigit():
- if int(self.cost) < 1 or int(self.cost) > 200000000:
- self.module.fail_json(
- msg='Error: The value of cost is out of [1 - 200000000].')
- else:
- self.module.fail_json(
- msg='Error: The cost is not digit.')
-
- if self.tc_protection_interval:
- if self.tc_protection_interval.isdigit():
- if int(self.tc_protection_interval) < 1 or int(self.tc_protection_interval) > 600:
- self.module.fail_json(
- msg='Error: The value of tc_protection_interval is out of [1 - 600].')
- else:
- self.module.fail_json(
- msg='Error: The tc_protection_interval is not digit.')
-
- if self.tc_protection_threshold:
- if self.tc_protection_threshold.isdigit():
- if int(self.tc_protection_threshold) < 1 or int(self.tc_protection_threshold) > 255:
- self.module.fail_json(
- msg='Error: The value of tc_protection_threshold is out of [1 - 255].')
- else:
- self.module.fail_json(
- msg='Error: The tc_protection_threshold is not digit.')
-
- if self.root_protection or self.loop_protection or self.cost:
- if not self.interface:
- self.module.fail_json(
- msg='Error: Please input interface.')
- elif self.interface == "all":
- self.module.fail_json(
- msg='Error: Interface can not be all when config root_protection or loop_protection or cost.')
-
- if self.root_protection and self.root_protection == "enable":
- if self.loop_protection and self.loop_protection == "enable":
- self.module.fail_json(
- msg='Error: Can not enable root_protection and loop_protection at the same interface.')
-
- if self.edged_port or self.bpdu_filter:
- if not self.interface:
- self.module.fail_json(
- msg='Error: Please input interface.')
-
- def get_proposed(self):
- """ Get module proposed """
-
- self.proposed["state"] = self.state
-
- if self.stp_mode:
- self.proposed["stp_mode"] = self.stp_mode
- if self.stp_enable:
- self.proposed["stp_enable"] = self.stp_enable
- if self.stp_converge:
- self.proposed["stp_converge"] = self.stp_converge
- if self.interface:
- self.proposed["interface"] = self.interface
- if self.edged_port:
- self.proposed["edged_port"] = self.edged_port
- if self.bpdu_filter:
- self.proposed["bpdu_filter"] = self.bpdu_filter
- if self.cost:
- self.proposed["cost"] = self.cost
- if self.bpdu_protection:
- self.proposed["bpdu_protection"] = self.bpdu_protection
- if self.tc_protection:
- self.proposed["tc_protection"] = self.tc_protection
- if self.tc_protection_interval:
- self.proposed["tc_protection_interval"] = self.tc_protection_interval
- if self.tc_protection_threshold:
- self.proposed["tc_protection_threshold"] = self.tc_protection_threshold
- if self.root_protection:
- self.proposed["root_protection"] = self.root_protection
- if self.loop_protection:
- self.proposed["loop_protection"] = self.loop_protection
-
- def get_existing(self):
- """ Get existing configuration """
-
- self.cli_get_stp_config()
- if self.interface and self.interface != "all":
- self.cli_get_interface_stp_config()
-
- if self.stp_mode:
- if "stp mode stp" in self.stp_cfg:
- self.cur_cfg["stp_mode"] = "stp"
- self.existing["stp_mode"] = "stp"
- elif "stp mode rstp" in self.stp_cfg:
- self.cur_cfg["stp_mode"] = "rstp"
- self.existing["stp_mode"] = "rstp"
- else:
- self.cur_cfg["stp_mode"] = "mstp"
- self.existing["stp_mode"] = "mstp"
-
- if self.stp_enable:
- if "stp disable" in self.stp_cfg:
- self.cur_cfg["stp_enable"] = "disable"
- self.existing["stp_enable"] = "disable"
- else:
- self.cur_cfg["stp_enable"] = "enable"
- self.existing["stp_enable"] = "enable"
-
- if self.stp_converge:
- if "stp converge fast" in self.stp_cfg:
- self.cur_cfg["stp_converge"] = "fast"
- self.existing["stp_converge"] = "fast"
- else:
- self.cur_cfg["stp_converge"] = "normal"
- self.existing["stp_converge"] = "normal"
-
- if self.edged_port:
- if self.interface == "all":
- if "stp edged-port default" in self.stp_cfg:
- self.cur_cfg["edged_port"] = "enable"
- self.existing["edged_port"] = "enable"
- else:
- self.cur_cfg["edged_port"] = "disable"
- self.existing["edged_port"] = "disable"
- else:
- if "stp edged-port enable" in self.interface_stp_cfg:
- self.cur_cfg["edged_port"] = "enable"
- self.existing["edged_port"] = "enable"
- else:
- self.cur_cfg["edged_port"] = "disable"
- self.existing["edged_port"] = "disable"
-
- if self.bpdu_filter:
- if self.interface == "all":
- if "stp bpdu-filter default" in self.stp_cfg:
- self.cur_cfg["bpdu_filter"] = "enable"
- self.existing["bpdu_filter"] = "enable"
- else:
- self.cur_cfg["bpdu_filter"] = "disable"
- self.existing["bpdu_filter"] = "disable"
- else:
- if "stp bpdu-filter enable" in self.interface_stp_cfg:
- self.cur_cfg["bpdu_filter"] = "enable"
- self.existing["bpdu_filter"] = "enable"
- else:
- self.cur_cfg["bpdu_filter"] = "disable"
- self.existing["bpdu_filter"] = "disable"
-
- if self.bpdu_protection:
- if "stp bpdu-protection" in self.stp_cfg:
- self.cur_cfg["bpdu_protection"] = "enable"
- self.existing["bpdu_protection"] = "enable"
- else:
- self.cur_cfg["bpdu_protection"] = "disable"
- self.existing["bpdu_protection"] = "disable"
-
- if self.tc_protection:
- pre_cfg = self.stp_cfg.split("\n")
- if "stp tc-protection" in pre_cfg:
- self.cur_cfg["tc_protection"] = "enable"
- self.existing["tc_protection"] = "enable"
- else:
- self.cur_cfg["tc_protection"] = "disable"
- self.existing["tc_protection"] = "disable"
-
- if self.tc_protection_interval:
- if "stp tc-protection interval" in self.stp_cfg:
- tmp_value = re.findall(r'stp tc-protection interval (.*)', self.stp_cfg)
- if not tmp_value:
- self.module.fail_json(
- msg='Error: Can not find tc-protection interval on the device.')
- self.cur_cfg["tc_protection_interval"] = tmp_value[0]
- self.existing["tc_protection_interval"] = tmp_value[0]
- else:
- self.cur_cfg["tc_protection_interval"] = "null"
- self.existing["tc_protection_interval"] = "null"
-
- if self.tc_protection_threshold:
- if "stp tc-protection threshold" in self.stp_cfg:
- tmp_value = re.findall(r'stp tc-protection threshold (.*)', self.stp_cfg)
- if not tmp_value:
- self.module.fail_json(
- msg='Error: Can not find tc-protection threshold on the device.')
- self.cur_cfg["tc_protection_threshold"] = tmp_value[0]
- self.existing["tc_protection_threshold"] = tmp_value[0]
- else:
- self.cur_cfg["tc_protection_threshold"] = "1"
- self.existing["tc_protection_threshold"] = "1"
-
- if self.cost:
- tmp_value = re.findall(r'stp instance (.*) cost (.*)', self.interface_stp_cfg)
- if not tmp_value:
- self.cur_cfg["cost"] = "null"
- self.existing["cost"] = "null"
- else:
- self.cur_cfg["cost"] = tmp_value[0][1]
- self.existing["cost"] = tmp_value[0][1]
-
- # root_protection and loop_protection should get configuration at the same time
- if self.root_protection or self.loop_protection:
- if "stp root-protection" in self.interface_stp_cfg:
- self.cur_cfg["root_protection"] = "enable"
- self.existing["root_protection"] = "enable"
- else:
- self.cur_cfg["root_protection"] = "disable"
- self.existing["root_protection"] = "disable"
-
- if "stp loop-protection" in self.interface_stp_cfg:
- self.cur_cfg["loop_protection"] = "enable"
- self.existing["loop_protection"] = "enable"
- else:
- self.cur_cfg["loop_protection"] = "disable"
- self.existing["loop_protection"] = "disable"
-
- def get_end_state(self):
- """ Get end state """
-
- self.cli_get_stp_config()
- if self.interface and self.interface != "all":
- self.cli_get_interface_stp_config()
-
- if self.stp_mode:
- if "stp mode stp" in self.stp_cfg:
- self.end_state["stp_mode"] = "stp"
- elif "stp mode rstp" in self.stp_cfg:
- self.end_state["stp_mode"] = "rstp"
- else:
- self.end_state["stp_mode"] = "mstp"
-
- if self.stp_enable:
- if "stp disable" in self.stp_cfg:
- self.end_state["stp_enable"] = "disable"
- else:
- self.end_state["stp_enable"] = "enable"
-
- if self.stp_converge:
- if "stp converge fast" in self.stp_cfg:
- self.end_state["stp_converge"] = "fast"
- else:
- self.end_state["stp_converge"] = "normal"
-
- if self.edged_port:
- if self.interface == "all":
- if "stp edged-port default" in self.stp_cfg:
- self.end_state["edged_port"] = "enable"
- else:
- self.end_state["edged_port"] = "disable"
- else:
- if "stp edged-port enable" in self.interface_stp_cfg:
- self.end_state["edged_port"] = "enable"
- else:
- self.end_state["edged_port"] = "disable"
-
- if self.bpdu_filter:
- if self.interface == "all":
- if "stp bpdu-filter default" in self.stp_cfg:
- self.end_state["bpdu_filter"] = "enable"
- else:
- self.end_state["bpdu_filter"] = "disable"
- else:
- if "stp bpdu-filter enable" in self.interface_stp_cfg:
- self.end_state["bpdu_filter"] = "enable"
- else:
- self.end_state["bpdu_filter"] = "disable"
-
- if self.bpdu_protection:
- if "stp bpdu-protection" in self.stp_cfg:
- self.end_state["bpdu_protection"] = "enable"
- else:
- self.end_state["bpdu_protection"] = "disable"
-
- if self.tc_protection:
- pre_cfg = self.stp_cfg.split("\n")
- if "stp tc-protection" in pre_cfg:
- self.end_state["tc_protection"] = "enable"
- else:
- self.end_state["tc_protection"] = "disable"
-
- if self.tc_protection_interval:
- if "stp tc-protection interval" in self.stp_cfg:
- tmp_value = re.findall(r'stp tc-protection interval (.*)', self.stp_cfg)
- if not tmp_value:
- self.module.fail_json(
- msg='Error: Can not find tc-protection interval on the device.')
- self.end_state["tc_protection_interval"] = tmp_value[0]
- else:
- self.end_state["tc_protection_interval"] = "null"
-
- if self.tc_protection_threshold:
- if "stp tc-protection threshold" in self.stp_cfg:
- tmp_value = re.findall(r'stp tc-protection threshold (.*)', self.stp_cfg)
- if not tmp_value:
- self.module.fail_json(
- msg='Error: Can not find tc-protection threshold on the device.')
- self.end_state["tc_protection_threshold"] = tmp_value[0]
- else:
- self.end_state["tc_protection_threshold"] = "1"
-
- if self.cost:
- tmp_value = re.findall(r'stp instance (.*) cost (.*)', self.interface_stp_cfg)
- if not tmp_value:
- self.end_state["cost"] = "null"
- else:
- self.end_state["cost"] = tmp_value[0][1]
-
- if self.root_protection or self.loop_protection:
- if "stp root-protection" in self.interface_stp_cfg:
- self.end_state["root_protection"] = "enable"
- else:
- self.end_state["root_protection"] = "disable"
-
- if "stp loop-protection" in self.interface_stp_cfg:
- self.end_state["loop_protection"] = "enable"
- else:
- self.end_state["loop_protection"] = "disable"
-
- if self.existing == self.end_state:
- self.changed = False
- self.updates_cmd = list()
-
- def present_stp(self):
- """ Present stp configuration """
-
- cmds = list()
-
- # config stp global
- if self.stp_mode:
- if self.stp_mode != self.cur_cfg["stp_mode"]:
- cmd = "stp mode %s" % self.stp_mode
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.stp_enable:
- if self.stp_enable != self.cur_cfg["stp_enable"]:
- cmd = "stp %s" % self.stp_enable
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.stp_converge:
- if self.stp_converge != self.cur_cfg["stp_converge"]:
- cmd = "stp converge %s" % self.stp_converge
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.edged_port:
- if self.interface == "all":
- if self.edged_port != self.cur_cfg["edged_port"]:
- if self.edged_port == "enable":
- cmd = "stp edged-port default"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- else:
- cmd = "undo stp edged-port default"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.bpdu_filter:
- if self.interface == "all":
- if self.bpdu_filter != self.cur_cfg["bpdu_filter"]:
- if self.bpdu_filter == "enable":
- cmd = "stp bpdu-filter default"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- else:
- cmd = "undo stp bpdu-filter default"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.bpdu_protection:
- if self.bpdu_protection != self.cur_cfg["bpdu_protection"]:
- if self.bpdu_protection == "enable":
- cmd = "stp bpdu-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- else:
- cmd = "undo stp bpdu-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.tc_protection:
- if self.tc_protection != self.cur_cfg["tc_protection"]:
- if self.tc_protection == "enable":
- cmd = "stp tc-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- else:
- cmd = "undo stp tc-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.tc_protection_interval:
- if self.tc_protection_interval != self.cur_cfg["tc_protection_interval"]:
- cmd = "stp tc-protection interval %s" % self.tc_protection_interval
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.tc_protection_threshold:
- if self.tc_protection_threshold != self.cur_cfg["tc_protection_threshold"]:
- cmd = "stp tc-protection threshold %s" % self.tc_protection_threshold
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- # config interface stp
- if self.interface and self.interface != "all":
- tmp_changed = False
-
- cmd = "interface %s" % self.interface
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.edged_port:
- if self.edged_port != self.cur_cfg["edged_port"]:
- if self.edged_port == "enable":
- cmd = "stp edged-port enable"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
- else:
- cmd = "undo stp edged-port"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
-
- if self.bpdu_filter:
- if self.bpdu_filter != self.cur_cfg["bpdu_filter"]:
- if self.bpdu_filter == "enable":
- cmd = "stp bpdu-filter enable"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
- else:
- cmd = "undo stp bpdu-filter"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
-
- if self.root_protection:
- if self.root_protection == "enable" and self.cur_cfg["loop_protection"] == "enable":
- self.module.fail_json(
- msg='Error: The interface has enable loop_protection, can not enable root_protection.')
- if self.root_protection != self.cur_cfg["root_protection"]:
- if self.root_protection == "enable":
- cmd = "stp root-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
- else:
- cmd = "undo stp root-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
-
- if self.loop_protection:
- if self.loop_protection == "enable" and self.cur_cfg["root_protection"] == "enable":
- self.module.fail_json(
- msg='Error: The interface has enable root_protection, can not enable loop_protection.')
- if self.loop_protection != self.cur_cfg["loop_protection"]:
- if self.loop_protection == "enable":
- cmd = "stp loop-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
- else:
- cmd = "undo stp loop-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
-
- if self.cost:
- if self.cost != self.cur_cfg["cost"]:
- cmd = "stp cost %s" % self.cost
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
-
- if not tmp_changed:
- cmd = "interface %s" % self.interface
- self.updates_cmd.remove(cmd)
- cmds.remove(cmd)
-
- if cmds:
- self.cli_load_config(cmds)
- self.changed = True
-
- def absent_stp(self):
- """ Absent stp configuration """
-
- cmds = list()
-
- if self.stp_mode:
- if self.stp_mode == self.cur_cfg["stp_mode"]:
- if self.stp_mode != "mstp":
- cmd = "undo stp mode"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- self.changed = True
-
- if self.stp_enable:
- if self.stp_enable != self.cur_cfg["stp_enable"]:
- cmd = "stp %s" % self.stp_enable
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.stp_converge:
- if self.stp_converge == self.cur_cfg["stp_converge"]:
- cmd = "undo stp converge"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- self.changed = True
-
- if self.edged_port:
- if self.interface == "all":
- if self.edged_port != self.cur_cfg["edged_port"]:
- if self.edged_port == "enable":
- cmd = "stp edged-port default"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- else:
- cmd = "undo stp edged-port default"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.bpdu_filter:
- if self.interface == "all":
- if self.bpdu_filter != self.cur_cfg["bpdu_filter"]:
- if self.bpdu_filter == "enable":
- cmd = "stp bpdu-filter default"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- else:
- cmd = "undo stp bpdu-filter default"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.bpdu_protection:
- if self.bpdu_protection != self.cur_cfg["bpdu_protection"]:
- if self.bpdu_protection == "enable":
- cmd = "stp bpdu-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- else:
- cmd = "undo stp bpdu-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.tc_protection:
- if self.tc_protection != self.cur_cfg["tc_protection"]:
- if self.tc_protection == "enable":
- cmd = "stp tc-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- else:
- cmd = "undo stp tc-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.tc_protection_interval:
- if self.tc_protection_interval == self.cur_cfg["tc_protection_interval"]:
- cmd = "undo stp tc-protection interval"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- self.changed = True
-
- if self.tc_protection_threshold:
- if self.tc_protection_threshold == self.cur_cfg["tc_protection_threshold"]:
- if self.tc_protection_threshold != "1":
- cmd = "undo stp tc-protection threshold"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- self.changed = True
-
- # undo interface stp
- if self.interface and self.interface != "all":
- tmp_changed = False
-
- cmd = "interface %s" % self.interface
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
-
- if self.edged_port:
- if self.edged_port != self.cur_cfg["edged_port"]:
- if self.edged_port == "enable":
- cmd = "stp edged-port enable"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
- else:
- cmd = "undo stp edged-port"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
-
- if self.bpdu_filter:
- if self.bpdu_filter != self.cur_cfg["bpdu_filter"]:
- if self.bpdu_filter == "enable":
- cmd = "stp bpdu-filter enable"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
- else:
- cmd = "undo stp bpdu-filter"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
-
- if self.root_protection:
- if self.root_protection == "enable" and self.cur_cfg["loop_protection"] == "enable":
- self.module.fail_json(
- msg='Error: The interface has enable loop_protection, can not enable root_protection.')
- if self.root_protection != self.cur_cfg["root_protection"]:
- if self.root_protection == "enable":
- cmd = "stp root-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
- else:
- cmd = "undo stp root-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
-
- if self.loop_protection:
- if self.loop_protection == "enable" and self.cur_cfg["root_protection"] == "enable":
- self.module.fail_json(
- msg='Error: The interface has enable root_protection, can not enable loop_protection.')
- if self.loop_protection != self.cur_cfg["loop_protection"]:
- if self.loop_protection == "enable":
- cmd = "stp loop-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
- else:
- cmd = "undo stp loop-protection"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
-
- if self.cost:
- if self.cost == self.cur_cfg["cost"]:
- cmd = "undo stp cost"
- cmds.append(cmd)
- self.updates_cmd.append(cmd)
- tmp_changed = True
-
- if not tmp_changed:
- cmd = "interface %s" % self.interface
- self.updates_cmd.remove(cmd)
- cmds.remove(cmd)
-
- if cmds:
- self.cli_load_config(cmds)
- self.changed = True
-
- def work(self):
- """ Work function """
-
- self.check_params()
- self.get_proposed()
- self.get_existing()
-
- if self.state == "present":
- self.present_stp()
- else:
- self.absent_stp()
-
- self.get_end_state()
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- self.results['updates'] = self.updates_cmd
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- state=dict(choices=['present', 'absent'], default='present'),
- stp_mode=dict(choices=['stp', 'rstp', 'mstp']),
- stp_enable=dict(choices=['enable', 'disable']),
- stp_converge=dict(choices=['fast', 'normal']),
- bpdu_protection=dict(choices=['enable', 'disable']),
- tc_protection=dict(choices=['enable', 'disable']),
- tc_protection_interval=dict(type='str'),
- tc_protection_threshold=dict(type='str'),
- interface=dict(type='str'),
- edged_port=dict(choices=['enable', 'disable']),
- bpdu_filter=dict(choices=['enable', 'disable']),
- cost=dict(type='str'),
- root_protection=dict(choices=['enable', 'disable']),
- loop_protection=dict(choices=['enable', 'disable'])
- )
-
- argument_spec.update(ce_argument_spec)
- module = Stp(argument_spec=argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_switchport.py b/plugins/modules/network/cloudengine/ce_switchport.py
deleted file mode 100644
index aeb8c365b9..0000000000
--- a/plugins/modules/network/cloudengine/ce_switchport.py
+++ /dev/null
@@ -1,1001 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_switchport
-short_description: Manages Layer 2 switchport interfaces on HUAWEI CloudEngine switches.
-description:
- - Manages Layer 2 switchport interfaces on HUAWEI CloudEngine switches.
-author: QijunPan (@QijunPan)
-notes:
- - When C(state=absent), VLANs can be added/removed from trunk links and
- the existing access VLAN can be 'unconfigured' to just having VLAN 1 on that interface.
- - When working with trunks VLANs the keywords add/remove are always sent
- in the C(port trunk allow-pass vlan) command. Use verbose mode to see commands sent.
- - When C(state=unconfigured), the interface will result with having a default Layer 2 interface, i.e. vlan 1 in access mode.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- interface:
- description:
- - Full name of the interface, i.e. 40GE1/0/22.
- required: true
- mode:
- description:
- - The link type of an interface.
- choices: ['access','trunk', 'hybrid', 'dot1qtunnel']
- default_vlan:
- description:
- - If C(mode=access, or mode=dot1qtunnel), used as the access VLAN ID, in the range from 1 to 4094.
- pvid_vlan:
- description:
- - If C(mode=trunk, or mode=hybrid), used as the trunk native VLAN ID, in the range from 1 to 4094.
- trunk_vlans:
- description:
- - If C(mode=trunk), used as the VLAN range to ADD or REMOVE
- from the trunk, such as 2-10 or 2,5,10-15, etc.
- untagged_vlans:
- description:
- - If C(mode=hybrid), used as the VLAN range to ADD or REMOVE
- from the trunk, such as 2-10 or 2,5,10-15, etc.
- tagged_vlans:
- description:
- - If C(mode=hybrid), used as the VLAN range to ADD or REMOVE
- from the trunk, such as 2-10 or 2,5,10-15, etc.
- state:
- description:
- - Manage the state of the resource.
- default: present
- choices: ['present', 'absent', 'unconfigured']
-'''
-
-EXAMPLES = '''
-- name: switchport module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
- - name: Ensure 10GE1/0/22 is in its default switchport state
- ce_switchport:
- interface: 10GE1/0/22
- state: unconfigured
- provider: '{{ cli }}'
-
- - name: Ensure 10GE1/0/22 is configured for access vlan 20
- ce_switchport:
- interface: 10GE1/0/22
- mode: access
- default_vlan: 20
- provider: '{{ cli }}'
-
- - name: Ensure 10GE1/0/22 only has vlans 5-10 as trunk vlans
- ce_switchport:
- interface: 10GE1/0/22
- mode: trunk
- pvid_vlan: 10
- trunk_vlans: 5-10
- provider: '{{ cli }}'
-
- - name: Ensure 10GE1/0/22 is a trunk port and ensure 2-50 are being tagged (doesn't mean others aren't also being tagged)
- ce_switchport:
- interface: 10GE1/0/22
- mode: trunk
- pvid_vlan: 10
- trunk_vlans: 2-50
- provider: '{{ cli }}'
-
- - name: Ensure these VLANs are not being tagged on the trunk
- ce_switchport:
- interface: 10GE1/0/22
- mode: trunk
- trunk_vlans: 51-4000
- state: absent
- provider: '{{ cli }}'
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"default_vlan": "20", "interface": "10GE1/0/22", "mode": "access"}
-existing:
- description: k/v pairs of existing switchport
- returned: always
- type: dict
- sample: {"default_vlan": "10", "interface": "10GE1/0/22",
- "mode": "access", "switchport": "enable"}
-end_state:
- description: k/v pairs of switchport after module execution
- returned: always
- type: dict
- sample: {"default_vlan": "20", "interface": "10GE1/0/22",
- "mode": "access", "switchport": "enable"}
-updates:
- description: command string sent to the device
- returned: always
- type: list
- sample: ["10GE1/0/22", "port default vlan 20"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import re
-from xml.etree import ElementTree as ET
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-
-CE_NC_GET_PORT_ATTR = """
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_SET_PORT = """
-
-
-
- %s
-
- %s
- %s
- %s
- %s
-
-
-
-
-"""
-
-CE_NC_SET_PORT_MODE = """
-
-
-
- %s
-
- %s
-
-
-
-
-"""
-
-CE_NC_SET_DEFAULT_PORT = """
-
-
-
-
- %s
-
- access
- 1
-
-
-
-
-
-
-
-"""
-
-
-SWITCH_PORT_TYPE = ('ge', '10ge', '25ge',
- '4x10ge', '40ge', '100ge', 'eth-trunk')
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- iftype = None
-
- if interface.upper().startswith('GE'):
- iftype = 'ge'
- elif interface.upper().startswith('10GE'):
- iftype = '10ge'
- elif interface.upper().startswith('25GE'):
- iftype = '25ge'
- elif interface.upper().startswith('4X10GE'):
- iftype = '4x10ge'
- elif interface.upper().startswith('40GE'):
- iftype = '40ge'
- elif interface.upper().startswith('100GE'):
- iftype = '100ge'
- elif interface.upper().startswith('VLANIF'):
- iftype = 'vlanif'
- elif interface.upper().startswith('LOOPBACK'):
- iftype = 'loopback'
- elif interface.upper().startswith('METH'):
- iftype = 'meth'
- elif interface.upper().startswith('ETH-TRUNK'):
- iftype = 'eth-trunk'
- elif interface.upper().startswith('VBDIF'):
- iftype = 'vbdif'
- elif interface.upper().startswith('NVE'):
- iftype = 'nve'
- elif interface.upper().startswith('TUNNEL'):
- iftype = 'tunnel'
- elif interface.upper().startswith('ETHERNET'):
- iftype = 'ethernet'
- elif interface.upper().startswith('FCOE-PORT'):
- iftype = 'fcoe-port'
- elif interface.upper().startswith('FABRIC-PORT'):
- iftype = 'fabric-port'
- elif interface.upper().startswith('STACK-PORT'):
- iftype = 'stack-port'
- elif interface.upper().startswith('NULL'):
- iftype = 'null'
- else:
- return None
-
- return iftype.lower()
-
-
-def is_portswitch_enalbed(iftype):
- """"[undo] portswitch"""
-
- return bool(iftype in SWITCH_PORT_TYPE)
-
-
-def vlan_bitmap_undo(bitmap):
- """convert vlan bitmap to undo bitmap"""
-
- vlan_bit = ['F'] * 1024
-
- if not bitmap or len(bitmap) == 0:
- return ''.join(vlan_bit)
-
- bit_len = len(bitmap)
- for num in range(bit_len):
- undo = (~int(bitmap[num], 16)) & 0xF
- vlan_bit[num] = hex(undo)[2]
-
- return ''.join(vlan_bit)
-
-
-def is_vlan_bitmap_empty(bitmap):
- """check vlan bitmap empty"""
-
- if not bitmap or len(bitmap) == 0:
- return True
-
- bit_len = len(bitmap)
- for num in range(bit_len):
- if bitmap[num] != '0':
- return False
-
- return True
-
-
-class SwitchPort(object):
- """
- Manages Layer 2 switchport interfaces.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # interface and vlan info
- self.interface = self.module.params['interface']
- self.mode = self.module.params['mode']
- self.state = self.module.params['state']
- self.default_vlan = self.module.params['default_vlan']
- self.pvid_vlan = self.module.params['pvid_vlan']
- self.trunk_vlans = self.module.params['trunk_vlans']
- self.untagged_vlans = self.module.params['untagged_vlans']
- self.tagged_vlans = self.module.params['tagged_vlans']
-
- # host info
- self.host = self.module.params['host']
- self.username = self.module.params['username']
- self.port = self.module.params['port']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
- self.intf_info = dict() # interface vlan info
- self.intf_type = None # loopback tunnel ...
-
- def init_module(self):
- """ init module """
-
- required_if = [('state', 'absent', ['mode']), ('state', 'present', ['mode'])]
- mutually_exclusive = [['default_vlan', 'trunk_vlans'],
- ['default_vlan', 'pvid_vlan'],
- ['default_vlan', 'untagged_vlans'],
- ['trunk_vlans', 'untagged_vlans'],
- ['trunk_vlans', 'tagged_vlans'],
- ['default_vlan', 'tagged_vlans']]
-
- self.module = AnsibleModule(
- argument_spec=self.spec, required_if=required_if, supports_check_mode=True, mutually_exclusive=mutually_exclusive)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_interface_dict(self, ifname):
- """ get one interface attributes dict."""
-
- intf_info = dict()
- conf_str = CE_NC_GET_PORT_ATTR % ifname
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return intf_info
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- tree = ET.fromstring(xml_str)
- l2Enable = tree.find('ethernet/ethernetIfs/ethernetIf/l2Enable')
- intf_info["l2Enable"] = l2Enable.text
- port_type = tree.find('ethernet/ethernetIfs/ethernetIf/l2Attribute')
- for pre in port_type:
- intf_info[pre.tag] = pre.text
- intf_info["ifName"] = ifname
- if intf_info["trunkVlans"] is None:
- intf_info["trunkVlans"] = ""
- if intf_info["untagVlans"] is None:
- intf_info["untagVlans"] = ""
- return intf_info
-
- def is_l2switchport(self):
- """Check layer2 switch port"""
-
- return bool(self.intf_info["l2Enable"] == "enable")
-
- def merge_access_vlan(self, ifname, default_vlan):
- """Merge access interface vlan"""
-
- change = False
- conf_str = ""
-
- self.updates_cmd.append("interface %s" % ifname)
- if self.state == "present":
- if self.intf_info["linkType"] == "access":
- if default_vlan and self.intf_info["pvid"] != default_vlan:
- self.updates_cmd.append(
- "port default vlan %s" % default_vlan)
- conf_str = CE_NC_SET_PORT % (ifname, "access", default_vlan, "", "")
- change = True
- else: # not access
- self.updates_cmd.append("port link-type access")
- if default_vlan:
- self.updates_cmd.append(
- "port default vlan %s" % default_vlan)
- conf_str = CE_NC_SET_PORT % (ifname, "access", default_vlan, "", "")
- else:
- conf_str = CE_NC_SET_PORT % (ifname, "access", "1", "", "")
- change = True
- elif self.state == "absent":
- if self.intf_info["linkType"] == "access":
- if default_vlan and self.intf_info["pvid"] == default_vlan and default_vlan != "1":
- self.updates_cmd.append(
- "undo port default vlan %s" % default_vlan)
- conf_str = CE_NC_SET_PORT % (ifname, "access", "1", "", "")
- change = True
-
- if not change:
- self.updates_cmd.pop() # remove interface
- return
- conf_str = "" + conf_str + ""
- rcv_xml = set_nc_config(self.module, conf_str)
- self.check_response(rcv_xml, "MERGE_ACCESS_PORT")
- self.changed = True
-
- def merge_trunk_vlan(self, ifname, pvid_vlan, trunk_vlans):
- """Merge trunk interface vlan"""
-
- change = False
- xmlstr = ""
- pvid = ""
- trunk = ""
- self.updates_cmd.append("interface %s" % ifname)
- if trunk_vlans:
- vlan_list = self.vlan_range_to_list(trunk_vlans)
- vlan_map = self.vlan_list_to_bitmap(vlan_list)
- if self.state == "present":
- if self.intf_info["linkType"] == "trunk":
- if pvid_vlan and self.intf_info["pvid"] != pvid_vlan:
- self.updates_cmd.append(
- "port trunk pvid vlan %s" % pvid_vlan)
- pvid = pvid_vlan
- change = True
-
- if trunk_vlans:
- add_vlans = self.vlan_bitmap_add(
- self.intf_info["trunkVlans"], vlan_map)
- if not is_vlan_bitmap_empty(add_vlans):
- self.updates_cmd.append(
- "port trunk allow-pass %s"
- % trunk_vlans.replace(',', ' ').replace('-', ' to '))
- trunk = "%s:%s" % (add_vlans, add_vlans)
- change = True
- if pvid or trunk:
- xmlstr += CE_NC_SET_PORT % (ifname, "trunk", pvid, trunk, "")
- if not pvid:
- xmlstr = xmlstr.replace("", "")
- if not trunk:
- xmlstr = xmlstr.replace("", "")
-
- else: # not trunk
- self.updates_cmd.append("port link-type trunk")
- change = True
- if pvid_vlan:
- self.updates_cmd.append(
- "port trunk pvid vlan %s" % pvid_vlan)
- pvid = pvid_vlan
- if trunk_vlans:
- self.updates_cmd.append(
- "port trunk allow-pass %s"
- % trunk_vlans.replace(',', ' ').replace('-', ' to '))
- trunk = "%s:%s" % (vlan_map, vlan_map)
- if pvid or trunk:
- xmlstr += CE_NC_SET_PORT % (ifname, "trunk", pvid, trunk, "")
- if not pvid:
- xmlstr = xmlstr.replace("", "")
- if not trunk:
- xmlstr = xmlstr.replace("", "")
-
- if not pvid_vlan and not trunk_vlans:
- xmlstr += CE_NC_SET_PORT_MODE % (ifname, "trunk")
- self.updates_cmd.append(
- "undo port trunk allow-pass vlan 1")
- elif self.state == "absent":
- if self.intf_info["linkType"] == "trunk":
- if pvid_vlan and self.intf_info["pvid"] == pvid_vlan and pvid_vlan != '1':
- self.updates_cmd.append(
- "undo port trunk pvid vlan %s" % pvid_vlan)
- pvid = "1"
- change = True
- if trunk_vlans:
- del_vlans = self.vlan_bitmap_del(
- self.intf_info["trunkVlans"], vlan_map)
- if not is_vlan_bitmap_empty(del_vlans):
- self.updates_cmd.append(
- "undo port trunk allow-pass %s"
- % trunk_vlans.replace(',', ' ').replace('-', ' to '))
- undo_map = vlan_bitmap_undo(del_vlans)
- trunk = "%s:%s" % (undo_map, del_vlans)
- change = True
- if pvid or trunk:
- xmlstr += CE_NC_SET_PORT % (ifname, "trunk", pvid, trunk, "")
- if not pvid:
- xmlstr = xmlstr.replace("", "")
- if not trunk:
- xmlstr = xmlstr.replace("", "")
-
- if not change:
- self.updates_cmd.pop()
- return
- conf_str = "" + xmlstr + ""
- rcv_xml = set_nc_config(self.module, conf_str)
- self.check_response(rcv_xml, "MERGE_TRUNK_PORT")
- self.changed = True
-
- def merge_hybrid_vlan(self, ifname, pvid_vlan, tagged_vlans, untagged_vlans):
- """Merge hybrid interface vlan"""
-
- change = False
- xmlstr = ""
- pvid = ""
- tagged = ""
- untagged = ""
- self.updates_cmd.append("interface %s" % ifname)
- if tagged_vlans:
- vlan_targed_list = self.vlan_range_to_list(tagged_vlans)
- vlan_targed_map = self.vlan_list_to_bitmap(vlan_targed_list)
- if untagged_vlans:
- vlan_untarged_list = self.vlan_range_to_list(untagged_vlans)
- vlan_untarged_map = self.vlan_list_to_bitmap(vlan_untarged_list)
- if self.state == "present":
- if self.intf_info["linkType"] == "hybrid":
- if pvid_vlan and self.intf_info["pvid"] != pvid_vlan:
- self.updates_cmd.append(
- "port hybrid pvid vlan %s" % pvid_vlan)
- pvid = pvid_vlan
- change = True
- if tagged_vlans:
- add_vlans = self.vlan_bitmap_add(
- self.intf_info["trunkVlans"], vlan_targed_map)
- if not is_vlan_bitmap_empty(add_vlans):
- self.updates_cmd.append(
- "port hybrid tagged vlan %s"
- % tagged_vlans.replace(',', ' ').replace('-', ' to '))
- tagged = "%s:%s" % (add_vlans, add_vlans)
- change = True
- if untagged_vlans:
- add_vlans = self.vlan_bitmap_add(
- self.intf_info["untagVlans"], vlan_untarged_map)
- if not is_vlan_bitmap_empty(add_vlans):
- self.updates_cmd.append(
- "port hybrid untagged vlan %s"
- % untagged_vlans.replace(',', ' ').replace('-', ' to '))
- untagged = "%s:%s" % (add_vlans, add_vlans)
- change = True
- if pvid or tagged or untagged:
- xmlstr += CE_NC_SET_PORT % (ifname, "hybrid", pvid, tagged, untagged)
- if not pvid:
- xmlstr = xmlstr.replace("", "")
- if not tagged:
- xmlstr = xmlstr.replace("", "")
- if not untagged:
- xmlstr = xmlstr.replace("", "")
- else:
- self.updates_cmd.append("port link-type hybrid")
- change = True
- if pvid_vlan:
- self.updates_cmd.append(
- "port hybrid pvid vlan %s" % pvid_vlan)
- pvid = pvid_vlan
- if tagged_vlans:
- self.updates_cmd.append(
- "port hybrid tagged vlan %s"
- % tagged_vlans.replace(',', ' ').replace('-', ' to '))
- tagged = "%s:%s" % (vlan_targed_map, vlan_targed_map)
- if untagged_vlans:
- self.updates_cmd.append(
- "port hybrid untagged vlan %s"
- % untagged_vlans.replace(',', ' ').replace('-', ' to '))
- untagged = "%s:%s" % (vlan_untarged_map, vlan_untarged_map)
- if pvid or tagged or untagged:
- xmlstr += CE_NC_SET_PORT % (ifname, "hybrid", pvid, tagged, untagged)
- if not pvid:
- xmlstr = xmlstr.replace("", "")
- if not tagged:
- xmlstr = xmlstr.replace("", "")
- if not untagged:
- xmlstr = xmlstr.replace("", "")
- if not pvid_vlan and not tagged_vlans and not untagged_vlans:
- xmlstr += CE_NC_SET_PORT_MODE % (ifname, "hybrid")
- self.updates_cmd.append(
- "undo port hybrid untagged vlan 1")
- elif self.state == "absent":
- if self.intf_info["linkType"] == "hybrid":
- if pvid_vlan and self.intf_info["pvid"] == pvid_vlan and pvid_vlan != '1':
- self.updates_cmd.append(
- "undo port hybrid pvid vlan %s" % pvid_vlan)
- pvid = "1"
- change = True
- if tagged_vlans:
- del_vlans = self.vlan_bitmap_del(
- self.intf_info["trunkVlans"], vlan_targed_map)
- if not is_vlan_bitmap_empty(del_vlans):
- self.updates_cmd.append(
- "undo port hybrid tagged vlan %s"
- % tagged_vlans.replace(',', ' ').replace('-', ' to '))
- undo_map = vlan_bitmap_undo(del_vlans)
- tagged = "%s:%s" % (undo_map, del_vlans)
- change = True
- if untagged_vlans:
- del_vlans = self.vlan_bitmap_del(
- self.intf_info["untagVlans"], vlan_untarged_map)
- if not is_vlan_bitmap_empty(del_vlans):
- self.updates_cmd.append(
- "undo port hybrid untagged vlan %s"
- % untagged_vlans.replace(',', ' ').replace('-', ' to '))
- undo_map = vlan_bitmap_undo(del_vlans)
- untagged = "%s:%s" % (undo_map, del_vlans)
- change = True
- if pvid or tagged or untagged:
- xmlstr += CE_NC_SET_PORT % (ifname, "hybrid", pvid, tagged, untagged)
- if not pvid:
- xmlstr = xmlstr.replace("", "")
- if not tagged:
- xmlstr = xmlstr.replace("", "")
- if not untagged:
- xmlstr = xmlstr.replace("", "")
-
- if not change:
- self.updates_cmd.pop()
- return
-
- conf_str = "" + xmlstr + ""
- rcv_xml = set_nc_config(self.module, conf_str)
- self.check_response(rcv_xml, "MERGE_HYBRID_PORT")
- self.changed = True
-
- def merge_dot1qtunnel_vlan(self, ifname, default_vlan):
- """Merge dot1qtunnel"""
-
- change = False
- conf_str = ""
-
- self.updates_cmd.append("interface %s" % ifname)
- if self.state == "present":
- if self.intf_info["linkType"] == "dot1qtunnel":
- if default_vlan and self.intf_info["pvid"] != default_vlan:
- self.updates_cmd.append(
- "port default vlan %s" % default_vlan)
- conf_str = CE_NC_SET_PORT % (ifname, "dot1qtunnel", default_vlan, "", "")
- change = True
- else:
- self.updates_cmd.append("port link-type dot1qtunnel")
- if default_vlan:
- self.updates_cmd.append(
- "port default vlan %s" % default_vlan)
- conf_str = CE_NC_SET_PORT % (ifname, "dot1qtunnel", default_vlan, "", "")
- else:
- conf_str = CE_NC_SET_PORT % (ifname, "dot1qtunnel", "1", "", "")
- change = True
- elif self.state == "absent":
- if self.intf_info["linkType"] == "dot1qtunnel":
- if default_vlan and self.intf_info["pvid"] == default_vlan and default_vlan != "1":
- self.updates_cmd.append(
- "undo port default vlan %s" % default_vlan)
- conf_str = CE_NC_SET_PORT % (ifname, "dot1qtunnel", "1", "", "")
- change = True
- if not change:
- self.updates_cmd.pop() # remove interface
- return
- conf_str = "" + conf_str + ""
- rcv_xml = set_nc_config(self.module, conf_str)
- self.check_response(rcv_xml, "MERGE_DOT1QTUNNEL_PORT")
- self.changed = True
-
- def default_switchport(self, ifname):
- """Set interface default or unconfigured"""
-
- change = False
- if self.intf_info["linkType"] != "access":
- self.updates_cmd.append("interface %s" % ifname)
- self.updates_cmd.append("port link-type access")
- self.updates_cmd.append("port default vlan 1")
- change = True
- else:
- if self.intf_info["pvid"] != "1":
- self.updates_cmd.append("interface %s" % ifname)
- self.updates_cmd.append("port default vlan 1")
- change = True
-
- if not change:
- return
-
- conf_str = CE_NC_SET_DEFAULT_PORT % ifname
- rcv_xml = set_nc_config(self.module, conf_str)
- self.check_response(rcv_xml, "DEFAULT_INTF_VLAN")
- self.changed = True
-
- def vlan_series(self, vlanid_s):
- """ convert vlan range to vlan list """
-
- vlan_list = []
- peerlistlen = len(vlanid_s)
- if peerlistlen != 2:
- self.module.fail_json(msg='Error: Format of vlanid is invalid.')
- for num in range(peerlistlen):
- if not vlanid_s[num].isdigit():
- self.module.fail_json(
- msg='Error: Format of vlanid is invalid.')
- if int(vlanid_s[0]) > int(vlanid_s[1]):
- self.module.fail_json(msg='Error: Format of vlanid is invalid.')
- elif int(vlanid_s[0]) == int(vlanid_s[1]):
- vlan_list.append(str(vlanid_s[0]))
- return vlan_list
- for num in range(int(vlanid_s[0]), int(vlanid_s[1])):
- vlan_list.append(str(num))
- vlan_list.append(vlanid_s[1])
-
- return vlan_list
-
- def vlan_region(self, vlanid_list):
- """ convert vlan range to vlan list """
-
- vlan_list = []
- peerlistlen = len(vlanid_list)
- for num in range(peerlistlen):
- if vlanid_list[num].isdigit():
- vlan_list.append(vlanid_list[num])
- else:
- vlan_s = self.vlan_series(vlanid_list[num].split('-'))
- vlan_list.extend(vlan_s)
-
- return vlan_list
-
- def vlan_range_to_list(self, vlan_range):
- """ convert vlan range to vlan list """
-
- vlan_list = self.vlan_region(vlan_range.split(','))
-
- return vlan_list
-
- def vlan_list_to_bitmap(self, vlanlist):
- """ convert vlan list to vlan bitmap """
-
- vlan_bit = ['0'] * 1024
- bit_int = [0] * 1024
-
- vlan_list_len = len(vlanlist)
- for num in range(vlan_list_len):
- tagged_vlans = int(vlanlist[num])
- if tagged_vlans <= 0 or tagged_vlans > 4094:
- self.module.fail_json(
- msg='Error: Vlan id is not in the range from 1 to 4094.')
- j = tagged_vlans // 4
- bit_int[j] |= 0x8 >> (tagged_vlans % 4)
- vlan_bit[j] = hex(bit_int[j])[2]
-
- vlan_xml = ''.join(vlan_bit)
-
- return vlan_xml
-
- def vlan_bitmap_add(self, oldmap, newmap):
- """vlan add bitmap"""
-
- vlan_bit = ['0'] * 1024
-
- if len(newmap) != 1024:
- self.module.fail_json(msg='Error: New vlan bitmap is invalid.')
-
- if len(oldmap) != 1024 and len(oldmap) != 0:
- self.module.fail_json(msg='Error: old vlan bitmap is invalid.')
-
- if len(oldmap) == 0:
- return newmap
-
- for num in range(1024):
- new_tmp = int(newmap[num], 16)
- old_tmp = int(oldmap[num], 16)
- add = (~(new_tmp & old_tmp)) & new_tmp
- vlan_bit[num] = hex(add)[2]
-
- vlan_xml = ''.join(vlan_bit)
-
- return vlan_xml
-
- def vlan_bitmap_del(self, oldmap, delmap):
- """vlan del bitmap"""
-
- vlan_bit = ['0'] * 1024
-
- if not oldmap or len(oldmap) == 0:
- return ''.join(vlan_bit)
-
- if len(oldmap) != 1024 or len(delmap) != 1024:
- self.module.fail_json(msg='Error: vlan bitmap is invalid.')
-
- for num in range(1024):
- tmp = int(delmap[num], 16) & int(oldmap[num], 16)
- vlan_bit[num] = hex(tmp)[2]
-
- vlan_xml = ''.join(vlan_bit)
-
- return vlan_xml
-
- def check_params(self):
- """Check all input params"""
-
- # interface type check
- if self.interface:
- self.intf_type = get_interface_type(self.interface)
- if not self.intf_type:
- self.module.fail_json(
- msg='Error: Interface name of %s is error.' % self.interface)
-
- if not self.intf_type or not is_portswitch_enalbed(self.intf_type):
- self.module.fail_json(msg='Error: Interface %s is error.')
-
- # check default_vlan
- if self.default_vlan:
- if not self.default_vlan.isdigit():
- self.module.fail_json(msg='Error: Access vlan id is invalid.')
- if int(self.default_vlan) <= 0 or int(self.default_vlan) > 4094:
- self.module.fail_json(
- msg='Error: Access vlan id is not in the range from 1 to 4094.')
-
- # check pvid_vlan
- if self.pvid_vlan:
- if not self.pvid_vlan.isdigit():
- self.module.fail_json(msg='Error: Pvid vlan id is invalid.')
- if int(self.pvid_vlan) <= 0 or int(self.pvid_vlan) > 4094:
- self.module.fail_json(
- msg='Error: Pvid vlan id is not in the range from 1 to 4094.')
-
- # get interface info
- self.intf_info = self.get_interface_dict(self.interface)
- if not self.intf_info:
- self.module.fail_json(msg='Error: Interface does not exist.')
-
- if not self.is_l2switchport():
- self.module.fail_json(
- msg='Error: Interface is not layer2 switch port.')
- if self.state == "unconfigured":
- if any([self.mode, self.default_vlan, self.pvid_vlan, self.trunk_vlans, self.untagged_vlans, self.tagged_vlans]):
- self.module.fail_json(
- msg='Error: When state is unconfigured, only interface name exists.')
- else:
- if self.mode == "access":
- if any([self.pvid_vlan, self.trunk_vlans, self.untagged_vlans, self.tagged_vlans]):
- self.module.fail_json(
- msg='Error: When mode is access, only default_vlan can be supported.')
- elif self.mode == "trunk":
- if any([self.default_vlan, self.untagged_vlans, self.tagged_vlans]):
- self.module.fail_json(
- msg='Error: When mode is trunk, only pvid_vlan and trunk_vlans can exist.')
- elif self.mode == "hybrid":
- if any([self.default_vlan, self.trunk_vlans]):
- self.module.fail_json(
- msg='Error: When mode is hybrid, default_vlan and trunk_vlans cannot exist')
- else:
- if any([self.pvid_vlan, self.trunk_vlans, self.untagged_vlans, self.tagged_vlans]):
- self.module.fail_json(
- msg='Error: When mode is dot1qtunnel, only default_vlan can be supported.')
-
- def get_proposed(self):
- """get proposed info"""
-
- self.proposed['state'] = self.state
- self.proposed['interface'] = self.interface
- self.proposed['mode'] = self.mode
- if self.mode:
- if self.mode == "access":
- self.proposed['access_pvid'] = self.default_vlan
- elif self.mode == "trunk":
- self.proposed['pvid_vlan'] = self.pvid_vlan
- self.proposed['trunk_vlans'] = self.trunk_vlans
- elif self.mode == "hybrid":
- self.proposed['pvid_vlan'] = self.pvid_vlan
- self.proposed['untagged_vlans'] = self.untagged_vlans
- self.proposed['tagged_vlans'] = self.tagged_vlans
- else:
- self.proposed['dot1qtunnel_pvid'] = self.default_vlan
-
- def get_existing(self):
- """get existing info"""
-
- if self.intf_info:
- self.existing["interface"] = self.intf_info["ifName"]
- self.existing["switchport"] = self.intf_info["l2Enable"]
- self.existing["mode"] = self.intf_info["linkType"]
- if self.intf_info["linkType"] == "access":
- self.existing['access_pvid'] = self.intf_info["pvid"]
- elif self.intf_info["linkType"] == "trunk":
- self.existing['trunk_pvid'] = self.intf_info["pvid"]
- self.existing['trunk_vlans'] = self.intf_info["trunkVlans"]
- elif self.intf_info["linkType"] == "hybrid":
- self.existing['hybrid_pvid'] = self.intf_info["pvid"]
- self.existing['hybrid_untagged_vlans'] = self.intf_info["untagVlans"]
- self.existing['hybrid_tagged_vlans'] = self.intf_info["trunkVlans"]
- else:
- self.existing['dot1qtunnel_pvid'] = self.intf_info["pvid"]
-
- def get_end_state(self):
- """get end state info"""
-
- end_info = self.get_interface_dict(self.interface)
- if end_info:
- self.end_state["interface"] = end_info["ifName"]
- self.end_state["switchport"] = end_info["l2Enable"]
- self.end_state["mode"] = end_info["linkType"]
- if end_info["linkType"] == "access":
- self.end_state['access_pvid'] = end_info["pvid"]
- elif end_info["linkType"] == "trunk":
- self.end_state['trunk_pvid'] = end_info["pvid"]
- self.end_state['trunk_vlans'] = end_info["trunkVlans"]
- elif end_info["linkType"] == "hybrid":
- self.end_state['hybrid_pvid'] = end_info["pvid"]
- self.end_state['hybrid_untagged_vlans'] = end_info["untagVlans"]
- self.end_state['hybrid_tagged_vlans'] = end_info["trunkVlans"]
- else:
- self.end_state['dot1qtunnel_pvid'] = end_info["pvid"]
- if self.end_state == self.existing:
- self.changed = False
-
- def work(self):
- """worker"""
-
- self.check_params()
- if not self.intf_info:
- self.module.fail_json(msg='Error: interface does not exist.')
- self.get_existing()
- self.get_proposed()
-
- # present or absent
- if self.state == "present" or self.state == "absent":
- if self.mode == "access":
- self.merge_access_vlan(self.interface, self.default_vlan)
- elif self.mode == "trunk":
- self.merge_trunk_vlan(
- self.interface, self.pvid_vlan, self.trunk_vlans)
- elif self.mode == "hybrid":
- self.merge_hybrid_vlan(self.interface, self.pvid_vlan, self.tagged_vlans, self.untagged_vlans)
- else:
- self.merge_dot1qtunnel_vlan(self.interface, self.default_vlan)
-
- # unconfigured
- else:
- self.default_switchport(self.interface)
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- interface=dict(required=True, type='str'),
- mode=dict(choices=['access', 'trunk', 'dot1qtunnel', 'hybrid'], required=False),
- default_vlan=dict(type='str', required=False),
- pvid_vlan=dict(type='str', required=False),
- trunk_vlans=dict(type='str', required=False),
- untagged_vlans=dict(type='str', required=False),
- tagged_vlans=dict(type='str', required=False),
- state=dict(choices=['absent', 'present', 'unconfigured'],
- default='present')
- )
-
- argument_spec.update(ce_argument_spec)
- switchport = SwitchPort(argument_spec)
- switchport.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_vlan.py b/plugins/modules/network/cloudengine/ce_vlan.py
deleted file mode 100644
index 05d109456a..0000000000
--- a/plugins/modules/network/cloudengine/ce_vlan.py
+++ /dev/null
@@ -1,691 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_vlan
-short_description: Manages VLAN resources and attributes on Huawei CloudEngine switches.
-description:
- - Manages VLAN configurations on Huawei CloudEngine switches.
-author: QijunPan (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- vlan_id:
- description:
- - Single VLAN ID, in the range from 1 to 4094.
- vlan_range:
- description:
- - Range of VLANs such as C(2-10) or C(2,5,10-15), etc.
- name:
- description:
- - Name of VLAN, minimum of 1 character, maximum of 31 characters.
- description:
- description:
- - Specify VLAN description, minimum of 1 character, maximum of 80 characters.
- state:
- description:
- - Manage the state of the resource.
- default: present
- choices: ['present','absent']
-'''
-
-EXAMPLES = '''
-- name: vlan module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Ensure a range of VLANs are not present on the switch
- ce_vlan:
- vlan_range: "2-10,20,50,55-60,100-150"
- state: absent
- provider: "{{ cli }}"
-
- - name: Ensure VLAN 50 exists with the name WEB
- ce_vlan:
- vlan_id: 50
- name: WEB
- state: absent
- provider: "{{ cli }}"
-
- - name: Ensure VLAN is NOT on the device
- ce_vlan:
- vlan_id: 50
- state: absent
- provider: "{{ cli }}"
-
-'''
-
-RETURN = '''
-proposed_vlans_list:
- description: list of VLANs being proposed
- returned: always
- type: list
- sample: ["100"]
-existing_vlans_list:
- description: list of existing VLANs on the switch prior to making changes
- returned: always
- type: list
- sample: ["1", "2", "3", "4", "5", "20"]
-end_state_vlans_list:
- description: list of VLANs after the module is executed
- returned: always
- type: list
- sample: ["1", "2", "3", "4", "5", "20", "100"]
-proposed:
- description: k/v pairs of parameters passed into module (does not include
- vlan_id or vlan_range)
- returned: always
- type: dict
- sample: {"vlan_id":"20", "name": "VLAN_APP", "description": "vlan for app" }
-existing:
- description: k/v pairs of existing vlan or null when using vlan_range
- returned: always
- type: dict
- sample: {"vlan_id":"20", "name": "VLAN_APP", "description": "" }
-end_state:
- description: k/v pairs of the VLAN after executing module or null
- when using vlan_range
- returned: always
- type: dict
- sample: {"vlan_id":"20", "name": "VLAN_APP", "description": "vlan for app" }
-updates:
- description: command string sent to the device
- returned: always
- type: list
- sample: ["vlan 20", "name VLAN20"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, execute_nc_action, ce_argument_spec
-
-CE_NC_CREATE_VLAN = """
-
-
-
-
- %s
- %s
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_DELETE_VLAN = """
-
-
-
-
- %s
-
-
-
-
-"""
-
-CE_NC_MERGE_VLAN_DES = """
-
-
-
-
- %s
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_VLAN_NAME = """
-
-
-
-
- %s
- %s
-
-
-
-
-
-
-"""
-
-
-CE_NC_MERGE_VLAN = """
-
-
-
-
- %s
- %s
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_GET_VLAN = """
-
-
-
-
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_GET_VLANS = """
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_CREATE_VLAN_BATCH = """
-
-
-
- %s:%s
-
-
-
-"""
-
-CE_NC_DELETE_VLAN_BATCH = """
-
-
-
- %s:%s
-
-
-
-"""
-
-
-class Vlan(object):
- """
- Manages VLAN resources and attributes
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # vlan config info
- self.vlan_id = self.module.params['vlan_id']
- self.vlan_range = self.module.params['vlan_range']
- self.name = self.module.params['name']
- self.description = self.module.params['description']
- self.state = self.module.params['state']
-
- # state
- self.changed = False
- self.vlan_exist = False
- self.vlan_attr_exist = None
- self.vlans_list_exist = list()
- self.vlans_list_change = list()
- self.updates_cmd = list()
- self.results = dict()
- self.vlan_attr_end = dict()
-
- def init_module(self):
- """
- init ansible NetworkModule.
- """
-
- required_one_of = [["vlan_id", "vlan_range"]]
- mutually_exclusive = [["vlan_id", "vlan_range"]]
-
- self.module = AnsibleModule(
- argument_spec=self.spec,
- required_one_of=required_one_of,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def config_vlan(self, vlan_id, name='', description=''):
- """Create vlan."""
-
- if name is None:
- name = ''
- if description is None:
- description = ''
-
- conf_str = CE_NC_CREATE_VLAN % (vlan_id, name, description)
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "CREATE_VLAN")
- self.changed = True
-
- def merge_vlan(self, vlan_id, name, description):
- """Merge vlan."""
-
- conf_str = None
-
- if not name and description:
- conf_str = CE_NC_MERGE_VLAN_DES % (vlan_id, description)
- if not description and name:
- conf_str = CE_NC_MERGE_VLAN_NAME % (vlan_id, name)
- if description and name:
- conf_str = CE_NC_MERGE_VLAN % (vlan_id, name, description)
-
- if not conf_str:
- return
-
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "MERGE_VLAN")
- self.changed = True
-
- def create_vlan_batch(self, vlan_list):
- """Create vlan batch."""
-
- if not vlan_list:
- return
-
- vlan_bitmap = self.vlan_list_to_bitmap(vlan_list)
- xmlstr = CE_NC_CREATE_VLAN_BATCH % (vlan_bitmap, vlan_bitmap)
-
- recv_xml = execute_nc_action(self.module, xmlstr)
- self.check_response(recv_xml, "CREATE_VLAN_BATCH")
- self.updates_cmd.append('vlan batch %s' % (
- self.vlan_range.replace(',', ' ').replace('-', ' to ')))
- self.changed = True
-
- def delete_vlan_batch(self, vlan_list):
- """Delete vlan batch."""
-
- if not vlan_list:
- return
-
- vlan_bitmap = self.vlan_list_to_bitmap(vlan_list)
- xmlstr = CE_NC_DELETE_VLAN_BATCH % (vlan_bitmap, vlan_bitmap)
-
- recv_xml = execute_nc_action(self.module, xmlstr)
- self.check_response(recv_xml, "DELETE_VLAN_BATCH")
- self.updates_cmd.append('undo vlan batch %s' % (
- self.vlan_range.replace(',', ' ').replace('-', ' to ')))
- self.changed = True
-
- def undo_config_vlan(self, vlanid):
- """Delete vlan."""
-
- conf_str = CE_NC_DELETE_VLAN % vlanid
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "DELETE_VLAN")
- self.changed = True
- self.updates_cmd.append('undo vlan %s' % self.vlan_id)
-
- def get_vlan_attr(self, vlan_id):
- """ get vlan attributes."""
-
- conf_str = CE_NC_GET_VLAN % vlan_id
- xml_str = get_nc_config(self.module, conf_str)
- attr = dict()
-
- if "" in xml_str:
- return attr
- else:
- re_find_id = re.findall(r'.*(.*).*\s*', xml_str)
- re_find_name = re.findall(r'.*(.*).*\s*', xml_str)
- re_find_desc = re.findall(r'.*(.*).*\s*', xml_str)
-
- if re_find_id:
- if re_find_name:
- attr = dict(vlan_id=re_find_id[0], name=re_find_name[0],
- description=re_find_desc[0])
- else:
- attr = dict(vlan_id=re_find_id[0], name=None,
- description=re_find_desc[0])
- return attr
-
- def get_vlans_name(self):
- """ get all vlan vid and its name list,
- sample: [ ("20", "VLAN_NAME_20"), ("30", "VLAN_NAME_30") ]"""
-
- conf_str = CE_NC_GET_VLANS
- xml_str = get_nc_config(self.module, conf_str)
- vlan_list = list()
-
- if "" in xml_str:
- return vlan_list
- else:
- vlan_list = re.findall(
- r'.*(.*).*\s*(.*).*', xml_str)
- return vlan_list
-
- def get_vlans_list(self):
- """ get all vlan vid list, sample: [ "20", "30", "31" ]"""
-
- conf_str = CE_NC_GET_VLANS
- xml_str = get_nc_config(self.module, conf_str)
- vlan_list = list()
-
- if "" in xml_str:
- return vlan_list
- else:
- vlan_list = re.findall(
- r'.*(.*).*', xml_str)
- return vlan_list
-
- def vlan_series(self, vlanid_s):
- """ convert vlan range to list """
-
- vlan_list = []
- peerlistlen = len(vlanid_s)
- if peerlistlen != 2:
- self.module.fail_json(msg='Error: Format of vlanid is invalid.')
- for num in range(peerlistlen):
- if not vlanid_s[num].isdigit():
- self.module.fail_json(
- msg='Error: Format of vlanid is invalid.')
- if int(vlanid_s[0]) > int(vlanid_s[1]):
- self.module.fail_json(msg='Error: Format of vlanid is invalid.')
- elif int(vlanid_s[0]) == int(vlanid_s[1]):
- vlan_list.append(str(vlanid_s[0]))
- return vlan_list
- for num in range(int(vlanid_s[0]), int(vlanid_s[1])):
- vlan_list.append(str(num))
- vlan_list.append(vlanid_s[1])
-
- return vlan_list
-
- def vlan_region(self, vlanid_list):
- """ convert vlan range to vlan list """
-
- vlan_list = []
- peerlistlen = len(vlanid_list)
- for num in range(peerlistlen):
- if vlanid_list[num].isdigit():
- vlan_list.append(vlanid_list[num])
- else:
- vlan_s = self.vlan_series(vlanid_list[num].split('-'))
- vlan_list.extend(vlan_s)
-
- return vlan_list
-
- def vlan_range_to_list(self, vlan_range):
- """ convert vlan range to vlan list """
-
- vlan_list = self.vlan_region(vlan_range.split(','))
-
- return vlan_list
-
- def vlan_list_to_bitmap(self, vlanlist):
- """ convert vlan list to vlan bitmap """
-
- vlan_bit = ['0'] * 1024
- bit_int = [0] * 1024
-
- vlan_list_len = len(vlanlist)
- for num in range(vlan_list_len):
- tagged_vlans = int(vlanlist[num])
- if tagged_vlans <= 0 or tagged_vlans > 4094:
- self.module.fail_json(
- msg='Error: Vlan id is not in the range from 1 to 4094.')
- j = tagged_vlans // 4
- bit_int[j] |= 0x8 >> (tagged_vlans % 4)
- vlan_bit[j] = hex(bit_int[j])[2]
-
- vlan_xml = ''.join(vlan_bit)
-
- return vlan_xml
-
- def check_params(self):
- """Check all input params"""
-
- if not self.vlan_id and self.description:
- self.module.fail_json(
- msg='Error: Vlan description could be set only at one vlan.')
-
- if not self.vlan_id and self.name:
- self.module.fail_json(
- msg='Error: Vlan name could be set only at one vlan.')
-
- # check vlan id
- if self.vlan_id:
- if not self.vlan_id.isdigit():
- self.module.fail_json(
- msg='Error: Vlan id is not digit.')
- if int(self.vlan_id) <= 0 or int(self.vlan_id) > 4094:
- self.module.fail_json(
- msg='Error: Vlan id is not in the range from 1 to 4094.')
-
- # check vlan description
- if self.description:
- if len(self.description) > 81 or len(self.description.replace(' ', '')) < 1:
- self.module.fail_json(
- msg='Error: vlan description is not in the range from 1 to 80.')
-
- # check vlan name
- if self.name:
- if len(self.name) > 31 or len(self.name.replace(' ', '')) < 1:
- self.module.fail_json(
- msg='Error: Vlan name is not in the range from 1 to 31.')
-
- def get_proposed(self):
- """
- get proposed config.
- """
-
- if self.vlans_list_change:
- if self.state == 'present':
- proposed_vlans_tmp = list(self.vlans_list_change)
- proposed_vlans_tmp.extend(self.vlans_list_exist)
- self.results['proposed_vlans_list'] = list(
- set(proposed_vlans_tmp))
- else:
- self.results['proposed_vlans_list'] = list(
- set(self.vlans_list_exist) - set(self.vlans_list_change))
- self.results['proposed_vlans_list'].sort()
- else:
- self.results['proposed_vlans_list'] = self.vlans_list_exist
-
- if self.vlan_id:
- if self.state == "present":
- self.results['proposed'] = dict(
- vlan_id=self.vlan_id,
- name=self.name,
- description=self.description
- )
- else:
- self.results['proposed'] = None
- else:
- self.results['proposed'] = None
-
- def get_existing(self):
- """
- get existing config.
- """
-
- self.results['existing_vlans_list'] = self.vlans_list_exist
-
- if self.vlan_id:
- if self.vlan_attr_exist:
- self.results['existing'] = dict(
- vlan_id=self.vlan_attr_exist['vlan_id'],
- name=self.vlan_attr_exist['name'],
- description=self.vlan_attr_exist['description']
- )
- else:
- self.results['existing'] = None
- else:
- self.results['existing'] = None
-
- def get_end_state(self):
- """
- get end state config.
- """
-
- self.results['end_state_vlans_list'] = self.get_vlans_list()
-
- if self.vlan_id:
- if self.vlan_attr_end:
- self.results['end_state'] = dict(
- vlan_id=self.vlan_attr_end['vlan_id'],
- name=self.vlan_attr_end['name'],
- description=self.vlan_attr_end['description']
- )
- else:
- self.results['end_state'] = None
-
- else:
- self.results['end_state'] = None
-
- def work(self):
- """
- worker.
- """
-
- # check param
- self.check_params()
-
- # get all vlan info
- self.vlans_list_exist = self.get_vlans_list()
-
- # get vlan attributes
- if self.vlan_id:
- self.vlans_list_change.append(self.vlan_id)
- self.vlan_attr_exist = self.get_vlan_attr(self.vlan_id)
- if self.vlan_attr_exist:
- self.vlan_exist = True
-
- if self.vlan_range:
- new_vlans_tmp = self.vlan_range_to_list(self.vlan_range)
- if self.state == 'present':
- self.vlans_list_change = list(
- set(new_vlans_tmp) - set(self.vlans_list_exist))
- else:
- self.vlans_list_change = [
- val for val in new_vlans_tmp if val in self.vlans_list_exist]
-
- if self.state == 'present':
- if self.vlan_id:
- if not self.vlan_exist:
- # create a new vlan
- self.config_vlan(self.vlan_id, self.name, self.description)
- elif self.description and self.description != self.vlan_attr_exist['description']:
- # merge vlan description
- self.merge_vlan(self.vlan_id, self.name, self.description)
- elif self.name and self.name != self.vlan_attr_exist['name']:
- # merge vlan name
- self.merge_vlan(self.vlan_id, self.name, self.description)
-
- # update command for results
- if self.changed:
- self.updates_cmd.append('vlan %s' % self.vlan_id)
- if self.name:
- self.updates_cmd.append('name %s' % self.name)
- if self.description:
- self.updates_cmd.append(
- 'description %s' % self.description)
- elif self.vlan_range and self.vlans_list_change:
- self.create_vlan_batch(self.vlans_list_change)
- else: # absent
- if self.vlan_id:
- if self.vlan_exist:
- # delete the vlan
- self.undo_config_vlan(self.vlan_id)
- elif self.vlan_range and self.vlans_list_change:
- self.delete_vlan_batch(self.vlans_list_change)
-
- # result
- if self.vlan_id:
- self.vlan_attr_end = self.get_vlan_attr(self.vlan_id)
-
- self.get_existing()
- self.get_proposed()
- self.get_end_state()
-
- self.results['changed'] = self.changed
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ module main """
-
- argument_spec = dict(
- vlan_id=dict(required=False),
- vlan_range=dict(required=False, type='str'),
- name=dict(required=False, type='str'),
- description=dict(required=False, type='str'),
- state=dict(choices=['absent', 'present'],
- default='present', required=False),
- )
-
- argument_spec.update(ce_argument_spec)
- vlancfg = Vlan(argument_spec)
- vlancfg.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_vrf.py b/plugins/modules/network/cloudengine/ce_vrf.py
deleted file mode 100644
index 7586e03292..0000000000
--- a/plugins/modules/network/cloudengine/ce_vrf.py
+++ /dev/null
@@ -1,356 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_vrf
-short_description: Manages VPN instance on HUAWEI CloudEngine switches.
-description:
- - Manages VPN instance of HUAWEI CloudEngine switches.
-author: Yang yang (@QijunPan)
-notes:
- - If I(state=absent), the route will be removed, regardless of the non-required options.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- vrf:
- description:
- - VPN instance, the length of vrf name is 1 - 31, i.e. "test", but can not be C(_public_).
- required: true
- description:
- description:
- - Description of the vrf, the string length is 1 - 242 .
- state:
- description:
- - Manage the state of the resource.
- choices: ['present','absent']
- default: present
-'''
-
-EXAMPLES = '''
-- name: vrf module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Config a vpn install named vpna, description is test
- ce_vrf:
- vrf: vpna
- description: test
- state: present
- provider: "{{ cli }}"
- - name: Delete a vpn install named vpna
- ce_vrf:
- vrf: vpna
- state: absent
- provider: "{{ cli }}"
-'''
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"vrf": "vpna",
- "description": "test",
- "state": "present"}
-existing:
- description: k/v pairs of existing switchport
- returned: always
- type: dict
- sample: {}
-end_state:
- description: k/v pairs of switchport after module execution
- returned: always
- type: dict
- sample: {"vrf": "vpna",
- "description": "test",
- "present": "present"}
-updates:
- description: command list sent to the device
- returned: always
- type: list
- sample: ["ip vpn-instance vpna",
- "description test"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-
-CE_NC_GET_VRF = """
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_CREATE_VRF = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-CE_NC_DELETE_VRF = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-
-def build_config_xml(xmlstr):
- """build_config_xml"""
-
- return ' ' + xmlstr + ' '
-
-
-class Vrf(object):
- """Manage vpn instance"""
-
- def __init__(self, argument_spec, ):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # vpn instance info
- self.vrf = self.module.params['vrf']
- self.description = self.module.params['description']
- self.state = self.module.params['state']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def init_module(self):
- """init_module"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def set_update_cmd(self):
- """ set update command"""
- if not self.changed:
- return
- if self.state == "present":
- self.updates_cmd.append('ip vpn-instance %s' % (self.vrf))
- if self.description:
- self.updates_cmd.append('description %s' % (self.description))
- else:
- self.updates_cmd.append('undo ip vpn-instance %s' % (self.vrf))
-
- def get_vrf(self):
- """ check if vrf is need to change"""
-
- getxmlstr = CE_NC_GET_VRF
- xml_str = get_nc_config(self.module, getxmlstr)
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- vpn_instances = root.findall(
- "l3vpn/l3vpncomm/l3vpnInstances/l3vpnInstance")
- if vpn_instances:
- for vpn_instance in vpn_instances:
- if vpn_instance.find('vrfName').text == self.vrf:
- if vpn_instance.find('vrfDescription').text == self.description:
- if self.state == "present":
- return False
- else:
- return True
- else:
- return True
- return self.state == "present"
- else:
- return self.state == "present"
-
- def check_params(self):
- """Check all input params"""
-
- # vrf and description check
- if self.vrf == '_public_':
- self.module.fail_json(
- msg='Error: The vrf name _public_ is reserved.')
- if len(self.vrf) < 1 or len(self.vrf) > 31:
- self.module.fail_json(
- msg='Error: The vrf name length must between 1 and 242.')
- if self.description:
- if len(self.description) < 1 or len(self.description) > 242:
- self.module.fail_json(
- msg='Error: The vrf description length must between 1 and 242.')
-
- def operate_vrf(self):
- """config/delete vrf"""
- if not self.changed:
- return
- if self.state == "present":
- if self.description is None:
- configxmlstr = CE_NC_CREATE_VRF % (self.vrf, '')
- else:
- configxmlstr = CE_NC_CREATE_VRF % (self.vrf, self.description)
- else:
- configxmlstr = CE_NC_DELETE_VRF % (self.vrf, self.description)
-
- conf_str = build_config_xml(configxmlstr)
-
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "OPERATE_VRF")
-
- def get_proposed(self):
- """get_proposed"""
-
- if self.state == 'present':
- self.proposed['vrf'] = self.vrf
- if self.description:
- self.proposed['description'] = self.description
-
- else:
- self.proposed = dict()
- self.proposed['state'] = self.state
-
- def get_existing(self):
- """get_existing"""
-
- change = self.get_vrf()
- if change:
- if self.state == 'present':
- self.existing = dict()
- else:
- self.existing['vrf'] = self.vrf
- if self.description:
- self.existing['description'] = self.description
- self.changed = True
- else:
- if self.state == 'absent':
- self.existing = dict()
- else:
- self.existing['vrf'] = self.vrf
- if self.description:
- self.existing['description'] = self.description
- self.changed = False
-
- def get_end_state(self):
- """get_end_state"""
-
- change = self.get_vrf()
- if not change:
- if self.state == 'present':
- self.end_state['vrf'] = self.vrf
- if self.description:
- self.end_state['description'] = self.description
- else:
- self.end_state = dict()
- else:
- if self.state == 'present':
- self.end_state = dict()
- else:
- self.end_state['vrf'] = self.vrf
- if self.description:
- self.end_state['description'] = self.description
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.get_existing()
- self.get_proposed()
- self.operate_vrf()
- self.set_update_cmd()
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """main"""
-
- argument_spec = dict(
- vrf=dict(required=True, type='str'),
- description=dict(required=False, type='str'),
- state=dict(choices=['absent', 'present'],
- default='present', required=False),
- )
- argument_spec.update(ce_argument_spec)
- interface = Vrf(argument_spec)
- interface.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_vrf_af.py b/plugins/modules/network/cloudengine/ce_vrf_af.py
deleted file mode 100644
index 562ffd800a..0000000000
--- a/plugins/modules/network/cloudengine/ce_vrf_af.py
+++ /dev/null
@@ -1,851 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-DOCUMENTATION = '''
----
-module: ce_vrf_af
-short_description: Manages VPN instance address family on HUAWEI CloudEngine switches.
-description:
- - Manages VPN instance address family of HUAWEI CloudEngine switches.
-author: Yang yang (@QijunPan)
-notes:
- - If I(state=absent), the vrf will be removed, regardless of the non-required parameters.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- vrf:
- description:
- - VPN instance.
- required: true
- vrf_aftype:
- description:
- - VPN instance address family.
- choices: ['v4','v6']
- default: v4
- route_distinguisher:
- description:
- - VPN instance route distinguisher,the RD used to distinguish same route prefix from different vpn.
- The RD must be setted before setting vpn_target_value.
- vpn_target_state:
- description:
- - Manage the state of the vpn target.
- choices: ['present','absent']
- vpn_target_type:
- description:
- - VPN instance vpn target type.
- choices: ['export_extcommunity', 'import_extcommunity']
- vpn_target_value:
- description:
- - VPN instance target value. Such as X.X.X.X:number<0-65535> or number<0-65535>:number<0-4294967295>
- or number<0-65535>.number<0-65535>:number<0-65535> or number<65536-4294967295>:number<0-65535>
- but not support 0:0 and 0.0:0.
- evpn:
- description:
- - Is extend vpn or normal vpn.
- type: bool
- default: 'no'
- state:
- description:
- - Manage the state of the af.
- choices: ['present','absent']
- default: present
-'''
-
-EXAMPLES = '''
-- name: vrf af module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Config vpna, set address family is ipv4
- ce_vrf_af:
- vrf: vpna
- vrf_aftype: v4
- state: present
- provider: "{{ cli }}"
- - name: Config vpna, delete address family is ipv4
- ce_vrf_af:
- vrf: vpna
- vrf_aftype: v4
- state: absent
- provider: "{{ cli }}"
- - name: Config vpna, set address family is ipv4,rd=1:1,set vpn_target_type=export_extcommunity,vpn_target_value=2:2
- ce_vrf_af:
- vrf: vpna
- vrf_aftype: v4
- route_distinguisher: 1:1
- vpn_target_type: export_extcommunity
- vpn_target_value: 2:2
- vpn_target_state: present
- state: present
- provider: "{{ cli }}"
- - name: Config vpna, set address family is ipv4,rd=1:1,delete vpn_target_type=export_extcommunity,vpn_target_value=2:2
- ce_vrf_af:
- vrf: vpna
- vrf_aftype: v4
- route_distinguisher: 1:1
- vpn_target_type: export_extcommunity
- vpn_target_value: 2:2
- vpn_target_state: absent
- state: present
- provider: "{{ cli }}"
-'''
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {"vrf": "vpna",
- "vrf_aftype": "v4",
- "state": "present",
- "vpn_targe_state":"absent",
- "evpn": "none",
- "vpn_target_type": "none",
- "vpn_target_value": "none"}
-existing:
- description: k/v pairs of existing switchport
- returned: always
- type: dict
- sample: {
- "route_distinguisher": [
- "1:1",
- "2:2"
- ],
- "vpn_target_type": [],
- "vpn_target_value": [],
- "vrf": "vpna",
- "vrf_aftype": [
- "ipv4uni",
- "ipv6uni"
- ]
- }
-end_state:
- description: k/v pairs of switchport after module execution
- returned: always
- type: dict
- sample: {
- "route_distinguisher": [
- "1:1",
- "2:2"
- ],
- "vpn_target_type": [
- "import_extcommunity",
- "3:3"
- ],
- "vpn_target_value": [],
- "vrf": "vpna",
- "vrf_aftype": [
- "ipv4uni",
- "ipv6uni"
- ]
- }
-updates:
- description: command list sent to the device
- returned: always
- type: list
- sample: [
- "ip vpn-instance vpna",
- "vpn-target 3:3 import_extcommunity"
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-
-import re
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-CE_NC_GET_VRF = """
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_GET_VRF_AF = """
-
-
-
-
-
- %s
-
-
-
- %s
-
-
-
-
-
-
-
-"""
-
-CE_NC_DELETE_VRF_AF = """
-
-
-
-
- %s
-
-
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_CREATE_VRF_AF = """
-
-
-
-
- %s
-
-
- %s
- %s%s
-
-
-
-
-
-"""
-CE_NC_CREATE_VRF_TARGET = """
-
-
- %s
- %s
-
-
-"""
-
-CE_NC_DELETE_VRF_TARGET = """
-
-
- %s
- %s
-
-
-"""
-
-CE_NC_GET_VRF_TARGET = """
-
-
-
-
-
-
-"""
-
-CE_NC_CREATE_EXTEND_VRF_TARGET = """
-
-
- %s
- %s
- evpn
-
-
-"""
-
-CE_NC_DELETE_EXTEND_VRF_TARGET = """
-
-
- %s
- %s
- evpn
-
-
-"""
-
-CE_NC_GET_EXTEND_VRF_TARGET = """
-
-
-
-
-
-
-
-"""
-
-
-def build_config_xml(xmlstr):
- """build_config_xml"""
-
- return ' ' + xmlstr + ' '
-
-
-def is_valid_value(vrf_targe_value):
- """check if the vrf target value is valid"""
-
- each_num = None
- if len(vrf_targe_value) > 21 or len(vrf_targe_value) < 3:
- return False
- if vrf_targe_value.find(':') == -1:
- return False
- elif vrf_targe_value == '0:0':
- return False
- elif vrf_targe_value == '0.0:0':
- return False
- else:
- value_list = vrf_targe_value.split(':')
- if value_list[0].find('.') != -1:
- if not value_list[1].isdigit():
- return False
- if int(value_list[1]) > 65535:
- return False
- value = value_list[0].split('.')
- if len(value) == 4:
- for each_num in value:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- return True
- elif len(value) == 2:
- for each_num in value:
- if not each_num.isdigit():
- return False
- if int(each_num) > 65535:
- return False
- return True
- else:
- return False
- elif not value_list[0].isdigit():
- return False
- elif not value_list[1].isdigit():
- return False
- elif int(value_list[0]) < 65536 and int(value_list[1]) < 4294967296:
- return True
- elif int(value_list[0]) > 65535 and int(value_list[0]) < 4294967296:
- return bool(int(value_list[1]) < 65536)
- else:
- return False
-
-
-class VrfAf(object):
- """manage the vrf address family and export/import target"""
-
- def __init__(self, argument_spec, ):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # vpn instance info
- self.vrf = self.module.params['vrf']
- self.vrf_aftype = self.module.params['vrf_aftype']
- if self.vrf_aftype == 'v4':
- self.vrf_aftype = 'ipv4uni'
- else:
- self.vrf_aftype = 'ipv6uni'
- self.route_distinguisher = self.module.params['route_distinguisher']
- self.evpn = self.module.params['evpn']
- self.vpn_target_type = self.module.params['vpn_target_type']
- self.vpn_target_value = self.module.params['vpn_target_value']
- self.vpn_target_state = self.module.params['vpn_target_state']
- self.state = self.module.params['state']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- self.vpn_target_changed = False
- self.vrf_af_type_changed = False
- self.vrf_rd_changed = False
- self.vrf_af_info = dict()
-
- def init_module(self):
- """init_module"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def is_vrf_af_exist(self):
- """is vrf address family exist"""
-
- if not self.vrf_af_info:
- return False
-
- for vrf_af_ele in self.vrf_af_info["vpnInstAF"]:
- if vrf_af_ele["afType"] == self.vrf_aftype:
- return True
- else:
- continue
- return False
-
- def get_exist_rd(self):
- """get exist route distinguisher """
-
- if not self.vrf_af_info:
- return None
-
- for vrf_af_ele in self.vrf_af_info["vpnInstAF"]:
- if vrf_af_ele["afType"] == self.vrf_aftype:
- if vrf_af_ele["vrfRD"] is None:
- return None
- else:
- return vrf_af_ele["vrfRD"]
- else:
- continue
- return None
-
- def is_vrf_rd_exist(self):
- """is vrf route distinguisher exist"""
-
- if not self.vrf_af_info:
- return False
-
- for vrf_af_ele in self.vrf_af_info["vpnInstAF"]:
- if vrf_af_ele["afType"] == self.vrf_aftype:
- if vrf_af_ele["vrfRD"] is None:
- return False
- if self.route_distinguisher is not None:
- return bool(vrf_af_ele["vrfRD"] == self.route_distinguisher)
- else:
- return True
- else:
- continue
- return False
-
- def is_vrf_rt_exist(self):
- """is vpn target exist"""
-
- if not self.vrf_af_info:
- return False
-
- for vrf_af_ele in self.vrf_af_info["vpnInstAF"]:
- if vrf_af_ele["afType"] == self.vrf_aftype:
- if self.evpn is False:
- if not vrf_af_ele.get("vpnTargets"):
- return False
- for vpn_target in vrf_af_ele.get("vpnTargets"):
- if vpn_target["vrfRTType"] == self.vpn_target_type \
- and vpn_target["vrfRTValue"] == self.vpn_target_value:
- return True
- else:
- continue
- else:
- if not vrf_af_ele.get("evpnTargets"):
- return False
- for evpn_target in vrf_af_ele.get("evpnTargets"):
- if evpn_target["vrfRTType"] == self.vpn_target_type \
- and evpn_target["vrfRTValue"] == self.vpn_target_value:
- return True
- else:
- continue
- else:
- continue
- return False
-
- def set_update_cmd(self):
- """ set update command"""
- if not self.changed:
- return
- if self.vpn_target_type:
- if self.vpn_target_type == "export_extcommunity":
- vpn_target_type = "export-extcommunity"
- else:
- vpn_target_type = "import-extcommunity"
- if self.state == "present":
- self.updates_cmd.append('ip vpn-instance %s' % (self.vrf))
- if self.vrf_aftype == 'ipv4uni':
- self.updates_cmd.append('ipv4-family')
- elif self.vrf_aftype == 'ipv6uni':
- self.updates_cmd.append('ipv6-family')
- if self.route_distinguisher:
- if not self.is_vrf_rd_exist():
- self.updates_cmd.append(
- 'route-distinguisher %s' % self.route_distinguisher)
- else:
- if self.get_exist_rd() is not None:
- self.updates_cmd.append(
- 'undo route-distinguisher %s' % self.get_exist_rd())
- if self.vpn_target_state == "present":
- if not self.is_vrf_rt_exist():
- if self.evpn is False:
- self.updates_cmd.append(
- 'vpn-target %s %s' % (self.vpn_target_value, vpn_target_type))
- else:
- self.updates_cmd.append(
- 'vpn-target %s %s evpn' % (self.vpn_target_value, vpn_target_type))
- elif self.vpn_target_state == "absent":
- if self.is_vrf_rt_exist():
- if self.evpn is False:
- self.updates_cmd.append(
- 'undo vpn-target %s %s' % (self.vpn_target_value, vpn_target_type))
- else:
- self.updates_cmd.append(
- 'undo vpn-target %s %s evpn' % (self.vpn_target_value, vpn_target_type))
- else:
- self.updates_cmd.append('ip vpn-instance %s' % (self.vrf))
- if self.vrf_aftype == 'ipv4uni':
- self.updates_cmd.append('undo ipv4-family')
- elif self.vrf_aftype == 'ipv6uni':
- self.updates_cmd.append('undo ipv6-family')
-
- def get_vrf(self):
- """ check if vrf is need to change"""
-
- getxmlstr = CE_NC_GET_VRF
- xmlstr_new_1 = (self.vrf.lower())
-
- xml_str = get_nc_config(self.module, getxmlstr)
- re_find_1 = re.findall(
- r'.*(.*).*', xml_str.lower())
-
- if re_find_1 is None:
- return False
-
- return xmlstr_new_1 in re_find_1
-
- def get_vrf_af(self):
- """ check if vrf is need to change"""
-
- self.vrf_af_info["vpnInstAF"] = list()
- if self.evpn is True:
- getxmlstr = CE_NC_GET_VRF_AF % (
- self.vrf, CE_NC_GET_EXTEND_VRF_TARGET)
- else:
- getxmlstr = CE_NC_GET_VRF_AF % (self.vrf, CE_NC_GET_VRF_TARGET)
-
- xml_str = get_nc_config(self.module, getxmlstr)
-
- if 'data/' in xml_str:
- return self.state == 'present'
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
-
- # get the vpn address family and RD text
- vrf_addr_types = root.findall(
- "l3vpn/l3vpncomm/l3vpnInstances/l3vpnInstance/vpnInstAFs/vpnInstAF")
- if vrf_addr_types:
- for vrf_addr_type in vrf_addr_types:
- vrf_af_info = dict()
- for vrf_addr_type_ele in vrf_addr_type:
- if vrf_addr_type_ele.tag in ["vrfName", "afType", "vrfRD"]:
- vrf_af_info[vrf_addr_type_ele.tag] = vrf_addr_type_ele.text
- if vrf_addr_type_ele.tag == 'vpnTargets':
- vrf_af_info["vpnTargets"] = list()
- for rtargets in vrf_addr_type_ele:
- rt_dict = dict()
- for rtarget in rtargets:
- if rtarget.tag in ["vrfRTValue", "vrfRTType"]:
- rt_dict[rtarget.tag] = rtarget.text
- vrf_af_info["vpnTargets"].append(rt_dict)
- if vrf_addr_type_ele.tag == 'exVpnTargets':
- vrf_af_info["evpnTargets"] = list()
- for rtargets in vrf_addr_type_ele:
- rt_dict = dict()
- for rtarget in rtargets:
- if rtarget.tag in ["vrfRTValue", "vrfRTType"]:
- rt_dict[rtarget.tag] = rtarget.text
- vrf_af_info["evpnTargets"].append(rt_dict)
- self.vrf_af_info["vpnInstAF"].append(vrf_af_info)
-
- def check_params(self):
- """Check all input params"""
-
- # vrf and description check
- if self.vrf == '_public_':
- self.module.fail_json(
- msg='Error: The vrf name _public_ is reserved.')
- if not self.get_vrf():
- self.module.fail_json(
- msg='Error: The vrf name do not exist.')
- if self.state == 'present':
- if self.route_distinguisher:
- if not is_valid_value(self.route_distinguisher):
- self.module.fail_json(msg='Error:The vrf route distinguisher length must between 3 ~ 21,'
- 'i.e. X.X.X.X:number<0-65535> or number<0-65535>:number<0-4294967295>'
- 'or number<0-65535>.number<0-65535>:number<0-65535>'
- 'or number<65536-4294967295>:number<0-65535>'
- ' but not be 0:0 or 0.0:0.')
- if not self.vpn_target_state:
- if self.vpn_target_value or self.vpn_target_type:
- self.module.fail_json(
- msg='Error: The vpn target state should be exist.')
- if self.vpn_target_state:
- if not self.vpn_target_value or not self.vpn_target_type:
- self.module.fail_json(
- msg='Error: The vpn target value and type should be exist.')
- if self.vpn_target_value:
- if not is_valid_value(self.vpn_target_value):
- self.module.fail_json(msg='Error:The vrf target value length must between 3 ~ 21,'
- 'i.e. X.X.X.X:number<0-65535> or number<0-65535>:number<0-4294967295>'
- 'or number<0-65535>.number<0-65535>:number<0-65535>'
- 'or number<65536-4294967295>:number<0-65535>'
- ' but not be 0:0 or 0.0:0.')
-
- def operate_vrf_af(self):
- """config/delete vrf"""
-
- vrf_target_operate = ''
- if self.route_distinguisher is None:
- route_d = ''
- else:
- route_d = self.route_distinguisher
-
- if self.state == 'present':
- if self.vrf_aftype:
- if self.is_vrf_af_exist():
- self.vrf_af_type_changed = False
- else:
- self.vrf_af_type_changed = True
- configxmlstr = CE_NC_CREATE_VRF_AF % (
- self.vrf, self.vrf_aftype, route_d, vrf_target_operate)
- else:
- self.vrf_af_type_changed = bool(self.is_vrf_af_exist())
-
- if self.vpn_target_state == 'present':
- if self.evpn is False and not self.is_vrf_rt_exist():
- vrf_target_operate = CE_NC_CREATE_VRF_TARGET % (
- self.vpn_target_type, self.vpn_target_value)
- configxmlstr = CE_NC_CREATE_VRF_AF % (
- self.vrf, self.vrf_aftype, route_d, vrf_target_operate)
- self.vpn_target_changed = True
- if self.evpn is True and not self.is_vrf_rt_exist():
- vrf_target_operate = CE_NC_CREATE_EXTEND_VRF_TARGET % (
- self.vpn_target_type, self.vpn_target_value)
- configxmlstr = CE_NC_CREATE_VRF_AF % (
- self.vrf, self.vrf_aftype, route_d, vrf_target_operate)
- self.vpn_target_changed = True
- elif self.vpn_target_state == 'absent':
- if self.evpn is False and self.is_vrf_rt_exist():
- vrf_target_operate = CE_NC_DELETE_VRF_TARGET % (
- self.vpn_target_type, self.vpn_target_value)
- configxmlstr = CE_NC_CREATE_VRF_AF % (
- self.vrf, self.vrf_aftype, route_d, vrf_target_operate)
- self.vpn_target_changed = True
- if self.evpn is True and self.is_vrf_rt_exist():
- vrf_target_operate = CE_NC_DELETE_EXTEND_VRF_TARGET % (
- self.vpn_target_type, self.vpn_target_value)
- configxmlstr = CE_NC_CREATE_VRF_AF % (
- self.vrf, self.vrf_aftype, route_d, vrf_target_operate)
- self.vpn_target_changed = True
- else:
- if self.route_distinguisher:
- if not self.is_vrf_rd_exist():
- configxmlstr = CE_NC_CREATE_VRF_AF % (
- self.vrf, self.vrf_aftype, route_d, vrf_target_operate)
- self.vrf_rd_changed = True
- else:
- self.vrf_rd_changed = False
- else:
- if self.is_vrf_rd_exist():
- configxmlstr = CE_NC_CREATE_VRF_AF % (
- self.vrf, self.vrf_aftype, route_d, vrf_target_operate)
- self.vrf_rd_changed = True
- else:
- self.vrf_rd_changed = False
- if not self.vrf_rd_changed and not self.vrf_af_type_changed and not self.vpn_target_changed:
- self.changed = False
- else:
- self.changed = True
- else:
- if self.is_vrf_af_exist():
- configxmlstr = CE_NC_DELETE_VRF_AF % (
- self.vrf, self.vrf_aftype)
- self.changed = True
- else:
- self.changed = False
-
- if not self.changed:
- return
-
- conf_str = build_config_xml(configxmlstr)
-
- recv_xml = set_nc_config(self.module, conf_str)
- self.check_response(recv_xml, "OPERATE_VRF_AF")
-
- def get_proposed(self):
- """get_proposed"""
-
- if self.state == 'present':
- self.proposed['vrf'] = self.vrf
- if self.vrf_aftype is None:
- self.proposed['vrf_aftype'] = 'ipv4uni'
- else:
- self.proposed['vrf_aftype'] = self.vrf_aftype
- if self.route_distinguisher is not None:
- self.proposed['route_distinguisher'] = self.route_distinguisher
- else:
- self.proposed['route_distinguisher'] = list()
- if self.vpn_target_state == 'present':
- self.proposed['evpn'] = self.evpn
- self.proposed['vpn_target_type'] = self.vpn_target_type
- self.proposed['vpn_target_value'] = self.vpn_target_value
- else:
- self.proposed['vpn_target_type'] = list()
- self.proposed['vpn_target_value'] = list()
- else:
- self.proposed = dict()
- self.proposed['state'] = self.state
- self.proposed['vrf'] = self.vrf
- self.proposed['vrf_aftype'] = list()
- self.proposed['route_distinguisher'] = list()
- self.proposed['vpn_target_value'] = list()
- self.proposed['vpn_target_type'] = list()
-
- def get_existing(self):
- """get_existing"""
-
- self.get_vrf_af()
- self.existing['vrf'] = self.vrf
- self.existing['vrf_aftype'] = list()
- self.existing['route_distinguisher'] = list()
- self.existing['vpn_target_value'] = list()
- self.existing['vpn_target_type'] = list()
- self.existing['evpn_target_value'] = list()
- self.existing['evpn_target_type'] = list()
- if self.vrf_af_info["vpnInstAF"] is None:
- return
- for vrf_af_ele in self.vrf_af_info["vpnInstAF"]:
- self.existing['vrf_aftype'].append(vrf_af_ele["afType"])
- self.existing['route_distinguisher'].append(
- vrf_af_ele["vrfRD"])
- if vrf_af_ele.get("vpnTargets"):
- for vpn_target in vrf_af_ele.get("vpnTargets"):
- self.existing['vpn_target_type'].append(
- vpn_target["vrfRTType"])
- self.existing['vpn_target_value'].append(
- vpn_target["vrfRTValue"])
- if vrf_af_ele.get("evpnTargets"):
- for evpn_target in vrf_af_ele.get("evpnTargets"):
- self.existing['evpn_target_type'].append(
- evpn_target["vrfRTType"])
- self.existing['evpn_target_value'].append(
- evpn_target["vrfRTValue"])
-
- def get_end_state(self):
- """get_end_state"""
-
- self.get_vrf_af()
- self.end_state['vrf'] = self.vrf
- self.end_state['vrf_aftype'] = list()
- self.end_state['route_distinguisher'] = list()
- self.end_state['vpn_target_value'] = list()
- self.end_state['vpn_target_type'] = list()
- self.end_state['evpn_target_value'] = list()
- self.end_state['evpn_target_type'] = list()
- if self.vrf_af_info["vpnInstAF"] is None:
- return
- for vrf_af_ele in self.vrf_af_info["vpnInstAF"]:
- self.end_state['vrf_aftype'].append(vrf_af_ele["afType"])
- self.end_state['route_distinguisher'].append(vrf_af_ele["vrfRD"])
- if vrf_af_ele.get("vpnTargets"):
- for vpn_target in vrf_af_ele.get("vpnTargets"):
- self.end_state['vpn_target_type'].append(
- vpn_target["vrfRTType"])
- self.end_state['vpn_target_value'].append(
- vpn_target["vrfRTValue"])
- if vrf_af_ele.get("evpnTargets"):
- for evpn_target in vrf_af_ele.get("evpnTargets"):
- self.end_state['evpn_target_type'].append(
- evpn_target["vrfRTType"])
- self.end_state['evpn_target_value'].append(
- evpn_target["vrfRTValue"])
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.get_existing()
- self.get_proposed()
- self.operate_vrf_af()
- self.set_update_cmd()
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """main"""
-
- argument_spec = dict(
- vrf=dict(required=True, type='str'),
- vrf_aftype=dict(choices=['v4', 'v6'],
- default='v4', required=False),
- route_distinguisher=dict(required=False, type='str'),
- evpn=dict(type='bool', default=False),
- vpn_target_type=dict(
- choices=['export_extcommunity', 'import_extcommunity'], required=False),
- vpn_target_value=dict(required=False, type='str'),
- vpn_target_state=dict(choices=['absent', 'present'], required=False),
- state=dict(choices=['absent', 'present'],
- default='present', required=False),
- )
- argument_spec.update(ce_argument_spec)
- interface = VrfAf(argument_spec)
- interface.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_vrf_interface.py b/plugins/modules/network/cloudengine/ce_vrf_interface.py
deleted file mode 100644
index 0eff09eee5..0000000000
--- a/plugins/modules/network/cloudengine/ce_vrf_interface.py
+++ /dev/null
@@ -1,521 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_vrf_interface
-short_description: Manages interface specific VPN configuration on HUAWEI CloudEngine switches.
-description:
- - Manages interface specific VPN configuration of HUAWEI CloudEngine switches.
-author: Zhijin Zhou (@QijunPan)
-notes:
- - Ensure that a VPN instance has been created and the IPv4 address family has been enabled for the VPN instance.
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- vrf:
- description:
- - VPN instance, the length of vrf name is 1 ~ 31, i.e. "test", but can not be C(_public_).
- required: true
- vpn_interface:
- description:
- - An interface that can binding VPN instance, i.e. 40GE1/0/22, Vlanif10.
- Must be fully qualified interface name.
- Interface types, such as 10GE, 40GE, 100GE, LoopBack, MEth, Tunnel, Vlanif....
- required: true
- state:
- description:
- - Manage the state of the resource.
- required: false
- choices: ['present','absent']
- default: present
-'''
-
-EXAMPLES = '''
-- name: VRF interface test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: "Configure a VPN instance for the interface"
- ce_vrf_interface:
- vpn_interface: 40GE1/0/2
- vrf: test
- state: present
- provider: "{{ cli }}"
-
- - name: "Disable the association between a VPN instance and an interface"
- ce_vrf_interface:
- vpn_interface: 40GE1/0/2
- vrf: test
- state: absent
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: verbose mode
- type: dict
- sample: {
- "state": "present",
- "vpn_interface": "40GE2/0/17",
- "vrf": "jss"
- }
-existing:
- description: k/v pairs of existing attributes on the interface
- returned: verbose mode
- type: dict
- sample: {
- "vpn_interface": "40GE2/0/17",
- "vrf": null
- }
-end_state:
- description: k/v pairs of end attributes on the interface
- returned: verbose mode
- type: dict
- sample: {
- "vpn_interface": "40GE2/0/17",
- "vrf": "jss"
- }
-updates:
- description: command list sent to the device
- returned: always
- type: list
- sample: [
- "ip binding vpn-instance jss",
- ]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec, get_nc_config, set_nc_config
-
-CE_NC_GET_VRF = """
-
-
-
-
-
- %s
-
-
-
-
-
-"""
-
-CE_NC_GET_VRF_INTERFACE = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_VRF_INTERFACE = """
-
-
-
-
-
- %s
-
-
- %s
-
-
-
-
-
-
-
-"""
-
-CE_NC_GET_INTF = """
-
-
-
-
- %s
-
-
-
-
-
-"""
-
-CE_NC_DEL_INTF_VPN = """
-
-
-
-
-
- %s
-
-
- %s
-
-
-
-
-
-
-
-"""
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- iftype = None
-
- if interface.upper().startswith('GE'):
- iftype = 'ge'
- elif interface.upper().startswith('10GE'):
- iftype = '10ge'
- elif interface.upper().startswith('25GE'):
- iftype = '25ge'
- elif interface.upper().startswith('4X10GE'):
- iftype = '4x10ge'
- elif interface.upper().startswith('40GE'):
- iftype = '40ge'
- elif interface.upper().startswith('100GE'):
- iftype = '100ge'
- elif interface.upper().startswith('VLANIF'):
- iftype = 'vlanif'
- elif interface.upper().startswith('LOOPBACK'):
- iftype = 'loopback'
- elif interface.upper().startswith('METH'):
- iftype = 'meth'
- elif interface.upper().startswith('ETH-TRUNK'):
- iftype = 'eth-trunk'
- elif interface.upper().startswith('VBDIF'):
- iftype = 'vbdif'
- elif interface.upper().startswith('NVE'):
- iftype = 'nve'
- elif interface.upper().startswith('TUNNEL'):
- iftype = 'tunnel'
- elif interface.upper().startswith('ETHERNET'):
- iftype = 'ethernet'
- elif interface.upper().startswith('FCOE-PORT'):
- iftype = 'fcoe-port'
- elif interface.upper().startswith('FABRIC-PORT'):
- iftype = 'fabric-port'
- elif interface.upper().startswith('STACK-PORT'):
- iftype = 'stack-Port'
- elif interface.upper().startswith('NULL'):
- iftype = 'null'
- else:
- return None
-
- return iftype.lower()
-
-
-class VrfInterface(object):
- """Manage vpn instance"""
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # vpn instance info
- self.vrf = self.module.params['vrf']
- self.vpn_interface = self.module.params['vpn_interface']
- self.vpn_interface = self.vpn_interface.upper().replace(' ', '')
- self.state = self.module.params['state']
- self.intf_info = dict()
- self.intf_info['isL2SwitchPort'] = None
- self.intf_info['vrfName'] = None
- self.conf_exist = False
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def init_module(self):
- """init_module"""
-
- required_one_of = [("vrf", "vpn_interface")]
- self.module = AnsibleModule(
- argument_spec=self.spec, required_one_of=required_one_of, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_update_cmd(self):
- """ get updated command"""
-
- if self.conf_exist:
- return
-
- if self.state == 'absent':
- self.updates_cmd.append(
- "undo ip binding vpn-instance %s" % self.vrf)
- return
-
- if self.vrf != self.intf_info['vrfName']:
- self.updates_cmd.append("ip binding vpn-instance %s" % self.vrf)
-
- return
-
- def check_params(self):
- """Check all input params"""
-
- if not self.is_vrf_exist():
- self.module.fail_json(
- msg='Error: The VPN instance is not existed.')
-
- if self.state == 'absent':
- if self.vrf != self.intf_info['vrfName']:
- self.module.fail_json(
- msg='Error: The VPN instance is not bound to the interface.')
-
- if self.intf_info['isL2SwitchPort'] == 'true':
- self.module.fail_json(
- msg='Error: L2Switch Port can not binding a VPN instance.')
-
- # interface type check
- if self.vpn_interface:
- intf_type = get_interface_type(self.vpn_interface)
- if not intf_type:
- self.module.fail_json(
- msg='Error: interface name of %s'
- ' is error.' % self.vpn_interface)
-
- # vrf check
- if self.vrf == '_public_':
- self.module.fail_json(
- msg='Error: The vrf name _public_ is reserved.')
- if len(self.vrf) < 1 or len(self.vrf) > 31:
- self.module.fail_json(
- msg='Error: The vrf name length must be between 1 and 31.')
-
- def get_interface_vpn_name(self, vpninfo, vpn_name):
- """ get vpn instance name"""
-
- l3vpn_if = vpninfo.findall("l3vpnIf")
- for l3vpn_ifinfo in l3vpn_if:
- for ele in l3vpn_ifinfo:
- if ele.tag in ['ifName']:
- if ele.text.lower() == self.vpn_interface.lower():
- self.intf_info['vrfName'] = vpn_name
-
- def get_interface_vpn(self):
- """ get the VPN instance associated with the interface"""
-
- xml_str = CE_NC_GET_VRF_INTERFACE
- con_obj = get_nc_config(self.module, xml_str)
- if "" in con_obj:
- return
-
- xml_str = con_obj.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get global vrf interface info
- root = ElementTree.fromstring(xml_str)
- vpns = root.findall(
- "l3vpn/l3vpncomm/l3vpnInstances/l3vpnInstance")
- if vpns:
- for vpnele in vpns:
- vpn_name = None
- for vpninfo in vpnele:
- if vpninfo.tag == 'vrfName':
- vpn_name = vpninfo.text
- if vpninfo.tag == 'l3vpnIfs':
- self.get_interface_vpn_name(vpninfo, vpn_name)
-
- return
-
- def is_vrf_exist(self):
- """ judge whether the VPN instance is existed"""
-
- conf_str = CE_NC_GET_VRF % self.vrf
- con_obj = get_nc_config(self.module, conf_str)
- if "" in con_obj:
- return False
-
- return True
-
- def get_intf_conf_info(self):
- """ get related configuration of the interface"""
-
- conf_str = CE_NC_GET_INTF % self.vpn_interface
- con_obj = get_nc_config(self.module, conf_str)
- if "" in con_obj:
- return
-
- # get interface base info
- xml_str = con_obj.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- interface = root.find("ifm/interfaces/interface")
- if interface:
- for eles in interface:
- if eles.tag in ["isL2SwitchPort"]:
- self.intf_info[eles.tag] = eles.text
-
- self.get_interface_vpn()
- return
-
- def get_existing(self):
- """get existing config"""
-
- self.existing = dict(vrf=self.intf_info['vrfName'],
- vpn_interface=self.vpn_interface)
-
- def get_proposed(self):
- """get_proposed"""
-
- self.proposed = dict(vrf=self.vrf,
- vpn_interface=self.vpn_interface,
- state=self.state)
-
- def get_end_state(self):
- """get_end_state"""
-
- self.intf_info['vrfName'] = None
- self.get_intf_conf_info()
-
- self.end_state = dict(vrf=self.intf_info['vrfName'],
- vpn_interface=self.vpn_interface)
-
- def show_result(self):
- """ show result"""
-
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
- def judge_if_config_exist(self):
- """ judge whether configuration has existed"""
-
- if self.state == 'absent':
- return False
-
- delta = set(self.proposed.items()).difference(
- self.existing.items())
- delta = dict(delta)
- if len(delta) == 1 and delta['state']:
- return True
-
- return False
-
- def config_interface_vrf(self):
- """ configure VPN instance of the interface"""
-
- if not self.conf_exist and self.state == 'present':
-
- xml_str = CE_NC_MERGE_VRF_INTERFACE % (
- self.vrf, self.vpn_interface)
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "VRF_INTERFACE_CONFIG")
- self.changed = True
- elif self.state == 'absent':
- xml_str = CE_NC_DEL_INTF_VPN % (self.vrf, self.vpn_interface)
- ret_xml = set_nc_config(self.module, xml_str)
- self.check_response(ret_xml, "DEL_VRF_INTERFACE_CONFIG")
- self.changed = True
-
- def work(self):
- """execute task"""
-
- self.get_intf_conf_info()
- self.check_params()
- self.get_existing()
- self.get_proposed()
- self.conf_exist = self.judge_if_config_exist()
-
- self.config_interface_vrf()
-
- self.get_update_cmd()
- self.get_end_state()
- self.show_result()
-
-
-def main():
- """main"""
-
- argument_spec = dict(
- vrf=dict(required=True, type='str'),
- vpn_interface=dict(required=True, type='str'),
- state=dict(choices=['absent', 'present'],
- default='present', required=False),
- )
- argument_spec.update(ce_argument_spec)
- vrf_intf = VrfInterface(argument_spec)
- vrf_intf.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_vrrp.py b/plugins/modules/network/cloudengine/ce_vrrp.py
deleted file mode 100644
index 6e3e5e1c26..0000000000
--- a/plugins/modules/network/cloudengine/ce_vrrp.py
+++ /dev/null
@@ -1,1331 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_vrrp
-short_description: Manages VRRP interfaces on HUAWEI CloudEngine devices.
-description:
- - Manages VRRP interface attributes on HUAWEI CloudEngine devices.
-author:
- - Li Yanfeng (@numone213)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- interface:
- description:
- - Name of an interface. The value is a string of 1 to 63 characters.
- vrid:
- description:
- - VRRP backup group ID.
- The value is an integer ranging from 1 to 255.
- default: present
- virtual_ip :
- description:
- - Virtual IP address. The value is a string of 0 to 255 characters.
- vrrp_type:
- description:
- - Type of a VRRP backup group.
- type: str
- choices: ['normal', 'member', 'admin']
- admin_ignore_if_down:
- description:
- - mVRRP ignores an interface Down event.
- type: bool
- default: 'false'
- admin_vrid:
- description:
- - Tracked mVRRP ID. The value is an integer ranging from 1 to 255.
- admin_interface:
- description:
- - Tracked mVRRP interface name. The value is a string of 1 to 63 characters.
- admin_flowdown:
- description:
- - Disable the flowdown function for service VRRP.
- type: bool
- default: 'false'
- priority:
- description:
- - Configured VRRP priority.
- The value ranges from 1 to 254. The default value is 100. A larger value indicates a higher priority.
- version:
- description:
- - VRRP version. The default version is v2.
- type: str
- choices: ['v2','v3']
- advertise_interval:
- description:
- - Configured interval between sending advertisements, in milliseconds.
- Only the master router sends VRRP advertisements. The default value is 1000 milliseconds.
- preempt_timer_delay:
- description:
- - Preemption delay.
- The value is an integer ranging from 0 to 3600. The default value is 0.
- gratuitous_arp_interval:
- description:
- - Interval at which gratuitous ARP packets are sent, in seconds.
- The value ranges from 30 to 1200.The default value is 300.
- recover_delay:
- description:
- - Delay in recovering after an interface goes Up.
- The delay is used for interface flapping suppression.
- The value is an integer ranging from 0 to 3600.
- The default value is 0 seconds.
- holding_multiplier:
- description:
- - The configured holdMultiplier.The value is an integer ranging from 3 to 10. The default value is 3.
- auth_mode:
- description:
- - Authentication type used for VRRP packet exchanges between virtual routers.
- The values are noAuthentication, simpleTextPassword, md5Authentication.
- The default value is noAuthentication.
- type: str
- choices: ['simple','md5','none']
- is_plain:
- description:
- - Select the display mode of an authentication key.
- By default, an authentication key is displayed in ciphertext.
- type: bool
- default: 'false'
- auth_key:
- description:
- - This object is set based on the authentication type.
- When noAuthentication is specified, the value is empty.
- When simpleTextPassword or md5Authentication is specified, the value is a string of 1 to 8 characters
- in plaintext and displayed as a blank text for security.
- fast_resume:
- description:
- - mVRRP's fast resume mode.
- type: str
- choices: ['enable','disable']
- state:
- description:
- - Specify desired state of the resource.
- type: str
- default: present
- choices: ['present','absent']
-'''
-
-EXAMPLES = '''
-- name: vrrp module test
- hosts: cloudengine
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
- tasks:
- - name: Set vrrp version
- ce_vrrp:
- version: v3
- provider: "{{ cli }}"
- - name: Set vrrp gratuitous-arp interval
- ce_vrrp:
- gratuitous_arp_interval: 40
- mlag_id: 4
- provider: "{{ cli }}"
- - name: Set vrrp recover-delay
- ce_vrrp:
- recover_delay: 10
- provider: "{{ cli }}"
- - name: Set vrrp vrid virtual-ip
- ce_vrrp:
- interface: 40GE2/0/8
- vrid: 1
- virtual_ip: 10.14.2.7
- provider: "{{ cli }}"
- - name: Set vrrp vrid admin
- ce_vrrp:
- interface: 40GE2/0/8
- vrid: 1
- vrrp_type: admin
- provider: "{{ cli }}"
- - name: Set vrrp vrid fast_resume
- ce_vrrp:
- interface: 40GE2/0/8
- vrid: 1
- fast_resume: enable
- provider: "{{ cli }}"
- - name: Set vrrp vrid holding-multiplier
- ce_vrrp:
- interface: 40GE2/0/8
- vrid: 1
- holding_multiplier: 4
- provider: "{{ cli }}"
- - name: Set vrrp vrid preempt timer delay
- ce_vrrp:
- interface: 40GE2/0/8
- vrid: 1
- preempt_timer_delay: 10
- provider: "{{ cli }}"
- - name: Set vrrp vrid admin-vrrp
- ce_vrrp:
- interface: 40GE2/0/8
- vrid: 1
- admin_interface: 40GE2/0/9
- admin_vrid: 2
- vrrp_type: member
- provider: "{{ cli }}"
- - name: Set vrrp vrid authentication-mode
- ce_vrrp:
- interface: 40GE2/0/8
- vrid: 1
- is_plain: true
- auth_mode: simple
- auth_key: aaa
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {
- "auth_key": "aaa",
- "auth_mode": "simple",
- "interface": "40GE2/0/8",
- "is_plain": true,
- "state": "present",
- "vrid": "1"
- }
-existing:
- description: k/v pairs of existing aaa server
- returned: always
- type: dict
- sample: {
- "auth_mode": "none",
- "interface": "40GE2/0/8",
- "is_plain": "false",
- "vrid": "1",
- "vrrp_type": "normal"
- }
-end_state:
- description: k/v pairs of aaa params after module execution
- returned: always
- type: dict
- sample: {
- "auth_mode": "simple",
- "interface": "40GE2/0/8",
- "is_plain": "true",
- "vrid": "1",
- "vrrp_type": "normal"
- }
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: { "interface 40GE2/0/8",
- "vrrp vrid 1 authentication-mode simple plain aaa"}
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-
-CE_NC_GET_VRRP_GROUP_INFO = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-CE_NC_SET_VRRP_GROUP_INFO_HEAD = """
-
-
-
-
- %s
- %s
-"""
-CE_NC_SET_VRRP_GROUP_INFO_TAIL = """
-
-
-
-
-"""
-CE_NC_GET_VRRP_GLOBAL_INFO = """
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_SET_VRRP_GLOBAL_HEAD = """
-
-
-
-"""
-CE_NC_SET_VRRP_GLOBAL_TAIL = """
-
-
-
-"""
-
-CE_NC_GET_VRRP_VIRTUAL_IP_INFO = """
-
-
-
-
- %s
- %s
-
-
-
-
-
-
-
-
-
-"""
-CE_NC_CREATE_VRRP_VIRTUAL_IP_INFO = """
-
-
-
-
- %s
- %s
-
-
- %s
-
-
-
-
-
-
-"""
-CE_NC_DELETE_VRRP_VIRTUAL_IP_INFO = """
-
-
-
-
- %s
- %s
-
-
- %s
-
-
-
-
-
-
-"""
-
-
-def is_valid_address(address):
- """check ip-address is valid"""
-
- if address.find('.') != -1:
- addr_list = address.split('.')
- if len(addr_list) != 4:
- return False
- for each_num in addr_list:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- return True
-
- return False
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- iftype = None
-
- if interface.upper().startswith('GE'):
- iftype = 'ge'
- elif interface.upper().startswith('10GE'):
- iftype = '10ge'
- elif interface.upper().startswith('25GE'):
- iftype = '25ge'
- elif interface.upper().startswith('40GE'):
- iftype = '40ge'
- elif interface.upper().startswith('100GE'):
- iftype = '100ge'
- elif interface.upper().startswith('ETH-TRUNK'):
- iftype = 'eth-trunk'
- elif interface.upper().startswith('NULL'):
- iftype = 'null'
- elif interface.upper().startswith('VLANIF'):
- iftype = 'vlanif'
- else:
- return None
-
- return iftype.lower()
-
-
-class Vrrp(object):
- """
- Manages Manages vrrp information.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.interface = self.module.params['interface']
- self.vrid = self.module.params['vrid']
- self.virtual_ip = self.module.params['virtual_ip']
- self.vrrp_type = self.module.params['vrrp_type']
- self.admin_ignore_if_down = 'false' if self.module.params['admin_ignore_if_down'] is False else 'true'
- self.admin_vrid = self.module.params['admin_vrid']
- self.admin_interface = self.module.params['admin_interface']
- self.admin_flowdown = 'false' if self.module.params['admin_flowdown'] is False else 'true'
- self.priority = self.module.params['priority']
- self.version = self.module.params['version']
- self.advertise_interval = self.module.params['advertise_interval']
- self.preempt_timer_delay = self.module.params['preempt_timer_delay']
- self.gratuitous_arp_interval = self.module.params[
- 'gratuitous_arp_interval']
- self.recover_delay = self.module.params['recover_delay']
- self.holding_multiplier = self.module.params['holding_multiplier']
- self.auth_mode = self.module.params['auth_mode']
- self.is_plain = 'false' if self.module.params['is_plain'] is False else 'true'
- self.auth_key = self.module.params['auth_key']
- self.fast_resume = self.module.params['fast_resume']
- self.state = self.module.params['state']
-
- # vrrp info
- self.vrrp_global_info = None
- self.virtual_ip_info = None
- self.vrrp_group_info = None
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.existing = dict()
- self.proposed = dict()
- self.end_state = dict()
-
- def init_module(self):
- """ init module """
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def get_virtual_ip_info(self):
- """ get vrrp virtual ip info."""
- virtual_ip_info = dict()
- conf_str = CE_NC_GET_VRRP_VIRTUAL_IP_INFO % (self.vrid, self.interface)
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return virtual_ip_info
- else:
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- virtual_ip_info["vrrpVirtualIpInfos"] = list()
- root = ElementTree.fromstring(xml_str)
- vrrp_virtual_ip_infos = root.findall(
- "vrrp/vrrpGroups/vrrpGroup/virtualIps/virtualIp")
- if vrrp_virtual_ip_infos:
- for vrrp_virtual_ip_info in vrrp_virtual_ip_infos:
- virtual_ip_dict = dict()
- for ele in vrrp_virtual_ip_info:
- if ele.tag in ["virtualIpAddress"]:
- virtual_ip_dict[ele.tag] = ele.text
- virtual_ip_info["vrrpVirtualIpInfos"].append(
- virtual_ip_dict)
- return virtual_ip_info
-
- def get_vrrp_global_info(self):
- """ get vrrp global info."""
-
- vrrp_global_info = dict()
- conf_str = CE_NC_GET_VRRP_GLOBAL_INFO
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return vrrp_global_info
- else:
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- global_info = root.findall(
- "vrrp/vrrpGlobalCfg")
-
- if global_info:
- for tmp in global_info:
- for site in tmp:
- if site.tag in ["gratuitousArpTimeOut", "gratuitousArpFlag", "recoverDelay", "version"]:
- vrrp_global_info[site.tag] = site.text
- return vrrp_global_info
-
- def get_vrrp_group_info(self):
- """ get vrrp group info."""
-
- vrrp_group_info = dict()
- conf_str = CE_NC_GET_VRRP_GROUP_INFO % (self.interface, self.vrid)
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return vrrp_group_info
- else:
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- root = ElementTree.fromstring(xml_str)
- global_info = root.findall(
- "vrrp/vrrpGroups/vrrpGroup")
-
- if global_info:
- for tmp in global_info:
- for site in tmp:
- if site.tag in ["ifName", "vrrpId", "priority", "advertiseInterval", "preemptMode", "delayTime",
- "authenticationMode", "authenticationKey", "vrrpType", "adminVrrpId",
- "adminIfName", "adminIgnoreIfDown", "isPlain", "unflowdown", "fastResume",
- "holdMultiplier"]:
- vrrp_group_info[site.tag] = site.text
- return vrrp_group_info
-
- def check_params(self):
- """Check all input params"""
-
- # interface check
- if self.interface:
- intf_type = get_interface_type(self.interface)
- if not intf_type:
- self.module.fail_json(
- msg='Error: Interface name of %s '
- 'is error.' % self.interface)
-
- # vrid check
- if self.vrid:
- if not self.vrid.isdigit():
- self.module.fail_json(
- msg='Error: The value of vrid is an integer.')
- if int(self.vrid) < 1 or int(self.vrid) > 255:
- self.module.fail_json(
- msg='Error: The value of vrid ranges from 1 to 255.')
-
- # virtual_ip check
- if self.virtual_ip:
- if not is_valid_address(self.virtual_ip):
- self.module.fail_json(
- msg='Error: The %s is not a valid ip address.' % self.virtual_ip)
-
- # admin_vrid check
- if self.admin_vrid:
- if not self.admin_vrid.isdigit():
- self.module.fail_json(
- msg='Error: The value of admin_vrid is an integer.')
- if int(self.admin_vrid) < 1 or int(self.admin_vrid) > 255:
- self.module.fail_json(
- msg='Error: The value of admin_vrid ranges from 1 to 255.')
-
- # admin_interface check
- if self.admin_interface:
- intf_type = get_interface_type(self.admin_interface)
- if not intf_type:
- self.module.fail_json(
- msg='Error: Admin interface name of %s '
- 'is error.' % self.admin_interface)
-
- # priority check
- if self.priority:
- if not self.priority.isdigit():
- self.module.fail_json(
- msg='Error: The value of priority is an integer.')
- if int(self.priority) < 1 or int(self.priority) > 254:
- self.module.fail_json(
- msg='Error: The value of priority ranges from 1 to 254. The default value is 100.')
-
- # advertise_interval check
- if self.advertise_interval:
- if not self.advertise_interval.isdigit():
- self.module.fail_json(
- msg='Error: The value of advertise_interval is an integer.')
- if int(self.advertise_interval) < 1000 or int(self.advertise_interval) > 255000:
- self.module.fail_json(
- msg='Error: The value of advertise_interval ranges from 1000 to 255000 milliseconds. The default value is 1000 milliseconds.')
- if int(self.advertise_interval) % 1000 != 0:
- self.module.fail_json(
- msg='Error: The advertisement interval value of VRRP must be a multiple of 1000 milliseconds.')
- # preempt_timer_delay check
- if self.preempt_timer_delay:
- if not self.preempt_timer_delay.isdigit():
- self.module.fail_json(
- msg='Error: The value of preempt_timer_delay is an integer.')
- if int(self.preempt_timer_delay) < 1 or int(self.preempt_timer_delay) > 3600:
- self.module.fail_json(
- msg='Error: The value of preempt_timer_delay ranges from 1 to 3600. The default value is 0.')
-
- # holding_multiplier check
- if self.holding_multiplier:
- if not self.holding_multiplier.isdigit():
- self.module.fail_json(
- msg='Error: The value of holding_multiplier is an integer.')
- if int(self.holding_multiplier) < 3 or int(self.holding_multiplier) > 10:
- self.module.fail_json(
- msg='Error: The value of holding_multiplier ranges from 3 to 10. The default value is 3.')
-
- # auth_key check
- if self.auth_key:
- if len(self.auth_key) > 16 \
- or len(self.auth_key.replace(' ', '')) < 1:
- self.module.fail_json(
- msg='Error: The length of auth_key is not in the range from 1 to 16.')
-
- def is_virtual_ip_change(self):
- """whether virtual ip change"""
-
- if not self.virtual_ip_info:
- return True
-
- for info in self.virtual_ip_info["vrrpVirtualIpInfos"]:
- if info["virtualIpAddress"] == self.virtual_ip:
- return False
- return True
-
- def is_virtual_ip_exist(self):
- """whether virtual ip info exist"""
-
- if not self.virtual_ip_info:
- return False
-
- for info in self.virtual_ip_info["vrrpVirtualIpInfos"]:
- if info["virtualIpAddress"] == self.virtual_ip:
- return True
- return False
-
- def is_vrrp_global_info_change(self):
- """whether vrrp global attribute info change"""
-
- if not self.vrrp_global_info:
- return True
-
- if self.gratuitous_arp_interval:
- if self.vrrp_global_info["gratuitousArpFlag"] == "false":
- self.module.fail_json(msg="Error: gratuitousArpFlag is false.")
- if self.vrrp_global_info["gratuitousArpTimeOut"] != self.gratuitous_arp_interval:
- return True
- if self.recover_delay:
- if self.vrrp_global_info["recoverDelay"] != self.recover_delay:
- return True
- if self.version:
- if self.vrrp_global_info["version"] != self.version:
- return True
- return False
-
- def is_vrrp_global_info_exist(self):
- """whether vrrp global attribute info exist"""
-
- if self.gratuitous_arp_interval or self.recover_delay or self.version:
- if self.gratuitous_arp_interval:
- if self.vrrp_global_info["gratuitousArpFlag"] == "false":
- self.module.fail_json(
- msg="Error: gratuitousArpFlag is false.")
- if self.vrrp_global_info["gratuitousArpTimeOut"] != self.gratuitous_arp_interval:
- return False
- if self.recover_delay:
- if self.vrrp_global_info["recoverDelay"] != self.recover_delay:
- return False
- if self.version:
- if self.vrrp_global_info["version"] != self.version:
- return False
- return True
-
- return False
-
- def is_vrrp_group_info_change(self):
- """whether vrrp group attribute info change"""
- if self.vrrp_type:
- if self.vrrp_group_info["vrrpType"] != self.vrrp_type:
- return True
- if self.admin_ignore_if_down:
- if self.vrrp_group_info["adminIgnoreIfDown"] != self.admin_ignore_if_down:
- return True
- if self.admin_vrid:
- if self.vrrp_group_info["adminVrrpId"] != self.admin_vrid:
- return True
- if self.admin_interface:
- if self.vrrp_group_info["adminIfName"] != self.admin_interface:
- return True
- if self.admin_flowdown:
- if self.vrrp_group_info["unflowdown"] != self.admin_flowdown:
- return True
- if self.priority:
- if self.vrrp_group_info["priority"] != self.priority:
- return True
- if self.fast_resume:
- fast_resume = "false"
- if self.fast_resume == "enable":
- fast_resume = "true"
- if self.vrrp_group_info["fastResume"] != fast_resume:
- return True
- if self.advertise_interval:
- if self.vrrp_group_info["advertiseInterval"] != self.advertise_interval:
- return True
- if self.preempt_timer_delay:
- if self.vrrp_group_info["delayTime"] != self.preempt_timer_delay:
- return True
- if self.holding_multiplier:
- if self.vrrp_group_info["holdMultiplier"] != self.holding_multiplier:
- return True
- if self.auth_mode:
- if self.vrrp_group_info["authenticationMode"] != self.auth_mode:
- return True
- if self.auth_key:
- return True
- if self.is_plain:
- if self.vrrp_group_info["isPlain"] != self.is_plain:
- return True
-
- return False
-
- def is_vrrp_group_info_exist(self):
- """whether vrrp group attribute info exist"""
-
- if self.vrrp_type:
- if self.vrrp_group_info["vrrpType"] != self.vrrp_type:
- return False
- if self.admin_ignore_if_down:
- if self.vrrp_group_info["adminIgnoreIfDown"] != self.admin_ignore_if_down:
- return False
- if self.admin_vrid:
- if self.vrrp_group_info["adminVrrpId"] != self.admin_vrid:
- return False
- if self.admin_interface:
- if self.vrrp_group_info["adminIfName"] != self.admin_interface:
- return False
- if self.admin_flowdown:
- if self.vrrp_group_info["unflowdown"] != self.admin_flowdown:
- return False
- if self.priority:
- if self.vrrp_group_info["priority"] != self.priority:
- return False
- if self.fast_resume:
- fast_resume = "false"
- if self.fast_resume == "enable":
- fast_resume = "true"
- if self.vrrp_group_info["fastResume"] != fast_resume:
- return False
- if self.advertise_interval:
- if self.vrrp_group_info["advertiseInterval"] != self.advertise_interval:
- return False
- if self.preempt_timer_delay:
- if self.vrrp_group_info["delayTime"] != self.preempt_timer_delay:
- return False
- if self.holding_multiplier:
- if self.vrrp_group_info["holdMultiplier"] != self.holding_multiplier:
- return False
- if self.auth_mode:
- if self.vrrp_group_info["authenticationMode"] != self.auth_mode:
- return False
- if self.is_plain:
- if self.vrrp_group_info["isPlain"] != self.is_plain:
- return False
- return True
-
- def create_virtual_ip(self):
- """create virtual ip info"""
-
- if self.is_virtual_ip_change():
- conf_str = CE_NC_CREATE_VRRP_VIRTUAL_IP_INFO % (
- self.vrid, self.interface, self.virtual_ip)
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: create virtual ip info failed.')
-
- self.updates_cmd.append("interface %s" % self.interface)
- self.updates_cmd.append(
- "vrrp vrid %s virtual-ip %s" % (self.vrid, self.virtual_ip))
- self.changed = True
-
- def delete_virtual_ip(self):
- """delete virtual ip info"""
-
- if self.is_virtual_ip_exist():
- conf_str = CE_NC_DELETE_VRRP_VIRTUAL_IP_INFO % (
- self.vrid, self.interface, self.virtual_ip)
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: delete virtual ip info failed.')
-
- self.updates_cmd.append("interface %s" % self.interface)
- self.updates_cmd.append(
- "undo vrrp vrid %s virtual-ip %s " % (self.vrid, self.virtual_ip))
- self.changed = True
-
- def set_vrrp_global(self):
- """set vrrp global attribute info"""
-
- if self.is_vrrp_global_info_change():
- conf_str = CE_NC_SET_VRRP_GLOBAL_HEAD
- if self.gratuitous_arp_interval:
- conf_str += "%s" % self.gratuitous_arp_interval
- if self.recover_delay:
- conf_str += "%s" % self.recover_delay
- if self.version:
- conf_str += "%s" % self.version
- conf_str += CE_NC_SET_VRRP_GLOBAL_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: set vrrp global attribute info failed.')
-
- if self.gratuitous_arp_interval:
- self.updates_cmd.append(
- "vrrp gratuitous-arp interval %s" % self.gratuitous_arp_interval)
-
- if self.recover_delay:
- self.updates_cmd.append(
- "vrrp recover-delay %s" % self.recover_delay)
-
- if self.version:
- version = "3"
- if self.version == "v2":
- version = "2"
- self.updates_cmd.append("vrrp version %s" % version)
- self.changed = True
-
- def delete_vrrp_global(self):
- """delete vrrp global attribute info"""
-
- if self.is_vrrp_global_info_exist():
- conf_str = CE_NC_SET_VRRP_GLOBAL_HEAD
- if self.gratuitous_arp_interval:
- if self.gratuitous_arp_interval == "120":
- self.module.fail_json(
- msg='Error: The default value of gratuitous_arp_interval is 120.')
- gratuitous_arp_interval = "120"
- conf_str += "%s" % gratuitous_arp_interval
- if self.recover_delay:
- if self.recover_delay == "0":
- self.module.fail_json(
- msg='Error: The default value of recover_delay is 0.')
- recover_delay = "0"
- conf_str += "%s" % recover_delay
- if self.version:
- if self.version == "v2":
- self.module.fail_json(
- msg='Error: The default value of version is v2.')
- version = "v2"
- conf_str += "%s" % version
- conf_str += CE_NC_SET_VRRP_GLOBAL_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: set vrrp global attribute info failed.')
- if self.gratuitous_arp_interval:
- self.updates_cmd.append("undo vrrp gratuitous-arp interval")
-
- if self.recover_delay:
- self.updates_cmd.append("undo vrrp recover-delay")
-
- if self.version == "v3":
- self.updates_cmd.append("undo vrrp version")
- self.changed = True
-
- def set_vrrp_group(self):
- """set vrrp group attribute info"""
-
- if self.is_vrrp_group_info_change():
- conf_str = CE_NC_SET_VRRP_GROUP_INFO_HEAD % (
- self.interface, self.vrid)
- if self.vrrp_type:
- conf_str += "%s" % self.vrrp_type
- if self.admin_vrid:
- conf_str += "%s" % self.admin_vrid
- if self.admin_interface:
- conf_str += "%s" % self.admin_interface
- if self.admin_flowdown:
- conf_str += "%s" % self.admin_flowdown
- if self.priority:
- conf_str += "%s" % self.priority
- if self.vrrp_type == "admin":
- if self.admin_ignore_if_down:
- conf_str += "%s" % self.admin_ignore_if_down
- if self.fast_resume:
- fast_resume = "false"
- if self.fast_resume == "enable":
- fast_resume = "true"
- conf_str += "%s" % fast_resume
- if self.advertise_interval:
- conf_str += "%s" % self.advertise_interval
- if self.preempt_timer_delay:
- conf_str += "%s" % self.preempt_timer_delay
- if self.holding_multiplier:
- conf_str += "%s" % self.holding_multiplier
- if self.auth_mode:
- conf_str += "%s" % self.auth_mode
- if self.auth_key:
- conf_str += "%s" % self.auth_key
- if self.auth_mode == "simple":
- conf_str += "%s" % self.is_plain
-
- conf_str += CE_NC_SET_VRRP_GROUP_INFO_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: set vrrp group attribute info failed.')
- if self.interface and self.vrid:
- self.updates_cmd.append("interface %s" % self.interface)
- if self.vrrp_type == "admin":
- if self.admin_ignore_if_down == "true":
- self.updates_cmd.append(
- "vrrp vrid %s admin ignore-if-down" % self.vrid)
- else:
- self.updates_cmd.append(
- "vrrp vrid %s admin" % self.vrid)
-
- if self.priority:
- self.updates_cmd.append(
- "vrrp vrid %s priority %s" % (self.vrid, self.priority))
-
- if self.fast_resume == "enable":
- self.updates_cmd.append(
- "vrrp vrid %s fast-resume" % self.vrid)
- if self.fast_resume == "disable":
- self.updates_cmd.append(
- "undo vrrp vrid %s fast-resume" % self.vrid)
-
- if self.advertise_interval:
- advertise_interval = int(self.advertise_interval) / 1000
- self.updates_cmd.append("vrrp vrid %s timer advertise %s" % (
- self.vrid, int(advertise_interval)))
-
- if self.preempt_timer_delay:
- self.updates_cmd.append("vrrp vrid %s preempt timer delay %s" % (self.vrid,
- self.preempt_timer_delay))
-
- if self.holding_multiplier:
- self.updates_cmd.append(
- "vrrp vrid %s holding-multiplier %s" % (self.vrid, self.holding_multiplier))
-
- if self.admin_vrid and self.admin_interface:
- if self.admin_flowdown == "true":
- self.updates_cmd.append("vrrp vrid %s track admin-vrrp interface %s vrid %s unflowdown" %
- (self.vrid, self.admin_interface, self.admin_vrid))
- else:
- self.updates_cmd.append("vrrp vrid %s track admin-vrrp interface %s vrid %s" %
- (self.vrid, self.admin_interface, self.admin_vrid))
-
- if self.auth_mode and self.auth_key:
- if self.auth_mode == "simple":
- if self.is_plain == "true":
- self.updates_cmd.append("vrrp vrid %s authentication-mode simple plain %s" %
- (self.vrid, self.auth_key))
- else:
- self.updates_cmd.append("vrrp vrid %s authentication-mode simple cipher %s" %
- (self.vrid, self.auth_key))
- if self.auth_mode == "md5":
- self.updates_cmd.append(
- "vrrp vrid %s authentication-mode md5 %s" % (self.vrid, self.auth_key))
- self.changed = True
-
- def delete_vrrp_group(self):
- """delete vrrp group attribute info"""
-
- if self.is_vrrp_group_info_exist():
- conf_str = CE_NC_SET_VRRP_GROUP_INFO_HEAD % (
- self.interface, self.vrid)
- if self.vrrp_type:
- vrrp_type = self.vrrp_type
- if self.vrrp_type == "admin":
- vrrp_type = "normal"
- if self.vrrp_type == "member" and self.admin_vrid and self.admin_interface:
- vrrp_type = "normal"
- conf_str += "%s" % vrrp_type
- if self.priority:
- if self.priority == "100":
- self.module.fail_json(
- msg='Error: The default value of priority is 100.')
- priority = "100"
- conf_str += "%s" % priority
-
- if self.fast_resume:
- fast_resume = "false"
- if self.fast_resume == "enable":
- fast_resume = "true"
- conf_str += "%s" % fast_resume
- if self.advertise_interval:
- if self.advertise_interval == "1000":
- self.module.fail_json(
- msg='Error: The default value of advertise_interval is 1000.')
- advertise_interval = "1000"
- conf_str += "%s" % advertise_interval
- if self.preempt_timer_delay:
- if self.preempt_timer_delay == "0":
- self.module.fail_json(
- msg='Error: The default value of preempt_timer_delay is 0.')
- preempt_timer_delay = "0"
- conf_str += "%s" % preempt_timer_delay
- if self.holding_multiplier:
- if self.holding_multiplier == "0":
- self.module.fail_json(
- msg='Error: The default value of holding_multiplier is 3.')
- holding_multiplier = "3"
- conf_str += "%s" % holding_multiplier
- if self.auth_mode:
- auth_mode = self.auth_mode
- if self.auth_mode == "md5" or self.auth_mode == "simple":
- auth_mode = "none"
- conf_str += "%s" % auth_mode
-
- conf_str += CE_NC_SET_VRRP_GROUP_INFO_TAIL
- recv_xml = set_nc_config(self.module, conf_str)
- if "" not in recv_xml:
- self.module.fail_json(
- msg='Error: set vrrp global attribute info failed.')
- if self.interface and self.vrid:
- self.updates_cmd.append("interface %s" % self.interface)
- if self.vrrp_type == "admin":
- self.updates_cmd.append(
- "undo vrrp vrid %s admin" % self.vrid)
-
- if self.priority:
- self.updates_cmd.append(
- "undo vrrp vrid %s priority" % self.vrid)
-
- if self.fast_resume:
- self.updates_cmd.append(
- "undo vrrp vrid %s fast-resume" % self.vrid)
-
- if self.advertise_interval:
- self.updates_cmd.append(
- "undo vrrp vrid %s timer advertise" % self.vrid)
-
- if self.preempt_timer_delay:
- self.updates_cmd.append(
- "undo vrrp vrid %s preempt timer delay" % self.vrid)
-
- if self.holding_multiplier:
- self.updates_cmd.append(
- "undo vrrp vrid %s holding-multiplier" % self.vrid)
-
- if self.admin_vrid and self.admin_interface:
- self.updates_cmd.append(
- "undo vrrp vrid %s track admin-vrrp" % self.vrid)
-
- if self.auth_mode:
- self.updates_cmd.append(
- "undo vrrp vrid %s authentication-mode" % self.vrid)
- self.changed = True
-
- def get_proposed(self):
- """get proposed info"""
-
- if self.interface:
- self.proposed["interface"] = self.interface
- if self.vrid:
- self.proposed["vrid"] = self.vrid
- if self.virtual_ip:
- self.proposed["virtual_ip"] = self.virtual_ip
- if self.vrrp_type:
- self.proposed["vrrp_type"] = self.vrrp_type
- if self.admin_vrid:
- self.proposed["admin_vrid"] = self.admin_vrid
- if self.admin_interface:
- self.proposed["admin_interface"] = self.admin_interface
- if self.admin_flowdown:
- self.proposed["unflowdown"] = self.admin_flowdown
- if self.admin_ignore_if_down:
- self.proposed["admin_ignore_if_down"] = self.admin_ignore_if_down
- if self.priority:
- self.proposed["priority"] = self.priority
- if self.version:
- self.proposed["version"] = self.version
- if self.advertise_interval:
- self.proposed["advertise_interval"] = self.advertise_interval
- if self.preempt_timer_delay:
- self.proposed["preempt_timer_delay"] = self.preempt_timer_delay
- if self.gratuitous_arp_interval:
- self.proposed[
- "gratuitous_arp_interval"] = self.gratuitous_arp_interval
- if self.recover_delay:
- self.proposed["recover_delay"] = self.recover_delay
- if self.holding_multiplier:
- self.proposed["holding_multiplier"] = self.holding_multiplier
- if self.auth_mode:
- self.proposed["auth_mode"] = self.auth_mode
- if self.is_plain:
- self.proposed["is_plain"] = self.is_plain
- if self.auth_key:
- self.proposed["auth_key"] = self.auth_key
- if self.fast_resume:
- self.proposed["fast_resume"] = self.fast_resume
- if self.state:
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- if self.gratuitous_arp_interval:
- self.existing["gratuitous_arp_interval"] = self.vrrp_global_info[
- "gratuitousArpTimeOut"]
- if self.version:
- self.existing["version"] = self.vrrp_global_info["version"]
- if self.recover_delay:
- self.existing["recover_delay"] = self.vrrp_global_info[
- "recoverDelay"]
-
- if self.virtual_ip:
- if self.virtual_ip_info:
- self.existing["interface"] = self.interface
- self.existing["vrid"] = self.vrid
- self.existing["virtual_ip_info"] = self.virtual_ip_info[
- "vrrpVirtualIpInfos"]
-
- if self.vrrp_group_info:
- self.existing["interface"] = self.vrrp_group_info["ifName"]
- self.existing["vrid"] = self.vrrp_group_info["vrrpId"]
- self.existing["vrrp_type"] = self.vrrp_group_info["vrrpType"]
- if self.vrrp_type == "admin":
- self.existing["admin_ignore_if_down"] = self.vrrp_group_info[
- "adminIgnoreIfDown"]
- if self.admin_vrid and self.admin_interface:
- self.existing["admin_vrid"] = self.vrrp_group_info[
- "adminVrrpId"]
- self.existing["admin_interface"] = self.vrrp_group_info[
- "adminIfName"]
- self.existing["admin_flowdown"] = self.vrrp_group_info[
- "unflowdown"]
- if self.priority:
- self.existing["priority"] = self.vrrp_group_info["priority"]
- if self.advertise_interval:
- self.existing["advertise_interval"] = self.vrrp_group_info[
- "advertiseInterval"]
- if self.preempt_timer_delay:
- self.existing["preempt_timer_delay"] = self.vrrp_group_info[
- "delayTime"]
- if self.holding_multiplier:
- self.existing["holding_multiplier"] = self.vrrp_group_info[
- "holdMultiplier"]
- if self.fast_resume:
- fast_resume_exist = "disable"
- fast_resume = self.vrrp_group_info["fastResume"]
- if fast_resume == "true":
- fast_resume_exist = "enable"
- self.existing["fast_resume"] = fast_resume_exist
- if self.auth_mode:
- self.existing["auth_mode"] = self.vrrp_group_info[
- "authenticationMode"]
- self.existing["is_plain"] = self.vrrp_group_info["isPlain"]
-
- def get_end_state(self):
- """get end state info"""
-
- if self.gratuitous_arp_interval or self.version or self.recover_delay:
- self.vrrp_global_info = self.get_vrrp_global_info()
- if self.interface and self.vrid:
- if self.virtual_ip:
- self.virtual_ip_info = self.get_virtual_ip_info()
- if self.virtual_ip_info:
- self.vrrp_group_info = self.get_vrrp_group_info()
-
- if self.gratuitous_arp_interval:
- self.end_state["gratuitous_arp_interval"] = self.vrrp_global_info[
- "gratuitousArpTimeOut"]
- if self.version:
- self.end_state["version"] = self.vrrp_global_info["version"]
- if self.recover_delay:
- self.end_state["recover_delay"] = self.vrrp_global_info[
- "recoverDelay"]
-
- if self.virtual_ip:
- if self.virtual_ip_info:
- self.end_state["interface"] = self.interface
- self.end_state["vrid"] = self.vrid
- self.end_state["virtual_ip_info"] = self.virtual_ip_info[
- "vrrpVirtualIpInfos"]
-
- if self.vrrp_group_info:
- self.end_state["interface"] = self.vrrp_group_info["ifName"]
- self.end_state["vrid"] = self.vrrp_group_info["vrrpId"]
- self.end_state["vrrp_type"] = self.vrrp_group_info["vrrpType"]
- if self.vrrp_type == "admin":
- self.end_state["admin_ignore_if_down"] = self.vrrp_group_info[
- "adminIgnoreIfDown"]
- if self.admin_vrid and self.admin_interface:
- self.end_state["admin_vrid"] = self.vrrp_group_info[
- "adminVrrpId"]
- self.end_state["admin_interface"] = self.vrrp_group_info[
- "adminIfName"]
- self.end_state["admin_flowdown"] = self.vrrp_group_info[
- "unflowdown"]
- if self.priority:
- self.end_state["priority"] = self.vrrp_group_info["priority"]
- if self.advertise_interval:
- self.end_state["advertise_interval"] = self.vrrp_group_info[
- "advertiseInterval"]
- if self.preempt_timer_delay:
- self.end_state["preempt_timer_delay"] = self.vrrp_group_info[
- "delayTime"]
- if self.holding_multiplier:
- self.end_state["holding_multiplier"] = self.vrrp_group_info[
- "holdMultiplier"]
- if self.fast_resume:
- fast_resume_end = "disable"
- fast_resume = self.vrrp_group_info["fastResume"]
- if fast_resume == "true":
- fast_resume_end = "enable"
- self.end_state["fast_resume"] = fast_resume_end
- if self.auth_mode:
- self.end_state["auth_mode"] = self.vrrp_group_info[
- "authenticationMode"]
- self.end_state["is_plain"] = self.vrrp_group_info["isPlain"]
- if self.existing == self.end_state:
- self.changed = False
-
- def work(self):
- """worker"""
-
- self.check_params()
- if self.gratuitous_arp_interval or self.version or self.recover_delay:
- self.vrrp_global_info = self.get_vrrp_global_info()
- if self.interface and self.vrid:
- self.virtual_ip_info = self.get_virtual_ip_info()
- if self.virtual_ip_info:
- self.vrrp_group_info = self.get_vrrp_group_info()
- self.get_proposed()
- self.get_existing()
-
- if self.gratuitous_arp_interval or self.version or self.recover_delay:
- if self.state == "present":
- self.set_vrrp_global()
- else:
- self.delete_vrrp_global()
- else:
- if not self.interface or not self.vrid:
- self.module.fail_json(
- msg='Error: interface, vrid must be config at the same time.')
-
- if self.interface and self.vrid:
- if self.virtual_ip:
- if self.state == "present":
- self.create_virtual_ip()
- else:
- self.delete_virtual_ip()
- else:
- if not self.vrrp_group_info:
- self.module.fail_json(
- msg='Error: The VRRP group does not exist.')
- if self.admin_ignore_if_down == "true":
- if self.vrrp_type != "admin":
- self.module.fail_json(
- msg='Error: vrrpType must be admin when admin_ignore_if_down is true.')
- if self.admin_interface or self.admin_vrid:
- if self.vrrp_type != "member":
- self.module.fail_json(
- msg='Error: it binds a VRRP group to an mVRRP group, vrrp_type must be "member".')
- if not self.vrrp_type or not self.interface or not self.vrid:
- self.module.fail_json(
- msg='Error: admin_interface admin_vrid vrrp_type interface vrid must '
- 'be config at the same time.')
- if self.auth_mode == "md5" and self.is_plain == "true":
- self.module.fail_json(
- msg='Error: is_plain can not be True when auth_mode is md5.')
-
- if self.state == "present":
- self.set_vrrp_group()
- else:
- self.delete_vrrp_group()
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """ Module main """
-
- argument_spec = dict(
- interface=dict(type='str'),
- vrid=dict(type='str'),
- virtual_ip=dict(type='str'),
- vrrp_type=dict(type='str', choices=['normal', 'member', 'admin']),
- admin_ignore_if_down=dict(type='bool', default=False),
- admin_vrid=dict(type='str'),
- admin_interface=dict(type='str'),
- admin_flowdown=dict(type='bool', default=False),
- priority=dict(type='str'),
- version=dict(type='str', choices=['v2', 'v3']),
- advertise_interval=dict(type='str'),
- preempt_timer_delay=dict(type='str'),
- gratuitous_arp_interval=dict(type='str'),
- recover_delay=dict(type='str'),
- holding_multiplier=dict(type='str'),
- auth_mode=dict(type='str', choices=['simple', 'md5', 'none']),
- is_plain=dict(type='bool', default=False),
- auth_key=dict(type='str'),
- fast_resume=dict(type='str', choices=['enable', 'disable']),
- state=dict(type='str', default='present',
- choices=['present', 'absent'])
- )
-
- argument_spec.update(ce_argument_spec)
- module = Vrrp(argument_spec=argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_vxlan_arp.py b/plugins/modules/network/cloudengine/ce_vxlan_arp.py
deleted file mode 100644
index 7198877371..0000000000
--- a/plugins/modules/network/cloudengine/ce_vxlan_arp.py
+++ /dev/null
@@ -1,692 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_vxlan_arp
-short_description: Manages ARP attributes of VXLAN on HUAWEI CloudEngine devices.
-description:
- - Manages ARP attributes of VXLAN on HUAWEI CloudEngine devices.
-author: QijunPan (@QijunPan)
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- evn_bgp:
- description:
- - Enables EVN BGP.
- choices: ['enable', 'disable']
- evn_source_ip:
- description:
- - Specifies the source address of an EVN BGP peer.
- The value is in dotted decimal notation.
- evn_peer_ip:
- description:
- - Specifies the IP address of an EVN BGP peer.
- The value is in dotted decimal notation.
- evn_server:
- description:
- - Configures the local device as the router reflector (RR) on the EVN network.
- choices: ['enable', 'disable']
- evn_reflect_client:
- description:
- - Configures the local device as the route reflector (RR) and its peer as the client.
- choices: ['enable', 'disable']
- vbdif_name:
- description:
- - Full name of VBDIF interface, i.e. Vbdif100.
- arp_collect_host:
- description:
- - Enables EVN BGP or BGP EVPN to collect host information.
- choices: ['enable', 'disable']
- host_collect_protocol:
- description:
- - Enables EVN BGP or BGP EVPN to advertise host information.
- choices: ['bgp','none']
- bridge_domain_id:
- description:
- - Specifies a BD(bridge domain) ID.
- The value is an integer ranging from 1 to 16777215.
- arp_suppress:
- description:
- - Enables ARP broadcast suppression in a BD.
- choices: ['enable', 'disable']
- state:
- description:
- - Determines whether the config should be present or not
- on the device.
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = '''
-- name: vxlan arp module test
- hosts: ce128
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Configure EVN BGP on Layer 2 and Layer 3 VXLAN gateways to establish EVN BGP peer relationships.
- ce_vxlan_arp:
- evn_bgp: enable
- evn_source_ip: 6.6.6.6
- evn_peer_ip: 7.7.7.7
- provider: "{{ cli }}"
- - name: Configure a Layer 3 VXLAN gateway as a BGP RR.
- ce_vxlan_arp:
- evn_bgp: enable
- evn_server: enable
- provider: "{{ cli }}"
- - name: Enable EVN BGP on a Layer 3 VXLAN gateway to collect host information.
- ce_vxlan_arp:
- vbdif_name: Vbdif100
- arp_collect_host: enable
- provider: "{{ cli }}"
- - name: Enable Layer 2 and Layer 3 VXLAN gateways to use EVN BGP to advertise host information.
- ce_vxlan_arp:
- host_collect_protocol: bgp
- provider: "{{ cli }}"
- - name: Enable ARP broadcast suppression on a Layer 2 VXLAN gateway.
- ce_vxlan_arp:
- bridge_domain_id: 100
- arp_suppress: enable
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: verbose mode
- type: dict
- sample: {"evn_bgp": "enable", "evn_source_ip": "6.6.6.6", "evn_peer_ip":"7.7.7.7", state: "present"}
-existing:
- description: k/v pairs of existing configuration
- returned: verbose mode
- type: dict
- sample: {"evn_bgp": "disable", "evn_source_ip": null, "evn_peer_ip": []}
-end_state:
- description: k/v pairs of configuration after module execution
- returned: verbose mode
- type: dict
- sample: {"evn_bgp": "enable", "evn_source_ip": "6.6.6.6", "evn_peer_ip": ["7.7.7.7"]}
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: ["evn bgp",
- "source-address 6.6.6.6",
- "peer 7.7.7.7"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import load_config
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec
-from ansible.module_utils.connection import exec_command
-
-
-def is_config_exist(cmp_cfg, test_cfg):
- """is configuration exist"""
-
- if not cmp_cfg or not test_cfg:
- return False
-
- return bool(test_cfg in cmp_cfg)
-
-
-def is_valid_v4addr(addr):
- """check is ipv4 addr is valid"""
-
- if addr.count('.') == 3:
- addr_list = addr.split('.')
- if len(addr_list) != 4:
- return False
- for each_num in addr_list:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- return True
-
- return False
-
-
-def get_evn_peers(config):
- """get evn peer ip list"""
-
- get = re.findall(r"peer ([0-9]+.[0-9]+.[0-9]+.[0-9]+)", config)
- if not get:
- return None
- else:
- return list(set(get))
-
-
-def get_evn_srouce(config):
- """get evn peer ip list"""
-
- get = re.findall(
- r"source-address ([0-9]+.[0-9]+.[0-9]+.[0-9]+)", config)
- if not get:
- return None
- else:
- return get[0]
-
-
-def get_evn_reflect_client(config):
- """get evn reflect client list"""
-
- get = re.findall(
- r"peer ([0-9]+.[0-9]+.[0-9]+.[0-9]+)\s*reflect-client", config)
- if not get:
- return None
- else:
- return list(get)
-
-
-class VxlanArp(object):
- """
- Manages arp attributes of VXLAN.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.evn_bgp = self.module.params['evn_bgp']
- self.evn_source_ip = self.module.params['evn_source_ip']
- self.evn_peer_ip = self.module.params['evn_peer_ip']
- self.evn_server = self.module.params['evn_server']
- self.evn_reflect_client = self.module.params['evn_reflect_client']
- self.vbdif_name = self.module.params['vbdif_name']
- self.arp_collect_host = self.module.params['arp_collect_host']
- self.host_collect_protocol = self.module.params[
- 'host_collect_protocol']
- self.bridge_domain_id = self.module.params['bridge_domain_id']
- self.arp_suppress = self.module.params['arp_suppress']
- self.state = self.module.params['state']
-
- # host info
- self.host = self.module.params['host']
- self.username = self.module.params['username']
- self.port = self.module.params['port']
-
- # state
- self.config = "" # current config
- self.changed = False
- self.updates_cmd = list()
- self.commands = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def init_module(self):
- """init module"""
-
- required_together = [("vbdif_name", "arp_collect_host"), ("bridge_domain_id", "arp_suppress")]
- self.module = AnsibleModule(argument_spec=self.spec,
- required_together=required_together,
- supports_check_mode=True)
-
- def cli_load_config(self, commands):
- """load config by cli"""
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def get_config(self, flags=None):
- """Retrieves the current config from the device or cache
- """
- flags = [] if flags is None else flags
-
- cmd = 'display current-configuration '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- cfg = str(out).strip()
-
- return cfg
-
- def get_current_config(self):
- """get current configuration"""
-
- flags = list()
- exp = r"| ignore-case section include evn bgp|host collect protocol bgp"
- if self.vbdif_name:
- exp += r"|^#\s+interface %s\s+" % self.vbdif_name.lower().capitalize().replace(" ", "")
-
- if self.bridge_domain_id:
- exp += r"|^#\s+bridge-domain %s\s+" % self.bridge_domain_id
-
- flags.append(exp)
- cfg_str = self.get_config(flags)
- config = cfg_str.split("\n")
-
- exist_config = ""
- for cfg in config:
- if not cfg.startswith("display"):
- exist_config += cfg
- return exist_config
-
- def cli_add_command(self, command, undo=False):
- """add command to self.update_cmd and self.commands"""
-
- if undo and command.lower() not in ["quit", "return"]:
- cmd = "undo " + command
- else:
- cmd = command
-
- self.commands.append(cmd) # set to device
- if command.lower() not in ["quit", "return"]:
- self.updates_cmd.append(cmd) # show updates result
-
- def config_bridge_domain(self):
- """manage bridge domain configuration"""
-
- if not self.bridge_domain_id:
- return
-
- # bridge-domain bd-id
- # [undo] arp broadcast-suppress enable
-
- cmd = "bridge-domain %s" % self.bridge_domain_id
- if not is_config_exist(self.config, cmd):
- self.module.fail_json(msg="Error: Bridge domain %s is not exist." % self.bridge_domain_id)
-
- cmd = "arp broadcast-suppress enable"
- exist = is_config_exist(self.config, cmd)
- if self.arp_suppress == "enable" and not exist:
- self.cli_add_command("bridge-domain %s" % self.bridge_domain_id)
- self.cli_add_command(cmd)
- self.cli_add_command("quit")
- elif self.arp_suppress == "disable" and exist:
- self.cli_add_command("bridge-domain %s" % self.bridge_domain_id)
- self.cli_add_command(cmd, undo=True)
- self.cli_add_command("quit")
-
- def config_evn_bgp(self):
- """enables EVN BGP and configure evn bgp command"""
-
- evn_bgp_view = False
- evn_bgp_enable = False
-
- cmd = "evn bgp"
- exist = is_config_exist(self.config, cmd)
- if self.evn_bgp == "enable" or exist:
- evn_bgp_enable = True
-
- # [undo] evn bgp
- if self.evn_bgp:
- if self.evn_bgp == "enable" and not exist:
- self.cli_add_command(cmd)
- evn_bgp_view = True
- elif self.evn_bgp == "disable" and exist:
- self.cli_add_command(cmd, undo=True)
- return
-
- # [undo] source-address ip-address
- if evn_bgp_enable and self.evn_source_ip:
- cmd = "source-address %s" % self.evn_source_ip
- exist = is_config_exist(self.config, cmd)
- if self.state == "present" and not exist:
- if not evn_bgp_view:
- self.cli_add_command("evn bgp")
- evn_bgp_view = True
- self.cli_add_command(cmd)
- elif self.state == "absent" and exist:
- if not evn_bgp_view:
- self.cli_add_command("evn bgp")
- evn_bgp_view = True
- self.cli_add_command(cmd, undo=True)
-
- # [undo] peer ip-address
- # [undo] peer ipv4-address reflect-client
- if evn_bgp_enable and self.evn_peer_ip:
- cmd = "peer %s" % self.evn_peer_ip
- exist = is_config_exist(self.config, cmd)
- if self.state == "present":
- if not exist:
- if not evn_bgp_view:
- self.cli_add_command("evn bgp")
- evn_bgp_view = True
- self.cli_add_command(cmd)
- if self.evn_reflect_client == "enable":
- self.cli_add_command(
- "peer %s reflect-client" % self.evn_peer_ip)
- else:
- if self.evn_reflect_client:
- cmd = "peer %s reflect-client" % self.evn_peer_ip
- exist = is_config_exist(self.config, cmd)
- if self.evn_reflect_client == "enable" and not exist:
- if not evn_bgp_view:
- self.cli_add_command("evn bgp")
- evn_bgp_view = True
- self.cli_add_command(cmd)
- elif self.evn_reflect_client == "disable" and exist:
- if not evn_bgp_view:
- self.cli_add_command("evn bgp")
- evn_bgp_view = True
- self.cli_add_command(cmd, undo=True)
- else:
- if exist:
- if not evn_bgp_view:
- self.cli_add_command("evn bgp")
- evn_bgp_view = True
- self.cli_add_command(cmd, undo=True)
-
- # [undo] server enable
- if evn_bgp_enable and self.evn_server:
- cmd = "server enable"
- exist = is_config_exist(self.config, cmd)
- if self.evn_server == "enable" and not exist:
- if not evn_bgp_view:
- self.cli_add_command("evn bgp")
- evn_bgp_view = True
- self.cli_add_command(cmd)
- elif self.evn_server == "disable" and exist:
- if not evn_bgp_view:
- self.cli_add_command("evn bgp")
- evn_bgp_view = True
- self.cli_add_command(cmd, undo=True)
-
- if evn_bgp_view:
- self.cli_add_command("quit")
-
- def config_vbdif(self):
- """configure command at the VBDIF interface view"""
-
- # interface vbdif bd-id
- # [undo] arp collect host enable
-
- cmd = "interface %s" % self.vbdif_name.lower().capitalize()
- exist = is_config_exist(self.config, cmd)
-
- if not exist:
- self.module.fail_json(
- msg="Error: Interface %s does not exist." % self.vbdif_name)
-
- cmd = "arp collect host enable"
- exist = is_config_exist(self.config, cmd)
- if self.arp_collect_host == "enable" and not exist:
- self.cli_add_command("interface %s" %
- self.vbdif_name.lower().capitalize())
- self.cli_add_command(cmd)
- self.cli_add_command("quit")
- elif self.arp_collect_host == "disable" and exist:
- self.cli_add_command("interface %s" %
- self.vbdif_name.lower().capitalize())
- self.cli_add_command(cmd, undo=True)
- self.cli_add_command("quit")
-
- def config_host_collect_protocal(self):
- """Enable EVN BGP or BGP EVPN to advertise host information"""
-
- # [undo] host collect protocol bgp
- cmd = "host collect protocol bgp"
- exist = is_config_exist(self.config, cmd)
-
- if self.state == "present":
- if self.host_collect_protocol == "bgp" and not exist:
- self.cli_add_command(cmd)
- elif self.host_collect_protocol == "none" and exist:
- self.cli_add_command(cmd, undo=True)
- else:
- if self.host_collect_protocol == "bgp" and exist:
- self.cli_add_command(cmd, undo=True)
-
- def is_valid_vbdif(self, ifname):
- """check is interface vbdif is valid"""
-
- if not ifname.upper().startswith('VBDIF'):
- return False
- bdid = self.vbdif_name.replace(" ", "").upper().replace("VBDIF", "")
- if not bdid.isdigit():
- return False
- if int(bdid) < 1 or int(bdid) > 16777215:
- return False
-
- return True
-
- def check_params(self):
- """Check all input params"""
-
- # bridge domain id check
- if self.bridge_domain_id:
- if not self.bridge_domain_id.isdigit():
- self.module.fail_json(
- msg="Error: Bridge domain id is not digit.")
- if int(self.bridge_domain_id) < 1 or int(self.bridge_domain_id) > 16777215:
- self.module.fail_json(
- msg="Error: Bridge domain id is not in the range from 1 to 16777215.")
-
- # evn_source_ip check
- if self.evn_source_ip:
- if not is_valid_v4addr(self.evn_source_ip):
- self.module.fail_json(msg="Error: evn_source_ip is invalid.")
-
- # evn_peer_ip check
- if self.evn_peer_ip:
- if not is_valid_v4addr(self.evn_peer_ip):
- self.module.fail_json(msg="Error: evn_peer_ip is invalid.")
-
- # vbdif_name check
- if self.vbdif_name:
- self.vbdif_name = self.vbdif_name.replace(
- " ", "").lower().capitalize()
- if not self.is_valid_vbdif(self.vbdif_name):
- self.module.fail_json(msg="Error: vbdif_name is invalid.")
-
- # evn_reflect_client and evn_peer_ip must set at the same time
- if self.evn_reflect_client and not self.evn_peer_ip:
- self.module.fail_json(
- msg="Error: evn_reflect_client and evn_peer_ip must set at the same time.")
-
- # evn_server and evn_reflect_client can not set at the same time
- if self.evn_server == "enable" and self.evn_reflect_client == "enable":
- self.module.fail_json(
- msg="Error: evn_server and evn_reflect_client can not set at the same time.")
-
- def get_proposed(self):
- """get proposed info"""
-
- if self.evn_bgp:
- self.proposed["evn_bgp"] = self.evn_bgp
- if self.evn_source_ip:
- self.proposed["evn_source_ip"] = self.evn_source_ip
- if self.evn_peer_ip:
- self.proposed["evn_peer_ip"] = self.evn_peer_ip
- if self.evn_server:
- self.proposed["evn_server"] = self.evn_server
- if self.evn_reflect_client:
- self.proposed["evn_reflect_client"] = self.evn_reflect_client
- if self.arp_collect_host:
- self.proposed["arp_collect_host"] = self.arp_collect_host
- if self.host_collect_protocol:
- self.proposed["host_collect_protocol"] = self.host_collect_protocol
- if self.arp_suppress:
- self.proposed["arp_suppress"] = self.arp_suppress
- if self.vbdif_name:
- self.proposed["vbdif_name"] = self.evn_peer_ip
- if self.bridge_domain_id:
- self.proposed["bridge_domain_id"] = self.bridge_domain_id
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- evn_bgp_exist = is_config_exist(self.config, "evn bgp")
- if evn_bgp_exist:
- self.existing["evn_bgp"] = "enable"
- else:
- self.existing["evn_bgp"] = "disable"
-
- if evn_bgp_exist:
- if is_config_exist(self.config, "server enable"):
- self.existing["evn_server"] = "enable"
- else:
- self.existing["evn_server"] = "disable"
-
- self.existing["evn_source_ip"] = get_evn_srouce(self.config)
- self.existing["evn_peer_ip"] = get_evn_peers(self.config)
- self.existing["evn_reflect_client"] = get_evn_reflect_client(
- self.config)
-
- if is_config_exist(self.config, "arp collect host enable"):
- self.existing["host_collect_protocol"] = "enable"
- else:
- self.existing["host_collect_protocol"] = "disable"
-
- if is_config_exist(self.config, "host collect protocol bgp"):
- self.existing["host_collect_protocol"] = "bgp"
- else:
- self.existing["host_collect_protocol"] = None
-
- if is_config_exist(self.config, "arp broadcast-suppress enable"):
- self.existing["arp_suppress"] = "enable"
- else:
- self.existing["arp_suppress"] = "disable"
-
- def get_end_state(self):
- """get end state info"""
-
- config = self.get_current_config()
- evn_bgp_exist = is_config_exist(config, "evn bgp")
- if evn_bgp_exist:
- self.end_state["evn_bgp"] = "enable"
- else:
- self.end_state["evn_bgp"] = "disable"
-
- if evn_bgp_exist:
- if is_config_exist(config, "server enable"):
- self.end_state["evn_server"] = "enable"
- else:
- self.end_state["evn_server"] = "disable"
-
- self.end_state["evn_source_ip"] = get_evn_srouce(config)
- self.end_state["evn_peer_ip"] = get_evn_peers(config)
- self.end_state[
- "evn_reflect_client"] = get_evn_reflect_client(config)
-
- if is_config_exist(config, "arp collect host enable"):
- self.end_state["host_collect_protocol"] = "enable"
- else:
- self.end_state["host_collect_protocol"] = "disable"
-
- if is_config_exist(config, "host collect protocol bgp"):
- self.end_state["host_collect_protocol"] = "bgp"
- else:
- self.end_state["host_collect_protocol"] = None
-
- if is_config_exist(config, "arp broadcast-suppress enable"):
- self.end_state["arp_suppress"] = "enable"
- else:
- self.end_state["arp_suppress"] = "disable"
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.config = self.get_current_config()
- self.get_existing()
- self.get_proposed()
-
- # deal present or absent
- if self.evn_bgp or self.evn_server or self.evn_peer_ip or self.evn_source_ip:
- self.config_evn_bgp()
-
- if self.vbdif_name and self.arp_collect_host:
- self.config_vbdif()
-
- if self.host_collect_protocol:
- self.config_host_collect_protocal()
-
- if self.bridge_domain_id and self.arp_suppress:
- self.config_bridge_domain()
-
- if self.commands:
- self.cli_load_config(self.commands)
- self.changed = True
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- evn_bgp=dict(required=False, type='str',
- choices=['enable', 'disable']),
- evn_source_ip=dict(required=False, type='str'),
- evn_peer_ip=dict(required=False, type='str'),
- evn_server=dict(required=False, type='str',
- choices=['enable', 'disable']),
- evn_reflect_client=dict(
- required=False, type='str', choices=['enable', 'disable']),
- vbdif_name=dict(required=False, type='str'),
- arp_collect_host=dict(required=False, type='str',
- choices=['enable', 'disable']),
- host_collect_protocol=dict(
- required=False, type='str', choices=['bgp', 'none']),
- bridge_domain_id=dict(required=False, type='str'),
- arp_suppress=dict(required=False, type='str',
- choices=['enable', 'disable']),
- state=dict(required=False, default='present',
- choices=['present', 'absent'])
- )
- argument_spec.update(ce_argument_spec)
- module = VxlanArp(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_vxlan_gateway.py b/plugins/modules/network/cloudengine/ce_vxlan_gateway.py
deleted file mode 100644
index da8e9a23fc..0000000000
--- a/plugins/modules/network/cloudengine/ce_vxlan_gateway.py
+++ /dev/null
@@ -1,940 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_vxlan_gateway
-short_description: Manages gateway for the VXLAN network on HUAWEI CloudEngine devices.
-description:
- - Configuring Centralized All-Active Gateways or Distributed Gateway for
- the VXLAN Network on HUAWEI CloudEngine devices.
-author: QijunPan (@QijunPan)
-notes:
- - Ensure All-Active Gateways or Distributed Gateway for the VXLAN Network can not configure at the same time.
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- dfs_id:
- description:
- - Specifies the ID of a DFS group.
- The value must be 1.
- dfs_source_ip:
- description:
- - Specifies the IPv4 address bound to a DFS group.
- The value is in dotted decimal notation.
- dfs_source_vpn:
- description:
- - Specifies the name of a VPN instance bound to a DFS group.
- The value is a string of 1 to 31 case-sensitive characters without spaces.
- If the character string is quoted by double quotation marks, the character string can contain spaces.
- The value C(_public_) is reserved and cannot be used as the VPN instance name.
- dfs_udp_port:
- description:
- - Specifies the UDP port number of the DFS group.
- The value is an integer that ranges from 1025 to 65535.
- dfs_all_active:
- description:
- - Creates all-active gateways.
- choices: ['enable', 'disable']
- dfs_peer_ip:
- description:
- - Configure the IP address of an all-active gateway peer.
- The value is in dotted decimal notation.
- dfs_peer_vpn:
- description:
- - Specifies the name of the VPN instance that is associated with all-active gateway peer.
- The value is a string of 1 to 31 case-sensitive characters, spaces not supported.
- When double quotation marks are used around the string, spaces are allowed in the string.
- The value C(_public_) is reserved and cannot be used as the VPN instance name.
- vpn_instance:
- description:
- - Specifies the name of a VPN instance.
- The value is a string of 1 to 31 case-sensitive characters, spaces not supported.
- When double quotation marks are used around the string, spaces are allowed in the string.
- The value C(_public_) is reserved and cannot be used as the VPN instance name.
- vpn_vni:
- description:
- - Specifies a VNI ID.
- Binds a VXLAN network identifier (VNI) to a virtual private network (VPN) instance.
- The value is an integer ranging from 1 to 16000000.
- vbdif_name:
- description:
- - Full name of VBDIF interface, i.e. Vbdif100.
- vbdif_bind_vpn:
- description:
- - Specifies the name of the VPN instance that is associated with the interface.
- The value is a string of 1 to 31 case-sensitive characters, spaces not supported.
- When double quotation marks are used around the string, spaces are allowed in the string.
- The value C(_public_) is reserved and cannot be used as the VPN instance name.
- vbdif_mac:
- description:
- - Specifies a MAC address for a VBDIF interface.
- The value is in the format of H-H-H. Each H is a 4-digit hexadecimal number, such as C(00e0) or C(fc01).
- If an H contains less than four digits, 0s are added ahead. For example, C(e0) is equal to C(00e0).
- A MAC address cannot be all 0s or 1s or a multicast MAC address.
- arp_distribute_gateway:
- description:
- - Enable the distributed gateway function on VBDIF interface.
- choices: ['enable','disable']
- arp_direct_route:
- description:
- - Enable VLINK direct route on VBDIF interface.
- choices: ['enable','disable']
- state:
- description:
- - Determines whether the config should be present or not
- on the device.
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = '''
-- name: vxlan gateway module test
- hosts: ce128
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Configuring Centralized All-Active Gateways for the VXLAN Network
- ce_vxlan_gateway:
- dfs_id: 1
- dfs_source_ip: 6.6.6.6
- dfs_all_active: enable
- dfs_peer_ip: 7.7.7.7
- provider: "{{ cli }}"
- - name: Bind the VPN instance to a Layer 3 gateway, enable distributed gateway, and configure host route advertisement.
- ce_vxlan_gateway:
- vbdif_name: Vbdif100
- vbdif_bind_vpn: vpn1
- arp_distribute_gateway: enable
- arp_direct_route: enable
- provider: "{{ cli }}"
- - name: Assign a VNI to a VPN instance.
- ce_vxlan_gateway:
- vpn_instance: vpn1
- vpn_vni: 100
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: verbose mode
- type: dict
- sample: {"dfs_id": "1", "dfs_source_ip": "6.6.6.6", "dfs_all_active":"enable", "dfs_peer_ip": "7.7.7.7"}
-existing:
- description: k/v pairs of existing configuration
- returned: verbose mode
- type: dict
- sample: {"dfs_id": "1", "dfs_source_ip": null, "evn_peer_ip": [], "dfs_all_active": "disable"}
-end_state:
- description: k/v pairs of configuration after module execution
- returned: verbose mode
- type: dict
- sample: {"dfs_id": "1", "evn_source_ip": "6.6.6.6", "evn_source_vpn": null,
- "evn_peers": [{"ip": "7.7.7.7", "vpn": ""}], "dfs_all_active": "enable"}
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: ["dfs-group 1",
- "source ip 6.6.6.6",
- "active-active-gateway",
- "peer 7.7.7.7"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import load_config
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec
-from ansible.module_utils.connection import exec_command
-
-
-def is_config_exist(cmp_cfg, test_cfg):
- """is configuration exist?"""
-
- if not cmp_cfg or not test_cfg:
- return False
-
- return bool(test_cfg in cmp_cfg)
-
-
-def is_valid_v4addr(addr):
- """check is ipv4 addr"""
-
- if not addr:
- return False
-
- if addr.count('.') == 3:
- addr_list = addr.split('.')
- if len(addr_list) != 4:
- return False
- for each_num in addr_list:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- return True
-
- return False
-
-
-def mac_format(mac):
- """convert mac format to xxxx-xxxx-xxxx"""
-
- if not mac:
- return None
-
- if mac.count("-") != 2:
- return None
-
- addrs = mac.split("-")
- for i in range(3):
- if not addrs[i] or not addrs[i].isalnum():
- return None
- if len(addrs[i]) < 1 or len(addrs[i]) > 4:
- return None
- try:
- addrs[i] = int(addrs[i], 16)
- except ValueError:
- return None
-
- try:
- return "%04x-%04x-%04x" % (addrs[0], addrs[1], addrs[2])
- except ValueError:
- return None
- except TypeError:
- return None
-
-
-def get_dfs_source_ip(config):
- """get dfs source ip address"""
-
- get = re.findall(r"source ip ([0-9]+.[0-9]+.[0-9]+.[0-9]+)", config)
- if not get:
- return None
- else:
- return get[0]
-
-
-def get_dfs_source_vpn(config):
- """get dfs source ip vpn instance name"""
-
- get = re.findall(
- r"source ip [0-9]+.[0-9]+.[0-9]+.[0-9]+ vpn-instance (\S+)", config)
- if not get:
- return None
- else:
- return get[0]
-
-
-def get_dfs_udp_port(config):
- """get dfs udp port"""
-
- get = re.findall(r"udp port (\d+)", config)
- if not get:
- return None
- else:
- return get[0]
-
-
-def get_dfs_peers(config):
- """get evn peer ip list"""
-
- get = re.findall(
- r"peer ([0-9]+.[0-9]+.[0-9]+.[0-9]+)\s?(vpn-instance)?\s?(\S*)", config)
- if not get:
- return None
- else:
- peers = list()
- for item in get:
- peers.append(dict(ip=item[0], vpn=item[2]))
- return peers
-
-
-def get_ip_vpn(config):
- """get ip vpn instance"""
-
- get = re.findall(r"ip vpn-instance (\S+)", config)
- if not get:
- return None
- else:
- return get[0]
-
-
-def get_ip_vpn_vni(config):
- """get ip vpn vxlan vni"""
-
- get = re.findall(r"vxlan vni (\d+)", config)
- if not get:
- return None
- else:
- return get[0]
-
-
-def get_vbdif_vpn(config):
- """get ip vpn name of interface vbdif"""
-
- get = re.findall(r"ip binding vpn-instance (\S+)", config)
- if not get:
- return None
- else:
- return get[0]
-
-
-def get_vbdif_mac(config):
- """get mac address of interface vbdif"""
-
- get = re.findall(
- r" mac-address ([0-9a-fA-F]{1,4}-[0-9a-fA-F]{1,4}-[0-9a-fA-F]{1,4})", config)
- if not get:
- return None
- else:
- return get[0]
-
-
-class VxlanGateway(object):
- """
- Manages Gateway for the VXLAN Network.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.dfs_id = self.module.params['dfs_id']
- self.dfs_source_ip = self.module.params['dfs_source_ip']
- self.dfs_source_vpn = self.module.params['dfs_source_vpn']
- self.dfs_udp_port = self.module.params['dfs_udp_port']
- self.dfs_all_active = self.module.params['dfs_all_active']
- self.dfs_peer_ip = self.module.params['dfs_peer_ip']
- self.dfs_peer_vpn = self.module.params['dfs_peer_vpn']
- self.vpn_instance = self.module.params['vpn_instance']
- self.vpn_vni = self.module.params['vpn_vni']
- self.vbdif_name = self.module.params['vbdif_name']
- self.vbdif_mac = self.module.params['vbdif_mac']
- self.vbdif_bind_vpn = self.module.params['vbdif_bind_vpn']
- self.arp_distribute_gateway = self.module.params['arp_distribute_gateway']
- self.arp_direct_route = self.module.params['arp_direct_route']
- self.state = self.module.params['state']
-
- # host info
- self.host = self.module.params['host']
- self.username = self.module.params['username']
- self.port = self.module.params['port']
-
- # state
- self.config = "" # current config
- self.changed = False
- self.updates_cmd = list()
- self.commands = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def init_module(self):
- """init module"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def cli_load_config(self, commands):
- """load config by cli"""
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def get_config(self, flags=None):
- """Retrieves the current config from the device or cache
- """
- flags = [] if flags is None else flags
-
- cmd = 'display current-configuration '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- cfg = str(out).strip()
-
- return cfg
-
- def get_current_config(self):
- """get current configuration"""
-
- flags = list()
- exp = r" | ignore-case section include ^#\s+dfs-group"
- if self.vpn_instance:
- exp += r"|^#\s+ip vpn-instance %s" % self.vpn_instance
- if self.vbdif_name:
- exp += r"|^#\s+interface %s" % self.vbdif_name
- flags.append(exp)
- return self.get_config(flags)
-
- def cli_add_command(self, command, undo=False):
- """add command to self.update_cmd and self.commands"""
-
- if undo and command.lower() not in ["quit", "return"]:
- cmd = "undo " + command
- else:
- cmd = command
-
- self.commands.append(cmd) # set to device
- if command.lower() not in ["quit", "return"]:
- self.updates_cmd.append(cmd) # show updates result
-
- def config_dfs_group(self):
- """manage Dynamic Fabric Service (DFS) group configuration"""
-
- if not self.dfs_id:
- return
-
- dfs_view = False
- view_cmd = "dfs-group %s" % self.dfs_id
- exist = is_config_exist(self.config, view_cmd)
- if self.state == "present" and not exist:
- self.cli_add_command(view_cmd)
- dfs_view = True
-
- # undo dfs-group dfs-group-id
- if self.state == "absent" and exist:
- if not self.dfs_source_ip and not self.dfs_udp_port and not self.dfs_all_active and not self.dfs_peer_ip:
- self.cli_add_command(view_cmd, undo=True)
- return
-
- # [undo] source ip ip-address [ vpn-instance vpn-instance-name ]
- if self.dfs_source_ip:
- cmd = "source ip %s" % self.dfs_source_ip
- if self.dfs_source_vpn:
- cmd += " vpn-instance %s" % self.dfs_source_vpn
- exist = is_config_exist(self.config, cmd)
- if self.state == "present" and not exist:
- if not dfs_view:
- self.cli_add_command(view_cmd)
- dfs_view = True
- self.cli_add_command(cmd)
- if self.state == "absent" and exist:
- if not dfs_view:
- self.cli_add_command(view_cmd)
- dfs_view = True
- self.cli_add_command(cmd, undo=True)
-
- # [undo] udp port port-number
- if self.dfs_udp_port:
- cmd = "udp port %s" % self.dfs_udp_port
- exist = is_config_exist(self.config, cmd)
- if self.state == "present" and not exist:
- if not dfs_view:
- self.cli_add_command(view_cmd)
- dfs_view = True
- self.cli_add_command(cmd)
- elif self.state == "absent" and exist:
- if not dfs_view:
- self.cli_add_command(view_cmd)
- dfs_view = True
- self.cli_add_command(cmd, undo=True)
-
- # [undo] active-active-gateway
- # [undo]peer[ vpn-instance vpn-instance-name ]
- aa_cmd = "active-active-gateway"
- aa_exist = is_config_exist(self.config, aa_cmd)
- aa_view = False
- if self.dfs_all_active == "disable":
- if aa_exist:
- cmd = "peer %s" % self.dfs_peer_ip
- if self.dfs_source_vpn:
- cmd += " vpn-instance %s" % self.dfs_peer_vpn
- exist = is_config_exist(self.config, cmd)
- if self.state == "absent" and exist:
- if not dfs_view:
- self.cli_add_command(view_cmd)
- dfs_view = True
- self.cli_add_command(aa_cmd)
- self.cli_add_command(cmd, undo=True)
- self.cli_add_command("quit")
- if not dfs_view:
- self.cli_add_command(view_cmd)
- dfs_view = True
- self.cli_add_command(aa_cmd, undo=True)
- elif self.dfs_all_active == "enable":
- if not aa_exist:
- if not dfs_view:
- self.cli_add_command(view_cmd)
- dfs_view = True
- self.cli_add_command(aa_cmd)
- aa_view = True
-
- if self.dfs_peer_ip:
- cmd = "peer %s" % self.dfs_peer_ip
- if self.dfs_peer_vpn:
- cmd += " vpn-instance %s" % self.dfs_peer_vpn
- exist = is_config_exist(self.config, cmd)
-
- if self.state == "present" and not exist:
- if not dfs_view:
- self.cli_add_command(view_cmd)
- dfs_view = True
- if not aa_view:
- self.cli_add_command(aa_cmd)
- self.cli_add_command(cmd)
- self.cli_add_command("quit")
- elif self.state == "absent" and exist:
- if not dfs_view:
- self.cli_add_command(view_cmd)
- dfs_view = True
- if not aa_view:
- self.cli_add_command(aa_cmd)
- self.cli_add_command(cmd, undo=True)
- self.cli_add_command("quit")
- else: # not input dfs_all_active
- if aa_exist and self.dfs_peer_ip:
- cmd = "peer %s" % self.dfs_peer_ip
- if self.dfs_peer_vpn:
- cmd += " vpn-instance %s" % self.dfs_peer_vpn
- exist = is_config_exist(self.config, cmd)
- if self.state == "present" and not exist:
- if not dfs_view:
- self.cli_add_command(view_cmd)
- dfs_view = True
- self.cli_add_command(aa_cmd)
- self.cli_add_command(cmd)
- self.cli_add_command("quit")
- elif self.state == "absent" and exist:
- if not dfs_view:
- self.cli_add_command(view_cmd)
- dfs_view = True
- self.cli_add_command(aa_cmd)
- self.cli_add_command(cmd, undo=True)
- self.cli_add_command("quit")
- else:
- pass
- elif not aa_exist and self.dfs_peer_ip and self.state == "present":
- self.module.fail_json(
- msg="Error: All-active gateways is not enable.")
- else:
- pass
-
- if dfs_view:
- self.cli_add_command("quit")
-
- def config_ip_vpn(self):
- """configure command at the ip vpn view"""
-
- if not self.vpn_instance or not self.vpn_vni:
- return
-
- # ip vpn-instance vpn-instance-name
- view_cmd = "ip vpn-instance %s" % self.vpn_instance
- exist = is_config_exist(self.config, view_cmd)
- if not exist:
- self.module.fail_json(
- msg="Error: ip vpn instance %s is not exist." % self.vpn_instance)
-
- # [undo] vxlan vni vni-id
- cmd = "vxlan vni %s" % self.vpn_vni
- exist = is_config_exist(self.config, cmd)
- if self.state == "present" and not exist:
- self.cli_add_command(view_cmd)
- self.cli_add_command(cmd)
- self.cli_add_command("quit")
- elif self.state == "absent" and exist:
- self.cli_add_command(view_cmd)
- self.cli_add_command(cmd, undo=True)
- self.cli_add_command("quit")
-
- def config_vbdif(self):
- """configure command at the VBDIF interface view"""
-
- if not self.vbdif_name:
- return
-
- vbdif_cmd = "interface %s" % self.vbdif_name.lower().capitalize()
- exist = is_config_exist(self.config, vbdif_cmd)
-
- if not exist:
- self.module.fail_json(
- msg="Error: Interface %s is not exist." % self.vbdif_name)
-
- # interface vbdif bd-id
- # [undo] ip binding vpn-instance vpn-instance-name
- vbdif_view = False
- if self.vbdif_bind_vpn:
- cmd = "ip binding vpn-instance %s" % self.vbdif_bind_vpn
- exist = is_config_exist(self.config, cmd)
-
- if self.state == "present" and not exist:
- if not vbdif_view:
- self.cli_add_command(vbdif_cmd)
- vbdif_view = True
- self.cli_add_command(cmd)
- elif self.state == "absent" and exist:
- if not vbdif_view:
- self.cli_add_command(vbdif_cmd)
- vbdif_view = True
- self.cli_add_command(cmd, undo=True)
-
- # [undo] arp distribute-gateway enable
- if self.arp_distribute_gateway:
- cmd = "arp distribute-gateway enable"
- exist = is_config_exist(self.config, cmd)
- if self.arp_distribute_gateway == "enable" and not exist:
- if not vbdif_view:
- self.cli_add_command(vbdif_cmd)
- vbdif_view = True
- self.cli_add_command(cmd)
- elif self.arp_distribute_gateway == "disable" and exist:
- if not vbdif_view:
- self.cli_add_command(vbdif_cmd)
- vbdif_view = True
- self.cli_add_command(cmd, undo=True)
-
- # [undo] arp direct-route enable
- if self.arp_direct_route:
- cmd = "arp direct-route enable"
- exist = is_config_exist(self.config, cmd)
- if self.arp_direct_route == "enable" and not exist:
- if not vbdif_view:
- self.cli_add_command(vbdif_cmd)
- vbdif_view = True
- self.cli_add_command(cmd)
- elif self.arp_direct_route == "disable" and exist:
- if not vbdif_view:
- self.cli_add_command(vbdif_cmd)
- vbdif_view = True
- self.cli_add_command(cmd, undo=True)
-
- # mac-address mac-address
- # undo mac-address
- if self.vbdif_mac:
- cmd = "mac-address %s" % self.vbdif_mac
- exist = is_config_exist(self.config, cmd)
- if self.state == "present" and not exist:
- if not vbdif_view:
- self.cli_add_command(vbdif_cmd)
- vbdif_view = True
- self.cli_add_command(cmd)
- elif self.state == "absent" and exist:
- if not vbdif_view:
- self.cli_add_command(vbdif_cmd)
- vbdif_view = True
- self.cli_add_command("undo mac-address")
-
- # quit
- if vbdif_view:
- self.cli_add_command("quit")
-
- def is_valid_vbdif(self, ifname):
- """check is interface vbdif"""
-
- if not ifname.upper().startswith('VBDIF'):
- return False
- bdid = self.vbdif_name.replace(" ", "").upper().replace("VBDIF", "")
- if not bdid.isdigit():
- return False
- if int(bdid) < 1 or int(bdid) > 16777215:
- return False
-
- return True
-
- def is_valid_ip_vpn(self, vpname):
- """check ip vpn"""
-
- if not vpname:
- return False
-
- if vpname == "_public_":
- self.module.fail_json(
- msg="Error: The value C(_public_) is reserved and cannot be used as the VPN instance name.")
-
- if len(vpname) < 1 or len(vpname) > 31:
- self.module.fail_json(
- msg="Error: IP vpn name length is not in the range from 1 to 31.")
-
- return True
-
- def check_params(self):
- """Check all input params"""
-
- # dfs id check
- if self.dfs_id:
- if not self.dfs_id.isdigit():
- self.module.fail_json(msg="Error: DFS id is not digit.")
- if int(self.dfs_id) != 1:
- self.module.fail_json(msg="Error: DFS is not 1.")
-
- # dfs_source_ip check
- if self.dfs_source_ip:
- if not is_valid_v4addr(self.dfs_source_ip):
- self.module.fail_json(msg="Error: dfs_source_ip is invalid.")
- # dfs_source_vpn check
- if self.dfs_source_vpn and not self.is_valid_ip_vpn(self.dfs_source_vpn):
- self.module.fail_json(msg="Error: dfs_source_vpn is invalid.")
-
- # dfs_source_vpn and dfs_source_ip must set at the same time
- if self.dfs_source_vpn and not self.dfs_source_ip:
- self.module.fail_json(
- msg="Error: dfs_source_vpn and dfs_source_ip must set at the same time.")
-
- # dfs_udp_port check
- if self.dfs_udp_port:
- if not self.dfs_udp_port.isdigit():
- self.module.fail_json(
- msg="Error: dfs_udp_port id is not digit.")
- if int(self.dfs_udp_port) < 1025 or int(self.dfs_udp_port) > 65535:
- self.module.fail_json(
- msg="dfs_udp_port is not ranges from 1025 to 65535.")
-
- # dfs_peer_ip check
- if self.dfs_peer_ip:
- if not is_valid_v4addr(self.dfs_peer_ip):
- self.module.fail_json(msg="Error: dfs_peer_ip is invalid.")
- # dfs_peer_vpn check
- if self.dfs_peer_vpn and not self.is_valid_ip_vpn(self.dfs_peer_vpn):
- self.module.fail_json(msg="Error: dfs_peer_vpn is invalid.")
-
- # dfs_peer_vpn and dfs_peer_ip must set at the same time
- if self.dfs_peer_vpn and not self.dfs_peer_ip:
- self.module.fail_json(
- msg="Error: dfs_peer_vpn and dfs_peer_ip must set at the same time.")
-
- # vpn_instance check
- if self.vpn_instance and not self.is_valid_ip_vpn(self.vpn_instance):
- self.module.fail_json(msg="Error: vpn_instance is invalid.")
-
- # vpn_vni check
- if self.vpn_vni:
- if not self.vpn_vni.isdigit():
- self.module.fail_json(msg="Error: vpn_vni id is not digit.")
- if int(self.vpn_vni) < 1 or int(self.vpn_vni) > 16000000:
- self.module.fail_json(
- msg="vpn_vni is not ranges from 1 to 16000000.")
-
- # vpn_instance and vpn_vni must set at the same time
- if bool(self.vpn_instance) != bool(self.vpn_vni):
- self.module.fail_json(
- msg="Error: vpn_instance and vpn_vni must set at the same time.")
-
- # vbdif_name check
- if self.vbdif_name:
- self.vbdif_name = self.vbdif_name.replace(" ", "").lower().capitalize()
- if not self.is_valid_vbdif(self.vbdif_name):
- self.module.fail_json(msg="Error: vbdif_name is invalid.")
-
- # vbdif_mac check
- if self.vbdif_mac:
- mac = mac_format(self.vbdif_mac)
- if not mac:
- self.module.fail_json(msg="Error: vbdif_mac is invalid.")
- self.vbdif_mac = mac
-
- # vbdif_bind_vpn check
- if self.vbdif_bind_vpn and not self.is_valid_ip_vpn(self.vbdif_bind_vpn):
- self.module.fail_json(msg="Error: vbdif_bind_vpn is invalid.")
-
- # All-Active Gateways or Distributed Gateway config can not set at the
- # same time.
- if self.dfs_id:
- if self.vpn_vni or self.arp_distribute_gateway == "enable":
- self.module.fail_json(msg="Error: All-Active Gateways or Distributed Gateway config "
- "can not set at the same time.")
-
- def get_proposed(self):
- """get proposed info"""
-
- if self.dfs_id:
- self.proposed["dfs_id"] = self.dfs_id
- self.proposed["dfs_source_ip"] = self.dfs_source_ip
- self.proposed["dfs_source_vpn"] = self.dfs_source_vpn
- self.proposed["dfs_udp_port"] = self.dfs_udp_port
- self.proposed["dfs_all_active"] = self.dfs_all_active
- self.proposed["dfs_peer_ip"] = self.dfs_peer_ip
- self.proposed["dfs_peer_vpn"] = self.dfs_peer_vpn
-
- if self.vpn_instance:
- self.proposed["vpn_instance"] = self.vpn_instance
- self.proposed["vpn_vni"] = self.vpn_vni
-
- if self.vbdif_name:
- self.proposed["vbdif_name"] = self.vbdif_name
- self.proposed["vbdif_mac"] = self.vbdif_mac
- self.proposed["vbdif_bind_vpn"] = self.vbdif_bind_vpn
- self.proposed[
- "arp_distribute_gateway"] = self.arp_distribute_gateway
- self.proposed["arp_direct_route"] = self.arp_direct_route
-
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- if not self.config:
- return
-
- if is_config_exist(self.config, "dfs-group 1"):
- self.existing["dfs_id"] = "1"
- self.existing["dfs_source_ip"] = get_dfs_source_ip(self.config)
- self.existing["dfs_source_vpn"] = get_dfs_source_vpn(self.config)
- self.existing["dfs_udp_port"] = get_dfs_udp_port(self.config)
- if is_config_exist(self.config, "active-active-gateway"):
- self.existing["dfs_all_active"] = "enable"
- self.existing["dfs_peers"] = get_dfs_peers(self.config)
- else:
- self.existing["dfs_all_active"] = "disable"
-
- if self.vpn_instance:
- self.existing["vpn_instance"] = get_ip_vpn(self.config)
- self.existing["vpn_vni"] = get_ip_vpn_vni(self.config)
-
- if self.vbdif_name:
- self.existing["vbdif_name"] = self.vbdif_name
- self.existing["vbdif_mac"] = get_vbdif_mac(self.config)
- self.existing["vbdif_bind_vpn"] = get_vbdif_vpn(self.config)
- if is_config_exist(self.config, "arp distribute-gateway enable"):
- self.existing["arp_distribute_gateway"] = "enable"
- else:
- self.existing["arp_distribute_gateway"] = "disable"
- if is_config_exist(self.config, "arp direct-route enable"):
- self.existing["arp_direct_route"] = "enable"
- else:
- self.existing["arp_direct_route"] = "disable"
-
- def get_end_state(self):
- """get end state info"""
-
- config = self.get_current_config()
- if not config:
- return
-
- if is_config_exist(config, "dfs-group 1"):
- self.end_state["dfs_id"] = "1"
- self.end_state["dfs_source_ip"] = get_dfs_source_ip(config)
- self.end_state["dfs_source_vpn"] = get_dfs_source_vpn(config)
- self.end_state["dfs_udp_port"] = get_dfs_udp_port(config)
- if is_config_exist(config, "active-active-gateway"):
- self.end_state["dfs_all_active"] = "enable"
- self.end_state["dfs_peers"] = get_dfs_peers(config)
- else:
- self.end_state["dfs_all_active"] = "disable"
-
- if self.vpn_instance:
- self.end_state["vpn_instance"] = get_ip_vpn(config)
- self.end_state["vpn_vni"] = get_ip_vpn_vni(config)
-
- if self.vbdif_name:
- self.end_state["vbdif_name"] = self.vbdif_name
- self.end_state["vbdif_mac"] = get_vbdif_mac(config)
- self.end_state["vbdif_bind_vpn"] = get_vbdif_vpn(config)
- if is_config_exist(config, "arp distribute-gateway enable"):
- self.end_state["arp_distribute_gateway"] = "enable"
- else:
- self.end_state["arp_distribute_gateway"] = "disable"
- if is_config_exist(config, "arp direct-route enable"):
- self.end_state["arp_direct_route"] = "enable"
- else:
- self.end_state["arp_direct_route"] = "disable"
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.config = self.get_current_config()
- self.get_existing()
- self.get_proposed()
-
- # deal present or absent
- if self.dfs_id:
- self.config_dfs_group()
-
- if self.vpn_instance:
- self.config_ip_vpn()
-
- if self.vbdif_name:
- self.config_vbdif()
-
- if self.commands:
- self.cli_load_config(self.commands)
- self.changed = True
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- dfs_id=dict(required=False, type='str'),
- dfs_source_ip=dict(required=False, type='str'),
- dfs_source_vpn=dict(required=False, type='str'),
- dfs_udp_port=dict(required=False, type='str'),
- dfs_all_active=dict(required=False, type='str',
- choices=['enable', 'disable']),
- dfs_peer_ip=dict(required=False, type='str'),
- dfs_peer_vpn=dict(required=False, type='str'),
- vpn_instance=dict(required=False, type='str'),
- vpn_vni=dict(required=False, type='str'),
- vbdif_name=dict(required=False, type='str'),
- vbdif_mac=dict(required=False, type='str'),
- vbdif_bind_vpn=dict(required=False, type='str'),
- arp_distribute_gateway=dict(
- required=False, type='str', choices=['enable', 'disable']),
- arp_direct_route=dict(required=False, type='str',
- choices=['enable', 'disable']),
- state=dict(required=False, default='present',
- choices=['present', 'absent'])
- )
- argument_spec.update(ce_argument_spec)
- module = VxlanGateway(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_vxlan_global.py b/plugins/modules/network/cloudengine/ce_vxlan_global.py
deleted file mode 100644
index 954c5bd7e3..0000000000
--- a/plugins/modules/network/cloudengine/ce_vxlan_global.py
+++ /dev/null
@@ -1,543 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_vxlan_global
-short_description: Manages global attributes of VXLAN and bridge domain on HUAWEI CloudEngine devices.
-description:
- - Manages global attributes of VXLAN and bridge domain on HUAWEI CloudEngine devices.
-author: QijunPan (@QijunPan)
-notes:
- - Recommended connection is C(network_cli).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- bridge_domain_id:
- description:
- - Specifies a bridge domain ID.
- The value is an integer ranging from 1 to 16777215.
- tunnel_mode_vxlan:
- description:
- - Set the tunnel mode to VXLAN when configuring the VXLAN feature.
- choices: ['enable', 'disable']
- nvo3_prevent_loops:
- description:
- - Loop prevention of VXLAN traffic in non-enhanced mode.
- When the device works in non-enhanced mode,
- inter-card forwarding of VXLAN traffic may result in loops.
- choices: ['enable', 'disable']
- nvo3_acl_extend:
- description:
- - Enabling or disabling the VXLAN ACL extension function.
- choices: ['enable', 'disable']
- nvo3_gw_enhanced:
- description:
- - Configuring the Layer 3 VXLAN Gateway to Work in Non-loopback Mode.
- choices: ['l2', 'l3']
- nvo3_service_extend:
- description:
- - Enabling or disabling the VXLAN service extension function.
- choices: ['enable', 'disable']
- nvo3_eth_trunk_hash:
- description:
- - Eth-Trunk from load balancing VXLAN packets in optimized mode.
- choices: ['enable','disable']
- nvo3_ecmp_hash:
- description:
- - Load balancing of VXLAN packets through ECMP in optimized mode.
- choices: ['enable', 'disable']
- state:
- description:
- - Determines whether the config should be present or not
- on the device.
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = '''
-- name: vxlan global module test
- hosts: ce128
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Create bridge domain and set tunnel mode to VXLAN
- ce_vxlan_global:
- bridge_domain_id: 100
- nvo3_acl_extend: enable
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: verbose mode
- type: dict
- sample: {"bridge_domain_id": "100", "nvo3_acl_extend": "enable", state="present"}
-existing:
- description: k/v pairs of existing configuration
- returned: verbose mode
- type: dict
- sample: {"bridge_domain": {"80", "90"}, "nvo3_acl_extend": "disable"}
-end_state:
- description: k/v pairs of configuration after module execution
- returned: verbose mode
- type: dict
- sample: {"bridge_domain_id": {"80", "90", "100"}, "nvo3_acl_extend": "enable"}
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: ["bridge-domain 100",
- "ip tunnel mode vxlan"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import load_config
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import ce_argument_spec
-from ansible.module_utils.connection import exec_command
-
-
-def is_config_exist(cmp_cfg, test_cfg):
- """is configuration exist?"""
-
- if not cmp_cfg or not test_cfg:
- return False
-
- return bool(test_cfg in cmp_cfg)
-
-
-def get_nvo3_gw_enhanced(cmp_cfg):
- """get the Layer 3 VXLAN Gateway to Work in Non-loopback Mode """
-
- get = re.findall(
- r"assign forward nvo3-gateway enhanced (l[2|3])", cmp_cfg)
- if not get:
- return None
- else:
- return get[0]
-
-
-class VxlanGlobal(object):
- """
- Manages global attributes of VXLAN and bridge domain.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.tunnel_mode_vxlan = self.module.params['tunnel_mode_vxlan']
- self.nvo3_prevent_loops = self.module.params['nvo3_prevent_loops']
- self.nvo3_acl_extend = self.module.params['nvo3_acl_extend']
- self.nvo3_gw_enhanced = self.module.params['nvo3_gw_enhanced']
- self.nvo3_service_extend = self.module.params['nvo3_service_extend']
- self.nvo3_eth_trunk_hash = self.module.params['nvo3_eth_trunk_hash']
- self.nvo3_ecmp_hash = self.module.params['nvo3_ecmp_hash']
- self.bridge_domain_id = self.module.params['bridge_domain_id']
- self.state = self.module.params['state']
-
- # state
- self.config = "" # current config
- self.bd_info = list()
- self.changed = False
- self.updates_cmd = list()
- self.commands = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def init_module(self):
- """init module"""
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def cli_load_config(self, commands):
- """load config by cli"""
-
- if not self.module.check_mode:
- load_config(self.module, commands)
-
- def get_config(self, flags=None):
- """Retrieves the current config from the device or cache
- """
- flags = [] if flags is None else flags
-
- cmd = 'display current-configuration '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- rc, out, err = exec_command(self.module, cmd)
- if rc != 0:
- self.module.fail_json(msg=err)
- cfg = str(out).strip()
-
- return cfg
-
- def get_current_config(self):
- """get current configuration"""
-
- flags = list()
- exp = " include-default | include vxlan|assign | exclude undo"
- flags.append(exp)
- return self.get_config(flags)
-
- def cli_add_command(self, command, undo=False):
- """add command to self.update_cmd and self.commands"""
-
- if undo and command.lower() not in ["quit", "return"]:
- cmd = "undo " + command
- else:
- cmd = command
-
- self.commands.append(cmd) # set to device
- if command.lower() not in ["quit", "return"]:
- self.updates_cmd.append(cmd) # show updates result
-
- def get_bd_list(self):
- """get bridge domain list"""
- flags = list()
- bd_info = list()
- exp = " include-default | include bridge-domain | exclude undo"
- flags.append(exp)
- bd_str = self.get_config(flags)
- if not bd_str:
- return bd_info
- bd_num = re.findall(r'bridge-domain\s*([0-9]+)', bd_str)
- bd_info.extend(bd_num)
- return bd_info
-
- def config_bridge_domain(self):
- """manage bridge domain"""
-
- if not self.bridge_domain_id:
- return
-
- cmd = "bridge-domain %s" % self.bridge_domain_id
- exist = self.bridge_domain_id in self.bd_info
- if self.state == "present":
- if not exist:
- self.cli_add_command(cmd)
- self.cli_add_command("quit")
- else:
- if exist:
- self.cli_add_command(cmd, undo=True)
-
- def config_tunnel_mode(self):
- """config tunnel mode vxlan"""
-
- # ip tunnel mode vxlan
- if self.tunnel_mode_vxlan:
- cmd = "ip tunnel mode vxlan"
- exist = is_config_exist(self.config, cmd)
- if self.tunnel_mode_vxlan == "enable":
- if not exist:
- self.cli_add_command(cmd)
- else:
- if exist:
- self.cli_add_command(cmd, undo=True)
-
- def config_assign_forward(self):
- """config assign forward command"""
-
- # [undo] assign forward nvo3-gateway enhanced {l2|l3)
- if self.nvo3_gw_enhanced:
- cmd = "assign forward nvo3-gateway enhanced %s" % self.nvo3_gw_enhanced
- exist = is_config_exist(self.config, cmd)
- if self.state == "present":
- if not exist:
- self.cli_add_command(cmd)
- else:
- if exist:
- self.cli_add_command(cmd, undo=True)
-
- # [undo] assign forward nvo3 f-linecard compatibility enable
- if self.nvo3_prevent_loops:
- cmd = "assign forward nvo3 f-linecard compatibility enable"
- exist = is_config_exist(self.config, cmd)
- if self.nvo3_prevent_loops == "enable":
- if not exist:
- self.cli_add_command(cmd)
- else:
- if exist:
- self.cli_add_command(cmd, undo=True)
-
- # [undo] assign forward nvo3 acl extend enable
- if self.nvo3_acl_extend:
- cmd = "assign forward nvo3 acl extend enable"
- exist = is_config_exist(self.config, cmd)
- if self.nvo3_acl_extend == "enable":
- if not exist:
- self.cli_add_command(cmd)
- else:
- if exist:
- self.cli_add_command(cmd, undo=True)
-
- # [undo] assign forward nvo3 service extend enable
- if self.nvo3_service_extend:
- cmd = "assign forward nvo3 service extend enable"
- exist = is_config_exist(self.config, cmd)
- if self.nvo3_service_extend == "enable":
- if not exist:
- self.cli_add_command(cmd)
- else:
- if exist:
- self.cli_add_command(cmd, undo=True)
-
- # assign forward nvo3 eth-trunk hash {enable|disable}
- if self.nvo3_eth_trunk_hash:
- cmd = "assign forward nvo3 eth-trunk hash enable"
- exist = is_config_exist(self.config, cmd)
- if self.nvo3_eth_trunk_hash == "enable":
- if not exist:
- self.cli_add_command(cmd)
- else:
- if exist:
- self.cli_add_command(cmd, undo=True)
-
- # [undo] assign forward nvo3 ecmp hash enable
- if self.nvo3_ecmp_hash:
- cmd = "assign forward nvo3 ecmp hash enable"
- exist = is_config_exist(self.config, cmd)
- if self.nvo3_ecmp_hash == "enable":
- if not exist:
- self.cli_add_command(cmd)
- else:
- if exist:
- self.cli_add_command(cmd, undo=True)
-
- def check_params(self):
- """Check all input params"""
-
- # bridge domain id check
- if self.bridge_domain_id:
- if not self.bridge_domain_id.isdigit():
- self.module.fail_json(
- msg="Error: bridge domain id is not digit.")
- if int(self.bridge_domain_id) < 1 or int(self.bridge_domain_id) > 16777215:
- self.module.fail_json(
- msg="Error: bridge domain id is not in the range from 1 to 16777215.")
-
- def get_proposed(self):
- """get proposed info"""
-
- if self.tunnel_mode_vxlan:
- self.proposed["tunnel_mode_vxlan"] = self.tunnel_mode_vxlan
- if self.nvo3_prevent_loops:
- self.proposed["nvo3_prevent_loops"] = self.nvo3_prevent_loops
- if self.nvo3_acl_extend:
- self.proposed["nvo3_acl_extend"] = self.nvo3_acl_extend
- if self.nvo3_gw_enhanced:
- self.proposed["nvo3_gw_enhanced"] = self.nvo3_gw_enhanced
- if self.nvo3_service_extend:
- self.proposed["nvo3_service_extend"] = self.nvo3_service_extend
- if self.nvo3_eth_trunk_hash:
- self.proposed["nvo3_eth_trunk_hash"] = self.nvo3_eth_trunk_hash
- if self.nvo3_ecmp_hash:
- self.proposed["nvo3_ecmp_hash"] = self.nvo3_ecmp_hash
- if self.bridge_domain_id:
- self.proposed["bridge_domain_id"] = self.bridge_domain_id
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- self.existing["bridge_domain"] = self.bd_info
-
- cmd = "ip tunnel mode vxlan"
- exist = is_config_exist(self.config, cmd)
- if exist:
- self.existing["tunnel_mode_vxlan"] = "enable"
- else:
- self.existing["tunnel_mode_vxlan"] = "disable"
-
- cmd = "assign forward nvo3 f-linecard compatibility enable"
- exist = is_config_exist(self.config, cmd)
- if exist:
- self.existing["nvo3_prevent_loops"] = "enable"
- else:
- self.existing["nvo3_prevent_loops"] = "disable"
-
- cmd = "assign forward nvo3 acl extend enable"
- exist = is_config_exist(self.config, cmd)
- if exist:
- self.existing["nvo3_acl_extend"] = "enable"
- else:
- self.existing["nvo3_acl_extend"] = "disable"
-
- self.existing["nvo3_gw_enhanced"] = get_nvo3_gw_enhanced(
- self.config)
-
- cmd = "assign forward nvo3 service extend enable"
- exist = is_config_exist(self.config, cmd)
- if exist:
- self.existing["nvo3_service_extend"] = "enable"
- else:
- self.existing["nvo3_service_extend"] = "disable"
-
- cmd = "assign forward nvo3 eth-trunk hash enable"
- exist = is_config_exist(self.config, cmd)
- if exist:
- self.existing["nvo3_eth_trunk_hash"] = "enable"
- else:
- self.existing["nvo3_eth_trunk_hash"] = "disable"
-
- cmd = "assign forward nvo3 ecmp hash enable"
- exist = is_config_exist(self.config, cmd)
- if exist:
- self.existing["nvo3_ecmp_hash"] = "enable"
- else:
- self.existing["nvo3_ecmp_hash"] = "disable"
-
- def get_end_state(self):
- """get end state info"""
-
- config = self.get_current_config()
-
- self.end_state["bridge_domain"] = self.get_bd_list()
-
- cmd = "ip tunnel mode vxlan"
- exist = is_config_exist(config, cmd)
- if exist:
- self.end_state["tunnel_mode_vxlan"] = "enable"
- else:
- self.end_state["tunnel_mode_vxlan"] = "disable"
-
- cmd = "assign forward nvo3 f-linecard compatibility enable"
- exist = is_config_exist(config, cmd)
- if exist:
- self.end_state["nvo3_prevent_loops"] = "enable"
- else:
- self.end_state["nvo3_prevent_loops"] = "disable"
-
- cmd = "assign forward nvo3 acl extend enable"
- exist = is_config_exist(config, cmd)
- if exist:
- self.end_state["nvo3_acl_extend"] = "enable"
- else:
- self.end_state["nvo3_acl_extend"] = "disable"
-
- self.end_state["nvo3_gw_enhanced"] = get_nvo3_gw_enhanced(config)
-
- cmd = "assign forward nvo3 service extend enable"
- exist = is_config_exist(config, cmd)
- if exist:
- self.end_state["nvo3_service_extend"] = "enable"
- else:
- self.end_state["nvo3_service_extend"] = "disable"
-
- cmd = "assign forward nvo3 eth-trunk hash enable"
- exist = is_config_exist(config, cmd)
- if exist:
- self.end_state["nvo3_eth_trunk_hash"] = "enable"
- else:
- self.end_state["nvo3_eth_trunk_hash"] = "disable"
-
- cmd = "assign forward nvo3 ecmp hash enable"
- exist = is_config_exist(config, cmd)
- if exist:
- self.end_state["nvo3_ecmp_hash"] = "enable"
- else:
- self.end_state["nvo3_ecmp_hash"] = "disable"
- if self.existing == self.end_state:
- self.changed = True
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.config = self.get_current_config()
- self.bd_info = self.get_bd_list()
- self.get_existing()
- self.get_proposed()
-
- # deal present or absent
- self.config_bridge_domain()
- self.config_tunnel_mode()
- self.config_assign_forward()
- if self.commands:
- self.cli_load_config(self.commands)
- self.changed = True
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- tunnel_mode_vxlan=dict(required=False, type='str',
- choices=['enable', 'disable']),
- nvo3_prevent_loops=dict(required=False, type='str',
- choices=['enable', 'disable']),
- nvo3_acl_extend=dict(required=False, type='str',
- choices=['enable', 'disable']),
- nvo3_gw_enhanced=dict(required=False, type='str',
- choices=['l2', 'l3']),
- nvo3_service_extend=dict(required=False, type='str',
- choices=['enable', 'disable']),
- nvo3_eth_trunk_hash=dict(required=False, type='str',
- choices=['enable', 'disable']),
- nvo3_ecmp_hash=dict(required=False, type='str',
- choices=['enable', 'disable']),
- bridge_domain_id=dict(required=False, type='str'),
- state=dict(required=False, default='present',
- choices=['present', 'absent'])
- )
- argument_spec.update(ce_argument_spec)
- module = VxlanGlobal(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_vxlan_tunnel.py b/plugins/modules/network/cloudengine/ce_vxlan_tunnel.py
deleted file mode 100644
index 0ca5c15656..0000000000
--- a/plugins/modules/network/cloudengine/ce_vxlan_tunnel.py
+++ /dev/null
@@ -1,944 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_vxlan_tunnel
-short_description: Manages VXLAN tunnel configuration on HUAWEI CloudEngine devices.
-description:
- - This module offers the ability to set the VNI and mapped to the BD,
- and configure an ingress replication list on HUAWEI CloudEngine devices.
-author:
- - Li Yanfeng (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- bridge_domain_id:
- description:
- - Specifies a bridge domain ID. The value is an integer ranging from 1 to 16777215.
- vni_id:
- description:
- - Specifies a VXLAN network identifier (VNI) ID. The value is an integer ranging from 1 to 16000000.
- nve_name:
- description:
- - Specifies the number of an NVE interface. The value ranges from 1 to 2.
- nve_mode:
- description:
- - Specifies the working mode of an NVE interface.
- choices: ['mode-l2','mode-l3']
- peer_list_ip:
- description:
- - Specifies the IP address of a remote VXLAN tunnel endpoints (VTEP).
- The value is in dotted decimal notation.
- protocol_type:
- description:
- - The operation type of routing protocol.
- choices: ['bgp','null']
- source_ip:
- description:
- - Specifies an IP address for a source VTEP. The value is in dotted decimal notation.
- state:
- description:
- - Manage the state of the resource.
- default: present
- choices: ['present','absent']
-'''
-EXAMPLES = '''
-- name: vxlan tunnel module test
- hosts: ce128
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Make sure nve_name is exist, ensure vni_id and protocol_type is configured on Nve1 interface.
- ce_vxlan_tunnel:
- nve_name: Nve1
- vni_id: 100
- protocol_type: bgp
- state: present
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: always
- type: dict
- sample: {nve_interface_name": "Nve1", nve_mode": "mode-l2", "source_ip": "0.0.0.0"}
-existing:
- description:
- - k/v pairs of existing rollback
- returned: always
- type: dict
- sample: {nve_interface_name": "Nve1", nve_mode": "mode-l3", "source_ip": "0.0.0.0"}
-
-updates:
- description: command sent to the device
- returned: always
- type: list
- sample: ["interface Nve1",
- "mode l3"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-end_state:
- description: k/v pairs of configuration after module execution
- returned: always
- type: dict
- sample: {nve_interface_name": "Nve1", nve_mode": "mode-l3", "source_ip": "0.0.0.0"}
-'''
-import re
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-CE_NC_GET_VNI_BD_INFO = """
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_GET_NVE_INFO = """
-
-
-
-
- %s
-
-
-
-
-"""
-
-CE_NC_MERGE_VNI_BD_ID = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-CE_NC_DELETE_VNI_BD_ID = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-CE_NC_MERGE_NVE_MODE = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-CE_NC_MERGE_NVE_SOURCE_IP_PROTOCOL = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-CE_NC_MERGE_VNI_PEER_ADDRESS_IP_HEAD = """
-
-
-
-
- %s
-
-
- %s
-"""
-
-CE_NC_MERGE_VNI_PEER_ADDRESS_IP_END = """
-
-
-
-
-
-
-"""
-CE_NC_MERGE_VNI_PEER_ADDRESS_IP_MERGE = """
-
-
- %s
-
-
-"""
-
-CE_NC_DELETE_VNI_PEER_ADDRESS_IP_HEAD = """
-
-
-
-
- %s
-
-
- %s
-"""
-CE_NC_DELETE_VNI_PEER_ADDRESS_IP_END = """
-
-
-
-
-
-
-"""
-CE_NC_DELETE_VNI_PEER_ADDRESS_IP_DELETE = """
-
-
- %s
-
-
-"""
-
-CE_NC_DELETE_PEER_ADDRESS_IP_HEAD = """
-
-
-
-
- %s
-
-
- %s
-"""
-CE_NC_DELETE_PEER_ADDRESS_IP_END = """
-
-
-
-
-
-
-"""
-CE_NC_MERGE_VNI_PROTOCOL = """
-
-
-
-
- %s
-
-
- %s
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_DELETE_VNI_PROTOCOL = """
-
-
-
-
- %s
-
-
- %s
- %s
-
-
-
-
-
-
-"""
-
-
-def is_valid_address(address):
- """check ip-address is valid"""
-
- if address.find('.') != -1:
- addr_list = address.split('.')
- if len(addr_list) != 4:
- return False
- for each_num in addr_list:
- if not each_num.isdigit():
- return False
- if int(each_num) > 255:
- return False
- return True
-
- return False
-
-
-class VxlanTunnel(object):
- """
- Manages vxlan tunnel configuration.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.init_module()
-
- # module input info
- self.bridge_domain_id = self.module.params['bridge_domain_id']
- self.vni_id = self.module.params['vni_id']
- self.nve_name = self.module.params['nve_name']
- self.nve_mode = self.module.params['nve_mode']
- self.peer_list_ip = self.module.params['peer_list_ip']
- self.protocol_type = self.module.params['protocol_type']
- self.source_ip = self.module.params['source_ip']
- self.state = self.module.params['state']
-
- # state
- self.changed = False
- self.updates_cmd = list()
- self.results = dict()
- self.existing = dict()
- self.proposed = dict()
- self.end_state = dict()
-
- # configuration nve info
- self.vni2bd_info = None
- self.nve_info = None
-
- def init_module(self):
- """ init module """
-
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_vni2bd_dict(self):
- """ get vni2bd attributes dict."""
-
- vni2bd_info = dict()
- # get vni bd info
- conf_str = CE_NC_GET_VNI_BD_INFO
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return vni2bd_info
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
- # get vni to bridge domain id info
- root = ElementTree.fromstring(xml_str)
- vni2bd_info["vni2BdInfos"] = list()
- vni2bds = root.findall("nvo3/nvo3Vni2Bds/nvo3Vni2Bd")
-
- if vni2bds:
- for vni2bd in vni2bds:
- vni_dict = dict()
- for ele in vni2bd:
- if ele.tag in ["vniId", "bdId"]:
- vni_dict[ele.tag] = ele.text
- vni2bd_info["vni2BdInfos"].append(vni_dict)
-
- return vni2bd_info
-
- def check_nve_interface(self, nve_name):
- """is nve interface exist"""
-
- if not self.nve_info:
- return False
-
- if self.nve_info["ifName"] == nve_name:
- return True
- return False
-
- def get_nve_dict(self, nve_name):
- """ get nve interface attributes dict."""
-
- nve_info = dict()
- # get nve info
- conf_str = CE_NC_GET_NVE_INFO % nve_name
- xml_str = get_nc_config(self.module, conf_str)
- if "" in xml_str:
- return nve_info
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get nve info
- root = ElementTree.fromstring(xml_str)
-
- nvo3 = root.find("nvo3/nvo3Nves/nvo3Nve")
- if nvo3:
- for nve in nvo3:
- if nve.tag in ["srcAddr", "ifName", "nveType"]:
- nve_info[nve.tag] = nve.text
-
- # get nve vni info
- nve_info["vni_peer_protocols"] = list()
-
- vni_members = root.findall(
- "nvo3/nvo3Nves/nvo3Nve/vniMembers/vniMember")
- if vni_members:
- for member in vni_members:
- vni_dict = dict()
- for ele in member:
- if ele.tag in ["vniId", "protocol"]:
- vni_dict[ele.tag] = ele.text
- nve_info["vni_peer_protocols"].append(vni_dict)
-
- # get vni peer address ip info
- nve_info["vni_peer_ips"] = list()
-
- re_find = re.findall(r'(.*?)\s*'
- r'(.*?)\s*'
- r'(.*?)', xml_str)
-
- if re_find:
- for vni_peers in re_find:
- vni_info = dict()
- vni_peer = re.findall(r'(.*?)', vni_peers[2])
- if vni_peer:
- vni_info["vniId"] = vni_peers[0]
- vni_peer_list = list()
- for peer in vni_peer:
- vni_peer_list.append(peer)
- vni_info["peerAddr"] = vni_peer_list
- nve_info["vni_peer_ips"].append(vni_info)
-
- return nve_info
-
- def check_nve_name(self):
- """Gets Nve interface name"""
-
- if self.nve_name is None:
- return False
- if self.nve_name in ["Nve1", "Nve2"]:
- return True
- return False
-
- def is_vni_bd_exist(self, vni_id, bd_id):
- """is vni to bridge-domain-id exist"""
-
- if not self.vni2bd_info:
- return False
-
- for vni2bd in self.vni2bd_info["vni2BdInfos"]:
- if vni2bd["vniId"] == vni_id and vni2bd["bdId"] == bd_id:
- return True
- return False
-
- def is_vni_bd_change(self, vni_id, bd_id):
- """is vni to bridge-domain-id change"""
-
- if not self.vni2bd_info:
- return True
-
- for vni2bd in self.vni2bd_info["vni2BdInfos"]:
- if vni2bd["vniId"] == vni_id and vni2bd["bdId"] == bd_id:
- return False
- return True
-
- def is_nve_mode_exist(self, nve_name, mode):
- """is nve interface mode exist"""
-
- if not self.nve_info:
- return False
-
- if self.nve_info["ifName"] == nve_name and self.nve_info["nveType"] == mode:
- return True
- return False
-
- def is_nve_mode_change(self, nve_name, mode):
- """is nve interface mode change"""
-
- if not self.nve_info:
- return True
-
- if self.nve_info["ifName"] == nve_name and self.nve_info["nveType"] == mode:
- return False
- return True
-
- def is_nve_source_ip_exist(self, nve_name, source_ip):
- """is vni to bridge-domain-id exist"""
-
- if not self.nve_info:
- return False
-
- if self.nve_info["ifName"] == nve_name and self.nve_info["srcAddr"] == source_ip:
- return True
- return False
-
- def is_nve_source_ip_change(self, nve_name, source_ip):
- """is vni to bridge-domain-id change"""
-
- if not self.nve_info:
- return True
-
- if self.nve_info["ifName"] == nve_name and self.nve_info["srcAddr"] == source_ip:
- return False
- return True
-
- def is_vni_protocol_exist(self, nve_name, vni_id, protocol_type):
- """is vni protocol exist"""
-
- if not self.nve_info:
- return False
- if self.nve_info["ifName"] == nve_name:
- for member in self.nve_info["vni_peer_protocols"]:
- if member["vniId"] == vni_id and member["protocol"] == protocol_type:
- return True
- return False
-
- def is_vni_protocol_change(self, nve_name, vni_id, protocol_type):
- """is vni protocol change"""
-
- if not self.nve_info:
- return True
- if self.nve_info["ifName"] == nve_name:
- for member in self.nve_info["vni_peer_protocols"]:
- if member["vniId"] == vni_id and member["protocol"] == protocol_type:
- return False
- return True
-
- def is_vni_peer_list_exist(self, nve_name, vni_id, peer_ip):
- """is vni peer list exist"""
-
- if not self.nve_info:
- return False
- if self.nve_info["ifName"] == nve_name:
- for member in self.nve_info["vni_peer_ips"]:
- if member["vniId"] == vni_id and peer_ip in member["peerAddr"]:
- return True
- return False
-
- def is_vni_peer_list_change(self, nve_name, vni_id, peer_ip_list):
- """is vni peer list change"""
-
- if not self.nve_info:
- return True
-
- if self.nve_info["ifName"] == nve_name:
- if not self.nve_info["vni_peer_ips"]:
- return True
-
- nve_peer_info = list()
- for nve_peer in self.nve_info["vni_peer_ips"]:
- if nve_peer["vniId"] == vni_id:
- nve_peer_info.append(nve_peer)
-
- if not nve_peer_info:
- return True
-
- nve_peer_list = nve_peer_info[0]["peerAddr"]
- for peer in peer_ip_list:
- if peer not in nve_peer_list:
- return True
-
- return False
-
- def config_merge_vni2bd(self, bd_id, vni_id):
- """config vni to bd id"""
-
- if self.is_vni_bd_change(vni_id, bd_id):
- cfg_xml = CE_NC_MERGE_VNI_BD_ID % (vni_id, bd_id)
- recv_xml = set_nc_config(self.module, cfg_xml)
- self.check_response(recv_xml, "MERGE_VNI_BD")
- self.updates_cmd.append("bridge-domain %s" % bd_id)
- self.updates_cmd.append("vxlan vni %s" % vni_id)
- self.changed = True
-
- def config_merge_mode(self, nve_name, mode):
- """config nve mode"""
-
- if self.is_nve_mode_change(nve_name, mode):
- cfg_xml = CE_NC_MERGE_NVE_MODE % (nve_name, mode)
- recv_xml = set_nc_config(self.module, cfg_xml)
- self.check_response(recv_xml, "MERGE_MODE")
- self.updates_cmd.append("interface %s" % nve_name)
- if mode == "mode-l3":
- self.updates_cmd.append("mode l3")
- else:
- self.updates_cmd.append("undo mode l3")
- self.changed = True
-
- def config_merge_source_ip(self, nve_name, source_ip):
- """config nve source ip"""
-
- if self.is_nve_source_ip_change(nve_name, source_ip):
- cfg_xml = CE_NC_MERGE_NVE_SOURCE_IP_PROTOCOL % (
- nve_name, source_ip)
- recv_xml = set_nc_config(self.module, cfg_xml)
- self.check_response(recv_xml, "MERGE_SOURCE_IP")
- self.updates_cmd.append("interface %s" % nve_name)
- self.updates_cmd.append("source %s" % source_ip)
- self.changed = True
-
- def config_merge_vni_peer_ip(self, nve_name, vni_id, peer_ip_list):
- """config vni peer ip"""
-
- if self.is_vni_peer_list_change(nve_name, vni_id, peer_ip_list):
- cfg_xml = CE_NC_MERGE_VNI_PEER_ADDRESS_IP_HEAD % (
- nve_name, vni_id)
- for peer_ip in peer_ip_list:
- cfg_xml += CE_NC_MERGE_VNI_PEER_ADDRESS_IP_MERGE % peer_ip
- cfg_xml += CE_NC_MERGE_VNI_PEER_ADDRESS_IP_END
- recv_xml = set_nc_config(self.module, cfg_xml)
- self.check_response(recv_xml, "MERGE_VNI_PEER_IP")
- self.updates_cmd.append("interface %s" % nve_name)
-
- for peer_ip in peer_ip_list:
- cmd_output = "vni %s head-end peer-list %s" % (vni_id, peer_ip)
- self.updates_cmd.append(cmd_output)
- self.changed = True
-
- def config_merge_vni_protocol_type(self, nve_name, vni_id, protocol_type):
- """config vni protocol type"""
-
- if self.is_vni_protocol_change(nve_name, vni_id, protocol_type):
- cfg_xml = CE_NC_MERGE_VNI_PROTOCOL % (
- nve_name, vni_id, protocol_type)
- recv_xml = set_nc_config(self.module, cfg_xml)
- self.check_response(recv_xml, "MERGE_VNI_PEER_PROTOCOL")
- self.updates_cmd.append("interface %s" % nve_name)
-
- if protocol_type == "bgp":
- self.updates_cmd.append(
- "vni %s head-end peer-list protocol %s" % (vni_id, protocol_type))
- else:
- self.updates_cmd.append(
- "undo vni %s head-end peer-list protocol bgp" % vni_id)
- self.changed = True
-
- def config_delete_vni2bd(self, bd_id, vni_id):
- """remove vni to bd id"""
-
- if not self.is_vni_bd_exist(vni_id, bd_id):
- return
- cfg_xml = CE_NC_DELETE_VNI_BD_ID % (vni_id, bd_id)
- recv_xml = set_nc_config(self.module, cfg_xml)
- self.check_response(recv_xml, "DELETE_VNI_BD")
- self.updates_cmd.append(
- "bridge-domain %s" % bd_id)
- self.updates_cmd.append(
- "undo vxlan vni %s" % vni_id)
-
- self.changed = True
-
- def config_delete_mode(self, nve_name, mode):
- """nve mode"""
-
- if mode == "mode-l3":
- if not self.is_nve_mode_exist(nve_name, mode):
- return
- cfg_xml = CE_NC_MERGE_NVE_MODE % (nve_name, "mode-l2")
-
- recv_xml = set_nc_config(self.module, cfg_xml)
- self.check_response(recv_xml, "DELETE_MODE")
- self.updates_cmd.append("interface %s" % nve_name)
- self.updates_cmd.append("undo mode l3")
- self.changed = True
- else:
- self.module.fail_json(
- msg='Error: Can not configure undo mode l2.')
-
- def config_delete_source_ip(self, nve_name, source_ip):
- """nve source ip"""
-
- if not self.is_nve_source_ip_exist(nve_name, source_ip):
- return
- ipaddr = "0.0.0.0"
- cfg_xml = CE_NC_MERGE_NVE_SOURCE_IP_PROTOCOL % (
- nve_name, ipaddr)
- recv_xml = set_nc_config(self.module, cfg_xml)
- self.check_response(recv_xml, "DELETE_SOURCE_IP")
- self.updates_cmd.append("interface %s" % nve_name)
- self.updates_cmd.append("undo source %s" % source_ip)
- self.changed = True
-
- def config_delete_vni_peer_ip(self, nve_name, vni_id, peer_ip_list):
- """remove vni peer ip"""
-
- for peer_ip in peer_ip_list:
- if not self.is_vni_peer_list_exist(nve_name, vni_id, peer_ip):
- self.module.fail_json(msg='Error: The %s does not exist' % peer_ip)
-
- config = False
-
- nve_peer_info = list()
- for nve_peer in self.nve_info["vni_peer_ips"]:
- if nve_peer["vniId"] == vni_id:
- nve_peer_info = nve_peer.get("peerAddr")
- for peer in nve_peer_info:
- if peer not in peer_ip_list:
- config = True
-
- if not config:
- cfg_xml = CE_NC_DELETE_VNI_PEER_ADDRESS_IP_HEAD % (
- nve_name, vni_id)
- for peer_ip in peer_ip_list:
- cfg_xml += CE_NC_DELETE_VNI_PEER_ADDRESS_IP_DELETE % peer_ip
- cfg_xml += CE_NC_DELETE_VNI_PEER_ADDRESS_IP_END
- else:
- cfg_xml = CE_NC_DELETE_PEER_ADDRESS_IP_HEAD % (
- nve_name, vni_id)
- for peer_ip in peer_ip_list:
- cfg_xml += CE_NC_DELETE_VNI_PEER_ADDRESS_IP_DELETE % peer_ip
- cfg_xml += CE_NC_DELETE_PEER_ADDRESS_IP_END
-
- recv_xml = set_nc_config(self.module, cfg_xml)
- self.check_response(recv_xml, "DELETE_VNI_PEER_IP")
- self.updates_cmd.append("interface %s" % nve_name)
-
- for peer_ip in peer_ip_list:
- cmd_output = "undo vni %s head-end peer-list %s" % (vni_id, peer_ip)
- self.updates_cmd.append(cmd_output)
-
- self.changed = True
-
- def config_delete_vni_protocol_type(self, nve_name, vni_id, protocol_type):
- """remove vni protocol type"""
-
- if not self.is_vni_protocol_exist(nve_name, vni_id, protocol_type):
- return
-
- cfg_xml = CE_NC_DELETE_VNI_PROTOCOL % (nve_name, vni_id, protocol_type)
- recv_xml = set_nc_config(self.module, cfg_xml)
- self.check_response(recv_xml, "DELETE_VNI_PEER_PROTOCOL")
- self.updates_cmd.append("interface %s" % nve_name)
- self.updates_cmd.append(
- "undo vni %s head-end peer-list protocol bgp " % vni_id)
- self.changed = True
-
- def check_params(self):
- """Check all input params"""
-
- # bridge_domain_id check
- if self.bridge_domain_id:
- if not self.bridge_domain_id.isdigit():
- self.module.fail_json(
- msg='Error: The parameter of bridge domain id is invalid.')
- if int(self.bridge_domain_id) > 16777215 or int(self.bridge_domain_id) < 1:
- self.module.fail_json(
- msg='Error: The bridge domain id must be an integer between 1 and 16777215.')
- # vni_id check
- if self.vni_id:
- if not self.vni_id.isdigit():
- self.module.fail_json(
- msg='Error: The parameter of vni id is invalid.')
- if int(self.vni_id) > 16000000 or int(self.vni_id) < 1:
- self.module.fail_json(
- msg='Error: The vni id must be an integer between 1 and 16000000.')
-
- # nve_name check
- if self.nve_name:
- if not self.check_nve_name():
- self.module.fail_json(
- msg='Error: Error: NVE interface %s is invalid.' % self.nve_name)
-
- # peer_list_ip check
- if self.peer_list_ip:
- for peer_ip in self.peer_list_ip:
- if not is_valid_address(peer_ip):
- self.module.fail_json(
- msg='Error: The ip address %s is invalid.' % self.peer_list_ip)
- # source_ip check
- if self.source_ip:
- if not is_valid_address(self.source_ip):
- self.module.fail_json(
- msg='Error: The ip address %s is invalid.' % self.source_ip)
-
- def get_proposed(self):
- """get proposed info"""
-
- if self.bridge_domain_id:
- self.proposed["bridge_domain_id"] = self.bridge_domain_id
- if self.vni_id:
- self.proposed["vni_id"] = self.vni_id
- if self.nve_name:
- self.proposed["nve_name"] = self.nve_name
- if self.nve_mode:
- self.proposed["nve_mode"] = self.nve_mode
- if self.peer_list_ip:
- self.proposed["peer_list_ip"] = self.peer_list_ip
- if self.source_ip:
- self.proposed["source_ip"] = self.source_ip
- if self.state:
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- if self.vni2bd_info:
- self.existing["vni_to_bridge_domain"] = self.vni2bd_info[
- "vni2BdInfos"]
-
- if self.nve_info:
- self.existing["nve_interface_name"] = self.nve_info["ifName"]
- self.existing["source_ip"] = self.nve_info["srcAddr"]
- self.existing["nve_mode"] = self.nve_info["nveType"]
- self.existing["vni_peer_list_ip"] = self.nve_info[
- "vni_peer_ips"]
- self.existing["vni_peer_list_protocol"] = self.nve_info[
- "vni_peer_protocols"]
-
- def get_end_state(self):
- """get end state info"""
-
- vni2bd_info = self.get_vni2bd_dict()
- if vni2bd_info:
- self.end_state["vni_to_bridge_domain"] = vni2bd_info["vni2BdInfos"]
-
- nve_info = self.get_nve_dict(self.nve_name)
- if nve_info:
- self.end_state["nve_interface_name"] = nve_info["ifName"]
- self.end_state["source_ip"] = nve_info["srcAddr"]
- self.end_state["nve_mode"] = nve_info["nveType"]
- self.end_state["vni_peer_list_ip"] = nve_info[
- "vni_peer_ips"]
- self.end_state["vni_peer_list_protocol"] = nve_info[
- "vni_peer_protocols"]
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.vni2bd_info = self.get_vni2bd_dict()
- if self.nve_name:
- self.nve_info = self.get_nve_dict(self.nve_name)
- self.get_existing()
- self.get_proposed()
- # deal present or absent
- if self.state == "present":
- if self.bridge_domain_id and self.vni_id:
- self.config_merge_vni2bd(self.bridge_domain_id, self.vni_id)
- if self.nve_name:
- if self.check_nve_interface(self.nve_name):
- if self.nve_mode:
- self.config_merge_mode(self.nve_name, self.nve_mode)
- if self.source_ip:
- self.config_merge_source_ip(
- self.nve_name, self.source_ip)
- if self.vni_id and self.peer_list_ip:
- self.config_merge_vni_peer_ip(
- self.nve_name, self.vni_id, self.peer_list_ip)
- if self.vni_id and self.protocol_type:
- self.config_merge_vni_protocol_type(
- self.nve_name, self.vni_id, self.protocol_type)
- else:
- self.module.fail_json(
- msg='Error: Nve interface %s does not exist.' % self.nve_name)
-
- else:
- if self.bridge_domain_id and self.vni_id:
- self.config_delete_vni2bd(self.bridge_domain_id, self.vni_id)
- if self.nve_name:
- if self.check_nve_interface(self.nve_name):
- if self.nve_mode:
- self.config_delete_mode(self.nve_name, self.nve_mode)
- if self.source_ip:
- self.config_delete_source_ip(
- self.nve_name, self.source_ip)
- if self.vni_id and self.peer_list_ip:
- self.config_delete_vni_peer_ip(
- self.nve_name, self.vni_id, self.peer_list_ip)
- if self.vni_id and self.protocol_type:
- self.config_delete_vni_protocol_type(
- self.nve_name, self.vni_id, self.protocol_type)
- else:
- self.module.fail_json(
- msg='Error: Nve interface %s does not exist.' % self.nve_name)
-
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
-
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- bridge_domain_id=dict(required=False),
- vni_id=dict(required=False, type='str'),
- nve_name=dict(required=False, type='str'),
- nve_mode=dict(required=False, choices=['mode-l2', 'mode-l3']),
- peer_list_ip=dict(required=False, type='list'),
- protocol_type=dict(required=False, type='str', choices=[
- 'bgp', 'null']),
-
- source_ip=dict(required=False),
- state=dict(required=False, default='present',
- choices=['present', 'absent'])
- )
- argument_spec.update(ce_argument_spec)
- module = VxlanTunnel(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudengine/ce_vxlan_vap.py b/plugins/modules/network/cloudengine/ce_vxlan_vap.py
deleted file mode 100644
index a25ee3d8c5..0000000000
--- a/plugins/modules/network/cloudengine/ce_vxlan_vap.py
+++ /dev/null
@@ -1,937 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ce_vxlan_vap
-short_description: Manages VXLAN virtual access point on HUAWEI CloudEngine Devices.
-description:
- - Manages VXLAN Virtual access point on HUAWEI CloudEngine Devices.
-author: QijunPan (@QijunPan)
-notes:
- - This module requires the netconf system service be enabled on the remote device being managed.
- - Recommended connection is C(netconf).
- - This module also works with C(local) connections for legacy playbooks.
-options:
- bridge_domain_id:
- description:
- - Specifies a bridge domain ID.
- The value is an integer ranging from 1 to 16777215.
- bind_vlan_id:
- description:
- - Specifies the VLAN binding to a BD(Bridge Domain).
- The value is an integer ranging ranging from 1 to 4094.
- l2_sub_interface:
- description:
- - Specifies an Sub-Interface full name, i.e. "10GE1/0/41.1".
- The value is a string of 1 to 63 case-insensitive characters, spaces supported.
- encapsulation:
- description:
- - Specifies an encapsulation type of packets allowed to pass through a Layer 2 sub-interface.
- choices: ['dot1q', 'default', 'untag', 'qinq', 'none']
- ce_vid:
- description:
- - When I(encapsulation) is 'dot1q', specifies a VLAN ID in the outer VLAN tag.
- When I(encapsulation) is 'qinq', specifies an outer VLAN ID for
- double-tagged packets to be received by a Layer 2 sub-interface.
- The value is an integer ranging from 1 to 4094.
- pe_vid:
- description:
- - When I(encapsulation) is 'qinq', specifies an inner VLAN ID for
- double-tagged packets to be received by a Layer 2 sub-interface.
- The value is an integer ranging from 1 to 4094.
- state:
- description:
- - Determines whether the config should be present or not
- on the device.
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = '''
-- name: vxlan vap module test
- hosts: ce128
- connection: local
- gather_facts: no
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: "{{ ansible_ssh_port }}"
- username: "{{ username }}"
- password: "{{ password }}"
- transport: cli
-
- tasks:
-
- - name: Create a mapping between a VLAN and a BD
- ce_vxlan_vap:
- bridge_domain_id: 100
- bind_vlan_id: 99
- provider: "{{ cli }}"
-
- - name: Bind a Layer 2 sub-interface to a BD
- ce_vxlan_vap:
- bridge_domain_id: 100
- l2_sub_interface: 10GE2/0/20.1
- provider: "{{ cli }}"
-
- - name: Configure an encapsulation type on a Layer 2 sub-interface
- ce_vxlan_vap:
- l2_sub_interface: 10GE2/0/20.1
- encapsulation: dot1q
- provider: "{{ cli }}"
-'''
-
-RETURN = '''
-proposed:
- description: k/v pairs of parameters passed into module
- returned: verbose mode
- type: dict
- sample: {"bridge_domain_id": "100", "bind_vlan_id": "99", state="present"}
-existing:
- description: k/v pairs of existing configuration
- returned: verbose mode
- type: dict
- sample: {"bridge_domain_id": "100", "bind_intf_list": ["10GE2/0/20.1", "10GE2/0/20.2"],
- "bind_vlan_list": []}
-end_state:
- description: k/v pairs of configuration after module execution
- returned: verbose mode
- type: dict
- sample: {"bridge_domain_id": "100", "bind_intf_list": ["110GE2/0/20.1", "10GE2/0/20.2"],
- "bind_vlan_list": ["99"]}
-updates:
- description: commands sent to the device
- returned: always
- type: list
- sample: ["bridge-domain 100",
- "l2 binding vlan 99"]
-changed:
- description: check to see if a change was made on the device
- returned: always
- type: bool
- sample: true
-'''
-
-from xml.etree import ElementTree
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec
-
-CE_NC_GET_BD_VAP = """
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_MERGE_BD_VLAN = """
-
-
-
-
- %s
-
- %s:%s
-
-
-
-
-
-"""
-
-CE_NC_MERGE_BD_INTF = """
-
-
-
-
- %s
-
-
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_DELETE_BD_INTF = """
-
-
-
-
- %s
-
-
- %s
-
-
-
-
-
-
-"""
-
-CE_NC_GET_ENCAP = """
-
-
-
-
- %s
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-CE_NC_SET_ENCAP = """
-
-
-
-
- %s
- %s
-
-
-
-
-"""
-
-CE_NC_UNSET_ENCAP = """
-
-
-
-
- %s
- none
-
-
-
-
-"""
-
-CE_NC_SET_ENCAP_DOT1Q = """
-
-
-
-
- %s
- dot1q
-
- %s:%s
-
-
-
-
-
-"""
-
-CE_NC_SET_ENCAP_QINQ = """
-
-
-
-
- %s
- qinq
-
-
- %s
- %s:%s
-
-
-
-
-
-
-"""
-
-
-def vlan_vid_to_bitmap(vid):
- """convert VLAN list to VLAN bitmap"""
-
- vlan_bit = ['0'] * 1024
- int_vid = int(vid)
- j = int_vid // 4
- bit_int = 0x8 >> (int_vid % 4)
- vlan_bit[j] = str(hex(bit_int))[2]
-
- return ''.join(vlan_bit)
-
-
-def bitmap_to_vlan_list(bitmap):
- """convert VLAN bitmap to VLAN list"""
-
- tmp = list()
- if not bitmap:
- return tmp
-
- bit_len = len(bitmap)
- for i in range(bit_len):
- if bitmap[i] == "0":
- continue
- bit = int(bitmap[i])
- if bit & 0x8:
- tmp.append(str(i * 4))
- if bit & 0x4:
- tmp.append(str(i * 4 + 1))
- if bit & 0x2:
- tmp.append(str(i * 4 + 2))
- if bit & 0x1:
- tmp.append(str(i * 4 + 3))
-
- return tmp
-
-
-def is_vlan_bitmap_empty(bitmap):
- """check VLAN bitmap empty"""
-
- if not bitmap or len(bitmap) == 0:
- return True
-
- for bit in bitmap:
- if bit != '0':
- return False
-
- return True
-
-
-def is_vlan_in_bitmap(vid, bitmap):
- """check is VLAN id in bitmap"""
-
- if is_vlan_bitmap_empty(bitmap):
- return False
-
- i = int(vid) // 4
- if i > len(bitmap):
- return False
-
- if int(bitmap[i]) & (0x8 >> (int(vid) % 4)):
- return True
-
- return False
-
-
-def get_interface_type(interface):
- """Gets the type of interface, such as 10GE, ETH-TRUNK, VLANIF..."""
-
- if interface is None:
- return None
-
- iftype = None
-
- if interface.upper().startswith('GE'):
- iftype = 'ge'
- elif interface.upper().startswith('10GE'):
- iftype = '10ge'
- elif interface.upper().startswith('25GE'):
- iftype = '25ge'
- elif interface.upper().startswith('4X10GE'):
- iftype = '4x10ge'
- elif interface.upper().startswith('40GE'):
- iftype = '40ge'
- elif interface.upper().startswith('100GE'):
- iftype = '100ge'
- elif interface.upper().startswith('VLANIF'):
- iftype = 'vlanif'
- elif interface.upper().startswith('LOOPBACK'):
- iftype = 'loopback'
- elif interface.upper().startswith('METH'):
- iftype = 'meth'
- elif interface.upper().startswith('ETH-TRUNK'):
- iftype = 'eth-trunk'
- elif interface.upper().startswith('VBDIF'):
- iftype = 'vbdif'
- elif interface.upper().startswith('NVE'):
- iftype = 'nve'
- elif interface.upper().startswith('TUNNEL'):
- iftype = 'tunnel'
- elif interface.upper().startswith('ETHERNET'):
- iftype = 'ethernet'
- elif interface.upper().startswith('FCOE-PORT'):
- iftype = 'fcoe-port'
- elif interface.upper().startswith('FABRIC-PORT'):
- iftype = 'fabric-port'
- elif interface.upper().startswith('STACK-PORT'):
- iftype = 'stack-Port'
- elif interface.upper().startswith('NULL'):
- iftype = 'null'
- else:
- return None
-
- return iftype.lower()
-
-
-class VxlanVap(object):
- """
- Manages VXLAN virtual access point.
- """
-
- def __init__(self, argument_spec):
- self.spec = argument_spec
- self.module = None
- self.__init_module__()
-
- # module input info
- self.bridge_domain_id = self.module.params['bridge_domain_id']
- self.bind_vlan_id = self.module.params['bind_vlan_id']
- self.l2_sub_interface = self.module.params['l2_sub_interface']
- self.ce_vid = self.module.params['ce_vid']
- self.pe_vid = self.module.params['pe_vid']
- self.encapsulation = self.module.params['encapsulation']
- self.state = self.module.params['state']
-
- # state
- self.vap_info = dict()
- self.l2sub_info = dict()
- self.changed = False
- self.updates_cmd = list()
- self.commands = list()
- self.results = dict()
- self.proposed = dict()
- self.existing = dict()
- self.end_state = dict()
-
- def __init_module__(self):
- """init module"""
-
- required_together = [()]
- self.module = AnsibleModule(
- argument_spec=self.spec, supports_check_mode=True)
-
- def check_response(self, xml_str, xml_name):
- """Check if response message is already succeed."""
-
- if "" not in xml_str:
- self.module.fail_json(msg='Error: %s failed.' % xml_name)
-
- def get_bd_vap_dict(self):
- """get virtual access point info"""
-
- vap_info = dict()
- conf_str = CE_NC_GET_BD_VAP % self.bridge_domain_id
- xml_str = get_nc_config(self.module, conf_str)
-
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get vap: VLAN
- vap_info["bdId"] = self.bridge_domain_id
- root = ElementTree.fromstring(xml_str)
- vap_info["vlanList"] = ""
- vap_vlan = root.find("evc/bds/bd/bdBindVlan")
- if vap_vlan:
- for ele in vap_vlan:
- if ele.tag == "vlanList":
- vap_info["vlanList"] = ele.text
-
- # get vap: l2 su-interface
- vap_ifs = root.findall(
- "evc/bds/bd/servicePoints/servicePoint/ifName")
- if_list = list()
- if vap_ifs:
- for vap_if in vap_ifs:
- if vap_if.tag == "ifName":
- if_list.append(vap_if.text)
- vap_info["intfList"] = if_list
-
- return vap_info
-
- def get_l2_sub_intf_dict(self, ifname):
- """get l2 sub-interface info"""
-
- intf_info = dict()
- if not ifname:
- return intf_info
-
- conf_str = CE_NC_GET_ENCAP % ifname
- xml_str = get_nc_config(self.module, conf_str)
-
- if "" in xml_str:
- return intf_info
-
- xml_str = xml_str.replace('\r', '').replace('\n', '').\
- replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
- replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
-
- # get l2 sub interface encapsulation info
- root = ElementTree.fromstring(xml_str)
- bds = root.find("ethernet/servicePoints/servicePoint")
- if not bds:
- return intf_info
-
- for ele in bds:
- if ele.tag in ["ifName", "flowType"]:
- intf_info[ele.tag] = ele.text.lower()
-
- if intf_info.get("flowType") == "dot1q":
- ce_vid = root.find(
- "ethernet/servicePoints/servicePoint/flowDot1qs")
- intf_info["dot1qVids"] = ""
- if ce_vid:
- for ele in ce_vid:
- if ele.tag == "dot1qVids":
- intf_info["dot1qVids"] = ele.text
- elif intf_info.get("flowType") == "qinq":
- vids = root.find(
- "ethernet/servicePoints/servicePoint/flowQinqs/flowQinq")
- if vids:
- for ele in vids:
- if ele.tag in ["peVlanId", "ceVids"]:
- intf_info[ele.tag] = ele.text
-
- return intf_info
-
- def config_traffic_encap_dot1q(self):
- """configure traffic encapsulation type dot1q"""
-
- xml_str = ""
- self.updates_cmd.append("interface %s" % self.l2_sub_interface)
- if self.state == "present":
- if self.encapsulation != self.l2sub_info.get("flowType"):
- if self.ce_vid:
- vlan_bitmap = vlan_vid_to_bitmap(self.ce_vid)
- xml_str = CE_NC_SET_ENCAP_DOT1Q % (
- self.l2_sub_interface, vlan_bitmap, vlan_bitmap)
- self.updates_cmd.append("encapsulation %s vid %s" % (
- self.encapsulation, self.ce_vid))
- else:
- xml_str = CE_NC_SET_ENCAP % (
- self.l2_sub_interface, self.encapsulation)
- self.updates_cmd.append(
- "encapsulation %s" % self.encapsulation)
- else:
- if self.ce_vid and not is_vlan_in_bitmap(
- self.ce_vid, self.l2sub_info.get("dot1qVids")):
- vlan_bitmap = vlan_vid_to_bitmap(self.ce_vid)
- xml_str = CE_NC_SET_ENCAP_DOT1Q % (
- self.l2_sub_interface, vlan_bitmap, vlan_bitmap)
- self.updates_cmd.append("encapsulation %s vid %s" % (
- self.encapsulation, self.ce_vid))
- else:
- if self.encapsulation == self.l2sub_info.get("flowType"):
- if self.ce_vid:
- if is_vlan_in_bitmap(self.ce_vid, self.l2sub_info.get("dot1qVids")):
- xml_str = CE_NC_UNSET_ENCAP % self.l2_sub_interface
- self.updates_cmd.append("undo encapsulation %s vid %s" % (
- self.encapsulation, self.ce_vid))
- else:
- xml_str = CE_NC_UNSET_ENCAP % self.l2_sub_interface
- self.updates_cmd.append(
- "undo encapsulation %s" % self.encapsulation)
-
- if not xml_str:
- self.updates_cmd.pop()
- return
- recv_xml = set_nc_config(self.module, xml_str)
- self.check_response(recv_xml, "CONFIG_INTF_ENCAP_DOT1Q")
- self.changed = True
-
- def config_traffic_encap_qinq(self):
- """configure traffic encapsulation type qinq"""
-
- xml_str = ""
- self.updates_cmd.append("interface %s" % self.l2_sub_interface)
- if self.state == "present":
- if self.encapsulation != self.l2sub_info.get("flowType"):
- if self.ce_vid:
- vlan_bitmap = vlan_vid_to_bitmap(self.ce_vid)
- xml_str = CE_NC_SET_ENCAP_QINQ % (self.l2_sub_interface,
- self.pe_vid,
- vlan_bitmap,
- vlan_bitmap)
- self.updates_cmd.append(
- "encapsulation %s vid %s ce-vid %s" % (self.encapsulation,
- self.pe_vid,
- self.ce_vid))
- else:
- xml_str = CE_NC_SET_ENCAP % (
- self.l2_sub_interface, self.encapsulation)
- self.updates_cmd.append(
- "encapsulation %s" % self.encapsulation)
- else:
- if self.ce_vid:
- if not is_vlan_in_bitmap(self.ce_vid, self.l2sub_info.get("ceVids")) \
- or self.pe_vid != self.l2sub_info.get("peVlanId"):
- vlan_bitmap = vlan_vid_to_bitmap(self.ce_vid)
- xml_str = CE_NC_SET_ENCAP_QINQ % (self.l2_sub_interface,
- self.pe_vid,
- vlan_bitmap,
- vlan_bitmap)
- self.updates_cmd.append(
- "encapsulation %s vid %s ce-vid %s" % (self.encapsulation,
- self.pe_vid,
- self.ce_vid))
- else:
- if self.encapsulation == self.l2sub_info.get("flowType"):
- if self.ce_vid:
- if is_vlan_in_bitmap(self.ce_vid, self.l2sub_info.get("ceVids")) \
- and self.pe_vid == self.l2sub_info.get("peVlanId"):
- xml_str = CE_NC_UNSET_ENCAP % self.l2_sub_interface
- self.updates_cmd.append(
- "undo encapsulation %s vid %s ce-vid %s" % (self.encapsulation,
- self.pe_vid,
- self.ce_vid))
- else:
- xml_str = CE_NC_UNSET_ENCAP % self.l2_sub_interface
- self.updates_cmd.append(
- "undo encapsulation %s" % self.encapsulation)
-
- if not xml_str:
- self.updates_cmd.pop()
- return
- recv_xml = set_nc_config(self.module, xml_str)
- self.check_response(recv_xml, "CONFIG_INTF_ENCAP_QINQ")
- self.changed = True
-
- def config_traffic_encap(self):
- """configure traffic encapsulation types"""
-
- if not self.l2sub_info:
- self.module.fail_json(msg="Error: Interface %s does not exist." % self.l2_sub_interface)
-
- if not self.encapsulation:
- return
-
- xml_str = ""
- if self.encapsulation in ["default", "untag"]:
- if self.state == "present":
- if self.encapsulation != self.l2sub_info.get("flowType"):
- xml_str = CE_NC_SET_ENCAP % (
- self.l2_sub_interface, self.encapsulation)
- self.updates_cmd.append(
- "interface %s" % self.l2_sub_interface)
- self.updates_cmd.append(
- "encapsulation %s" % self.encapsulation)
- else:
- if self.encapsulation == self.l2sub_info.get("flowType"):
- xml_str = CE_NC_UNSET_ENCAP % self.l2_sub_interface
- self.updates_cmd.append(
- "interface %s" % self.l2_sub_interface)
- self.updates_cmd.append(
- "undo encapsulation %s" % self.encapsulation)
- elif self.encapsulation == "none":
- if self.state == "present":
- if self.encapsulation != self.l2sub_info.get("flowType"):
- xml_str = CE_NC_UNSET_ENCAP % self.l2_sub_interface
- self.updates_cmd.append(
- "interface %s" % self.l2_sub_interface)
- self.updates_cmd.append(
- "undo encapsulation %s" % self.l2sub_info.get("flowType"))
- elif self.encapsulation == "dot1q":
- self.config_traffic_encap_dot1q()
- return
- elif self.encapsulation == "qinq":
- self.config_traffic_encap_qinq()
- return
- else:
- pass
-
- if not xml_str:
- return
- recv_xml = set_nc_config(self.module, xml_str)
- self.check_response(recv_xml, "CONFIG_INTF_ENCAP")
- self.changed = True
-
- def config_vap_sub_intf(self):
- """configure a Layer 2 sub-interface as a service access point"""
-
- if not self.vap_info:
- self.module.fail_json(msg="Error: Bridge domain %s does not exist." % self.bridge_domain_id)
-
- xml_str = ""
- if self.state == "present":
- if self.l2_sub_interface not in self.vap_info["intfList"]:
- self.updates_cmd.append("interface %s" % self.l2_sub_interface)
- self.updates_cmd.append("bridge-domain %s" %
- self.bridge_domain_id)
- xml_str = CE_NC_MERGE_BD_INTF % (
- self.bridge_domain_id, self.l2_sub_interface)
- else:
- if self.l2_sub_interface in self.vap_info["intfList"]:
- self.updates_cmd.append("interface %s" % self.l2_sub_interface)
- self.updates_cmd.append(
- "undo bridge-domain %s" % self.bridge_domain_id)
- xml_str = CE_NC_DELETE_BD_INTF % (
- self.bridge_domain_id, self.l2_sub_interface)
-
- if not xml_str:
- return
- recv_xml = set_nc_config(self.module, xml_str)
- self.check_response(recv_xml, "CONFIG_VAP_SUB_INTERFACE")
- self.changed = True
-
- def config_vap_vlan(self):
- """configure a VLAN as a service access point"""
-
- xml_str = ""
- if self.state == "present":
- if not is_vlan_in_bitmap(self.bind_vlan_id, self.vap_info["vlanList"]):
- self.updates_cmd.append("bridge-domain %s" %
- self.bridge_domain_id)
- self.updates_cmd.append(
- "l2 binding vlan %s" % self.bind_vlan_id)
- vlan_bitmap = vlan_vid_to_bitmap(self.bind_vlan_id)
- xml_str = CE_NC_MERGE_BD_VLAN % (
- self.bridge_domain_id, vlan_bitmap, vlan_bitmap)
- else:
- if is_vlan_in_bitmap(self.bind_vlan_id, self.vap_info["vlanList"]):
- self.updates_cmd.append("bridge-domain %s" %
- self.bridge_domain_id)
- self.updates_cmd.append(
- "undo l2 binding vlan %s" % self.bind_vlan_id)
- vlan_bitmap = vlan_vid_to_bitmap(self.bind_vlan_id)
- xml_str = CE_NC_MERGE_BD_VLAN % (
- self.bridge_domain_id, "0" * 1024, vlan_bitmap)
-
- if not xml_str:
- return
- recv_xml = set_nc_config(self.module, xml_str)
- self.check_response(recv_xml, "CONFIG_VAP_VLAN")
- self.changed = True
-
- def is_vlan_valid(self, vid, name):
- """check VLAN id"""
-
- if not vid:
- return
-
- if not vid.isdigit():
- self.module.fail_json(msg="Error: %s is not digit." % name)
- return
-
- if int(vid) < 1 or int(vid) > 4094:
- self.module.fail_json(
- msg="Error: %s is not in the range from 1 to 4094." % name)
-
- def is_l2_sub_intf_valid(self, ifname):
- """check l2 sub interface valid"""
-
- if ifname.count('.') != 1:
- return False
-
- if_num = ifname.split('.')[1]
- if not if_num.isdigit():
- return False
-
- if int(if_num) < 1 or int(if_num) > 4096:
- self.module.fail_json(
- msg="Error: Sub-interface number is not in the range from 1 to 4096.")
- return False
-
- if not get_interface_type(ifname):
- return False
-
- return True
-
- def check_params(self):
- """Check all input params"""
-
- # bridge domain id check
- if self.bridge_domain_id:
- if not self.bridge_domain_id.isdigit():
- self.module.fail_json(
- msg="Error: Bridge domain id is not digit.")
- if int(self.bridge_domain_id) < 1 or int(self.bridge_domain_id) > 16777215:
- self.module.fail_json(
- msg="Error: Bridge domain id is not in the range from 1 to 16777215.")
-
- # check bind_vlan_id
- if self.bind_vlan_id:
- self.is_vlan_valid(self.bind_vlan_id, "bind_vlan_id")
-
- # check l2_sub_interface
- if self.l2_sub_interface and not self.is_l2_sub_intf_valid(self.l2_sub_interface):
- self.module.fail_json(msg="Error: l2_sub_interface is invalid.")
-
- # check ce_vid
- if self.ce_vid:
- self.is_vlan_valid(self.ce_vid, "ce_vid")
- if not self.encapsulation or self.encapsulation not in ["dot1q", "qinq"]:
- self.module.fail_json(msg="Error: ce_vid can not be set "
- "when encapsulation is '%s'." % self.encapsulation)
- if self.encapsulation == "qinq" and not self.pe_vid:
- self.module.fail_json(msg="Error: ce_vid and pe_vid must be set at the same time "
- "when encapsulation is '%s'." % self.encapsulation)
- # check pe_vid
- if self.pe_vid:
- self.is_vlan_valid(self.pe_vid, "pe_vid")
- if not self.encapsulation or self.encapsulation != "qinq":
- self.module.fail_json(msg="Error: pe_vid can not be set "
- "when encapsulation is '%s'." % self.encapsulation)
- if not self.ce_vid:
- self.module.fail_json(msg="Error: ce_vid and pe_vid must be set at the same time "
- "when encapsulation is '%s'." % self.encapsulation)
-
- def get_proposed(self):
- """get proposed info"""
-
- if self.bridge_domain_id:
- self.proposed["bridge_domain_id"] = self.bridge_domain_id
- if self.bind_vlan_id:
- self.proposed["bind_vlan_id"] = self.bind_vlan_id
- if self.l2_sub_interface:
- self.proposed["l2_sub_interface"] = self.l2_sub_interface
- if self.encapsulation:
- self.proposed["encapsulation"] = self.encapsulation
- if self.ce_vid:
- self.proposed["ce_vid"] = self.ce_vid
- if self.pe_vid:
- self.proposed["pe_vid"] = self.pe_vid
- self.proposed["state"] = self.state
-
- def get_existing(self):
- """get existing info"""
-
- if self.bridge_domain_id:
- if self.bind_vlan_id or self.l2_sub_interface:
- self.existing["bridge_domain_id"] = self.bridge_domain_id
- self.existing["bind_vlan_list"] = bitmap_to_vlan_list(
- self.vap_info.get("vlanList"))
- self.existing["bind_intf_list"] = self.vap_info.get("intfList")
-
- if self.encapsulation and self.l2_sub_interface:
- self.existing["l2_sub_interface"] = self.l2_sub_interface
- self.existing["encapsulation"] = self.l2sub_info.get("flowType")
- if self.existing["encapsulation"] == "dot1q":
- self.existing["ce_vid"] = bitmap_to_vlan_list(
- self.l2sub_info.get("dot1qVids"))
- if self.existing["encapsulation"] == "qinq":
- self.existing["ce_vid"] = bitmap_to_vlan_list(
- self.l2sub_info.get("ceVids"))
- self.existing["pe_vid"] = self.l2sub_info.get("peVlanId")
-
- def get_end_state(self):
- """get end state info"""
-
- if self.bridge_domain_id:
- if self.bind_vlan_id or self.l2_sub_interface:
- vap_info = self.get_bd_vap_dict()
- self.end_state["bridge_domain_id"] = self.bridge_domain_id
- self.end_state["bind_vlan_list"] = bitmap_to_vlan_list(
- vap_info.get("vlanList"))
- self.end_state["bind_intf_list"] = vap_info.get("intfList")
-
- if self.encapsulation and self.l2_sub_interface:
- l2sub_info = self.get_l2_sub_intf_dict(self.l2_sub_interface)
- self.end_state["l2_sub_interface"] = self.l2_sub_interface
- self.end_state["encapsulation"] = l2sub_info.get("flowType")
- if self.end_state["encapsulation"] == "dot1q":
- self.end_state["ce_vid"] = bitmap_to_vlan_list(
- l2sub_info.get("dot1qVids"))
- if self.end_state["encapsulation"] == "qinq":
- self.end_state["ce_vid"] = bitmap_to_vlan_list(
- l2sub_info.get("ceVids"))
- self.end_state["pe_vid"] = l2sub_info.get("peVlanId")
-
- def data_init(self):
- """data init"""
- if self.l2_sub_interface:
- self.l2_sub_interface = self.l2_sub_interface.replace(
- " ", "").upper()
- if self.encapsulation and self.l2_sub_interface:
- self.l2sub_info = self.get_l2_sub_intf_dict(self.l2_sub_interface)
- if self.bridge_domain_id:
- if self.bind_vlan_id or self.l2_sub_interface:
- self.vap_info = self.get_bd_vap_dict()
-
- def work(self):
- """worker"""
-
- self.check_params()
- self.data_init()
- self.get_existing()
- self.get_proposed()
-
- # Traffic encapsulation types
- if self.encapsulation and self.l2_sub_interface:
- self.config_traffic_encap()
-
- # A VXLAN service access point can be a Layer 2 sub-interface or VLAN
- if self.bridge_domain_id:
- if self.l2_sub_interface:
- # configure a Layer 2 sub-interface as a service access point
- self.config_vap_sub_intf()
-
- if self.bind_vlan_id:
- # configure a VLAN as a service access point
- self.config_vap_vlan()
- self.get_end_state()
- self.results['changed'] = self.changed
- self.results['proposed'] = self.proposed
- self.results['existing'] = self.existing
- self.results['end_state'] = self.end_state
- if self.changed:
- self.results['updates'] = self.updates_cmd
- else:
- self.results['updates'] = list()
- self.module.exit_json(**self.results)
-
-
-def main():
- """Module main"""
-
- argument_spec = dict(
- bridge_domain_id=dict(required=False, type='str'),
- bind_vlan_id=dict(required=False, type='str'),
- l2_sub_interface=dict(required=False, type='str'),
- encapsulation=dict(required=False, type='str',
- choices=['dot1q', 'default', 'untag', 'qinq', 'none']),
- ce_vid=dict(required=False, type='str'),
- pe_vid=dict(required=False, type='str'),
- state=dict(required=False, default='present',
- choices=['present', 'absent'])
- )
- argument_spec.update(ce_argument_spec)
- module = VxlanVap(argument_spec)
- module.work()
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cloudvision/cv_server_provision.py b/plugins/modules/network/cloudvision/cv_server_provision.py
deleted file mode 100644
index 24f4a46f91..0000000000
--- a/plugins/modules/network/cloudvision/cv_server_provision.py
+++ /dev/null
@@ -1,642 +0,0 @@
-#!/usr/bin/python
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: cv_server_provision
-author: "EOS+ CS (ansible-dev@arista.com) (@mharista)"
-short_description:
- Provision server port by applying or removing template configuration to an
- Arista CloudVision Portal configlet that is applied to a switch.
-description:
- - This module allows a server team to provision server network ports for
- new servers without having to access Arista CVP or asking the network team
- to do it for them. Provide the information for connecting to CVP, switch
- rack, port the new server is connected to, optional vlan, and an action
- and the module will apply the configuration to the switch port via CVP.
- Actions are add (applies template config to port),
- remove (defaults the interface config) and
- show (returns the current port config).
-options:
- host:
- description:
- - The hostname or IP address of the CVP node being connected to.
- required: true
- port:
- description:
- - The port number to use when making API calls to the CVP node. This
- will default to the default port for the specified protocol. Port 80
- for http and port 443 for https.
- protocol:
- description:
- - The protocol to use when making API calls to CVP. CVP defaults to https
- and newer versions of CVP no longer support http.
- default: https
- choices: [https, http]
- username:
- description:
- - The user that will be used to connect to CVP for making API calls.
- required: true
- password:
- description:
- - The password of the user that will be used to connect to CVP for API
- calls.
- required: true
- server_name:
- description:
- - The hostname or identifier for the server that is having it's switch
- port provisioned.
- required: true
- switch_name:
- description:
- - The hostname of the switch is being configured for the server being
- provisioned.
- required: true
- switch_port:
- description:
- - The physical port number on the switch that the new server is
- connected to.
- required: true
- port_vlan:
- description:
- - The vlan that should be applied to the port for this server.
- This parameter is dependent on a proper template that supports single
- vlan provisioning with it. If a port vlan is specified by the template
- specified does not support this the module will exit out with no
- changes. If a template is specified that requires a port vlan but no
- port vlan is specified the module will exit out with no changes.
- template:
- description:
- - A path to a Jinja formatted template file that contains the
- configuration block that will be applied to the specified switch port.
- This template will have variable fields replaced by the module before
- being applied to the switch configuration.
- required: true
- action:
- description:
- - The action for the module to take. The actions are add, which applies
- the specified template config to port, remove, which defaults the
- specified interface configuration, and show, which will return the
- current port configuration with no changes.
- default: show
- choices: [show, add, remove]
- auto_run:
- description:
- - Flag that determines whether or not the module will execute the CVP
- task spawned as a result of changes to a switch configlet. When an
- add or remove action is taken which results in a change to a switch
- configlet, CVP will spawn a task that needs to be executed for the
- configuration to be applied to the switch. If this option is True then
- the module will determined the task number created by the configuration
- change, execute it and wait for the task to complete. If the option
- is False then the task will remain in the Pending state in CVP for
- a network administrator to review and execute.
- type: bool
- default: 'no'
-requirements: [Jinja2, cvprac >= 0.7.0]
-'''
-
-EXAMPLES = '''
-- name: Get current configuration for interface Ethernet2
- cv_server_provision:
- host: cvp_node
- username: cvp_user
- password: cvp_pass
- protocol: https
- server_name: new_server
- switch_name: eos_switch_1
- switch_port: 2
- template: template_file.j2
- action: show
-
-- name: Remove existing configuration from interface Ethernet2. Run task.
- cv_server_provision:
- host: cvp_node
- username: cvp_user
- password: cvp_pass
- protocol: https
- server_name: new_server
- switch_name: eos_switch_1
- switch_port: 2
- template: template_file.j2
- action: remove
- auto_run: True
-
-- name: Add template configuration to interface Ethernet2. No VLAN. Run task.
- cv_server_provision:
- host: cvp_node
- username: cvp_user
- password: cvp_pass
- protocol: https
- server_name: new_server
- switch_name: eos_switch_1
- switch_port: 2
- template: single_attached_trunk.j2
- action: add
- auto_run: True
-
-- name: Add template with VLAN configuration to interface Ethernet2. Run task.
- cv_server_provision:
- host: cvp_node
- username: cvp_user
- password: cvp_pass
- protocol: https
- server_name: new_server
- switch_name: eos_switch_1
- switch_port: 2
- port_vlan: 22
- template: single_attached_vlan.j2
- action: add
- auto_run: True
-'''
-
-RETURN = '''
-changed:
- description: Signifies if a change was made to the configlet
- returned: success
- type: bool
- sample: true
-currentConfigBlock:
- description: The current config block for the user specified interface
- returned: when action = show
- type: str
- sample: |
- interface Ethernet4
- !
-newConfigBlock:
- description: The new config block for the user specified interface
- returned: when action = add or remove
- type: str
- sample: |
- interface Ethernet3
- description example
- no switchport
- !
-oldConfigBlock:
- description: The current config block for the user specified interface
- before any changes are made
- returned: when action = add or remove
- type: str
- sample: |
- interface Ethernet3
- !
-fullConfig:
- description: The full config of the configlet after being updated
- returned: when action = add or remove
- type: str
- sample: |
- !
- interface Ethernet3
- !
- interface Ethernet4
- !
-updateConfigletResponse:
- description: Response returned from CVP when configlet update is triggered
- returned: when action = add or remove and configuration changes
- type: str
- sample: "Configlet veos1-server successfully updated and task initiated."
-portConfigurable:
- description: Signifies if the user specified port has an entry in the
- configlet that Ansible has access to
- returned: success
- type: bool
- sample: true
-switchConfigurable:
- description: Signifies if the user specified switch has a configlet
- applied to it that CVP is allowed to edit
- returned: success
- type: bool
- sample: true
-switchInfo:
- description: Information from CVP describing the switch being configured
- returned: success
- type: dict
- sample: {"architecture": "i386",
- "bootupTimeStamp": 1491264298.21,
- "complianceCode": "0000",
- "complianceIndication": "NONE",
- "deviceInfo": "Registered",
- "deviceStatus": "Registered",
- "fqdn": "veos1",
- "hardwareRevision": "",
- "internalBuildId": "12-12",
- "internalVersion": "4.17.1F-11111.4171F",
- "ipAddress": "192.168.1.20",
- "isDANZEnabled": "no",
- "isMLAGEnabled": "no",
- "key": "00:50:56:5d:e5:e0",
- "lastSyncUp": 1496432895799,
- "memFree": 472976,
- "memTotal": 1893460,
- "modelName": "vEOS",
- "parentContainerId": "container_13_5776759195930",
- "serialNumber": "",
- "systemMacAddress": "00:50:56:5d:e5:e0",
- "taskIdList": [],
- "tempAction": null,
- "type": "netelement",
- "unAuthorized": false,
- "version": "4.17.1F",
- "ztpMode": "false"}
-taskCompleted:
- description: Signifies if the task created and executed has completed successfully
- returned: when action = add or remove, and auto_run = true,
- and configuration changes
- type: bool
- sample: true
-taskCreated:
- description: Signifies if a task was created due to configlet changes
- returned: when action = add or remove, and auto_run = true or false,
- and configuration changes
- type: bool
- sample: true
-taskExecuted:
- description: Signifies if the automation executed the spawned task
- returned: when action = add or remove, and auto_run = true,
- and configuration changes
- type: bool
- sample: true
-taskId:
- description: The task ID created by CVP because of changes to configlet
- returned: when action = add or remove, and auto_run = true or false,
- and configuration changes
- type: str
- sample: "500"
-'''
-
-import re
-import time
-from ansible.module_utils.basic import AnsibleModule
-try:
- import jinja2
- from jinja2 import meta
- HAS_JINJA2 = True
-except ImportError:
- HAS_JINJA2 = False
-try:
- from cvprac.cvp_client import CvpClient
- from cvprac.cvp_client_errors import CvpLoginError, CvpApiError
- HAS_CVPRAC = True
-except ImportError:
- HAS_CVPRAC = False
-
-
-def connect(module):
- ''' Connects to CVP device using user provided credentials from playbook.
-
- :param module: Ansible module with parameters and client connection.
- :return: CvpClient object with connection instantiated.
- '''
- client = CvpClient()
- try:
- client.connect([module.params['host']],
- module.params['username'],
- module.params['password'],
- protocol=module.params['protocol'],
- port=module.params['port'])
- except CvpLoginError as e:
- module.fail_json(msg=str(e))
- return client
-
-
-def switch_info(module):
- ''' Get dictionary of switch info from CVP.
-
- :param module: Ansible module with parameters and client connection.
- :return: Dict of switch info from CVP or exit with failure if no
- info for device is found.
- '''
- switch_name = module.params['switch_name']
- switch_info = module.client.api.get_device_by_name(switch_name)
- if not switch_info:
- module.fail_json(msg=str("Device with name '%s' does not exist."
- % switch_name))
- return switch_info
-
-
-def switch_in_compliance(module, sw_info):
- ''' Check if switch is currently in compliance.
-
- :param module: Ansible module with parameters and client connection.
- :param sw_info: Dict of switch info.
- :return: Nothing or exit with failure if device is not in compliance.
- '''
- compliance = module.client.api.check_compliance(sw_info['key'],
- sw_info['type'])
- if compliance['complianceCode'] != '0000':
- module.fail_json(msg=str('Switch %s is not in compliance. Returned'
- ' compliance code %s.'
- % (sw_info['fqdn'],
- compliance['complianceCode'])))
-
-
-def server_configurable_configlet(module, sw_info):
- ''' Check CVP that the user specified switch has a configlet assigned to
- it that Ansible is allowed to edit.
-
- :param module: Ansible module with parameters and client connection.
- :param sw_info: Dict of switch info.
- :return: Dict of configlet information or None.
- '''
- configurable_configlet = None
- configlet_name = module.params['switch_name'] + '-server'
- switch_configlets = module.client.api.get_configlets_by_device_id(
- sw_info['key'])
- for configlet in switch_configlets:
- if configlet['name'] == configlet_name:
- configurable_configlet = configlet
- return configurable_configlet
-
-
-def port_configurable(module, configlet):
- ''' Check configlet if the user specified port has a configuration entry
- in the configlet to determine if Ansible is allowed to configure the
- port on this switch.
-
- :param module: Ansible module with parameters and client connection.
- :param configlet: Dict of configlet info.
- :return: True or False.
- '''
- configurable = False
- regex = r'^interface Ethernet%s' % module.params['switch_port']
- for config_line in configlet['config'].split('\n'):
- if re.match(regex, config_line):
- configurable = True
- return configurable
-
-
-def configlet_action(module, configlet):
- ''' Take appropriate action based on current state of device and user
- requested action.
-
- Return current config block for specified port if action is show.
-
- If action is add or remove make the appropriate changes to the
- configlet and return the associated information.
-
- :param module: Ansible module with parameters and client connection.
- :param configlet: Dict of configlet info.
- :return: Dict of information to updated results with.
- '''
- result = dict()
- existing_config = current_config(module, configlet['config'])
- if module.params['action'] == 'show':
- result['currentConfigBlock'] = existing_config
- return result
- elif module.params['action'] == 'add':
- result['newConfigBlock'] = config_from_template(module)
- elif module.params['action'] == 'remove':
- result['newConfigBlock'] = ('interface Ethernet%s\n!'
- % module.params['switch_port'])
- result['oldConfigBlock'] = existing_config
- result['fullConfig'] = updated_configlet_content(module,
- configlet['config'],
- result['newConfigBlock'])
- resp = module.client.api.update_configlet(result['fullConfig'],
- configlet['key'],
- configlet['name'])
- if 'data' in resp:
- result['updateConfigletResponse'] = resp['data']
- if 'task' in resp['data']:
- result['changed'] = True
- result['taskCreated'] = True
- return result
-
-
-def current_config(module, config):
- ''' Parse the full port configuration for the user specified port out of
- the full configlet configuration and return as a string.
-
- :param module: Ansible module with parameters and client connection.
- :param config: Full config to parse specific port config from.
- :return: String of current config block for user specified port.
- '''
- regex = r'^interface Ethernet%s' % module.params['switch_port']
- match = re.search(regex, config, re.M)
- if not match:
- module.fail_json(msg=str('interface section not found - %s'
- % config))
- block_start, line_end = match.regs[0]
-
- match = re.search(r'!', config[line_end:], re.M)
- if not match:
- return config[block_start:]
- _, block_end = match.regs[0]
-
- block_end = line_end + block_end
- return config[block_start:block_end]
-
-
-def valid_template(port, template):
- ''' Test if the user provided Jinja template is valid.
-
- :param port: User specified port.
- :param template: Contents of Jinja template.
- :return: True or False
- '''
- valid = True
- regex = r'^interface Ethernet%s' % port
- match = re.match(regex, template, re.M)
- if not match:
- valid = False
- return valid
-
-
-def config_from_template(module):
- ''' Load the Jinja template and apply user provided parameters in necessary
- places. Fail if template is not found. Fail if rendered template does
- not reference the correct port. Fail if the template requires a VLAN
- but the user did not provide one with the port_vlan parameter.
-
- :param module: Ansible module with parameters and client connection.
- :return: String of Jinja template rendered with parameters or exit with
- failure.
- '''
- template_loader = jinja2.FileSystemLoader('./templates')
- env = jinja2.Environment(loader=template_loader,
- undefined=jinja2.DebugUndefined)
- template = env.get_template(module.params['template'])
- if not template:
- module.fail_json(msg=str('Could not find template - %s'
- % module.params['template']))
-
- data = {'switch_port': module.params['switch_port'],
- 'server_name': module.params['server_name']}
-
- temp_source = env.loader.get_source(env, module.params['template'])[0]
- parsed_content = env.parse(temp_source)
- temp_vars = list(meta.find_undeclared_variables(parsed_content))
- if 'port_vlan' in temp_vars:
- if module.params['port_vlan']:
- data['port_vlan'] = module.params['port_vlan']
- else:
- module.fail_json(msg=str('Template %s requires a vlan. Please'
- ' re-run with vlan number provided.'
- % module.params['template']))
-
- template = template.render(data)
- if not valid_template(module.params['switch_port'], template):
- module.fail_json(msg=str('Template content does not configure proper'
- ' interface - %s' % template))
- return template
-
-
-def updated_configlet_content(module, existing_config, new_config):
- ''' Update the configlet configuration with the new section for the port
- specified by the user.
-
- :param module: Ansible module with parameters and client connection.
- :param existing_config: String of current configlet configuration.
- :param new_config: String of configuration for user specified port to
- replace in the existing config.
- :return: String of the full updated configuration.
- '''
- regex = r'^interface Ethernet%s' % module.params['switch_port']
- match = re.search(regex, existing_config, re.M)
- if not match:
- module.fail_json(msg=str('interface section not found - %s'
- % existing_config))
- block_start, line_end = match.regs[0]
-
- updated_config = existing_config[:block_start] + new_config
- match = re.search(r'!\n', existing_config[line_end:], re.M)
- if match:
- _, block_end = match.regs[0]
- block_end = line_end + block_end
- updated_config += '\n%s' % existing_config[block_end:]
- return updated_config
-
-
-def configlet_update_task(module):
- ''' Poll device info of switch from CVP up to three times to see if the
- configlet updates have spawned a task. It sometimes takes a second for
- the task to be spawned after configlet updates. If a task is found
- return the task ID. Otherwise return None.
-
- :param module: Ansible module with parameters and client connection.
- :return: Task ID or None.
- '''
- for num in range(3):
- device_info = switch_info(module)
- if (('taskIdList' in device_info) and
- (len(device_info['taskIdList']) > 0)):
- for task in device_info['taskIdList']:
- if ('Configlet Assign' in task['description'] and
- task['data']['WORKFLOW_ACTION'] == 'Configlet Push'):
- return task['workOrderId']
- time.sleep(1)
- return None
-
-
-def wait_for_task_completion(module, task):
- ''' Poll CVP for the executed task to complete. There is currently no
- timeout. Exits with failure if task status is Failed or Cancelled.
-
- :param module: Ansible module with parameters and client connection.
- :param task: Task ID to poll for completion.
- :return: True or exit with failure if task is cancelled or fails.
- '''
- task_complete = False
- while not task_complete:
- task_info = module.client.api.get_task_by_id(task)
- task_status = task_info['workOrderUserDefinedStatus']
- if task_status == 'Completed':
- return True
- elif task_status in ['Failed', 'Cancelled']:
- module.fail_json(msg=str('Task %s has reported status %s. Please'
- ' consult the CVP admins for more'
- ' information.' % (task, task_status)))
- time.sleep(2)
-
-
-def main():
- """ main entry point for module execution
- """
- argument_spec = dict(
- host=dict(required=True),
- port=dict(required=False, default=None),
- protocol=dict(default='https', choices=['http', 'https']),
- username=dict(required=True),
- password=dict(required=True, no_log=True),
- server_name=dict(required=True),
- switch_name=dict(required=True),
- switch_port=dict(required=True),
- port_vlan=dict(required=False, default=None),
- template=dict(require=True),
- action=dict(default='show', choices=['show', 'add', 'remove']),
- auto_run=dict(type='bool', default=False))
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=False)
- if not HAS_JINJA2:
- module.fail_json(msg='The Jinja2 python module is required.')
- if not HAS_CVPRAC:
- module.fail_json(msg='The cvprac python module is required.')
- result = dict(changed=False)
- module.client = connect(module)
-
- try:
- result['switchInfo'] = switch_info(module)
- if module.params['action'] in ['add', 'remove']:
- switch_in_compliance(module, result['switchInfo'])
- switch_configlet = server_configurable_configlet(module,
- result['switchInfo'])
- if not switch_configlet:
- module.fail_json(msg=str('Switch %s has no configurable server'
- ' ports.' % module.params['switch_name']))
- result['switchConfigurable'] = True
- if not port_configurable(module, switch_configlet):
- module.fail_json(msg=str('Port %s is not configurable as a server'
- ' port on switch %s.'
- % (module.params['switch_port'],
- module.params['switch_name'])))
- result['portConfigurable'] = True
- result['taskCreated'] = False
- result['taskExecuted'] = False
- result['taskCompleted'] = False
- result.update(configlet_action(module, switch_configlet))
- if module.params['auto_run'] and module.params['action'] != 'show':
- task_id = configlet_update_task(module)
- if task_id:
- result['taskId'] = task_id
- note = ('Update config on %s with %s action from Ansible.'
- % (module.params['switch_name'],
- module.params['action']))
- module.client.api.add_note_to_task(task_id, note)
- module.client.api.execute_task(task_id)
- result['taskExecuted'] = True
- task_completed = wait_for_task_completion(module, task_id)
- if task_completed:
- result['taskCompleted'] = True
- else:
- result['taskCreated'] = False
- except CvpApiError as e:
- module.fail_json(msg=str(e))
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_backup.py b/plugins/modules/network/cnos/cnos_backup.py
deleted file mode 100644
index 366906f902..0000000000
--- a/plugins/modules/network/cnos/cnos_backup.py
+++ /dev/null
@@ -1,276 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2017 Lenovo, Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to Backup Config to Lenovo Switches
-# Lenovo Networking
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_backup
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Backup the current running or startup configuration to a
- remote server on devices running Lenovo CNOS
-description:
- - This module allows you to work with switch configurations. It provides a
- way to back up the running or startup configurations of a switch to a
- remote server. This is achieved by periodically saving a copy of the
- startup or running configuration of the network device to a remote server
- using FTP, SFTP, TFTP, or SCP. The first step is to create a directory from
- where the remote server can be reached. The next step is to provide the
- full file path of the location where the configuration will be backed up.
- Authentication details required by the remote server must be provided as
- well. This module uses SSH to manage network device configuration.
- The results of the operation will be placed in a directory named 'results'
- that must be created by the user in their local directory to where the
- playbook is run.
-extends_documentation_fragment:
-- community.general.cnos
-
-options:
- configType:
- description:
- - This specifies what type of configuration will be backed up. The
- choices are the running or startup configurations. There is no
- default value, so it will result in an error if the input is
- incorrect.
- required: Yes
- default: Null
- choices: [running-config, startup-config]
- protocol:
- description:
- - This refers to the protocol used by the network device to
- interact with the remote server to where to upload the backup
- configuration. The choices are FTP, SFTP, TFTP, or SCP. Any other
- protocols will result in error. If this parameter is
- not specified, there is no default value to be used.
- required: Yes
- default: Null
- choices: [SFTP, SCP, FTP, TFTP]
- rcserverip:
- description:
- -This specifies the IP Address of the remote server to where the
- configuration will be backed up.
- required: Yes
- default: Null
- rcpath:
- description:
- - This specifies the full file path where the configuration file
- will be copied on the remote server. In case the relative path is
- used as the variable value, the root folder for the user of the
- server needs to be specified.
- required: Yes
- default: Null
- serverusername:
- description:
- - Specify the username for the server relating to the protocol
- used.
- required: Yes
- default: Null
- serverpassword:
- description:
- - Specify the password for the server relating to the protocol
- used.
- required: Yes
- default: Null
-'''
-EXAMPLES = '''
-Tasks : The following are examples of using the module cnos_backup.
- These are written in the main.yml file of the tasks directory.
----
-- name: Test Running Config Backup
- cnos_backup:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_backup_{{ inventory_hostname }}_output.txt"
- configType: running-config
- protocol: "sftp"
- serverip: "10.241.106.118"
- rcpath: "/root/cnos/G8272-running-config.txt"
- serverusername: "root"
- serverpassword: "root123"
-
-- name: Test Startup Config Backup
- cnos_backup:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_backup_{{ inventory_hostname }}_output.txt"
- configType: startup-config
- protocol: "sftp"
- serverip: "10.241.106.118"
- rcpath: "/root/cnos/G8272-startup-config.txt"
- serverusername: "root"
- serverpassword: "root123"
-
-- name: Test Running Config Backup -TFTP
- cnos_backup:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_backup_{{ inventory_hostname }}_output.txt"
- configType: running-config
- protocol: "tftp"
- serverip: "10.241.106.118"
- rcpath: "/anil/G8272-running-config.txt"
- serverusername: "root"
- serverpassword: "root123"
-
-- name: Test Startup Config Backup - TFTP
- cnos_backup:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_backup_{{ inventory_hostname }}_output.txt"
- configType: startup-config
- protocol: "tftp"
- serverip: "10.241.106.118"
- rcpath: "/anil/G8272-startup-config.txt"
- serverusername: "root"
- serverpassword: "root123"
-
-'''
-RETURN = '''
-msg:
- description: Success or failure message
- returned: always
- type: str
- sample: "Config file transferred to server"
-'''
-
-import sys
-import time
-import socket
-import array
-import json
-import time
-import re
-import os
-try:
- from ansible_collections.community.general.plugins.module_utils.network.cnos import cnos
- HAS_LIB = True
-except Exception:
- HAS_LIB = False
-from ansible.module_utils.basic import AnsibleModule
-from collections import defaultdict
-
-
-# Utility Method to back up the running config or start up config
-# This method supports only SCP or SFTP or FTP or TFTP
-# Tuning of timeout parameter is pending
-def doConfigBackUp(module, prompt, answer):
- host = module.params['host']
- server = module.params['serverip']
- username = module.params['serverusername']
- password = module.params['serverpassword']
- protocol = module.params['protocol'].lower()
- rcPath = module.params['rcpath']
- configType = module.params['configType']
- confPath = rcPath + host + '_' + configType + '.txt'
-
- retVal = ''
-
- # config backup command happens here
- command = "copy " + configType + " " + protocol + " " + protocol + "://"
- command = command + username + "@" + server + "/" + confPath
- command = command + " vrf management\n"
- cnos.debugOutput(command + "\n")
- # cnos.checkForFirstTimeAccess(module, command, 'yes/no', 'yes')
- cmd = []
- if(protocol == "scp"):
- scp_cmd1 = [{'command': command, 'prompt': 'timeout:', 'answer': '0'}]
- scp_cmd2 = [{'command': '\n', 'prompt': 'Password:',
- 'answer': password}]
- cmd.extend(scp_cmd1)
- cmd.extend(scp_cmd2)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- elif(protocol == "sftp"):
- sftp_cmd = [{'command': command, 'prompt': 'Password:',
- 'answer': password}]
- cmd.extend(sftp_cmd)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- elif(protocol == "ftp"):
- ftp_cmd = [{'command': command, 'prompt': 'Password:',
- 'answer': password}]
- cmd.extend(ftp_cmd)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- elif(protocol == "tftp"):
- command = "copy " + configType + " " + protocol + " " + protocol
- command = command + "://" + server + "/" + confPath
- command = command + " vrf management\n"
- # cnos.debugOutput(command)
- tftp_cmd = [{'command': command, 'prompt': None, 'answer': None}]
- cmd.extend(tftp_cmd)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- else:
- return "Error-110"
-
- return retVal
-# EOM
-
-
-def main():
-
- module = AnsibleModule(
- argument_spec=dict(
- outputfile=dict(required=True),
- host=dict(required=False),
- username=dict(required=False),
- password=dict(required=False, no_log=True),
- enablePassword=dict(required=False, no_log=True),
- deviceType=dict(required=True),
- configType=dict(required=True),
- protocol=dict(required=True),
- serverip=dict(required=True),
- rcpath=dict(required=True),
- serverusername=dict(required=False),
- serverpassword=dict(required=False, no_log=True),),
- supports_check_mode=False)
-
- outputfile = module.params['outputfile']
- protocol = module.params['protocol'].lower()
- output = ''
- if(protocol == "tftp" or protocol == "ftp" or
- protocol == "sftp" or protocol == "scp"):
- transfer_status = doConfigBackUp(module, None, None)
- else:
- transfer_status = "Invalid Protocol option"
-
- output = output + "\n Config Back Up status \n" + transfer_status
-
- # Save it into the file
- path = outputfile.rsplit('/', 1)
- # cnos.debugOutput(path[0])
- if not os.path.exists(path[0]):
- os.makedirs(path[0])
- file = open(outputfile, "a")
- file.write(output)
- file.close()
-
- # Logic to check when changes occur or not
- errorMsg = cnos.checkOutputForError(output)
- if(errorMsg is None):
- module.exit_json(changed=True, msg="Config file transferred to server")
- else:
- module.fail_json(msg=errorMsg)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_banner.py b/plugins/modules/network/cnos/cnos_banner.py
deleted file mode 100644
index c78b37ce6f..0000000000
--- a/plugins/modules/network/cnos/cnos_banner.py
+++ /dev/null
@@ -1,263 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2017 Lenovo, Inc.
-# (c) 2017, Ansible by Red Hat, inc
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to send banner commands to Lenovo Switches
-# Two types of banners are supported login and motd
-# Lenovo Networking
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_banner
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Manage multiline banners on Lenovo CNOS devices
-description:
- - This will configure both login and motd banners on remote devices
- running Lenovo CNOS. It allows playbooks to add or remote
- banner text from the active running configuration.
-notes:
- - Tested against CNOS 10.8.1
-options:
- banner:
- description:
- - Specifies which banner should be configured on the remote device.
- In Ansible 2.8 and earlier only I(login) and I(motd) were supported.
- required: true
- choices: ['login', 'motd']
- text:
- description:
- - The banner text that should be
- present in the remote device running configuration. This argument
- accepts a multiline string, with no empty lines. Requires
- I(state=present).
- state:
- description:
- - Specifies whether or not the configuration is
- present in the current devices active running configuration.
- default: present
- choices: ['present', 'absent']
- provider:
- description:
- - B(Deprecated)
- - "Starting with Ansible 2.5 we recommend using
- C(connection: network_cli)."
- - For more information please see the
- L(CNOS Platform Options guide, ../network/user_guide/platform_cnos.html).
- - HORIZONTALLINE
- - A dict object containing connection details.
- suboptions:
- host:
- description:
- - Specifies the DNS host name or address for connecting to the remote
- device over the specified transport. The value of host is used as
- the destination address for the transport.
- required: true
- port:
- description:
- - Specifies the port to use when building the connection to the
- remote device.
- default: 22
- username:
- description:
- - Configures the username to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_USERNAME) will be used
- instead.
- password:
- description:
- - Specifies the password to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_PASSWORD) will be used
- instead.
- timeout:
- description:
- - Specifies the timeout in seconds for communicating with the network
- device for either connecting or sending commands. If the timeout
- is exceeded before the operation is completed, the module will
- error.
- default: 10
- ssh_keyfile:
- description:
- - Specifies the SSH key to use to authenticate the connection to
- the remote device. This value is the path to the
- key used to authenticate the SSH session. If the value is not
- specified in the task, the value of environment variable
- C(ANSIBLE_NET_SSH_KEYFILE)will be used instead.
- authorize:
- description:
- - Instructs the module to enter privileged mode on the remote device
- before sending any commands. If not specified, the device will
- attempt to execute all commands in non-privileged mode. If the
- value is not specified in the task, the value of environment
- variable C(ANSIBLE_NET_AUTHORIZE) will be used instead.
- type: bool
- default: 'no'
- auth_pass:
- description:
- - Specifies the password to use if required to enter privileged mode
- on the remote device. If I(authorize) is false, then this argument
- does nothing. If the value is not specified in the task, the value
- of environment variable C(ANSIBLE_NET_AUTH_PASS) will be used
- instead.
-'''
-
-EXAMPLES = """
-- name: configure the login banner
- cnos_banner:
- banner: login
- text: |
- this is my login banner
- that contains a multiline
- string
- state: present
-
-- name: remove the motd banner
- cnos_banner:
- banner: motd
- state: absent
-
-- name: Configure banner from file
- cnos_banner:
- banner: motd
- text: "{{ lookup('file', './config_partial/raw_banner.cfg') }}"
- state: present
-
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always
- type: list
- sample:
- - banner login
- - this is my login banner
- - that contains a multiline
- - string
-"""
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import exec_command
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import load_config, run_commands
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import check_args
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import cnos_argument_spec
-from ansible.module_utils._text import to_text
-import re
-
-
-def map_obj_to_commands(updates, module):
- commands = list()
- want, have = updates
- state = module.params['state']
-
- if state == 'absent' and 'text' in have.keys() and have['text']:
- commands.append('no banner %s' % module.params['banner'])
-
- elif state == 'present':
- if want['text'] and (want['text'] != have.get('text')):
- banner_cmd = 'banner %s ' % module.params['banner']
- for bline in want['text'].strip().splitlines():
- final_cmd = banner_cmd + bline.strip()
- commands.append(final_cmd)
-
- return commands
-
-
-def map_config_to_obj(module):
- rc, out, err = exec_command(module,
- 'show banner %s' % module.params['banner'])
- if rc == 0:
- output = out
- else:
- rc, out, err = exec_command(module,
- 'show running-config | include banner %s'
- % module.params['banner'])
- if out:
- output = re.search(r'\^C(.*)\^C', out, re.S).group(1).strip()
- else:
- output = None
- obj = {'banner': module.params['banner'], 'state': 'absent'}
- if output:
- obj['text'] = output
- obj['state'] = 'present'
- return obj
-
-
-def map_params_to_obj(module):
- text = module.params['text']
- if text:
- text = to_text(text).strip()
-
- return {
- 'banner': module.params['banner'],
- 'text': text,
- 'state': module.params['state']
- }
-
-
-def main():
- """ main entry point for module execution
- """
- argument_spec = dict(
- banner=dict(required=True, choices=['login', 'motd']),
- text=dict(),
- state=dict(default='present', choices=['present', 'absent'])
- )
-
- argument_spec.update(cnos_argument_spec)
-
- required_if = [('state', 'present', ('text',))]
-
- module = AnsibleModule(argument_spec=argument_spec,
- required_if=required_if,
- supports_check_mode=True)
-
- warnings = list()
- check_args(module, warnings)
-
- result = {'changed': False}
- if warnings:
- result['warnings'] = warnings
- want = map_params_to_obj(module)
- have = map_config_to_obj(module)
-
- commands = map_obj_to_commands((want, have), module)
- result['commands'] = commands
-
- if commands:
- if not module.check_mode:
- response = load_config(module, commands)
-
- result['changed'] = True
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_bgp.py b/plugins/modules/network/cnos/cnos_bgp.py
deleted file mode 100644
index a6ce89e3e7..0000000000
--- a/plugins/modules/network/cnos/cnos_bgp.py
+++ /dev/null
@@ -1,1180 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2017 Lenovo, Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to send BGP commands to Lenovo Switches
-# Lenovo Networking
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: cnos_bgp
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Manage BGP resources and attributes on devices running CNOS
-description:
- - This module allows you to work with Border Gateway Protocol (BGP) related
- configurations. The operators used are overloaded to ensure control over
- switch BGP configurations. This module is invoked using method with
- asNumber as one of its arguments. The first level of the BGP configuration
- allows to set up an AS number, with the following attributes going
- into various configuration operations under the context of BGP.
- After passing this level, there are eight BGP arguments that will perform
- further configurations. They are bgpArg1, bgpArg2, bgpArg3, bgpArg4,
- bgpArg5, bgpArg6, bgpArg7, and bgpArg8. For more details on how to use
- these arguments, see [Overloaded Variables].
- This module uses SSH to manage network device configuration.
- The results of the operation will be placed in a directory named 'results'
- that must be created by the user in their local directory to where the
- playbook is run.
-extends_documentation_fragment:
-- community.general.cnos
-
-options:
- asNum:
- description:
- - AS number
- required: Yes
- default: Null
- bgpArg1:
- description:
- - This is an overloaded bgp first argument. Usage of this argument
- can be found is the User Guide referenced above.
- required: Yes
- default: Null
- choices: [address-family,bestpath,bgp,cluster-id,confederation,
- enforce-first-as,fast-external-failover,graceful-restart,
- graceful-restart-helper,log-neighbor-changes,
- maxas-limit,neighbor,router-id,shutdown,synchronization,
- timers,vrf]
- bgpArg2:
- description:
- - This is an overloaded bgp second argument. Usage of this argument
- can be found is the User Guide referenced above.
- required: No
- default: Null
- choices: [ipv4 or ipv6, always-compare-med,compare-confed-aspath,
- compare-routerid,dont-compare-originator-id,tie-break-on-age,
- as-path,med,identifier,peers]
- bgpArg3:
- description:
- - This is an overloaded bgp third argument. Usage of this argument
- can be found is the User Guide referenced above.
- required: No
- default: Null
- choices: [aggregate-address,client-to-client,dampening,distance,
- maximum-paths,network,nexthop,redistribute,save,
- synchronization,ignore or multipath-relax,
- confed or missing-as-worst or non-deterministic or
- remove-recv-med or remove-send-med]
- bgpArg4:
- description:
- - This is an overloaded bgp fourth argument. Usage of this argument
- can be found is the User Guide referenced above.
- required: No
- default: Null
- choices: [Aggregate prefix, Reachability Half-life time,route-map,
- Distance for routes ext,ebgp or ibgp,IP prefix ,
- IP prefix /, synchronization,
- Delay value, direct, ospf, static, memory]
- bgpArg5:
- description:
- - This is an overloaded bgp fifth argument. Usage of this argument
- can be found is the User Guide referenced above.
- required: No
- default: Null
- choices: [as-set, summary-only, Value to start reusing a route,
- Distance for routes internal, Supported multipath numbers,
- backdoor, map, route-map ]
- bgpArg6:
- description:
- - This is an overloaded bgp sixth argument. Usage of this argument
- can be found is the User Guide referenced above.
- required: No
- default: Null
- choices: [summary-only,as-set, route-map name,
- Value to start suppressing a route, Distance local routes,
- Network mask, Pointer to route-map entries]
- bgpArg7:
- description:
- - This is an overloaded bgp seventh argument. Use of this argument
- can be found is the User Guide referenced above.
- required: No
- default: Null
- choices: [Maximum duration to suppress a stable route(minutes),
- backdoor,route-map, Name of the route map ]
- bgpArg8:
- description:
- - This is an overloaded bgp eight argument. Usage of this argument
- can be found is the User Guide referenced above.
- required: No
- default: Null
- choices: [Un-reachability Half-life time for the penalty(minutes),
- backdoor]
-'''
-EXAMPLES = '''
-Tasks: The following are examples of using the module cnos_bgp. These are
- written in the main.yml file of the tasks directory.
----
-- name: Test BGP - neighbor
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "neighbor"
- bgpArg2: "10.241.107.40"
- bgpArg3: 13
- bgpArg4: "address-family"
- bgpArg5: "ipv4"
- bgpArg6: "next-hop-self"
-
-- name: Test BGP - BFD
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "neighbor"
- bgpArg2: "10.241.107.40"
- bgpArg3: 13
- bgpArg4: "bfd"
-
-- name: Test BGP - address-family - dampening
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "address-family"
- bgpArg2: "ipv4"
- bgpArg3: "dampening"
- bgpArg4: 13
- bgpArg5: 233
- bgpArg6: 333
- bgpArg7: 15
- bgpArg8: 33
-
-- name: Test BGP - address-family - network
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "address-family"
- bgpArg2: "ipv4"
- bgpArg3: "network"
- bgpArg4: "1.2.3.4/5"
- bgpArg5: "backdoor"
-
-- name: Test BGP - bestpath - always-compare-med
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "bestpath"
- bgpArg2: "always-compare-med"
-
-- name: Test BGP - bestpath-compare-confed-aspat
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "bestpath"
- bgpArg2: "compare-confed-aspath"
-
-- name: Test BGP - bgp
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "bgp"
- bgpArg2: 33
-
-- name: Test BGP - cluster-id
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "cluster-id"
- bgpArg2: "1.2.3.4"
-
-- name: Test BGP - confederation-identifier
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "confederation"
- bgpArg2: "identifier"
- bgpArg3: 333
-
-- name: Test BGP - enforce-first-as
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "enforce-first-as"
-
-- name: Test BGP - fast-external-failover
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "fast-external-failover"
-
-- name: Test BGP - graceful-restart
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "graceful-restart"
- bgpArg2: 333
-
-- name: Test BGP - graceful-restart-helper
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "graceful-restart-helper"
-
-- name: Test BGP - maxas-limit
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "maxas-limit"
- bgpArg2: 333
-
-- name: Test BGP - neighbor
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "neighbor"
- bgpArg2: "10.241.107.40"
- bgpArg3: 13
- bgpArg4: "address-family"
- bgpArg5: "ipv4"
- bgpArg6: "next-hop-self"
-
-- name: Test BGP - router-id
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "router-id"
- bgpArg2: "1.2.3.4"
-
-- name: Test BGP - synchronization
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "synchronization"
-
-- name: Test BGP - timers
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "timers"
- bgpArg2: 333
- bgpArg3: 3333
-
-- name: Test BGP - vrf
- cnos_bgp:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
- asNum: 33
- bgpArg1: "vrf"
-
-'''
-RETURN = '''
-msg:
- description: Success or failure message. Upon any failure, the method returns
- an error display string.
- returned: always
- type: str
-'''
-
-import sys
-import time
-import socket
-import array
-import json
-import time
-import re
-try:
- from ansible_collections.community.general.plugins.module_utils.network.cnos import cnos
- HAS_LIB = True
-except Exception:
- HAS_LIB = False
-from ansible.module_utils.basic import AnsibleModule
-from collections import defaultdict
-
-
-def bgpNeighborConfig(module, cmd, prompt, answer):
- retVal = ''
- command = ''
- bgpNeighborArg1 = module.params['bgpArg4']
- bgpNeighborArg2 = module.params['bgpArg5']
- bgpNeighborArg3 = module.params['bgpArg6']
- bgpNeighborArg4 = module.params['bgpArg7']
- bgpNeighborArg5 = module.params['bgpArg8']
- deviceType = module.params['deviceType']
-
- if(bgpNeighborArg1 == "address-family"):
- command = command + bgpNeighborArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_address_family", bgpNeighborArg2)
- if(value == "ok"):
- command = command + bgpNeighborArg2 + " unicast"
- # debugOutput(command)
- inner_cmd = [{'command': command, 'prompt': None, 'answer': None}]
- cmd.extend(inner_cmd)
- retVal = retVal + bgpNeighborAFConfig(module, cmd, '(config-router-neighbor-af)#', answer)
- return retVal
- else:
- retVal = "Error-316"
- return retVal
-
- elif(bgpNeighborArg1 == "advertisement-interval"):
- command = command + bgpNeighborArg1
-
- elif(bgpNeighborArg1 == "bfd"):
- command = command + bgpNeighborArg1 + " "
- if(bgpNeighborArg2 is not None and bgpNeighborArg2 == "mutihop"):
- command = command + bgpNeighborArg2
-
- elif(bgpNeighborArg1 == "connection-retry-time"):
- command = command + bgpNeighborArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_connection_retrytime", bgpNeighborArg2)
- if(value == "ok"):
- command = command + bgpNeighborArg2
- else:
- retVal = "Error-315"
- return retVal
-
- elif(bgpNeighborArg1 == "description"):
- command = command + bgpNeighborArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_description", bgpNeighborArg2)
- if(value == "ok"):
- command = command + bgpNeighborArg2
- else:
- retVal = "Error-314"
- return retVal
-
- elif(bgpNeighborArg1 == "disallow-infinite-holdtime"):
- command = command + bgpNeighborArg1
-
- elif(bgpNeighborArg1 == "dont-capability-negotiate"):
- command = command + bgpNeighborArg1
-
- elif(bgpNeighborArg1 == "dynamic-capability"):
- command = command + bgpNeighborArg1
-
- elif(bgpNeighborArg1 == "ebgp-multihop"):
- command = command + bgpNeighborArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_maxhopcount", bgpNeighborArg2)
- if(value == "ok"):
- command = command + bgpNeighborArg2
- else:
- retVal = "Error-313"
- return retVal
-
- elif(bgpNeighborArg1 == "interface"):
- command = command + bgpNeighborArg1 + " "
- # TBD
-
- elif(bgpNeighborArg1 == "local-as"):
- command = command + bgpNeighborArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_local_as", bgpNeighborArg2)
- if(value == "ok"):
- command = command + bgpNeighborArg2 + " "
- if(bgpNeighborArg3 is not None and
- bgpNeighborArg3 == "no-prepend"):
- command = command + bgpNeighborArg3 + " "
- if(bgpNeighborArg4 is not None and
- bgpNeighborArg4 == "replace-as"):
- command = command + bgpNeighborArg4 + " "
- if(bgpNeighborArg5 is not None and
- bgpNeighborArg5 == "dual-as"):
- command = command + bgpNeighborArg5
- else:
- command = command.strip()
- else:
- command = command.strip()
- else:
- command = command.strip()
- else:
- retVal = "Error-312"
- return retVal
-
- elif(bgpNeighborArg1 == "maximum-peers"):
- command = command + bgpNeighborArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_maxpeers", bgpNeighborArg2)
- if(value == "ok"):
- command = command + bgpNeighborArg2
- else:
- retVal = "Error-311"
- return retVal
-
- elif(bgpNeighborArg1 == "password"):
- command = command + bgpNeighborArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_password", bgpNeighborArg2)
- if(value == "ok"):
- command = command + bgpNeighborArg2
- else:
- retVal = "Error-310"
- return retVal
-
- elif(bgpNeighborArg1 == "remove-private-AS"):
- command = command + bgpNeighborArg1
-
- elif(bgpNeighborArg1 == "timers"):
- command = command + bgpNeighborArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_timers_Keepalive", bgpNeighborArg2)
- if(value == "ok"):
- command = command + bgpNeighborArg2 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_timers_holdtime", bgpNeighborArg3)
- if(value == "ok"):
- command = command + bgpNeighborArg3
- else:
- retVal = "Error-309"
- return retVal
- else:
- retVal = "Error-308"
- return retVal
-
- elif(bgpNeighborArg1 == "transport"):
- command = command + bgpNeighborArg1 + " connection-mode passive "
-
- elif(bgpNeighborArg1 == "ttl-security"):
- command = command + bgpNeighborArg1 + " hops "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_ttl_hops", bgpNeighborArg2)
- if(value == "ok"):
- command = command + bgpNeighborArg2
- else:
- retVal = "Error-307"
- return retVal
-
- elif(bgpNeighborArg1 == "update-source"):
- command = command + bgpNeighborArg1 + " "
- if(bgpNeighborArg2 is not None):
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_update_options", bgpNeighborArg2)
- if(value == "ok"):
- command = command + bgpNeighborArg2 + " "
- if(bgpNeighborArg2 == "ethernet"):
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_update_ethernet",
- bgpNeighborArg3)
- if(value == "ok"):
- command = command + bgpNeighborArg3
- else:
- retVal = "Error-304"
- return retVal
- elif(bgpNeighborArg2 == "loopback"):
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_update_loopback",
- bgpNeighborArg3)
- if(value == "ok"):
- command = command + bgpNeighborArg3
- else:
- retVal = "Error-305"
- return retVal
- else:
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_update_vlan",
- bgpNeighborArg3)
- if(value == "ok"):
- command = command + bgpNeighborArg3
- else:
- retVal = "Error-306"
- return retVal
- else:
- command = command + bgpNeighborArg2
- else:
- retVal = "Error-303"
- return retVal
-
- elif(bgpNeighborArg1 == "weight"):
- command = command + bgpNeighborArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_weight", bgpNeighborArg2)
- if(value == "ok"):
- command = command + bgpNeighborArg2
- else:
- retVal = "Error-302"
- return retVal
-
- else:
- retVal = "Error-301"
- return retVal
-
- # debugOutput(command)
- inner_cmd = [{'command': command, 'prompt': None, 'answer': None}]
- cmd.extend(inner_cmd)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- command = "exit \n"
- return retVal
-# EOM
-
-
-def bgpNeighborAFConfig(module, cmd, prompt, answer):
- retVal = ''
- command = ''
- bgpNeighborAFArg1 = module.params['bgpArg6']
- bgpNeighborAFArg2 = module.params['bgpArg7']
- bgpNeighborAFArg3 = module.params['bgpArg8']
- deviceType = module.params['deviceType']
- if(bgpNeighborAFArg1 == "allowas-in"):
- command = command + bgpNeighborAFArg1 + " "
- if(bgpNeighborAFArg2 is not None):
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_af_occurances", bgpNeighborAFArg2)
- if(value == "ok"):
- command = command + bgpNeighborAFArg2
- else:
- retVal = "Error-325"
- return retVal
-
- elif(bgpNeighborAFArg1 == "default-originate"):
- command = command + bgpNeighborAFArg1 + " "
- if(bgpNeighborAFArg2 is not None and bgpNeighborAFArg2 == "route-map"):
- command = command + bgpNeighborAFArg2 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_af_routemap", bgpNeighborAFArg2)
- if(value == "ok"):
- command = command + bgpNeighborAFArg3
- else:
- retVal = "Error-324"
- return retVal
-
- elif(bgpNeighborAFArg1 == "filter-list"):
- command = command + bgpNeighborAFArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_af_filtername", bgpNeighborAFArg2)
- if(value == "ok"):
- command = command + bgpNeighborAFArg2 + " "
- if(bgpNeighborAFArg3 == "in" or bgpNeighborAFArg3 == "out"):
- command = command + bgpNeighborAFArg3
- else:
- retVal = "Error-323"
- return retVal
- else:
- retVal = "Error-322"
- return retVal
-
- elif(bgpNeighborAFArg1 == "maximum-prefix"):
- command = command + bgpNeighborAFArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_af_maxprefix", bgpNeighborAFArg2)
- if(value == "ok"):
- command = command + bgpNeighborAFArg2 + " "
- if(bgpNeighborAFArg3 is not None):
- command = command + bgpNeighborAFArg3
- else:
- command = command.strip()
- else:
- retVal = "Error-326"
- return retVal
-
- elif(bgpNeighborAFArg1 == "next-hop-self"):
- command = command + bgpNeighborAFArg1
-
- elif(bgpNeighborAFArg1 == "prefix-list"):
- command = command + bgpNeighborAFArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_af_prefixname", bgpNeighborAFArg2)
- if(value == "ok"):
- command = command + bgpNeighborAFArg2 + " "
- if(bgpNeighborAFArg3 == "in" or bgpNeighborAFArg3 == "out"):
- command = command + bgpNeighborAFArg3
- else:
- retVal = "Error-321"
- return retVal
- else:
- retVal = "Error-320"
- return retVal
-
- elif(bgpNeighborAFArg1 == "route-map"):
- command = command + bgpNeighborAFArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_af_routemap", bgpNeighborAFArg2)
- if(value == "ok"):
- command = command + bgpNeighborAFArg2
- else:
- retVal = "Error-319"
- return retVal
- elif(bgpNeighborAFArg1 == "route-reflector-client"):
- command = command + bgpNeighborAFArg1
-
- elif(bgpNeighborAFArg1 == "send-community"):
- command = command + bgpNeighborAFArg1 + " "
- if(bgpNeighborAFArg2 is not None and bgpNeighborAFArg2 == "extended"):
- command = command + bgpNeighborAFArg2
-
- elif(bgpNeighborAFArg1 == "soft-reconfiguration"):
- command = command + bgpNeighborAFArg1 + " inbound"
-
- elif(bgpNeighborAFArg1 == "unsuppress-map"):
- command = command + bgpNeighborAFArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_neighbor_af_routemap", bgpNeighborAFArg2)
- if(value == "ok"):
- command = command + bgpNeighborAFArg2
- else:
- retVal = "Error-318"
- return retVal
-
- else:
- retVal = "Error-317"
- return retVal
-
- # debugOutput(command)
- inner_cmd = [{'command': command, 'prompt': None, 'answer': None}]
- cmd.extend(inner_cmd)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- return retVal
-# EOM
-
-
-def bgpAFConfig(module, cmd, prompt, answer):
- retVal = ''
- command = ''
- bgpAFArg1 = module.params['bgpArg3']
- bgpAFArg2 = module.params['bgpArg4']
- bgpAFArg3 = module.params['bgpArg5']
- bgpAFArg4 = module.params['bgpArg6']
- bgpAFArg5 = module.params['bgpArg7']
- bgpAFArg6 = module.params['bgpArg8']
- deviceType = module.params['deviceType']
- if(bgpAFArg1 == "aggregate-address"):
- command = command + bgpAFArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_aggregate_prefix", bgpAFArg2)
- if(value == "ok"):
- if(bgpAFArg2 is None):
- command = command.strip()
- elif(bgpAFArg2 == "as-set" or bgpAFArg2 == "summary-only"):
- command = command + bgpAFArg2 + " "
- if((bgpAFArg3 is not None) and (bgpAFArg2 == "as-set")):
- command = command + "summary-only"
- else:
- retVal = "Error-297"
- return retVal
- else:
- retVal = "Error-296"
- return retVal
-
- elif(bgpAFArg1 == "client-to-client"):
- command = command + bgpAFArg1 + " reflection "
-
- elif(bgpAFArg1 == "dampening"):
- command = command + bgpAFArg1 + " "
- if(bgpAFArg2 == "route-map"):
- command = command + bgpAFArg2 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "addrfamily_routemap_name", bgpAFArg3)
- if(value == "ok"):
- command = command + bgpAFArg3
- else:
- retVal = "Error-196"
- return retVal
- elif(bgpAFArg2 is not None):
- value = cnos.checkSanityofVariable(
- deviceType, "reachability_half_life", bgpAFArg2)
- if(value == "ok"):
- command = command + bgpAFArg2 + " "
- if(bgpAFArg3 is not None):
- value1 = cnos.checkSanityofVariable(
- deviceType, "start_reuse_route_value", bgpAFArg3)
- value2 = cnos.checkSanityofVariable(
- deviceType, "start_suppress_route_value", bgpAFArg4)
- value3 = cnos.checkSanityofVariable(
- deviceType, "max_duration_to_suppress_route",
- bgpAFArg5)
- if(value1 == "ok" and value2 == "ok" and value3 == "ok"):
- command = command + bgpAFArg3 + " " + bgpAFArg4 + \
- " " + bgpAFArg5 + " "
- if(bgpAFArg6 is not None):
- value = cnos.checkSanityofVariable(
- deviceType,
- "unreachability_halftime_for_penalty",
- bgpAFArg6)
- if(value == "ok"):
- command = command + bgpAFArg6
- else:
- retVal = "Error-295"
- return retVal
- else:
- command = command.strip()
- else:
- retVal = "Error-294"
- return retVal
-
- elif(bgpAFArg1 == "distance"):
- command = command + bgpAFArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "distance_external_AS", bgpAFArg2)
- if(value == "ok"):
- command = command + bgpAFArg2 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "distance_internal_AS", bgpAFArg3)
- if(value == "ok"):
- command = command + bgpAFArg3 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "distance_local_routes", bgpAFArg4)
- if(value == "ok"):
- command = command + bgpAFArg4
- else:
- retVal = "Error-291"
- return retVal
- else:
- retVal = "Error-292"
- return retVal
- else:
- retVal = "Error-293"
- return retVal
-
- elif(bgpAFArg1 == "maximum-paths"):
- command = command + bgpAFArg1 + " "
- value = cnos.checkSanityofVariable(deviceType, "maxpath_option", bgpAFArg2)
- if(value == "ok"):
- command = command + bgpAFArg2 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "maxpath_numbers", bgpAFArg3)
- if(value == "ok"):
- command = command + bgpAFArg3
- else:
- retVal = "Error-199"
- return retVal
- else:
- retVal = "Error-290"
- return retVal
-
- elif(bgpAFArg1 == "network"):
- command = command + bgpAFArg1 + " "
- if(bgpAFArg2 == "synchronization"):
- command = command + bgpAFArg2
- else:
- value = cnos.checkSanityofVariable(
- deviceType, "network_ip_prefix_with_mask", bgpAFArg2)
- if(value == "ok"):
- command = command + bgpAFArg2 + " "
- if(bgpAFArg3 is not None and bgpAFArg3 == "backdoor"):
- command = command + bgpAFArg3
- elif(bgpAFArg3 is not None and bgpAFArg3 == "route-map"):
- command = command + bgpAFArg3
- value = cnos.checkSanityofVariable(
- deviceType, "addrfamily_routemap_name", bgpAFArg4)
- if(value == "ok"):
- command = command + bgpAFArg4 + " "
- if(bgpAFArg5 is not None and bgpAFArg5 == "backdoor"):
- command = command + bgpAFArg5
- else:
- retVal = "Error-298"
- return retVal
- else:
- retVal = "Error-196"
- return retVal
- else:
- command = command.strip()
- else:
- value = cnos.checkSanityofVariable(
- deviceType, "network_ip_prefix_value", bgpAFArg2)
- if(value == "ok"):
- command = command + bgpAFArg2 + " "
- if(bgpAFArg3 is not None and bgpAFArg3 == "backdoor"):
- command = command + bgpAFArg3
- elif(bgpAFArg3 is not None and bgpAFArg3 == "route-map"):
- command = command + bgpAFArg3
- value = cnos.checkSanityofVariable(
- deviceType, "addrfamily_routemap_name", bgpAFArg4)
- if(value == "ok"):
- command = command + bgpAFArg4 + " "
- if(bgpAFArg5 is not None and
- bgpAFArg5 == "backdoor"):
- command = command + bgpAFArg5
- else:
- retVal = "Error-298"
- return retVal
- else:
- retVal = "Error-196"
- return retVal
- elif(bgpAFArg3 is not None and bgpAFArg3 == "mask"):
- command = command + bgpAFArg3
- value = cnos.checkSanityofVariable(
- deviceType, "network_ip_prefix_mask", bgpAFArg4)
- if(value == "ok"):
- command = command + bgpAFArg4 + " "
- else:
- retVal = "Error-299"
- return retVal
- else:
- command = command.strip()
- else:
- retVal = "Error-300"
- return retVal
-
- elif(bgpAFArg1 == "nexthop"):
- command = command + bgpAFArg1 + " trigger-delay critical "
- value = cnos.checkSanityofVariable(
- deviceType, "nexthop_crtitical_delay", bgpAFArg2)
- if(value == "ok"):
- command = command + bgpAFArg2 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "nexthop_noncrtitical_delay", bgpAFArg3)
- if(value == "ok"):
- command = command + bgpAFArg3 + " "
- else:
- retVal = "Error-198"
- return retVal
- else:
- retVal = "Error-197"
- return retVal
-
- elif(bgpAFArg1 == "redistribute"):
- command = command + bgpAFArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "addrfamily_redistribute_option", bgpAFArg2)
- if(value == "ok"):
- if(bgpAFArg2 is not None):
- command = command + bgpAFArg2 + " " + "route-map "
- value = cnos.checkSanityofVariable(
- deviceType, "addrfamily_routemap_name", bgpAFArg3)
- if(value == "ok"):
- command = command + bgpAFArg3
- else:
- retVal = "Error-196"
- return retVal
- else:
- retVal = "Error-195"
- return retVal
-
- elif(bgpAFArg1 == "save" or bgpAFArg1 == "synchronization"):
- command = command + bgpAFArg1
-
- else:
- retVal = "Error-194"
- return retVal
- # debugOutput(command)
- inner_cmd = [{'command': command, 'prompt': None, 'answer': None}]
- cmd.extend(inner_cmd)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- command = "exit \n"
- return retVal
-# EOM
-
-
-def bgpConfig(module, cmd, prompt, answer):
- retVal = ''
- command = ''
- bgpArg1 = module.params['bgpArg1']
- bgpArg2 = module.params['bgpArg2']
- bgpArg3 = module.params['bgpArg3']
- bgpArg4 = module.params['bgpArg4']
- bgpArg5 = module.params['bgpArg5']
- bgpArg6 = module.params['bgpArg6']
- bgpArg7 = module.params['bgpArg7']
- bgpArg8 = module.params['bgpArg8']
- asNum = module.params['asNum']
- deviceType = module.params['deviceType']
- # cnos.debugOutput(bgpArg1)
- if(bgpArg1 == "address-family"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_address_family", bgpArg2)
- if(value == "ok"):
- command = command + bgpArg2 + " " + "unicast \n"
- # debugOutput(command)
- inner_cmd = [{'command': command, 'prompt': None, 'answer': None}]
- cmd.extend(inner_cmd)
- retVal = retVal + bgpAFConfig(module, cmd, prompt, answer)
- return retVal
- else:
- retVal = "Error-178"
- return retVal
-
- elif(bgpArg1 == "bestpath"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1 + " "
- if(bgpArg2 == "always-compare-med"):
- # debugOutput(bgpArg2)
- command = command + bgpArg2
- elif(bgpArg2 == "compare-confed-aspath"):
- # debugOutput(bgpArg2)
- command = command + bgpArg2
- elif(bgpArg2 == "compare-routerid"):
- # debugOutput(bgpArg2)
- command = command + bgpArg2
- elif(bgpArg2 == "dont-compare-originator-id"):
- # debugOutput(bgpArg2)
- command = command + bgpArg2
- elif(bgpArg2 == "tie-break-on-age"):
- # debugOutput(bgpArg2)
- command = command + bgpArg2
- elif(bgpArg2 == "as-path"):
- # debugOutput(bgpArg2)
- command = command + bgpArg2 + " "
- if(bgpArg3 == "ignore" or bgpArg3 == "multipath-relax"):
- command = command + bgpArg3
- else:
- retVal = "Error-179"
- return retVal
- elif(bgpArg2 == "med"):
- # debugOutput(bgpArg2)
- command = command + bgpArg2 + " "
- if(bgpArg3 == "confed" or
- bgpArg3 == "missing-as-worst" or
- bgpArg3 == "non-deterministic" or
- bgpArg3 == "remove-recv-med" or
- bgpArg3 == "remove-send-med"):
- command = command + bgpArg3
- else:
- retVal = "Error-180"
- return retVal
- else:
- retVal = "Error-181"
- return retVal
-
- elif(bgpArg1 == "bgp"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1 + " as-local-count "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_bgp_local_count", bgpArg2)
- if(value == "ok"):
- command = command + bgpArg2
- else:
- retVal = "Error-182"
- return retVal
-
- elif(bgpArg1 == "cluster-id"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1 + " "
- value = cnos.checkSanityofVariable(deviceType, "cluster_id_as_ip", bgpArg2)
- if(value == "ok"):
- command = command + bgpArg2
- else:
- value = cnos.checkSanityofVariable(
- deviceType, "cluster_id_as_number", bgpArg2)
- if(value == "ok"):
- command = command + bgpArg2
- else:
- retVal = "Error-183"
- return retVal
-
- elif(bgpArg1 == "confederation"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1 + " "
- if(bgpArg2 == "identifier"):
- value = cnos.checkSanityofVariable(
- deviceType, "confederation_identifier", bgpArg3)
- if(value == "ok"):
- command = command + bgpArg2 + " " + bgpArg3 + "\n"
- else:
- retVal = "Error-184"
- return retVal
- elif(bgpArg2 == "peers"):
- value = cnos.checkSanityofVariable(
- deviceType, "confederation_peers_as", bgpArg3)
- if(value == "ok"):
- command = command + bgpArg2 + " " + bgpArg3
- else:
- retVal = "Error-185"
- return retVal
- else:
- retVal = "Error-186"
- return retVal
-
- elif(bgpArg1 == "enforce-first-as"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1
-
- elif(bgpArg1 == "fast-external-failover"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1
-
- elif(bgpArg1 == "graceful-restart"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1 + " stalepath-time "
- value = cnos.checkSanityofVariable(
- deviceType, "stalepath_delay_value", bgpArg2)
- if(value == "ok"):
- command = command + bgpArg2
- else:
- retVal = "Error-187"
- return retVal
-
- elif(bgpArg1 == "graceful-restart-helper"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1
-
- elif(bgpArg1 == "log-neighbor-changes"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1
-
- elif(bgpArg1 == "maxas-limit"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1 + " "
- value = cnos.checkSanityofVariable(deviceType, "maxas_limit_as", bgpArg2)
- if(value == "ok"):
- command = command + bgpArg2
- else:
- retVal = "Error-188"
- return retVal
-
- elif(bgpArg1 == "neighbor"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "neighbor_ipaddress", bgpArg2)
- if(value == "ok"):
- command = command + bgpArg2
- if(bgpArg3 is not None):
- command = command + " remote-as "
- value = cnos.checkSanityofVariable(
- deviceType, "neighbor_as", bgpArg3)
- if(value == "ok"):
- # debugOutput(command)
- command = command + bgpArg3
- inner_cmd = [{'command': command, 'prompt': None, 'answer': None}]
- cmd.extend(inner_cmd)
- retVal = retVal + bgpNeighborConfig(module, cmd, prompt, answer)
- return retVal
- else:
- retVal = "Error-189"
- return retVal
-
- elif(bgpArg1 == "router-id"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1 + " "
- value = cnos.checkSanityofVariable(deviceType, "router_id", bgpArg2)
- if(value == "ok"):
- command = command + bgpArg2
- else:
- retVal = "Error-190"
- return retVal
-
- elif(bgpArg1 == "shutdown"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1
-
- elif(bgpArg1 == "synchronization"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1
-
- elif(bgpArg1 == "timers"):
- # cnos.debugOutput(bgpArg3)
- command = command + bgpArg1 + " bgp "
- value = cnos.checkSanityofVariable(
- deviceType, "bgp_keepalive_interval", bgpArg2)
- if(value == "ok"):
- command = command + bgpArg2
- else:
- retVal = "Error-191"
- return retVal
- if(bgpArg3 is not None):
- value = cnos.checkSanityofVariable(deviceType, "bgp_holdtime", bgpArg3)
- if(value == "ok"):
- command = command + " " + bgpArg3
- else:
- retVal = "Error-192"
- return retVal
- else:
- retVal = "Error-192"
- return retVal
-
- elif(bgpArg1 == "vrf"):
- # debugOutput(bgpArg1)
- command = command + bgpArg1 + " default"
- else:
- # debugOutput(bgpArg1)
- retVal = "Error-192"
- return retVal
- # debugOutput(command)
- inner_cmd = [{'command': command, 'prompt': None, 'answer': None}]
- cmd.extend(inner_cmd)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- command = "exit \n"
- # debugOutput(command)
- return retVal
-# EOM
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- outputfile=dict(required=True),
- host=dict(required=False),
- username=dict(required=False),
- password=dict(required=False, no_log=True),
- enablePassword=dict(required=False, no_log=True),
- deviceType=dict(required=True),
- bgpArg1=dict(required=True),
- bgpArg2=dict(required=False),
- bgpArg3=dict(required=False),
- bgpArg4=dict(required=False),
- bgpArg5=dict(required=False),
- bgpArg6=dict(required=False),
- bgpArg7=dict(required=False),
- bgpArg8=dict(required=False),
- asNum=dict(required=True),),
- supports_check_mode=False)
-
- asNum = module.params['asNum']
- outputfile = module.params['outputfile']
- deviceType = module.params['deviceType']
- output = ''
- command = 'router bgp '
- value = cnos.checkSanityofVariable(deviceType, "bgp_as_number", asNum)
- if(value == "ok"):
- # BGP command happens here. It creates if not present
- command = command + asNum
- cmd = [{'command': command, 'prompt': None, 'answer': None}]
- output = output + bgpConfig(module, cmd, '(config)#', None)
- else:
- output = "Error-176"
- # Save it into the file
- file = open(outputfile, "a")
- file.write(output)
- file.close()
-
- # Logic to check when changes occur or not
- errorMsg = cnos.checkOutputForError(output)
- if(errorMsg is None):
- module.exit_json(changed=True, msg="BGP configurations accomplished")
- else:
- module.fail_json(msg=errorMsg)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_command.py b/plugins/modules/network/cnos/cnos_command.py
deleted file mode 100644
index b81812b415..0000000000
--- a/plugins/modules/network/cnos/cnos_command.py
+++ /dev/null
@@ -1,208 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# (C) 2017 Red Hat Inc.
-# Copyright (C) 2017 Lenovo.
-#
-# GNU General Public License v3.0+
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-# Module to execute CNOS Commands on Lenovo Switches.
-# Lenovo Networking
-#
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_command
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Run arbitrary commands on Lenovo CNOS devices
-description:
- - Sends arbitrary commands to an CNOS node and returns the results
- read from the device. The C(cnos_command) module includes an
- argument that will cause the module to wait for a specific condition
- before returning or timing out if the condition is not met.
-options:
- commands:
- description:
- - List of commands to send to the remote device.
- The resulting output from the command is returned.
- If the I(wait_for) argument is provided, the module is not
- returned until the condition is satisfied or the number of
- retires is expired.
- required: true
- wait_for:
- description:
- - List of conditions to evaluate against the output of the
- command. The task will wait for each condition to be true
- before moving forward. If the conditional is not true
- within the configured number of retries, the task fails.
- See examples.
- match:
- description:
- - The I(match) argument is used in conjunction with the
- I(wait_for) argument to specify the match policy. Valid
- values are C(all) or C(any). If the value is set to C(all)
- then all conditionals in the wait_for must be satisfied. If
- the value is set to C(any) then only one of the values must be
- satisfied.
- default: all
- choices: ['any', 'all']
- retries:
- description:
- - Specifies the number of retries a command should by tried
- before it is considered failed. The command is run on the
- target device every retry and evaluated against the
- I(wait_for) conditions.
- default: 10
- interval:
- description:
- - Configures the interval in seconds to wait between retries
- of the command. If the command does not pass the specified
- conditions, the interval indicates how long to wait before
- trying the command again.
- default: 1
-'''
-
-EXAMPLES = """
----
-- name: test contains operator
- cnos_command:
- commands:
- - show version
- - show system memory
- wait_for:
- - "result[0] contains 'Lenovo'"
- - "result[1] contains 'MemFree'"
- register: result
-
-- assert:
- that:
- - "result.changed == false"
- - "result.stdout is defined"
-
-- name: get output for single command
- cnos_command:
- commands: ['show version']
- register: result
-
-- assert:
- that:
- - "result.changed == false"
- - "result.stdout is defined"
-
-- name: get output for multiple commands
- cnos_command:
- commands:
- - show version
- - show interface information
- register: result
-
-- assert:
- that:
- - "result.changed == false"
- - "result.stdout is defined"
- - "result.stdout | length == 2"
-"""
-
-RETURN = """
-stdout:
- description: the set of responses from the commands
- returned: always
- type: list
- sample: ['...', '...']
-stdout_lines:
- description: The value of stdout split into a list
- returned: always
- type: list
- sample: [['...', '...'], ['...'], ['...']]
-failed_conditions:
- description: the conditionals that failed
- returned: failed
- type: list
- sample: ['...', '...']
-"""
-
-import time
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import run_commands, check_args
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import Conditional
-from ansible.module_utils.six import string_types
-
-
-def to_lines(stdout):
- for item in stdout:
- if isinstance(item, string_types):
- item = str(item).split('\n')
- yield item
-
-
-def main():
- spec = dict(
- # { command: , prompt: , response: }
- commands=dict(type='list', required=True),
-
- wait_for=dict(type='list'),
- match=dict(default='all', choices=['all', 'any']),
-
- retries=dict(default=10, type='int'),
- interval=dict(default=1, type='int')
- )
-
- module = AnsibleModule(argument_spec=spec, supports_check_mode=True)
- result = {'changed': False}
-
- wait_for = module.params['wait_for'] or list()
- conditionals = [Conditional(c) for c in wait_for]
-
- commands = module.params['commands']
- retries = module.params['retries']
- interval = module.params['interval']
- match = module.params['match']
-
- while retries > 0:
- responses = run_commands(module, commands)
-
- for item in list(conditionals):
- if item(responses):
- if match == 'any':
- conditionals = list()
- break
- conditionals.remove(item)
-
- if not conditionals:
- break
-
- time.sleep(interval)
- retries -= 1
-
- if conditionals:
- failed_conditions = [item.raw for item in conditionals]
- msg = 'One or more conditional statements have not been satisfied'
- module.fail_json(msg=msg, failed_conditions=failed_conditions)
-
- result.update({
- 'changed': False,
- 'stdout': responses,
- 'stdout_lines': list(to_lines(responses))
- })
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_conditional_command.py b/plugins/modules/network/cnos/cnos_conditional_command.py
deleted file mode 100644
index 4caee7a95f..0000000000
--- a/plugins/modules/network/cnos/cnos_conditional_command.py
+++ /dev/null
@@ -1,168 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2017 Lenovo, Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to send Conditional CLI commands to Lenovo Switches
-# Lenovo Networking
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_conditional_command
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Execute a single command based on condition on devices
- running Lenovo CNOS
-description:
- - This module allows you to modify the running configuration of a switch. It
- provides a way to execute a single CNOS command on a network device by
- evaluating the current running configuration and executing the command only
- if the specific settings have not been already configured.
- The CNOS command is passed as an argument of the method.
- This module functions the same as the cnos_command module.
- The only exception is that following inventory variable can be specified
- ["condition = "]
- When this inventory variable is specified as the variable of a task, the
- command is executed for the network element that matches the flag string.
- Usually, commands are executed across a group of network devices. When
- there is a requirement to skip the execution of the command on one or
- more devices, it is recommended to use this module. This module uses SSH to
- manage network device configuration.
-extends_documentation_fragment:
-- community.general.cnos
-
-options:
- clicommand:
- description:
- - This specifies the CLI command as an attribute to this method.
- The command is passed using double quotes. The variables can be
- placed directly on to the CLI commands or can be invoked
- from the vars directory.
- required: true
- default: Null
- condition:
- description:
- - If you specify condition=false in the inventory file against any
- device, the command execution is skipped for that device.
- required: true
- default: Null
- flag:
- description:
- - If a task needs to be executed, you have to set the flag the same
- as it is specified in the inventory for that device.
- required: true
- default: Null
-
-'''
-EXAMPLES = '''
-Tasks : The following are examples of using the module
- cnos_conditional_command. These are written in the main.yml file of the tasks
- directory.
----
-- name: Applying CLI template on VLAG Tier1 Leaf Switch1
- cnos_conditional_command:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_conditional_command_
- {{ inventory_hostname }}_output.txt"
- condition: "{{ hostvars[inventory_hostname]['condition']}}"
- flag: leaf_switch2
- command: "spanning-tree mode enable"
-
-'''
-RETURN = '''
-msg:
- description: Success or failure message
- returned: always
- type: str
- sample: "Command Applied"
-'''
-
-import sys
-import time
-import socket
-import array
-import json
-import time
-import re
-import os
-try:
- from ansible_collections.community.general.plugins.module_utils.network.cnos import cnos
- HAS_LIB = True
-except Exception:
- HAS_LIB = False
-from ansible.module_utils.basic import AnsibleModule
-from collections import defaultdict
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- clicommand=dict(required=True),
- outputfile=dict(required=True),
- condition=dict(required=True),
- flag=dict(required=True),
- host=dict(required=False),
- deviceType=dict(required=True),
- username=dict(required=False),
- password=dict(required=False, no_log=True),
- enablePassword=dict(required=False,
- no_log=True), ), supports_check_mode=False)
-
- condition = module.params['condition']
- flag = module.params['flag']
- cliCommand = module.params['clicommand']
- outputfile = module.params['outputfile']
- output = ''
- if (condition is None or condition != flag):
- module.exit_json(changed=True, msg="Command Skipped for this switch")
- return ''
- # Send the CLi command
- cmd = [{'command': cliCommand, 'prompt': None, 'answer': None}]
- output = output + str(cnos.run_cnos_commands(module, cmd))
- # Write to memory
- save_cmd = [{'command': 'save', 'prompt': None, 'answer': None}]
- cmd.extend(save_cmd)
- output = output + str(cnos.run_cnos_commands(module, cmd))
-
- # Save it into the file
- path = outputfile.rsplit('/', 1)
- # cnos.debugOutput(path[0])
- if not os.path.exists(path[0]):
- os.makedirs(path[0])
- file = open(outputfile, "a")
- file.write(output)
- file.close()
-
- # Logic to check when changes occur or not
- errorMsg = cnos.checkOutputForError(output)
- if(errorMsg is None):
- module.exit_json(changed=True,
- msg="CLI Command executed and results saved in file ")
- else:
- module.fail_json(msg=errorMsg)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_conditional_template.py b/plugins/modules/network/cnos/cnos_conditional_template.py
deleted file mode 100644
index 244c4fe8de..0000000000
--- a/plugins/modules/network/cnos/cnos_conditional_template.py
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2017 Lenovo, Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to send conditional template to Lenovo Switches
-# Lenovo Networking
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_conditional_template
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Manage switch configuration using templates based on
- condition on devices running Lenovo CNOS
-description:
- - This module allows you to work with the running configuration of a
- switch. It provides a way to execute a set of CNOS commands on a switch by
- evaluating the current running configuration and executing the commands
- only if the specific settings have not been already configured.
- The configuration source can be a set of commands or a template written in
- the Jinja2 templating language. This module functions the same as the
- cnos_template module. The only exception is that the following inventory
- variable can be specified.
- ["condition = "]
- When this inventory variable is specified as the variable of a task, the
- template is executed for the network element that matches the flag string.
- Usually, templates are used when commands are the same across a group of
- network devices. When there is a requirement to skip the execution of the
- template on one or more devices, it is recommended to use this module.
- This module uses SSH to manage network device configuration.
-extends_documentation_fragment:
-- community.general.cnos
-
-options:
- commandfile:
- description:
- - This specifies the path to the CNOS command file which needs to
- be applied. This usually comes from the commands folder. Generally
- this file is the output of the variables applied on a template
- file. So this command is preceded by a template module. The
- command file must contain the Ansible keyword
- {{ inventory_hostname }} and the condition flag in its filename to
- ensure that the command file is unique for each switch and
- condition. If this is omitted, the command file will be
- overwritten during iteration. For example,
- commandfile=./commands/clos_leaf_bgp_
- {{ inventory_hostname }}_LP21_commands.txt
- required: true
- default: Null
- condition:
- description:
- - If you specify condition= in the inventory file
- against any device, the template execution is done for that device
- in case it matches the flag setting for that task.
- required: true
- default: Null
- flag:
- description:
- - If a task needs to be executed, you have to set the flag the same
- as it is specified in the inventory for that device.
- required: true
- default: Null
-'''
-EXAMPLES = '''
-Tasks : The following are examples of using the module
- cnos_conditional_template. These are written in the main.yml file of the
- tasks directory.
----
-- name: Applying CLI template on VLAG Tier1 Leaf Switch1
- cnos_conditional_template:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/vlag_1tier_leaf_switch1_
- {{ inventory_hostname }}_output.txt"
- condition: "{{ hostvars[inventory_hostname]['condition']}}"
- flag: "leaf_switch1"
- commandfile: "./commands/vlag_1tier_leaf_switch1_
- {{ inventory_hostname }}_commands.txt"
- stp_mode1: "disable"
- port_range1: "17,18,29,30"
- portchannel_interface_number1: 1001
- portchannel_mode1: active
- slot_chassis_number1: 1/48
- switchport_mode1: trunk
-'''
-RETURN = '''
-msg:
- description: Success or failure message
- returned: always
- type: str
- sample: "Template Applied."
-'''
-
-import sys
-import time
-import socket
-import array
-import json
-import time
-import re
-import os
-try:
- from ansible_collections.community.general.plugins.module_utils.network.cnos import cnos
- HAS_LIB = True
-except Exception:
- HAS_LIB = False
-from ansible.module_utils.basic import AnsibleModule
-from collections import defaultdict
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- commandfile=dict(required=True),
- outputfile=dict(required=True),
- condition=dict(required=True),
- flag=dict(required=True),
- host=dict(required=False),
- deviceType=dict(required=True),
- username=dict(required=False),
- password=dict(required=False, no_log=True),
- enablePassword=dict(required=False, no_log=True),),
- supports_check_mode=False)
-
- condition = module.params['condition']
- flag = module.params['flag']
- commandfile = module.params['commandfile']
- outputfile = module.params['outputfile']
-
- output = ''
- if (condition is None or condition != flag):
- module.exit_json(changed=True, msg="Template Skipped for this switch")
- return " "
- # Send commands one by one
- f = open(commandfile, "r")
- cmd = []
- for line in f:
- # Omit the comment lines in template file
- if not line.startswith("#"):
- # cnos.debugOutput(line)
- command = line.strip()
- inner_cmd = [{'command': command, 'prompt': None, 'answer': None}]
- cmd.extend(inner_cmd)
- # Write to memory
- save_cmd = [{'command': 'save', 'prompt': None, 'answer': None}]
- cmd.extend(save_cmd)
- output = output + str(cnos.run_cnos_commands(module, cmd))
- # Write output to file
- path = outputfile.rsplit('/', 1)
- # cnos.debugOutput(path[0])
- if not os.path.exists(path[0]):
- os.makedirs(path[0])
- file = open(outputfile, "a")
- file.write(output)
- file.close()
-
- # Logic to check when changes occur or not
- errorMsg = cnos.checkOutputForError(output)
- if(errorMsg is None):
- module.exit_json(changed=True, msg="Template Applied")
- else:
- module.fail_json(msg=errorMsg)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_config.py b/plugins/modules/network/cnos/cnos_config.py
deleted file mode 100644
index abbf95c04d..0000000000
--- a/plugins/modules/network/cnos/cnos_config.py
+++ /dev/null
@@ -1,307 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# (C) 2017 Red Hat Inc.
-# Copyright (C) 2017 Lenovo.
-#
-# GNU General Public License v3.0+
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-# Module to configure Lenovo Switches.
-# Lenovo Networking
-#
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_config
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Manage Lenovo CNOS configuration sections
-description:
- - Lenovo CNOS configurations use a simple block indent file syntax
- for segmenting configuration into sections. This module provides
- an implementation for working with CNOS configuration sections in
- a deterministic way.
-notes:
- - Tested against CNOS 10.9.1
-options:
- lines:
- description:
- - The ordered set of commands that should be configured in the
- section. The commands must be the exact same commands as found
- in the device running-config. Be sure to note the configuration
- command syntax as some commands are automatically modified by the
- device config parser.
- aliases: ['commands']
- parents:
- description:
- - The ordered set of parents that uniquely identify the section
- the commands should be checked against. If the parents argument
- is omitted, the commands are checked against the set of top
- level or global commands.
- src:
- description:
- - Specifies the source path to the file that contains the configuration
- or configuration template to load. The path to the source file can
- either be the full path on the Ansible control host or a relative
- path from the playbook or role root directory. This argument is
- mutually exclusive with I(lines), I(parents).
- before:
- description:
- - The ordered set of commands to push on to the command stack if
- a change needs to be made. This allows the playbook designer
- the opportunity to perform configuration commands prior to pushing
- any changes without affecting how the set of commands are matched
- against the system.
- after:
- description:
- - The ordered set of commands to append to the end of the command
- stack if a change needs to be made. Just like with I(before) this
- allows the playbook designer to append a set of commands to be
- executed after the command set.
- match:
- description:
- - Instructs the module on the way to perform the matching of
- the set of commands against the current device config. If
- match is set to I(line), commands are matched line by line. If
- match is set to I(strict), command lines are matched with respect
- to position. If match is set to I(exact), command lines
- must be an equal match. Finally, if match is set to I(none), the
- module will not attempt to compare the source configuration with
- the running configuration on the remote device.
- default: line
- choices: ['line', 'strict', 'exact', 'none']
- replace:
- description:
- - Instructs the module on the way to perform the configuration
- on the device. If the replace argument is set to I(line) then
- the modified lines are pushed to the device in configuration
- mode. If the replace argument is set to I(block) then the entire
- command block is pushed to the device in configuration mode if any
- line is not correct.
- default: line
- choices: ['line', 'block', 'config']
- config:
- description:
- - The module, by default, will connect to the remote device and
- retrieve the current running-config to use as a base for comparing
- against the contents of source. There are times when it is not
- desirable to have the task get the current running-config for
- every task in a playbook. The I(config) argument allows the
- implementer to pass in the configuration to use as the base
- config for comparison.
- backup:
- description:
- - This argument will cause the module to create a full backup of
- the current C(running-config) from the remote device before any
- changes are made. If the C(backup_options) value is not given,
- the backup file is written to the C(backup) folder in the playbook
- root directory. If the directory does not exist, it is created.
- type: bool
- default: 'no'
- comment:
- description:
- - Allows a commit description to be specified to be included
- when the configuration is committed. If the configuration is
- not changed or committed, this argument is ignored.
- default: 'configured by cnos_config'
- admin:
- description:
- - Enters into administration configuration mode for making config
- changes to the device.
- type: bool
- default: 'no'
- backup_options:
- description:
- - This is a dict object containing configurable options related to backup file path.
- The value of this option is read only when C(backup) is set to I(yes), if C(backup) is set
- to I(no) this option will be silently ignored.
- suboptions:
- filename:
- description:
- - The filename to be used to store the backup configuration. If the filename
- is not given it will be generated based on the hostname, current time and date
- in format defined by _config.@
- dir_path:
- description:
- - This option provides the path ending with directory name in which the backup
- configuration file will be stored. If the directory does not exist it will be first
- created and the filename is either the value of C(filename) or default filename
- as described in C(filename) options description. If the path value is not given
- in that case a I(backup) directory will be created in the current working directory
- and backup configuration will be copied in C(filename) within I(backup) directory.
- type: path
- type: dict
-'''
-
-EXAMPLES = """
-Tasks: The following are examples of using the module cnos_config.
----
-- name: configure top level configuration
- cnos_config:
- "lines: hostname {{ inventory_hostname }}"
-
-- name: configure interface settings
- cnos_config:
- lines:
- - enable
- - ip ospf enable
- parents: interface ip 13
-
-- name: load a config from disk and replace the current config
- cnos_config:
- src: config.cfg
- backup: yes
-
-- name: configurable backup path
- cnos_config:
- src: config.cfg
- backup: yes
- backup_options:
- filename: backup.cfg
- dir_path: /home/user
-"""
-
-RETURN = """
-updates:
- description: The set of commands that will be pushed to the remote device
- returned: Only when lines is specified.
- type: list
- sample: ['...', '...']
-backup_path:
- description: The full path to the backup file
- returned: when backup is yes
- type: str
- sample: /playbooks/ansible/backup/cnos01.2016-07-16@22:28:34
-"""
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import load_config, get_config
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import check_args
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, dumps
-
-
-DEFAULT_COMMIT_COMMENT = 'configured by cnos_config'
-
-
-def get_running_config(module):
- contents = module.params['config']
- if not contents:
- contents = get_config(module)
- return NetworkConfig(indent=1, contents=contents)
-
-
-def get_candidate(module):
- candidate = NetworkConfig(indent=1)
- if module.params['src']:
- candidate.load(module.params['src'])
- elif module.params['lines']:
- parents = module.params['parents'] or list()
- candidate.add(module.params['lines'], parents=parents)
- return candidate
-
-
-def run(module, result):
- match = module.params['match']
- replace = module.params['replace']
- replace_config = replace == 'config'
- path = module.params['parents']
- comment = module.params['comment']
- admin = module.params['admin']
- check_mode = module.check_mode
-
- candidate = get_candidate(module)
-
- if match != 'none' and replace != 'config':
- contents = get_running_config(module)
- configobj = NetworkConfig(contents=contents, indent=1)
- commands = candidate.difference(configobj, path=path, match=match,
- replace=replace)
- else:
- commands = candidate.items
-
- if commands:
- commands = dumps(commands, 'commands').split('\n')
-
- if any((module.params['lines'], module.params['src'])):
- if module.params['before']:
- commands[:0] = module.params['before']
-
- if module.params['after']:
- commands.extend(module.params['after'])
-
- result['commands'] = commands
-
- diff = load_config(module, commands)
- if diff:
- result['diff'] = dict(prepared=diff)
- result['changed'] = True
-
-
-def main():
- """main entry point for module execution
- """
- backup_spec = dict(
- filename=dict(),
- dir_path=dict(type='path')
- )
- argument_spec = dict(
- src=dict(type='path'),
-
- lines=dict(aliases=['commands'], type='list'),
- parents=dict(type='list'),
-
- before=dict(type='list'),
- after=dict(type='list'),
-
- match=dict(default='line', choices=['line', 'strict',
- 'exact', 'none']),
- replace=dict(default='line', choices=['line', 'block', 'config']),
-
- config=dict(),
- backup=dict(type='bool', default=False),
- backup_options=dict(type='dict', options=backup_spec),
- comment=dict(default=DEFAULT_COMMIT_COMMENT),
- admin=dict(type='bool', default=False)
- )
-
- mutually_exclusive = [('lines', 'src'),
- ('parents', 'src')]
-
- required_if = [('match', 'strict', ['lines']),
- ('match', 'exact', ['lines']),
- ('replace', 'block', ['lines']),
- ('replace', 'config', ['src'])]
-
- module = AnsibleModule(argument_spec=argument_spec,
- mutually_exclusive=mutually_exclusive,
- required_if=required_if,
- supports_check_mode=True)
-
- warnings = list()
- check_args(module, warnings)
-
- result = dict(changed=False, warnings=warnings)
-
- if module.params['backup']:
- result['__backup__'] = get_config(module)
-
- run(module, result)
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_factory.py b/plugins/modules/network/cnos/cnos_factory.py
deleted file mode 100644
index 7aa0ab712a..0000000000
--- a/plugins/modules/network/cnos/cnos_factory.py
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2017 Lenovo, Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to Reset to factory settings of Lenovo Switches
-# Lenovo Networking
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_factory
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Reset the switch startup configuration to default (factory)
- on devices running Lenovo CNOS.
-description:
- - This module allows you to reset a switch's startup configuration. The
- method provides a way to reset the startup configuration to its factory
- settings. This is helpful when you want to move the switch to another
- topology as a new network device. This module uses SSH to manage network
- device configuration. The result of the operation can be viewed in results
- directory.
-extends_documentation_fragment:
-- community.general.cnos
-
-options: {}
-
-'''
-EXAMPLES = '''
-Tasks : The following are examples of using the module cnos_reload. These are
- written in the main.yml file of the tasks directory.
----
-- name: Test Reset to factory
- cnos_factory:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_factory_{{ inventory_hostname }}_output.txt"
-
-'''
-RETURN = '''
-msg:
- description: Success or failure message
- returned: always
- type: str
- sample: "Switch Startup Config is Reset to factory settings"
-'''
-
-import sys
-import time
-import socket
-import array
-import json
-import time
-import re
-try:
- from ansible_collections.community.general.plugins.module_utils.network.cnos import cnos
- HAS_LIB = True
-except Exception:
- HAS_LIB = False
-from ansible.module_utils.basic import AnsibleModule
-from collections import defaultdict
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- outputfile=dict(required=True),
- host=dict(required=False),
- username=dict(required=False),
- password=dict(required=False, no_log=True),
- enablePassword=dict(required=False, no_log=True),
- deviceType=dict(required=True),),
- supports_check_mode=False)
-
- command = 'write erase'
- outputfile = module.params['outputfile']
- output = ''
- cmd = [{'command': command, 'prompt': '[n]', 'answer': 'y'}]
- output = output + str(cnos.run_cnos_commands(module, cmd))
-
- # Save it into the file
- file = open(outputfile, "a")
- file.write(output)
- file.close()
-
- errorMsg = cnos.checkOutputForError(output)
- if(errorMsg is None):
- module.exit_json(changed=True,
- msg="Switch Startup Config is Reset to Factory settings")
- else:
- module.fail_json(msg=errorMsg)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_facts.py b/plugins/modules/network/cnos/cnos_facts.py
deleted file mode 100644
index a3efab537f..0000000000
--- a/plugins/modules/network/cnos/cnos_facts.py
+++ /dev/null
@@ -1,539 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# (C) 2019 Red Hat Inc.
-# Copyright (C) 2019 Lenovo.
-#
-# GNU General Public License v3.0+
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-# Module to Collect facts from Lenovo Switches running Lenovo CNOS commands
-# Lenovo Networking
-#
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: cnos_facts
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Collect facts from remote devices running Lenovo CNOS
-description:
- - Collects a base set of device facts from a remote Lenovo device
- running on CNOS. This module prepends all of the
- base network fact keys with C(ansible_net_). The facts
- module will always collect a base set of facts from the device
- and can enable or disable collection of additional facts.
-notes:
- - Tested against CNOS 10.8.1
-options:
- authorize:
- description:
- - Instructs the module to enter privileged mode on the remote device
- before sending any commands. If not specified, the device will
- attempt to execute all commands in non-privileged mode. If the value
- is not specified in the task, the value of environment variable
- C(ANSIBLE_NET_AUTHORIZE) will be used instead.
- type: bool
- default: 'no'
- auth_pass:
- description:
- - Specifies the password to use if required to enter privileged mode
- on the remote device. If I(authorize) is false, then this argument
- does nothing. If the value is not specified in the task, the value of
- environment variable C(ANSIBLE_NET_AUTH_PASS) will be used instead.
- gather_subset:
- description:
- - When supplied, this argument will restrict the facts collected
- to a given subset. Possible values for this argument include
- all, hardware, config, and interfaces. Can specify a list of
- values to include a larger subset. Values can also be used
- with an initial C(M(!)) to specify that a specific subset should
- not be collected.
- required: false
- default: '!config'
-'''
-EXAMPLES = '''
-Tasks: The following are examples of using the module cnos_facts.
----
-- name: Test cnos Facts
- cnos_facts:
-
----
-# Collect all facts from the device
-- cnos_facts:
- gather_subset: all
-
-# Collect only the config and default facts
-- cnos_facts:
- gather_subset:
- - config
-
-# Do not collect hardware facts
-- cnos_facts:
- gather_subset:
- - "!hardware"
-'''
-RETURN = '''
- ansible_net_gather_subset:
- description: The list of fact subsets collected from the device
- returned: always
- type: list
-# default
- ansible_net_model:
- description: The model name returned from the Lenovo CNOS device
- returned: always
- type: str
- ansible_net_serialnum:
- description: The serial number of the Lenovo CNOS device
- returned: always
- type: str
- ansible_net_version:
- description: The CNOS operating system version running on the remote device
- returned: always
- type: str
- ansible_net_hostname:
- description: The configured hostname of the device
- returned: always
- type: str
- ansible_net_image:
- description: Indicates the active image for the device
- returned: always
- type: str
-# hardware
- ansible_net_memfree_mb:
- description: The available free memory on the remote device in MB
- returned: when hardware is configured
- type: int
-# config
- ansible_net_config:
- description: The current active config from the device
- returned: when config is configured
- type: str
-# interfaces
- ansible_net_all_ipv4_addresses:
- description: All IPv4 addresses configured on the device
- returned: when interfaces is configured
- type: list
- ansible_net_all_ipv6_addresses:
- description: All IPv6 addresses configured on the device
- returned: when interfaces is configured
- type: list
- ansible_net_interfaces:
- description: A hash of all interfaces running on the system.
- This gives information on description, mac address, mtu, speed,
- duplex and operstatus
- returned: when interfaces is configured
- type: dict
- ansible_net_neighbors:
- description: The list of LLDP neighbors from the remote device
- returned: when interfaces is configured
- type: dict
-'''
-
-import re
-
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import run_commands
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import check_args
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.six import iteritems
-from ansible.module_utils.six.moves import zip
-
-
-class FactsBase(object):
-
- COMMANDS = list()
-
- def __init__(self, module):
- self.module = module
- self.facts = dict()
- self.responses = None
- self.PERSISTENT_COMMAND_TIMEOUT = 60
-
- def populate(self):
- self.responses = run_commands(self.module, self.COMMANDS,
- check_rc=False)
-
- def run(self, cmd):
- return run_commands(self.module, cmd, check_rc=False)
-
-
-class Default(FactsBase):
-
- COMMANDS = ['show sys-info', 'show running-config']
-
- def populate(self):
- super(Default, self).populate()
- data = self.responses[0]
- data_run = self.responses[1]
- if data:
- self.facts['version'] = self.parse_version(data)
- self.facts['serialnum'] = self.parse_serialnum(data)
- self.facts['model'] = self.parse_model(data)
- self.facts['image'] = self.parse_image(data)
- if data_run:
- self.facts['hostname'] = self.parse_hostname(data_run)
-
- def parse_version(self, data):
- for line in data.split('\n'):
- line = line.strip()
- match = re.match(r'System Software Revision (.*?)',
- line, re.M | re.I)
- if match:
- vers = line.split(':')
- ver = vers[1].strip()
- return ver
- return "NA"
-
- def parse_hostname(self, data_run):
- for line in data_run.split('\n'):
- line = line.strip()
- match = re.match(r'hostname (.*?)', line, re.M | re.I)
- if match:
- hosts = line.split()
- hostname = hosts[1].strip('\"')
- return hostname
- return "NA"
-
- def parse_model(self, data):
- for line in data.split('\n'):
- line = line.strip()
- match = re.match(r'System Model (.*?)', line, re.M | re.I)
- if match:
- mdls = line.split(':')
- mdl = mdls[1].strip()
- return mdl
- return "NA"
-
- def parse_image(self, data):
- match = re.search(r'(.*) image(.*)', data, re.M | re.I)
- if match:
- return "Image1"
- else:
- return "Image2"
-
- def parse_serialnum(self, data):
- for line in data.split('\n'):
- line = line.strip()
- match = re.match(r'System Serial Number (.*?)', line, re.M | re.I)
- if match:
- serNums = line.split(':')
- ser = serNums[1].strip()
- return ser
- return "NA"
-
-
-class Hardware(FactsBase):
-
- COMMANDS = [
- 'show running-config'
- ]
-
- def populate(self):
- super(Hardware, self).populate()
- data = self.run(['show process memory'])
- data = to_text(data, errors='surrogate_or_strict').strip()
- data = data.replace(r"\n", "\n")
- if data:
- for line in data.split('\n'):
- line = line.strip()
- match = re.match(r'Mem: (.*?)', line, re.M | re.I)
- if match:
- memline = line.split(':')
- mems = memline[1].strip().split()
- self.facts['memtotal_mb'] = int(mems[0]) / 1024
- self.facts['memused_mb'] = int(mems[1]) / 1024
- self.facts['memfree_mb'] = int(mems[2]) / 1024
- self.facts['memshared_mb'] = int(mems[3]) / 1024
- self.facts['memavailable_mb'] = int(mems[5]) / 1024
-
- def parse_memtotal(self, data):
- match = re.search(r'^MemTotal:\s*(.*) kB', data, re.M | re.I)
- if match:
- return int(match.group(1)) / 1024
-
- def parse_memfree(self, data):
- match = re.search(r'^MemFree:\s*(.*) kB', data, re.M | re.I)
- if match:
- return int(match.group(1)) / 1024
-
-
-class Config(FactsBase):
-
- COMMANDS = ['show running-config']
-
- def populate(self):
- super(Config, self).populate()
- data = self.responses[0]
- if data:
- self.facts['config'] = data
-
-
-class Interfaces(FactsBase):
-
- COMMANDS = ['show interface brief']
-
- def populate(self):
- super(Interfaces, self).populate()
-
- self.facts['all_ipv4_addresses'] = list()
- self.facts['all_ipv6_addresses'] = list()
-
- data1 = self.run(['show interface status'])
- data1 = to_text(data1, errors='surrogate_or_strict').strip()
- data1 = data1.replace(r"\n", "\n")
- data2 = self.run(['show interface mac-address'])
- data2 = to_text(data2, errors='surrogate_or_strict').strip()
- data2 = data2.replace(r"\n", "\n")
- lines1 = None
- lines2 = None
- if data1:
- lines1 = self.parse_interfaces(data1)
- if data2:
- lines2 = self.parse_interfaces(data2)
- if lines1 is not None and lines2 is not None:
- self.facts['interfaces'] = self.populate_interfaces(lines1, lines2)
- data3 = self.run(['show lldp neighbors'])
- data3 = to_text(data3, errors='surrogate_or_strict').strip()
- data3 = data3.replace(r"\n", "\n")
- if data3:
- lines3 = self.parse_neighbors(data3)
- if lines3 is not None:
- self.facts['neighbors'] = self.populate_neighbors(lines3)
-
- data4 = self.run(['show ip interface brief vrf all'])
- data5 = self.run(['show ipv6 interface brief vrf all'])
- data4 = to_text(data4, errors='surrogate_or_strict').strip()
- data4 = data4.replace(r"\n", "\n")
- data5 = to_text(data5, errors='surrogate_or_strict').strip()
- data5 = data5.replace(r"\n", "\n")
- lines4 = None
- lines5 = None
- if data4:
- lines4 = self.parse_ipaddresses(data4)
- ipv4_interfaces = self.set_ip_interfaces(lines4)
- self.facts['all_ipv4_addresses'] = ipv4_interfaces
- if data5:
- lines5 = self.parse_ipaddresses(data5)
- ipv6_interfaces = self.set_ipv6_interfaces(lines5)
- self.facts['all_ipv6_addresses'] = ipv6_interfaces
-
- def parse_ipaddresses(self, data):
- parsed = list()
- for line in data.split('\n'):
- if len(line) == 0:
- continue
- else:
- line = line.strip()
- match = re.match(r'^(Ethernet+)', line)
- if match:
- key = match.group(1)
- parsed.append(line)
- match = re.match(r'^(po+)', line)
- if match:
- key = match.group(1)
- parsed.append(line)
- match = re.match(r'^(mgmt+)', line)
- if match:
- key = match.group(1)
- parsed.append(line)
- match = re.match(r'^(loopback+)', line)
- if match:
- key = match.group(1)
- parsed.append(line)
- return parsed
-
- def populate_interfaces(self, lines1, lines2):
- interfaces = dict()
- for line1, line2 in zip(lines1, lines2):
- line = line1 + " " + line2
- intfSplit = line.split()
- innerData = dict()
- innerData['description'] = intfSplit[1].strip()
- innerData['macaddress'] = intfSplit[8].strip()
- innerData['type'] = intfSplit[6].strip()
- innerData['speed'] = intfSplit[5].strip()
- innerData['duplex'] = intfSplit[4].strip()
- innerData['operstatus'] = intfSplit[2].strip()
- interfaces[intfSplit[0].strip()] = innerData
- return interfaces
-
- def parse_interfaces(self, data):
- parsed = list()
- for line in data.split('\n'):
- if len(line) == 0:
- continue
- else:
- line = line.strip()
- match = re.match(r'^(Ethernet+)', line)
- if match:
- key = match.group(1)
- parsed.append(line)
- match = re.match(r'^(po+)', line)
- if match:
- key = match.group(1)
- parsed.append(line)
- match = re.match(r'^(mgmt+)', line)
- if match:
- key = match.group(1)
- parsed.append(line)
- return parsed
-
- def set_ip_interfaces(self, line4):
- ipv4_addresses = list()
- for line in line4:
- ipv4Split = line.split()
- if 'Ethernet' in ipv4Split[0]:
- ipv4_addresses.append(ipv4Split[1])
- if 'mgmt' in ipv4Split[0]:
- ipv4_addresses.append(ipv4Split[1])
- if 'po' in ipv4Split[0]:
- ipv4_addresses.append(ipv4Split[1])
- if 'loopback' in ipv4Split[0]:
- ipv4_addresses.append(ipv4Split[1])
- return ipv4_addresses
-
- def set_ipv6_interfaces(self, line4):
- ipv6_addresses = list()
- for line in line4:
- ipv6Split = line.split()
- if 'Ethernet' in ipv6Split[0]:
- ipv6_addresses.append(ipv6Split[1])
- if 'mgmt' in ipv6Split[0]:
- ipv6_addresses.append(ipv6Split[1])
- if 'po' in ipv6Split[0]:
- ipv6_addresses.append(ipv6Split[1])
- if 'loopback' in ipv6Split[0]:
- ipv6_addresses.append(ipv6Split[1])
- return ipv6_addresses
-
- def populate_neighbors(self, lines3):
- neighbors = dict()
- device_name = ''
- for line in lines3:
- neighborSplit = line.split()
- innerData = dict()
- count = len(neighborSplit)
- if count == 5:
- local_interface = neighborSplit[1].strip()
- innerData['Device Name'] = neighborSplit[0].strip()
- innerData['Hold Time'] = neighborSplit[2].strip()
- innerData['Capability'] = neighborSplit[3].strip()
- innerData['Remote Port'] = neighborSplit[4].strip()
- neighbors[local_interface] = innerData
- elif count == 4:
- local_interface = neighborSplit[0].strip()
- innerData['Hold Time'] = neighborSplit[1].strip()
- innerData['Capability'] = neighborSplit[2].strip()
- innerData['Remote Port'] = neighborSplit[3].strip()
- neighbors[local_interface] = innerData
- return neighbors
-
- def parse_neighbors(self, neighbors):
- parsed = list()
- for line in neighbors.split('\n'):
- if len(line) == 0:
- continue
- else:
- line = line.strip()
- if 'Ethernet' in line:
- parsed.append(line)
- if 'mgmt' in line:
- parsed.append(line)
- if 'po' in line:
- parsed.append(line)
- if 'loopback' in line:
- parsed.append(line)
- return parsed
-
-
-FACT_SUBSETS = dict(
- default=Default,
- hardware=Hardware,
- interfaces=Interfaces,
- config=Config,
-)
-
-VALID_SUBSETS = frozenset(FACT_SUBSETS.keys())
-
-PERSISTENT_COMMAND_TIMEOUT = 60
-
-
-def main():
- """main entry point for module execution
- """
- argument_spec = dict(
- gather_subset=dict(default=['!config'], type='list')
- )
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- gather_subset = module.params['gather_subset']
-
- runable_subsets = set()
- exclude_subsets = set()
-
- for subset in gather_subset:
- if subset == 'all':
- runable_subsets.update(VALID_SUBSETS)
- continue
-
- if subset.startswith('!'):
- subset = subset[1:]
- if subset == 'all':
- exclude_subsets.update(VALID_SUBSETS)
- continue
- exclude = True
- else:
- exclude = False
-
- if subset not in VALID_SUBSETS:
- module.fail_json(msg='Bad subset')
-
- if exclude:
- exclude_subsets.add(subset)
- else:
- runable_subsets.add(subset)
-
- if not runable_subsets:
- runable_subsets.update(VALID_SUBSETS)
-
- runable_subsets.difference_update(exclude_subsets)
- runable_subsets.add('default')
-
- facts = dict()
- facts['gather_subset'] = list(runable_subsets)
-
- instances = list()
- for key in runable_subsets:
- instances.append(FACT_SUBSETS[key](module))
-
- for inst in instances:
- inst.populate()
- facts.update(inst.facts)
-
- ansible_facts = dict()
- for key, value in iteritems(facts):
- key = 'ansible_net_%s' % key
- ansible_facts[key] = value
-
- warnings = list()
- check_args(module, warnings)
-
- module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_image.py b/plugins/modules/network/cnos/cnos_image.py
deleted file mode 100644
index 0ab3d809a5..0000000000
--- a/plugins/modules/network/cnos/cnos_image.py
+++ /dev/null
@@ -1,241 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2017 Lenovo, Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to download new image to Lenovo Switches
-# Lenovo Networking
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_image
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Perform firmware upgrade/download from a remote server on
- devices running Lenovo CNOS
-description:
- - This module allows you to work with switch firmware images. It provides a
- way to download a firmware image to a network device from a remote server
- using FTP, SFTP, TFTP, or SCP. The first step is to create a directory
- from where the remote server can be reached. The next step is to provide
- the full file path of the image's location. Authentication details
- required by the remote server must be provided as well. By default, this
- method makes the newly downloaded firmware image the active image, which
- will be used by the switch during the next restart.
- This module uses SSH to manage network device configuration.
- The results of the operation will be placed in a directory named 'results'
- that must be created by the user in their local directory to where the
- playbook is run.
-extends_documentation_fragment:
-- community.general.cnos
-
-options:
- protocol:
- description:
- - This refers to the protocol used by the network device to
- interact with the remote server from where to download the
- firmware image. The choices are FTP, SFTP, TFTP, or SCP. Any other
- protocols will result in error. If this parameter is not specified
- there is no default value to be used.
- required: true
- choices: [SFTP, SCP, FTP, TFTP]
- serverip:
- description:
- - This specifies the IP Address of the remote server from where the
- software image will be downloaded.
- required: true
- imgpath:
- description:
- - This specifies the full file path of the image located on the
- remote server. In case the relative path is used as the variable
- value, the root folder for the user of the server needs to be
- specified.
- required: true
- imgtype:
- description:
- - This specifies the firmware image type to be downloaded
- required: true
- choices: [all, boot, os, onie]
- serverusername:
- description:
- - Specify the username for the server relating to the protocol used
- required: true
- serverpassword:
- description:
- - Specify the password for the server relating to the protocol used
-'''
-EXAMPLES = '''
-Tasks : The following are examples of using the module cnos_image. These are
- written in the main.yml file of the tasks directory.
----
-- name: Test Image transfer
- cnos_image:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_image_{{ inventory_hostname }}_output.txt"
- protocol: "sftp"
- serverip: "10.241.106.118"
- imgpath: "/root/cnos_images/G8272-10.1.0.112.img"
- imgtype: "os"
- serverusername: "root"
- serverpassword: "root123"
-
-- name: Test Image tftp
- cnos_image:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_image_{{ inventory_hostname }}_output.txt"
- protocol: "tftp"
- serverip: "10.241.106.118"
- imgpath: "/anil/G8272-10.2.0.34.img"
- imgtype: "os"
- serverusername: "root"
- serverpassword: "root123"
-'''
-RETURN = '''
-msg:
- description: Success or failure message
- returned: always
- type: str
- sample: "Image file transferred to device"
-'''
-
-import sys
-import time
-import socket
-import array
-import json
-import time
-import re
-import os
-try:
- from ansible_collections.community.general.plugins.module_utils.network.cnos import cnos
- HAS_LIB = True
-except Exception:
- HAS_LIB = False
-from ansible.module_utils.basic import AnsibleModule
-from collections import defaultdict
-
-
-def doImageDownload(module, prompt, answer):
- protocol = module.params['protocol'].lower()
- server = module.params['serverip']
- imgPath = module.params['imgpath']
- imgType = module.params['imgtype']
- username = module.params['serverusername']
- password = module.params['serverpassword']
- retVal = ''
- command = "copy " + protocol + " " + protocol + "://" + username + "@"
- command = command + server + "/" + imgPath + " system-image "
- command = command + imgType + " vrf management"
- cmd = []
- if(protocol == "scp"):
- prompt = ['timeout', 'Confirm download operation', 'Password',
- 'Do you want to change that to the standby image']
- answer = ['240', 'y', password, 'y']
- scp_cmd = [{'command': command, 'prompt': prompt, 'answer': answer,
- 'check_all': True}]
- cmd.extend(scp_cmd)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- elif(protocol == "sftp"):
- prompt = ['Confirm download operation', 'Password',
- 'Do you want to change that to the standby image']
- answer = ['y', password, 'y']
- sftp_cmd = [{'command': command, 'prompt': prompt, 'answer': answer,
- 'check_all': True}]
- cmd.extend(sftp_cmd)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- elif(protocol == "ftp"):
- prompt = ['Confirm download operation', 'Password',
- 'Do you want to change that to the standby image']
- answer = ['y', password, 'y']
- ftp_cmd = [{'command': command, 'prompt': prompt, 'answer': answer,
- 'check_all': True}]
- cmd.extend(ftp_cmd)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- elif(protocol == "tftp"):
- command = "copy " + protocol + " " + protocol + "://" + server
- command = command + "/" + imgPath + " system-image " + imgType
- command = command + " vrf management"
- prompt = ['Confirm download operation',
- 'Do you want to change that to the standby image']
- answer = ['y', 'y']
- tftp_cmd = [{'command': command, 'prompt': prompt, 'answer': answer,
- 'check_all': True}]
- cmd.extend(tftp_cmd)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- else:
- return "Error-110"
-
- return retVal
-# EOM
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- outputfile=dict(required=True),
- host=dict(required=False),
- username=dict(required=False),
- password=dict(required=False, no_log=True),
- enablePassword=dict(required=False, no_log=True),
- deviceType=dict(required=True),
- protocol=dict(required=True),
- serverip=dict(required=True),
- imgpath=dict(required=True),
- imgtype=dict(required=True),
- serverusername=dict(required=False),
- serverpassword=dict(required=False, no_log=True),),
- supports_check_mode=False)
-
- outputfile = module.params['outputfile']
- protocol = module.params['protocol'].lower()
- output = ''
-
- # Invoke method for image transfer from server
- if(protocol == "tftp" or protocol == "ftp" or protocol == "sftp" or
- protocol == "scp"):
- transfer_status = doImageDownload(module, None, None)
- else:
- transfer_status = "Invalid Protocol option"
-
- output = output + "\n Image Transfer status \n" + transfer_status
-
- # Save it into the file
- path = outputfile.rsplit('/', 1)
- if not os.path.exists(path[0]):
- os.makedirs(path[0])
- file = open(outputfile, "a")
- file.write(output)
- file.close()
-
- # Logic to check when changes occur or not
- errorMsg = cnos.checkOutputForError(output)
- if(errorMsg is None):
- module.exit_json(changed=True, msg="Image file transferred to device")
- else:
- module.fail_json(msg=errorMsg)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_interface.py b/plugins/modules/network/cnos/cnos_interface.py
deleted file mode 100644
index 7d32044cb6..0000000000
--- a/plugins/modules/network/cnos/cnos_interface.py
+++ /dev/null
@@ -1,555 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2017 Lenovo, Inc.
-# (c) 2017, Ansible by Red Hat, inc
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to work on Interfaces with Lenovo Switches
-# Lenovo Networking
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_interface
-author: "Anil Kumar Muraleedharan(@amuraleedhar)"
-short_description: Manage Interface on Lenovo CNOS network devices
-description:
- - This module provides declarative management of Interfaces
- on Lenovo CNOS network devices.
-notes:
- - Tested against CNOS 10.8.1
-options:
- name:
- description:
- - Name of the Interface.
- required: true
- description:
- description:
- - Description of Interface.
- enabled:
- description:
- - Interface link status.
- type: bool
- default: True
- speed:
- description:
- - Interface link speed.
- mtu:
- description:
- - Maximum size of transmit packet.
- duplex:
- description:
- - Interface link status
- default: auto
- choices: ['full', 'half', 'auto']
- tx_rate:
- description:
- - Transmit rate in bits per second (bps).
- - This is state check parameter only.
- - Supports conditionals, see L(Conditionals in Networking Modules,
- ../network/user_guide/network_working_with_command_output.html)
- rx_rate:
- description:
- - Receiver rate in bits per second (bps).
- - This is state check parameter only.
- - Supports conditionals, see L(Conditionals in Networking Modules,
- ../network/user_guide/network_working_with_command_output.html)
- neighbors:
- description:
- - Check operational state of given interface C(name) for LLDP neighbor.
- - The following suboptions are available.
- suboptions:
- host:
- description:
- - "LLDP neighbor host for given interface C(name)."
- port:
- description:
- - "LLDP neighbor port to which interface C(name) is connected."
- aggregate:
- description: List of Interfaces definitions.
- delay:
- description:
- - Time in seconds to wait before checking for the operational state on
- remote device. This wait is applicable for operational state argument
- which are I(state) with values C(up)/C(down), I(tx_rate) and I(rx_rate)
- default: 20
- state:
- description:
- - State of the Interface configuration, C(up) means present and
- operationally up and C(down) means present and operationally C(down)
- default: present
- choices: ['present', 'absent', 'up', 'down']
- provider:
- description:
- - B(Deprecated)
- - "Starting with Ansible 2.5 we recommend using C(connection: network_cli)."
- - For more information please see the L(CNOS Platform Options guide, ../network/user_guide/platform_cnos.html).
- - HORIZONTALLINE
- - A dict object containing connection details.
- suboptions:
- host:
- description:
- - Specifies the DNS host name or address for connecting to the remote
- device over the specified transport. The value of host is used as
- the destination address for the transport.
- required: true
- port:
- description:
- - Specifies the port to use when building the connection to the remote device.
- default: 22
- username:
- description:
- - Configures the username to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_USERNAME) will be used instead.
- password:
- description:
- - Specifies the password to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_PASSWORD) will be used instead.
- timeout:
- description:
- - Specifies the timeout in seconds for communicating with the network device
- for either connecting or sending commands. If the timeout is
- exceeded before the operation is completed, the module will error.
- default: 10
- ssh_keyfile:
- description:
- - Specifies the SSH key to use to authenticate the connection to
- the remote device. This value is the path to the
- key used to authenticate the SSH session. If the value is not specified
- in the task, the value of environment variable C(ANSIBLE_NET_SSH_KEYFILE)
- will be used instead.
- authorize:
- description:
- - Instructs the module to enter privileged mode on the remote device
- before sending any commands. If not specified, the device will
- attempt to execute all commands in non-privileged mode. If the value
- is not specified in the task, the value of environment variable
- C(ANSIBLE_NET_AUTHORIZE) will be used instead.
- type: bool
- default: 'no'
- auth_pass:
- description:
- - Specifies the password to use if required to enter privileged mode
- on the remote device. If I(authorize) is false, then this argument
- does nothing. If the value is not specified in the task, the value of
- environment variable C(ANSIBLE_NET_AUTH_PASS) will be used instead.
-'''
-
-EXAMPLES = """
-- name: configure interface
- cnos_interface:
- name: Ethernet1/33
- description: test-interface
- speed: 100
- duplex: half
- mtu: 999
-
-- name: remove interface
- cnos_interface:
- name: loopback3
- state: absent
-
-- name: make interface up
- cnos_interface:
- name: Ethernet1/33
- enabled: True
-
-- name: make interface down
- cnos_interface:
- name: Ethernet1/33
- enabled: False
-
-- name: Check intent arguments
- cnos_interface:
- name: Ethernet1/33
- state: up
- tx_rate: ge(0)
- rx_rate: le(0)
-
-- name: Check neighbors intent arguments
- cnos_interface:
- name: Ethernet1/33
- neighbors:
- - port: eth0
- host: netdev
-
-- name: Config + intent
- cnos_interface:
- name: Ethernet1/33
- enabled: False
- state: down
-
-- name: Add interface using aggregate
- cnos_interface:
- aggregate:
- - { name: Ethernet1/33, mtu: 256, description: test-interface-1 }
- - { name: Ethernet1/44, mtu: 516, description: test-interface-2 }
- duplex: full
- speed: 100
- state: present
-
-- name: Delete interface using aggregate
- cnos_interface:
- aggregate:
- - name: loopback3
- - name: loopback6
- state: absent
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device.
- returned: always, except for the platforms that use Netconf transport to
- manage the device.
- type: list
- sample:
- - interface Ethernet1/33
- - description test-interface
- - duplex half
- - mtu 512
-"""
-import re
-
-from copy import deepcopy
-from time import sleep
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import exec_command
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import get_config, load_config
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import cnos_argument_spec
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import debugOutput, check_args
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import conditional
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec
-
-
-def validate_mtu(value, module):
- if value and not 64 <= int(value) <= 9216:
- module.fail_json(msg='mtu must be between 64 and 9216')
-
-
-def validate_param_values(module, obj, param=None):
- if param is None:
- param = module.params
- for key in obj:
- # validate the param value (if validator func exists)
- validator = globals().get('validate_%s' % key)
- if callable(validator):
- validator(param.get(key), module)
-
-
-def parse_shutdown(configobj, name):
- cfg = configobj['interface %s' % name]
- cfg = '\n'.join(cfg.children)
- match = re.search(r'^shutdown', cfg, re.M)
- if match:
- return True
- else:
- return False
-
-
-def parse_config_argument(configobj, name, arg=None):
- cfg = configobj['interface %s' % name]
- cfg = '\n'.join(cfg.children)
- match = re.search(r'%s (.+)$' % arg, cfg, re.M)
- if match:
- return match.group(1)
-
-
-def search_obj_in_list(name, lst):
- for o in lst:
- if o['name'] == name:
- return o
-
- return None
-
-
-def add_command_to_interface(interface, cmd, commands):
- if interface not in commands:
- commands.append(interface)
- commands.append(cmd)
-
-
-def map_config_to_obj(module):
- config = get_config(module)
- configobj = NetworkConfig(indent=1, contents=config)
-
- match = re.findall(r'^interface (\S+)', config, re.M)
- if not match:
- return list()
-
- instances = list()
-
- for item in set(match):
- obj = {
- 'name': item,
- 'description': parse_config_argument(configobj, item, 'description'),
- 'speed': parse_config_argument(configobj, item, 'speed'),
- 'duplex': parse_config_argument(configobj, item, 'duplex'),
- 'mtu': parse_config_argument(configobj, item, 'mtu'),
- 'disable': True if parse_shutdown(configobj, item) else False,
- 'state': 'present'
- }
- instances.append(obj)
- return instances
-
-
-def map_params_to_obj(module):
- obj = []
- aggregate = module.params.get('aggregate')
- if aggregate:
- for item in aggregate:
- for key in item:
- if item.get(key) is None:
- item[key] = module.params[key]
-
- validate_param_values(module, item, item)
- d = item.copy()
-
- if d['enabled']:
- d['disable'] = False
- else:
- d['disable'] = True
-
- obj.append(d)
-
- else:
- params = {
- 'name': module.params['name'],
- 'description': module.params['description'],
- 'speed': module.params['speed'],
- 'mtu': module.params['mtu'],
- 'duplex': module.params['duplex'],
- 'state': module.params['state'],
- 'delay': module.params['delay'],
- 'tx_rate': module.params['tx_rate'],
- 'rx_rate': module.params['rx_rate'],
- 'neighbors': module.params['neighbors']
- }
-
- validate_param_values(module, params)
- if module.params['enabled']:
- params.update({'disable': False})
- else:
- params.update({'disable': True})
-
- obj.append(params)
- return obj
-
-
-def map_obj_to_commands(updates):
- commands = list()
- want, have = updates
-
- args = ('speed', 'description', 'duplex', 'mtu')
- for w in want:
- name = w['name']
- disable = w['disable']
- state = w['state']
-
- obj_in_have = search_obj_in_list(name, have)
- interface = 'interface ' + name
- if state == 'absent' and obj_in_have:
- commands.append('no ' + interface)
- elif state in ('present', 'up', 'down'):
- if obj_in_have:
- for item in args:
- candidate = w.get(item)
- running = obj_in_have.get(item)
- if candidate != running:
- if candidate:
- cmd = item + ' ' + str(candidate)
- add_command_to_interface(interface, cmd, commands)
-
- if disable and not obj_in_have.get('disable', False):
- add_command_to_interface(interface, 'shutdown', commands)
- elif not disable and obj_in_have.get('disable', False):
- add_command_to_interface(interface, 'no shutdown', commands)
- else:
- commands.append(interface)
- for item in args:
- value = w.get(item)
- if value:
- commands.append(item + ' ' + str(value))
-
- if disable:
- commands.append('no shutdown')
- return commands
-
-
-def check_declarative_intent_params(module, want, result):
- failed_conditions = []
- have_neighbors_lldp = None
- for w in want:
- want_state = w.get('state')
- want_tx_rate = w.get('tx_rate')
- want_rx_rate = w.get('rx_rate')
- want_neighbors = w.get('neighbors')
-
- if want_state not in ('up', 'down') and not want_tx_rate and not want_rx_rate and not want_neighbors:
- continue
-
- if result['changed']:
- sleep(w['delay'])
-
- command = 'show interface %s brief' % w['name']
- rc, out, err = exec_command(module, command)
- if rc != 0:
- module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc)
- if want_state in ('up', 'down'):
- state_data = out.strip().lower().split(w['name'])
- have_state = None
- have_state = state_data[1].split()[3]
- if have_state is None or not conditional(want_state, have_state.strip()):
- failed_conditions.append('state ' + 'eq(%s)' % want_state)
-
- command = 'show interface %s' % w['name']
- rc, out, err = exec_command(module, command)
- have_tx_rate = None
- have_rx_rate = None
- rates = out.splitlines()
- for s in rates:
- s = s.strip()
- if 'output rate' in s and 'input rate' in s:
- sub = s.split()
- if want_tx_rate:
- have_tx_rate = sub[8]
- if have_tx_rate is None or not conditional(want_tx_rate, have_tx_rate.strip(), cast=int):
- failed_conditions.append('tx_rate ' + want_tx_rate)
- if want_rx_rate:
- have_rx_rate = sub[2]
- if have_rx_rate is None or not conditional(want_rx_rate, have_rx_rate.strip(), cast=int):
- failed_conditions.append('rx_rate ' + want_rx_rate)
- if want_neighbors:
- have_host = []
- have_port = []
-
- # Process LLDP neighbors
- if have_neighbors_lldp is None:
- rc, have_neighbors_lldp, err = exec_command(module, 'show lldp neighbors detail')
- if rc != 0:
- module.fail_json(msg=to_text(err,
- errors='surrogate_then_replace'),
- command=command, rc=rc)
-
- if have_neighbors_lldp:
- lines = have_neighbors_lldp.strip().split('Local Port ID: ')
- for line in lines:
- field = line.split('\n')
- if field[0].strip() == w['name']:
- for item in field:
- if item.startswith('System Name:'):
- have_host.append(item.split(':')[1].strip())
- if item.startswith('Port Description:'):
- have_port.append(item.split(':')[1].strip())
-
- for item in want_neighbors:
- host = item.get('host')
- port = item.get('port')
- if host and host not in have_host:
- failed_conditions.append('host ' + host)
- if port and port not in have_port:
- failed_conditions.append('port ' + port)
- return failed_conditions
-
-
-def main():
- """ main entry point for module execution
- """
- neighbors_spec = dict(
- host=dict(),
- port=dict()
- )
-
- element_spec = dict(
- name=dict(),
- description=dict(),
- speed=dict(),
- mtu=dict(),
- duplex=dict(default='auto', choices=['full', 'half', 'auto']),
- enabled=dict(default=True, type='bool'),
- tx_rate=dict(),
- rx_rate=dict(),
- neighbors=dict(type='list', elements='dict', options=neighbors_spec),
- delay=dict(default=20, type='int'),
- state=dict(default='present',
- choices=['present', 'absent', 'up', 'down'])
- )
-
- aggregate_spec = deepcopy(element_spec)
- aggregate_spec['name'] = dict(required=True)
-
- # remove default in aggregate spec, to handle common arguments
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec),
- )
-
- argument_spec.update(element_spec)
- argument_spec.update(cnos_argument_spec)
-
- required_one_of = [['name', 'aggregate']]
- mutually_exclusive = [['name', 'aggregate']]
-
- module = AnsibleModule(argument_spec=argument_spec,
- required_one_of=required_one_of,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
- warnings = list()
- check_args(module, warnings)
-
- result = {'changed': False}
- if warnings:
- result['warnings'] = warnings
-
- want = map_params_to_obj(module)
- have = map_config_to_obj(module)
-
- commands = map_obj_to_commands((want, have))
- result['commands'] = commands
-
- if commands:
- if not module.check_mode:
- load_config(module, commands)
- result['changed'] = True
-
- failed_conditions = check_declarative_intent_params(module, want, result)
-
- if failed_conditions:
- msg = 'One or more conditional statements have not been satisfied'
- module.fail_json(msg=msg, failed_conditions=failed_conditions)
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_l2_interface.py b/plugins/modules/network/cnos/cnos_l2_interface.py
deleted file mode 100644
index a6decc39b9..0000000000
--- a/plugins/modules/network/cnos/cnos_l2_interface.py
+++ /dev/null
@@ -1,598 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2017 Lenovo, Inc.
-# (c) 2017, Ansible by Red Hat, inc
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to send banner commands to Lenovo Switches
-# Two types of banners are supported login and motd
-# Lenovo Networking
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_l2_interface
-short_description: Manage Layer-2 interface on Lenovo CNOS devices.
-description:
- - This module provides declarative management of Layer-2 interfaces on
- Lenovo CNOS devices.
-author:
- - Anil Kumar Muraleedharan (@amuraleedhar)
-options:
- name:
- description:
- - Full name of the interface excluding any logical
- unit number, i.e. Ethernet1/3.
- required: true
- aliases: ['interface']
- mode:
- description:
- - Mode in which interface needs to be configured.
- default: access
- choices: ['access', 'trunk']
- access_vlan:
- description:
- - Configure given VLAN in access port.
- If C(mode=access), used as the access VLAN ID.
- trunk_vlans:
- description:
- - List of VLANs to be configured in trunk port.
- If C(mode=trunk), used as the VLAN range to ADD or REMOVE
- from the trunk.
- native_vlan:
- description:
- - Native VLAN to be configured in trunk port.
- If C(mode=trunk), used as the trunk native VLAN ID.
- trunk_allowed_vlans:
- description:
- - List of allowed VLANs in a given trunk port.
- If C(mode=trunk), these are the only VLANs that will be
- configured on the trunk, i.e. "2-10,15".
- aggregate:
- description:
- - List of Layer-2 interface definitions.
- state:
- description:
- - Manage the state of the Layer-2 Interface configuration.
- default: present
- choices: ['present','absent', 'unconfigured']
- provider:
- description:
- - B(Deprecated)
- - "Starting with Ansible 2.5 we recommend using
- C(connection: network_cli)."
- - For more information please see the
- L(CNOS Platform Options guide, ../network/user_guide/platform_cnos.html).
- - HORIZONTALLINE
- - A dict object containing connection details.
- suboptions:
- host:
- description:
- - Specifies the DNS host name or address for connecting to the remote
- device over the specified transport. The value of host is used as
- the destination address for the transport.
- required: true
- port:
- description:
- - Specifies the port to use when building the connection to the
- remote device.
- default: 22
- username:
- description:
- - Configures the username to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_USERNAME) will be used
- instead.
- password:
- description:
- - Specifies the password to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_PASSWORD) will be used
- instead.
- timeout:
- description:
- - Specifies the timeout in seconds for communicating with the network
- device for either connecting or sending commands. If the timeout
- is exceeded before the operation is completed, the module will
- error.
- default: 10
- ssh_keyfile:
- description:
- - Specifies the SSH key to use to authenticate the connection to
- the remote device. This value is the path to the
- key used to authenticate the SSH session. If the value is not
- specified in the task, the value of environment variable
- C(ANSIBLE_NET_SSH_KEYFILE)will be used instead.
- authorize:
- description:
- - Instructs the module to enter privileged mode on the remote device
- before sending any commands. If not specified, the device will
- attempt to execute all commands in non-privileged mode. If the
- value is not specified in the task, the value of environment
- variable C(ANSIBLE_NET_AUTHORIZE) will be used instead.
- type: bool
- default: 'no'
- auth_pass:
- description:
- - Specifies the password to use if required to enter privileged mode
- on the remote device. If I(authorize) is false, then this argument
- does nothing. If the value is not specified in the task, the value
- of environment variable C(ANSIBLE_NET_AUTH_PASS) will be used
- instead.
-'''
-
-EXAMPLES = """
-- name: Ensure Ethernet1/5 is in its default l2 interface state
- cnos_l2_interface:
- name: Ethernet1/5
- state: unconfigured
-
-- name: Ensure Ethernet1/5 is configured for access vlan 20
- cnos_l2_interface:
- name: Ethernet1/5
- mode: access
- access_vlan: 20
-
-- name: Ensure Ethernet1/5 only has vlans 5-10 as trunk vlans
- cnos_l2_interface:
- name: Ethernet1/5
- mode: trunk
- native_vlan: 10
- trunk_vlans: 5-10
-
-- name: Ensure Ethernet1/5 is a trunk port and ensure 2-50 are being tagged
- (doesn't mean others aren't also being tagged)
- cnos_l2_interface:
- name: Ethernet1/5
- mode: trunk
- native_vlan: 10
- trunk_vlans: 2-50
-
-- name: Ensure these VLANs are not being tagged on the trunk
- cnos_l2_interface:
- name: Ethernet1/5
- mode: trunk
- trunk_vlans: 51-4094
- state: absent
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always, except for the platforms that use Netconf transport to
- manage the device.
- type: list
- sample:
- - interface Ethernet1/5
- - switchport access vlan 20
-"""
-
-import re
-from copy import deepcopy
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import get_config, load_config
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import cnos_argument_spec
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import run_commands
-
-
-def get_interface_type(interface):
- intf_type = 'unknown'
- if interface.upper()[:2] in ('ET', 'GI', 'FA', 'TE', 'FO', 'HU', 'TWE'):
- intf_type = 'ethernet'
- elif interface.upper().startswith('VL'):
- intf_type = 'svi'
- elif interface.upper().startswith('LO'):
- intf_type = 'loopback'
- elif interface.upper()[:2] in ('MG', 'MA'):
- intf_type = 'management'
- elif interface.upper().startswith('PO'):
- intf_type = 'portchannel'
- elif interface.upper().startswith('NV'):
- intf_type = 'nve'
-
- return intf_type
-
-
-def is_switchport(name, module):
- intf_type = get_interface_type(name)
-
- if intf_type in ('ethernet', 'portchannel'):
- config = run_commands(module,
- ['show interface {0} switchport'.format(name)])[0]
- match = re.search(r'Switchport : enabled', config)
- return bool(match)
- return False
-
-
-def interface_is_portchannel(name, module):
- if get_interface_type(name) == 'ethernet':
- config = run_commands(module, ['show run interface {0}'.format(name)])[0]
- if any(c in config for c in ['channel group', 'channel-group']):
- return True
- return False
-
-
-def get_switchport(name, module):
- config = run_commands(module,
- ['show interface {0} switchport'.format(name)])[0]
- mode = re.search(r'Switchport mode : (?:.* )?(\w+)$', config, re.M)
- access = re.search(r'Configured Vlans : (\d+)', config)
- native = re.search(r'Default/Native Vlan : (\d+)', config)
- trunk = re.search(r'Enabled Vlans : (.+)$', config, re.M)
- if mode:
- mode = mode.group(1)
- if access:
- access = access.group(1)
- if native:
- native = native.group(1)
- if trunk:
- trunk = trunk.group(1)
- if trunk == 'ALL':
- trunk = '1-4094'
-
- switchport_config = {
- "interface": name,
- "mode": mode,
- "access_vlan": access,
- "native_vlan": native,
- "trunk_vlans": trunk,
- }
-
- return switchport_config
-
-
-def remove_switchport_config_commands(name, existing, proposed, module):
- mode = proposed.get('mode')
- commands = []
- command = None
-
- if mode == 'access':
- av_check = existing.get('access_vlan') == proposed.get('access_vlan')
- if av_check:
- command = 'no switchport access vlan'
- commands.append(command)
-
- elif mode == 'trunk':
- # Supported Remove Scenarios for trunk_vlans_list
- # 1) Existing: 1,2,3 Proposed: 1,2,3 - Remove all
- # 2) Existing: 1,2,3 Proposed: 1,2 - Remove 1,2 Leave 3
- # 3) Existing: 1,2,3 Proposed: 2,3 - Remove 2,3 Leave 1
- # 4) Existing: 1,2,3 Proposed: 4,5,6 - None removed.
- # 5) Existing: None Proposed: 1,2,3 - None removed.
- existing_vlans = existing.get('trunk_vlans_list')
- proposed_vlans = proposed.get('trunk_vlans_list')
- vlans_to_remove = set(proposed_vlans).intersection(existing_vlans)
-
- if vlans_to_remove:
- proposed_allowed_vlans = proposed.get('trunk_allowed_vlans')
- remove_trunk_allowed_vlans = proposed.get('trunk_vlans',
- proposed_allowed_vlans)
- command = 'switchport trunk allowed vlan remove {0}'
- command = command.format(remove_trunk_allowed_vlans)
- commands.append(command)
-
- native_check = existing.get('native_vlan') == proposed.get('native_vlan')
- if native_check and proposed.get('native_vlan'):
- command = 'no switchport trunk native vlan'
- commands.append(command)
-
- if commands:
- commands.insert(0, 'interface ' + name)
- return commands
-
-
-def get_switchport_config_commands(name, existing, proposed, module):
- """Gets commands required to config a given switchport interface
- """
-
- proposed_mode = proposed.get('mode')
- existing_mode = existing.get('mode')
- commands = []
- command = None
-
- if proposed_mode != existing_mode:
- if proposed_mode == 'trunk':
- command = 'switchport mode trunk'
- elif proposed_mode == 'access':
- command = 'switchport mode access'
-
- if command:
- commands.append(command)
-
- if proposed_mode == 'access':
- av_check = str(existing.get('access_vlan')) == str(proposed.get('access_vlan'))
- if not av_check:
- command = 'switchport access vlan {0}'.format(proposed.get('access_vlan'))
- commands.append(command)
-
- elif proposed_mode == 'trunk':
- tv_check = existing.get('trunk_vlans_list') == proposed.get('trunk_vlans_list')
-
- if not tv_check:
- if proposed.get('allowed'):
- command = 'switchport trunk allowed vlan {0}'
- command = command.format(proposed.get('trunk_allowed_vlans'))
- commands.append(command)
-
- else:
- existing_vlans = existing.get('trunk_vlans_list')
- proposed_vlans = proposed.get('trunk_vlans_list')
- vlans_to_add = set(proposed_vlans).difference(existing_vlans)
- if vlans_to_add:
- command = 'switchport trunk allowed vlan add {0}'
- command = command.format(proposed.get('trunk_vlans'))
- commands.append(command)
-
- native_check = str(existing.get('native_vlan')) == str(proposed.get('native_vlan'))
- if not native_check and proposed.get('native_vlan'):
- command = 'switchport trunk native vlan {0}'
- command = command.format(proposed.get('native_vlan'))
- commands.append(command)
-
- if commands:
- commands.insert(0, 'interface ' + name)
- return commands
-
-
-def is_switchport_default(existing):
- """Determines if switchport has a default config based on mode
- Args:
- existing (dict): existing switchport configuration from Ansible mod
- Returns:
- boolean: True if switchport has OOB Layer 2 config, i.e.
- vlan 1 and trunk all and mode is access
- """
-
- c1 = str(existing['access_vlan']) == '1'
- c2 = str(existing['native_vlan']) == '1'
- c3 = existing['trunk_vlans'] == '1-4094'
- c4 = existing['mode'] == 'access'
-
- default = c1 and c2 and c3 and c4
-
- return default
-
-
-def default_switchport_config(name):
- commands = []
- commands.append('interface ' + name)
- commands.append('switchport mode access')
- commands.append('switch access vlan 1')
- commands.append('switchport trunk native vlan 1')
- commands.append('switchport trunk allowed vlan all')
- return commands
-
-
-def vlan_range_to_list(vlans):
- result = []
- if vlans:
- for part in vlans.split(','):
- if part.lower() == 'none':
- break
- if part:
- if '-' in part:
- start, stop = (int(i) for i in part.split('-'))
- result.extend(range(start, stop + 1))
- else:
- result.append(int(part))
- return sorted(result)
-
-
-def get_list_of_vlans(module):
- config = run_commands(module, ['show vlan'])[0]
- vlans = set()
-
- lines = config.strip().splitlines()
- for line in lines:
- line_parts = line.split()
- if line_parts:
- try:
- int(line_parts[0])
- except ValueError:
- continue
- vlans.add(line_parts[0])
-
- return list(vlans)
-
-
-def flatten_list(commands):
- flat_list = []
- for command in commands:
- if isinstance(command, list):
- flat_list.extend(command)
- else:
- flat_list.append(command)
- return flat_list
-
-
-def map_params_to_obj(module):
- obj = []
-
- aggregate = module.params.get('aggregate')
- if aggregate:
- for item in aggregate:
- for key in item:
- if item.get(key) is None:
- item[key] = module.params[key]
-
- obj.append(item.copy())
- else:
- obj.append({
- 'name': module.params['name'],
- 'mode': module.params['mode'],
- 'access_vlan': module.params['access_vlan'],
- 'native_vlan': module.params['native_vlan'],
- 'trunk_vlans': module.params['trunk_vlans'],
- 'trunk_allowed_vlans': module.params['trunk_allowed_vlans'],
- 'state': module.params['state']
- })
-
- return obj
-
-
-def main():
- """ main entry point for module execution
- """
- element_spec = dict(
- name=dict(type='str', aliases=['interface']),
- mode=dict(choices=['access', 'trunk'], default='access'),
- access_vlan=dict(type='str'),
- native_vlan=dict(type='str'),
- trunk_vlans=dict(type='str'),
- trunk_allowed_vlans=dict(type='str'),
- state=dict(choices=['absent', 'present', 'unconfigured'],
- default='present')
- )
-
- aggregate_spec = deepcopy(element_spec)
-
- # remove default in aggregate spec, to handle common arguments
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec),
- )
-
- argument_spec.update(element_spec)
- argument_spec.update(cnos_argument_spec)
-
- module = AnsibleModule(argument_spec=argument_spec,
- mutually_exclusive=[['access_vlan', 'trunk_vlans'],
- ['access_vlan', 'native_vlan'],
- ['access_vlan', 'trunk_allowed_vlans']],
- supports_check_mode=True)
-
- warnings = list()
- commands = []
- result = {'changed': False, 'warnings': warnings}
-
- want = map_params_to_obj(module)
- for w in want:
- name = w['name']
- mode = w['mode']
- access_vlan = w['access_vlan']
- state = w['state']
- trunk_vlans = w['trunk_vlans']
- native_vlan = w['native_vlan']
- trunk_allowed_vlans = w['trunk_allowed_vlans']
-
- args = dict(name=name, mode=mode, access_vlan=access_vlan,
- native_vlan=native_vlan, trunk_vlans=trunk_vlans,
- trunk_allowed_vlans=trunk_allowed_vlans)
-
- proposed = dict((k, v) for k, v in args.items() if v is not None)
-
- name = name.lower()
-
- if mode == 'access' and state == 'present' and not access_vlan:
- msg = 'access_vlan param required for mode=access && state=present'
- module.fail_json(msg=msg)
-
- if mode == 'trunk' and access_vlan:
- msg = 'access_vlan param not supported when using mode=trunk'
- module.fail_json(msg=msg)
-
- if not is_switchport(name, module):
- module.fail_json(msg='Ensure interface is configured to be a L2'
- '\nport first before using this module. You can use'
- '\nthe cnos_interface module for this.')
-
- if interface_is_portchannel(name, module):
- module.fail_json(msg='Cannot change L2 config on physical '
- '\nport because it is in a portchannel. '
- '\nYou should update the portchannel config.')
-
- # existing will never be null for Eth intfs as there is always a default
- existing = get_switchport(name, module)
-
- # Safeguard check
- # If there isn't an existing, something is wrong per previous comment
- if not existing:
- msg = 'Make sure you are using the FULL interface name'
- module.fail_json(msg=msg)
-
- if trunk_vlans or trunk_allowed_vlans:
- if trunk_vlans:
- trunk_vlans_list = vlan_range_to_list(trunk_vlans)
- elif trunk_allowed_vlans:
- trunk_vlans_list = vlan_range_to_list(trunk_allowed_vlans)
- proposed['allowed'] = True
-
- existing_trunks_list = vlan_range_to_list((existing['trunk_vlans']))
-
- existing['trunk_vlans_list'] = existing_trunks_list
- proposed['trunk_vlans_list'] = trunk_vlans_list
-
- current_vlans = get_list_of_vlans(module)
-
- if state == 'present':
- if access_vlan and access_vlan not in current_vlans:
- module.fail_json(msg='You are trying to configure a VLAN'
- ' on an interface that\ndoes not exist on the '
- ' switch yet!', vlan=access_vlan)
- elif native_vlan and native_vlan not in current_vlans:
- module.fail_json(msg='You are trying to configure a VLAN on'
- ' an interface that\ndoes not exist on the '
- ' switch yet!', vlan=native_vlan)
- else:
- command = get_switchport_config_commands(name, existing,
- proposed, module)
- commands.append(command)
- elif state == 'unconfigured':
- is_default = is_switchport_default(existing)
- if not is_default:
- command = default_switchport_config(name)
- commands.append(command)
- elif state == 'absent':
- command = remove_switchport_config_commands(name, existing,
- proposed, module)
- commands.append(command)
-
- if trunk_vlans or trunk_allowed_vlans:
- existing.pop('trunk_vlans_list')
- proposed.pop('trunk_vlans_list')
-
- cmds = flatten_list(commands)
- if cmds:
- if module.check_mode:
- module.exit_json(changed=True, commands=cmds)
- else:
- result['changed'] = True
- load_config(module, cmds)
- if 'configure' in cmds:
- cmds.pop(0)
-
- result['commands'] = cmds
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_l3_interface.py b/plugins/modules/network/cnos/cnos_l3_interface.py
deleted file mode 100644
index cf68a237f6..0000000000
--- a/plugins/modules/network/cnos/cnos_l3_interface.py
+++ /dev/null
@@ -1,461 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2019 Lenovo, Inc.
-# (c) 2019, Ansible by Red Hat, inc
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to work on Link Aggregation with Lenovo Switches
-# Lenovo Networking
-#
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: cnos_l3_interface
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Manage Layer-3 interfaces on Lenovo CNOS network devices.
-description:
- - This module provides declarative management of Layer-3 interfaces
- on CNOS network devices.
-notes:
- - Tested against CNOS 10.8.1
-options:
- name:
- description:
- - Name of the Layer-3 interface to be configured eg. Ethernet1/2
- ipv4:
- description:
- - IPv4 address to be set for the Layer-3 interface mentioned in I(name)
- option. The address format is /, the mask is number
- in range 0-32 eg. 10.241.107.1/24
- ipv6:
- description:
- - IPv6 address to be set for the Layer-3 interface mentioned in I(name)
- option. The address format is /, the mask is number
- in range 0-128 eg. fd5d:12c9:2201:1::1/64
- aggregate:
- description:
- - List of Layer-3 interfaces definitions. Each of the entry in aggregate
- list should define name of interface C(name) and a optional C(ipv4) or
- C(ipv6) address.
- state:
- description:
- - State of the Layer-3 interface configuration. It indicates if the
- configuration should be present or absent on remote device.
- default: present
- choices: ['present', 'absent']
- provider:
- description:
- - B(Deprecated)
- - "Starting with Ansible 2.5 we recommend using
- C(connection: network_cli)."
- - For more information please see the
- L(CNOS Platform Options guide, ../network/user_guide/platform_cnos.html).
- - HORIZONTALLINE
- - A dict object containing connection details.
- suboptions:
- host:
- description:
- - Specifies the DNS host name or address for connecting to the remote
- device over the specified transport. The value of host is used as
- the destination address for the transport.
- required: true
- port:
- description:
- - Specifies the port to use when building the connection to the
- remote device.
- default: 22
- username:
- description:
- - Configures the username to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_USERNAME) will be used
- instead.
- password:
- description:
- - Specifies the password to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_PASSWORD) will be used
- instead.
- timeout:
- description:
- - Specifies the timeout in seconds for communicating with the network
- device for either connecting or sending commands. If the timeout
- is exceeded before the operation is completed, the module will
- error.
- default: 10
- ssh_keyfile:
- description:
- - Specifies the SSH key to use to authenticate the connection to
- the remote device. This value is the path to the
- key used to authenticate the SSH session. If the value is not
- specified in the task, the value of environment variable
- C(ANSIBLE_NET_SSH_KEYFILE)will be used instead.
- authorize:
- description:
- - Instructs the module to enter privileged mode on the remote device
- before sending any commands. If not specified, the device will
- attempt to execute all commands in non-privileged mode. If the
- value is not specified in the task, the value of environment
- variable C(ANSIBLE_NET_AUTHORIZE) will be used instead.
- type: bool
- default: 'no'
- auth_pass:
- description:
- - Specifies the password to use if required to enter privileged mode
- on the remote device. If I(authorize) is false, then this argument
- does nothing. If the value is not specified in the task, the value
- of environment variable C(ANSIBLE_NET_AUTH_PASS) will be used
- instead.
-'''
-
-EXAMPLES = """
-- name: Remove Ethernet1/33 IPv4 and IPv6 address
- cnos_l3_interface:
- name: Ethernet1/33
- state: absent
-
-- name: Set Ethernet1/33 IPv4 address
- cnos_l3_interface:
- name: Ethernet1/33
- ipv4: 10.241.107.1/24
-
-- name: Set Ethernet1/33 IPv6 address
- cnos_l3_interface:
- name: Ethernet1/33
- ipv6: "fd5d:12c9:2201:1::1/64"
-
-- name: Set Ethernet1/33 in dhcp
- cnos_l3_interface:
- name: Ethernet1/33
- ipv4: dhcp
- ipv6: dhcp
-
-- name: Set interface Vlan1 (SVI) IPv4 address
- cnos_l3_interface:
- name: Vlan1
- ipv4: 192.168.0.5/24
-
-- name: Set IP addresses on aggregate
- cnos_l3_interface:
- aggregate:
- - { name: Ethernet1/33, ipv4: 10.241.107.1/24 }
- - { name: Ethernet1/44, ipv4: 10.240.106.1/24,
- ipv6: "fd5d:12c9:2201:1::1/64" }
-
-- name: Remove IP addresses on aggregate
- cnos_l3_interface:
- aggregate:
- - { name: Ethernet1/33, ipv4: 10.241.107.1/24 }
- - { name: Ethernet1/44, ipv4: 10.240.106.1/24,
- ipv6: "fd5d:12c9:2201:1::1/64" }
- state: absent
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always, except for the platforms that use Netconf transport to
- manage the device.
- type: list
- sample:
- - interface Ethernet1/33
- - ip address 10.241.107.1 255.255.255.0
- - ipv6 address fd5d:12c9:2201:1::1/64
-"""
-import re
-
-from copy import deepcopy
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import get_config, load_config
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import cnos_argument_spec
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import run_commands
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import is_netmask, is_masklen
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_netmask, to_masklen
-
-
-def validate_ipv4(value, module):
- if value:
- address = value.split('/')
- if len(address) != 2:
- module.fail_json(
- msg='address format is /,got invalid format %s' % value)
- if not is_masklen(address[1]):
- module.fail_json(
- msg='invalid value for mask: %s, mask should be in range 0-32' % address[1])
-
-
-def validate_ipv6(value, module):
- if value:
- address = value.split('/')
- if len(address) != 2:
- module.fail_json(
- msg='address format is /, got invalid format %s' % value)
- else:
- if not 0 <= int(address[1]) <= 128:
- module.fail_json(
- msg='invalid value for mask: %s, mask should be in range 0-128' % address[1])
-
-
-def validate_param_values(module, obj, param=None):
- if param is None:
- param = module.params
- for key in obj:
- # validate the param value (if validator func exists)
- validator = globals().get('validate_%s' % key)
- if callable(validator):
- validator(param.get(key), module)
-
-
-def parse_config_argument(configobj, name, arg=None):
- cfg = configobj['interface %s' % name]
- cfg = '\n'.join(cfg.children)
-
- values = []
- matches = re.finditer(r'%s (.+)$' % arg, cfg, re.M)
- for match in matches:
- match_str = match.group(1).strip()
- if arg == 'ipv6 address':
- values.append(match_str)
- else:
- values = match_str
- break
-
- return values or None
-
-
-def search_obj_in_list(name, lst):
- for o in lst:
- if o['name'].lower() == name.lower():
- return o
-
- return None
-
-
-def get_interface_type(interface):
- intf_type = 'unknown'
- if interface.upper()[:2] in ('ET', 'GI', 'FA', 'TE', 'FO', 'HU', 'TWE'):
- intf_type = 'ethernet'
- elif interface.upper().startswith('VL'):
- intf_type = 'svi'
- elif interface.upper().startswith('LO'):
- intf_type = 'loopback'
- elif interface.upper()[:2] in ('MG', 'MA'):
- intf_type = 'management'
- elif interface.upper().startswith('PO'):
- intf_type = 'portchannel'
- elif interface.upper().startswith('NV'):
- intf_type = 'nve'
-
- return intf_type
-
-
-def is_switchport(name, module):
- intf_type = get_interface_type(name)
-
- if intf_type in ('ethernet', 'portchannel'):
- config = run_commands(module,
- ['show interface {0} switchport'.format(name)])[0]
- match = re.search(r'Switchport : enabled', config)
- return bool(match)
- return False
-
-
-def map_obj_to_commands(updates, module):
- commands = list()
- want, have = updates
- for w in want:
- name = w['name']
- ipv4 = w['ipv4']
- ipv6 = w['ipv6']
- state = w['state']
-
- interface = 'interface ' + name
- commands.append(interface)
-
- obj_in_have = search_obj_in_list(name, have)
- if state == 'absent' and obj_in_have:
- if obj_in_have['ipv4']:
- if ipv4:
- address = ipv4.split('/')
- if len(address) == 2:
- ipv4 = '{0} {1}'.format(
- address[0], to_netmask(address[1]))
- commands.append('no ip address %s' % ipv4)
- else:
- commands.append('no ip address')
- if obj_in_have['ipv6']:
- if ipv6:
- commands.append('no ipv6 address %s' % ipv6)
- else:
- commands.append('no ipv6 address')
- if 'dhcp' in obj_in_have['ipv6']:
- commands.append('no ipv6 address dhcp')
-
- elif state == 'present':
- if ipv4:
- if obj_in_have is None or obj_in_have.get('ipv4') is None or ipv4 != obj_in_have['ipv4']:
- address = ipv4.split('/')
- if len(address) == 2:
- ipv4 = '{0} {1}'.format(
- address[0], to_netmask(address[1]))
- commands.append('ip address %s' % ipv4)
-
- if ipv6:
- if obj_in_have is None or obj_in_have.get('ipv6') is None or ipv6.lower() not in [addr.lower() for addr in obj_in_have['ipv6']]:
- commands.append('ipv6 address %s' % ipv6)
- if commands[-1] == interface:
- commands.pop(-1)
-
- return commands
-
-
-def map_config_to_obj(module):
- config = get_config(module)
- configobj = NetworkConfig(indent=1, contents=config)
-
- match = re.findall(r'^interface (\S+)', config, re.M)
- if not match:
- return list()
-
- instances = list()
-
- for item in set(match):
- ipv4 = parse_config_argument(configobj, item, 'ip address')
- if ipv4:
- # eg. 192.168.2.10 255.255.255.0 -> 192.168.2.10/24
- address = ipv4.strip().split(' ')
- if len(address) == 2 and is_netmask(address[1]):
- ipv4 = '{0}/{1}'.format(address[0], to_text(to_masklen(address[1])))
-
- obj = {
- 'name': item,
- 'ipv4': ipv4,
- 'ipv6': parse_config_argument(configobj, item, 'ipv6 address'),
- 'state': 'present'
- }
- instances.append(obj)
-
- return instances
-
-
-def map_params_to_obj(module):
- obj = []
-
- aggregate = module.params.get('aggregate')
- if aggregate:
- for item in aggregate:
- for key in item:
- if item.get(key) is None:
- item[key] = module.params[key]
-
- validate_param_values(module, item, item)
- obj.append(item.copy())
- else:
- obj.append({
- 'name': module.params['name'],
- 'ipv4': module.params['ipv4'],
- 'ipv6': module.params['ipv6'],
- 'state': module.params['state']
- })
-
- validate_param_values(module, obj)
-
- return obj
-
-
-def main():
- """ main entry point for module execution
- """
- element_spec = dict(
- name=dict(),
- ipv4=dict(),
- ipv6=dict(),
- state=dict(default='present',
- choices=['present', 'absent'])
- )
-
- aggregate_spec = deepcopy(element_spec)
- aggregate_spec['name'] = dict(required=True)
-
- # remove default in aggregate spec, to handle common arguments
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec),
- )
-
- argument_spec.update(element_spec)
- argument_spec.update(cnos_argument_spec)
-
- required_one_of = [['name', 'aggregate']]
- mutually_exclusive = [['name', 'aggregate']]
- module = AnsibleModule(argument_spec=argument_spec,
- required_one_of=required_one_of,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
-
- warnings = list()
-
- result = {'changed': False}
-
- want = map_params_to_obj(module)
- for w in want:
- name = w['name']
- name = name.lower()
- if is_switchport(name, module):
- module.fail_json(msg='Ensure interface is configured to be a L3'
- '\nport first before using this module. You can use'
- '\nthe cnos_interface module for this.')
-
- have = map_config_to_obj(module)
-
- commands = map_obj_to_commands((want, have), module)
- result['commands'] = commands
-
- if commands:
- if not module.check_mode:
- resp = load_config(module, commands)
- if resp is not None:
- warnings.extend((out for out in resp if out))
-
- result['changed'] = True
-
- if warnings:
- result['warnings'] = warnings
- if 'overlaps with address configured on' in warnings[0]:
- result['failed'] = True
- result['msg'] = warnings[0]
- if 'Cannot set overlapping address' in warnings[0]:
- result['failed'] = True
- result['msg'] = warnings[0]
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_linkagg.py b/plugins/modules/network/cnos/cnos_linkagg.py
deleted file mode 100644
index 1725bafa82..0000000000
--- a/plugins/modules/network/cnos/cnos_linkagg.py
+++ /dev/null
@@ -1,391 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2017 Lenovo, Inc.
-# (c) 2017, Ansible by Red Hat, inc
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to work on Link Aggregation with Lenovo Switches
-# Lenovo Networking
-#
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: cnos_linkagg
-author: "Anil Kumar Muraleedharan (@auraleedhar)"
-short_description: Manage link aggregation groups on Lenovo CNOS devices
-description:
- - This module provides declarative management of link aggregation groups
- on Lenovo CNOS network devices.
-notes:
- - Tested against CNOS 10.8.1
-options:
- group:
- description:
- - Channel-group number for the port-channel
- Link aggregation group. Range 1-255.
- mode:
- description:
- - Mode of the link aggregation group.
- choices: ['active', 'on', 'passive']
- members:
- description:
- - List of members of the link aggregation group.
- aggregate:
- description: List of link aggregation definitions.
- state:
- description:
- - State of the link aggregation group.
- default: present
- choices: ['present', 'absent']
- purge:
- description:
- - Purge links not defined in the I(aggregate) parameter.
- type: bool
- default: no
- provider:
- description:
- - B(Deprecated)
- - "Starting with Ansible 2.5 we recommend using C(connection: network_cli)."
- - For more information please see the L(CNOS Platform Options guide, ../network/user_guide/platform_cnos.html).
- - HORIZONTALLINE
- - A dict object containing connection details.
- suboptions:
- host:
- description:
- - Specifies the DNS host name or address for connecting to the remote
- device over the specified transport. The value of host is used as
- the destination address for the transport.
- required: true
- port:
- description:
- - Specifies the port to use when building the connection to the remote device.
- default: 22
- username:
- description:
- - Configures the username to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_USERNAME) will be used instead.
- password:
- description:
- - Specifies the password to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_PASSWORD) will be used instead.
- timeout:
- description:
- - Specifies the timeout in seconds for communicating with the network device
- for either connecting or sending commands. If the timeout is
- exceeded before the operation is completed, the module will error.
- default: 10
- ssh_keyfile:
- description:
- - Specifies the SSH key to use to authenticate the connection to
- the remote device. This value is the path to the
- key used to authenticate the SSH session. If the value is not specified
- in the task, the value of environment variable C(ANSIBLE_NET_SSH_KEYFILE)
- will be used instead.
- authorize:
- description:
- - Instructs the module to enter privileged mode on the remote device
- before sending any commands. If not specified, the device will
- attempt to execute all commands in non-privileged mode. If the value
- is not specified in the task, the value of environment variable
- C(ANSIBLE_NET_AUTHORIZE) will be used instead.
- type: bool
- default: 'no'
- auth_pass:
- description:
- - Specifies the password to use if required to enter privileged mode
- on the remote device. If I(authorize) is false, then this argument
- does nothing. If the value is not specified in the task, the value of
- environment variable C(ANSIBLE_NET_AUTH_PASS) will be used instead.
-'''
-
-EXAMPLES = """
-- name: create link aggregation group
- cnos_linkagg:
- group: 10
- state: present
-
-- name: delete link aggregation group
- cnos_linkagg:
- group: 10
- state: absent
-
-- name: set link aggregation group to members
- cnos_linkagg:
- group: 200
- mode: active
- members:
- - Ethernet1/33
- - Ethernet1/44
-
-- name: remove link aggregation group from GigabitEthernet0/0
- cnos_linkagg:
- group: 200
- mode: active
- members:
- - Ethernet1/33
-
-- name: Create aggregate of linkagg definitions
- cnos_linkagg:
- aggregate:
- - { group: 3, mode: on, members: [Ethernet1/33] }
- - { group: 100, mode: passive, members: [Ethernet1/44] }
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always, except for the platforms that use Netconf transport to
- manage the device.
- type: list
- sample:
- - interface port-channel 30
- - interface Ethernet1/33
- - channel-group 30 mode on
- - no interface port-channel 30
-"""
-
-import re
-from copy import deepcopy
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import CustomNetworkConfig
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import get_config, load_config
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import cnos_argument_spec
-
-
-def search_obj_in_list(group, lst):
- for o in lst:
- if o['group'] == group:
- return o
-
-
-def map_obj_to_commands(updates, module):
- commands = list()
- want, have = updates
- purge = module.params['purge']
-
- for w in want:
- group = w['group']
- mode = w['mode']
- members = w.get('members') or []
- state = w['state']
- del w['state']
-
- obj_in_have = search_obj_in_list(group, have)
-
- if state == 'absent':
- if obj_in_have:
- commands.append('no interface port-channel {0}'.format(group))
-
- elif state == 'present':
- cmd = ['interface port-channel {0}'.format(group),
- 'exit']
- if not obj_in_have:
- if not group:
- module.fail_json(msg='group is a required option')
- commands.extend(cmd)
-
- if members:
- for m in members:
- commands.append('interface {0}'.format(m))
- commands.append('channel-group {0} mode {1}'.format(group, mode))
-
- else:
- if members:
- if 'members' not in obj_in_have.keys():
- for m in members:
- commands.extend(cmd)
- commands.append('interface {0}'.format(m))
- commands.append('channel-group {0} mode {1}'.format(group, mode))
-
- elif set(members) != set(obj_in_have['members']):
- missing_members = list(set(members) - set(obj_in_have['members']))
- for m in missing_members:
- commands.extend(cmd)
- commands.append('interface {0}'.format(m))
- commands.append('channel-group {0} mode {1}'.format(group, mode))
-
- superfluous_members = list(set(obj_in_have['members']) - set(members))
- for m in superfluous_members:
- commands.extend(cmd)
- commands.append('interface {0}'.format(m))
- commands.append('no channel-group')
-
- if purge:
- for h in have:
- obj_in_want = search_obj_in_list(h['group'], want)
- if not obj_in_want:
- commands.append('no interface port-channel {0}'.format(h['group']))
-
- return commands
-
-
-def map_params_to_obj(module):
- obj = []
-
- aggregate = module.params.get('aggregate')
- if aggregate:
- for item in aggregate:
- for key in item:
- if item.get(key) is None:
- item[key] = module.params[key]
-
- d = item.copy()
- d['group'] = str(d['group'])
-
- obj.append(d)
- else:
- obj.append({
- 'group': str(module.params['group']),
- 'mode': module.params['mode'],
- 'members': module.params['members'],
- 'state': module.params['state']
- })
-
- return obj
-
-
-def parse_mode(module, config, group, member):
- mode = None
- netcfg = CustomNetworkConfig(indent=1, contents=config)
- parents = ['interface {0}'.format(member)]
- body = netcfg.get_section(parents)
-
- match_int = re.findall(r'interface {0}\n'.format(member), body, re.M)
- if match_int:
- match = re.search(r'channel-group {0} mode (\S+)'.format(group),
- body, re.M)
- if match:
- mode = match.group(1)
-
- return mode
-
-
-def parse_members(module, config, group):
- members = []
-
- for line in config.strip().split('!'):
- l = line.strip()
- if l.startswith('interface'):
- match_group = re.findall(r'channel-group {0} mode'.format(group), l, re.M)
- if match_group:
- match = re.search(r'interface (\S+)', l, re.M)
- if match:
- members.append(match.group(1))
-
- return members
-
-
-def get_channel(module, config, group):
- match = re.findall(r'^interface (\S+)', config, re.M)
-
- if not match:
- return {}
-
- channel = {}
- for item in set(match):
- member = item
- channel['mode'] = parse_mode(module, config, group, member)
- channel['members'] = parse_members(module, config, group)
-
- return channel
-
-
-def map_config_to_obj(module):
- objs = list()
- config = get_config(module)
-
- for line in config.split('\n'):
- l = line.strip()
- match = re.search(r'interface port-channel(\S+)', l, re.M)
- if match:
- obj = {}
- group = match.group(1)
- obj['group'] = group
- obj.update(get_channel(module, config, group))
- objs.append(obj)
-
- return objs
-
-
-def main():
- """ main entry point for module execution
- """
- element_spec = dict(
- group=dict(type='int'),
- mode=dict(choices=['active', 'on', 'passive']),
- members=dict(type='list'),
- state=dict(default='present',
- choices=['present', 'absent'])
- )
-
- aggregate_spec = deepcopy(element_spec)
- aggregate_spec['group'] = dict(required=True)
-
- required_one_of = [['group', 'aggregate']]
- required_together = [['members', 'mode']]
- mutually_exclusive = [['group', 'aggregate']]
-
- # remove default in aggregate spec, to handle common arguments
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec,
- required_together=required_together),
- purge=dict(default=False, type='bool')
- )
-
- argument_spec.update(element_spec)
- argument_spec.update(cnos_argument_spec)
-
- module = AnsibleModule(argument_spec=argument_spec,
- required_one_of=required_one_of,
- required_together=required_together,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
-
- warnings = list()
- result = {'changed': False}
- if warnings:
- result['warnings'] = warnings
-
- want = map_params_to_obj(module)
- have = map_config_to_obj(module)
-
- commands = map_obj_to_commands((want, have), module)
- result['commands'] = commands
-
- if commands:
- if not module.check_mode:
- load_config(module, commands)
- result['changed'] = True
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_lldp.py b/plugins/modules/network/cnos/cnos_lldp.py
deleted file mode 100644
index d9853de516..0000000000
--- a/plugins/modules/network/cnos/cnos_lldp.py
+++ /dev/null
@@ -1,139 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2019 Lenovo.
-# (c) 2017, Ansible by Red Hat, inc
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to work on Link Aggregation with Lenovo Switches
-# Lenovo Networking
-#
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: cnos_lldp
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Manage LLDP configuration on Lenovo CNOS network devices.
-description:
- - This module provides declarative management of LLDP service
- on Lenovc CNOS network devices.
-notes:
- - Tested against CNOS 10.9.1
-options:
- state:
- description:
- - State of the LLDP configuration. If value is I(present) lldp will be
- enabled else if it is I(absent) it will be disabled.
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = """
-- name: Enable LLDP service
- cnos_lldp:
- state: present
-
-- name: Disable LLDP service
- cnos_lldp:
- state: absent
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always, except for the platforms that use Netconf transport to
- manage the device.
- type: list
- sample:
- - lldp timer 1024
- - lldp trap-interval 330
-"""
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import get_config, load_config
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import cnos_argument_spec
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import debugOutput, run_commands
-from ansible.module_utils.connection import exec_command
-
-
-def get_ethernet_range(module):
- output = run_commands(module, ['show interface brief'])[0].split('\n')
- maxport = None
- last_interface = None
- for line in output:
- if line.startswith('Ethernet1/'):
- last_interface = line.split(' ')[0]
- if last_interface is not None:
- eths = last_interface.split('/')
- maxport = eths[1]
- return maxport
-
-
-def main():
- """ main entry point for module execution
- """
- argument_spec = dict(
- state=dict(default='present',
- choices=['present', 'absent'])
- )
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
- warnings = list()
- result = {'changed': False}
- if warnings:
- result['warnings'] = warnings
-
- maxport = get_ethernet_range(module)
- commands = []
- prime_cmd = 'interface ethernet 1/1-' + maxport
-
- if module.params['state'] == 'absent':
- commands.append(prime_cmd)
- commands.append('no lldp receive')
- commands.append('no lldp transmit')
- commands.append('exit')
- commands.append('interface mgmt 0')
- commands.append('no lldp receive')
- commands.append('no lldp transmit')
- commands.append('exit')
- elif module.params['state'] == 'present':
- commands.append(prime_cmd)
- commands.append('lldp receive')
- commands.append('lldp transmit')
- commands.append('exit')
- commands.append('interface mgmt 0')
- commands.append('lldp receive')
- commands.append('lldp transmit')
- commands.append('exit')
-
- result['commands'] = commands
-
- if commands:
- if not module.check_mode:
- load_config(module, commands)
-
- result['changed'] = True
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_logging.py b/plugins/modules/network/cnos/cnos_logging.py
deleted file mode 100644
index e78174b4e6..0000000000
--- a/plugins/modules/network/cnos/cnos_logging.py
+++ /dev/null
@@ -1,425 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2019 Lenovo, Inc.
-# (c) 2017, Ansible by Red Hat, inc
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to work on Link Aggregation with Lenovo Switches
-# Lenovo Networking
-#
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: cnos_logging
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Manage logging on network devices
-description:
- - This module provides declarative management of logging
- on Cisco Cnos devices.
-notes:
- - Tested against CNOS 10.9.1
-options:
- dest:
- description:
- - Destination of the logs. Lenovo uses the term server instead of host in
- its CLI.
- choices: ['server', 'console', 'monitor', 'logfile']
- name:
- description:
- - If value of C(dest) is I(file) it indicates file-name
- and for I(server) indicates the server name to be notified.
- size:
- description:
- - Size of buffer. The acceptable value is in range from 4096 to
- 4294967295 bytes.
- default: 10485760
- facility:
- description:
- - Set logging facility. This is applicable only for server logging
- level:
- description:
- - Set logging severity levels. 0-emerg;1-alert;2-crit;3-err;4-warn;
- 5-notif;6-inform;7-debug
- default: 5
- aggregate:
- description: List of logging definitions.
- state:
- description:
- - State of the logging configuration.
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = """
-- name: configure server logging
- cnos_logging:
- dest: server
- name: 10.241.107.224
- facility: local7
- state: present
-
-- name: remove server logging configuration
- cnos_logging:
- dest: server
- name: 10.241.107.224
- state: absent
-
-- name: configure console logging level and facility
- cnos_logging:
- dest: console
- level: 7
- state: present
-
-- name: configure buffer size
- cnos_logging:
- dest: logfile
- level: 5
- name: testfile
- size: 5000
-
-- name: Configure logging using aggregate
- cnos_logging:
- aggregate:
- - { dest: console, level: 6 }
- - { dest: logfile, size: 9000 }
-
-- name: remove logging using aggregate
- cnos_logging:
- aggregate:
- - { dest: console, level: 6 }
- - { dest: logfile, name: anil, size: 9000 }
- state: absent
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always
- type: list
- sample:
- - logging console 7
- - logging server 10.241.107.224
-"""
-
-import re
-
-from copy import deepcopy
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import validate_ip_address
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import get_config, load_config
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import get_capabilities
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import check_args
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import cnos_argument_spec
-
-
-def validate_size(value, module):
- if value:
- if not int(4096) <= int(value) <= int(4294967295):
- module.fail_json(msg='size must be between 4096 and 4294967295')
- else:
- return value
-
-
-def map_obj_to_commands(updates, module):
- dest_group = ('console', 'monitor', 'logfile', 'server')
- commands = list()
- want, have = updates
- for w in want:
- dest = w['dest']
- name = w['name']
- size = w['size']
- facility = w['facility']
- level = w['level']
- state = w['state']
- del w['state']
-
- if state == 'absent':
- if dest:
-
- if dest == 'server':
- commands.append('no logging server {0}'.format(name))
-
- elif dest in dest_group:
- commands.append('no logging {0}'.format(dest))
-
- else:
- module.fail_json(msg='dest must be among console, monitor, logfile, server')
-
- if state == 'present' and w not in have:
- if dest == 'server':
- cmd_str = 'logging server {0}'.format(name)
- if level is not None and level > 0 and level < 8:
- cmd_str = cmd_str + ' ' + level
- if facility is not None:
- cmd_str = cmd_str + ' facility ' + facility
- commands.append(cmd_str)
-
- elif dest == 'logfile' and size:
- present = False
-
- for entry in have:
- if entry['dest'] == 'logfile' and entry['size'] == size and entry['level'] == level:
- present = True
-
- if not present:
- cmd_str = 'logging logfile '
- if name is not None:
- cmd_str = cmd_str + name
- if level and level != '7':
- cmd_str = cmd_str + ' ' + level
- else:
- cmd_str = cmd_str + ' 7'
- if size is not None:
- cmd_str = cmd_str + ' size ' + size
- commands.append(cmd_str)
- else:
- module.fail_json(msg='Name of the logfile is a mandatory parameter')
-
- else:
- if dest:
- dest_cmd = 'logging {0}'.format(dest)
- if level:
- dest_cmd += ' {0}'.format(level)
- commands.append(dest_cmd)
- return commands
-
-
-def parse_facility(line, dest):
- facility = None
- if dest == 'server':
- result = line.split()
- i = 0
- for x in result:
- if x == 'facility':
- return result[i + 1]
- i = i + 1
- return facility
-
-
-def parse_size(line, dest):
- size = None
- if dest == 'logfile':
- if 'logging logfile' in line:
- result = line.split()
- i = 0
- for x in result:
- if x == 'size':
- return result[i + 1]
- i = i + 1
- return '10485760'
- return size
-
-
-def parse_name(line, dest):
- name = None
- if dest == 'server':
- if 'logging server' in line:
- result = line.split()
- i = 0
- for x in result:
- if x == 'server':
- name = result[i + 1]
- elif dest == 'logfile':
- if 'logging logfile' in line:
- result = line.split()
- i = 0
- for x in result:
- if x == 'logfile':
- name = result[i + 1]
- else:
- name = None
- return name
-
-
-def parse_level(line, dest):
- level_group = ('0', '1', '2', '3', '4', '5', '6', '7')
- level = '7'
- if dest == 'server':
- if 'logging server' in line:
- result = line.split()
- if(len(result) > 3):
- if result[3].isdigit():
- level = result[3]
- else:
- if dest == 'logfile':
- if 'logging logfile' in line:
- result = line.split()
- if result[3].isdigit():
- level = result[3]
- else:
- match = re.search(r'logging {0} (\S+)'.format(dest), line, re.M)
-
- return level
-
-
-def map_config_to_obj(module):
- obj = []
- dest_group = ('console', 'server', 'monitor', 'logfile')
- data = get_config(module, flags=['| include logging'])
- index = 0
- for line in data.split('\n'):
- logs = line.split()
- index = len(logs)
- if index == 0 or index == 1:
- continue
- if logs[0] != 'logging':
- continue
- if logs[1] == 'monitor' or logs[1] == 'console':
- obj.append({'dest': logs[1], 'level': logs[2]})
- elif logs[1] == 'logfile':
- level = '5'
- if index > 3 and logs[3].isdigit():
- level = logs[3]
- size = '10485760'
- if len(logs) > 4:
- size = logs[5]
- obj.append({'dest': logs[1], 'name': logs[2], 'size': size, 'level': level})
- elif logs[1] == 'server':
- level = '5'
- facility = None
-
- if index > 3 and logs[3].isdigit():
- level = logs[3]
- if index > 3 and logs[3] == 'facility':
- facility = logs[4]
- if index > 4 and logs[4] == 'facility':
- facility = logs[5]
- obj.append({'dest': logs[1], 'name': logs[2], 'facility': facility, 'level': level})
- else:
- continue
- return obj
-
-
-def map_params_to_obj(module, required_if=None):
- obj = []
- aggregate = module.params.get('aggregate')
-
- if aggregate:
- for item in aggregate:
- for key in item:
- if item.get(key) is None:
- item[key] = module.params[key]
-
- module._check_required_if(required_if, item)
-
- d = item.copy()
- if d['dest'] != 'server' and d['dest'] != 'logfile':
- d['name'] = None
-
- if d['dest'] == 'logfile':
- if 'size' in d:
- d['size'] = str(validate_size(d['size'], module))
- elif 'size' not in d:
- d['size'] = str(10485760)
- else:
- pass
-
- if d['dest'] != 'logfile':
- d['size'] = None
-
- obj.append(d)
-
- else:
- if module.params['dest'] != 'server' and module.params['dest'] != 'logfile':
- module.params['name'] = None
-
- if module.params['dest'] == 'logfile':
- if not module.params['size']:
- module.params['size'] = str(10485760)
- else:
- module.params['size'] = None
-
- if module.params['size'] is None:
- obj.append({
- 'dest': module.params['dest'],
- 'name': module.params['name'],
- 'size': module.params['size'],
- 'facility': module.params['facility'],
- 'level': module.params['level'],
- 'state': module.params['state']
- })
-
- else:
- obj.append({
- 'dest': module.params['dest'],
- 'name': module.params['name'],
- 'size': str(validate_size(module.params['size'], module)),
- 'facility': module.params['facility'],
- 'level': module.params['level'],
- 'state': module.params['state']
- })
- return obj
-
-
-def main():
- """ main entry point for module execution
- """
- element_spec = dict(
- dest=dict(type='str',
- choices=['server', 'console', 'monitor', 'logfile']),
- name=dict(type='str'),
- size=dict(type='int', default=10485760),
- facility=dict(type='str'),
- level=dict(type='str', default='5'),
- state=dict(default='present', choices=['present', 'absent']),
- )
-
- aggregate_spec = deepcopy(element_spec)
-
- # remove default in aggregate spec, to handle common arguments
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec),
- )
-
- argument_spec.update(element_spec)
-
- required_if = [('dest', 'server', ['name'])]
-
- module = AnsibleModule(argument_spec=argument_spec,
- required_if=required_if,
- supports_check_mode=True)
- warnings = list()
- check_args(module, warnings)
-
- result = {'changed': False}
- if warnings:
- result['warnings'] = warnings
-
- want = map_params_to_obj(module, required_if=required_if)
- have = map_config_to_obj(module)
-
- commands = map_obj_to_commands((want, have), module)
- result['commands'] = commands
-
- if commands:
- if not module.check_mode:
- load_config(module, commands)
- result['changed'] = True
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_reload.py b/plugins/modules/network/cnos/cnos_reload.py
deleted file mode 100644
index 0d456e9028..0000000000
--- a/plugins/modules/network/cnos/cnos_reload.py
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2017 Lenovo, Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to reload Lenovo Switches
-# Lenovo Networking
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_reload
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Perform switch restart on devices running Lenovo CNOS
-description:
- - This module allows you to restart the switch using the current startup
- configuration. The module is usually invoked after the running
- configuration has been saved over the startup configuration.
- This module uses SSH to manage network device configuration.
- The results of the operation can be viewed in results directory.
-extends_documentation_fragment:
-- community.general.cnos
-
-options: {}
-
-'''
-EXAMPLES = '''
-Tasks : The following are examples of using the module cnos_reload. These are
- written in the main.yml file of the tasks directory.
----
-- name: Test Reload
- cnos_reload:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_reload_{{ inventory_hostname }}_output.txt"
-'''
-RETURN = '''
-msg:
- description: Success or failure message
- returned: always
- type: str
- sample: "Device is Reloading. Please wait..."
-'''
-
-import sys
-import time
-import socket
-import array
-import json
-import time
-import re
-try:
- from ansible_collections.community.general.plugins.module_utils.network.cnos import cnos
- HAS_LIB = True
-except Exception:
- HAS_LIB = False
-from ansible.module_utils.basic import AnsibleModule
-from collections import defaultdict
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- outputfile=dict(required=True),
- host=dict(required=False),
- username=dict(required=False),
- password=dict(required=False, no_log=True),
- enablePassword=dict(required=False, no_log=True),
- deviceType=dict(required=True),),
- supports_check_mode=False)
-
- command = 'reload'
- outputfile = module.params['outputfile']
- output = ''
- cmd = [{'command': command, 'prompt': 'reboot system? (y/n): ',
- 'answer': 'y'}]
- output = output + str(cnos.run_cnos_commands(module, cmd))
-
- # Save it into the file
- file = open(outputfile, "a")
- file.write(output)
- file.close()
-
- errorMsg = cnos.checkOutputForError(output)
- if(errorMsg in "Device Response Timed out"):
- module.exit_json(changed=True,
- msg="Device is Reloading. Please wait...")
- else:
- module.fail_json(msg=errorMsg)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_rollback.py b/plugins/modules/network/cnos/cnos_rollback.py
deleted file mode 100644
index f8a2e1179c..0000000000
--- a/plugins/modules/network/cnos/cnos_rollback.py
+++ /dev/null
@@ -1,285 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2017 Lenovo, Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to Rollback Config back to Lenovo Switches
-#
-# Lenovo Networking
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_rollback
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Roll back the running or startup configuration from a remote
- server on devices running Lenovo CNOS
-description:
- - This module allows you to work with switch configurations. It provides a
- way to roll back configurations of a switch from a remote server. This is
- achieved by using startup or running configurations of the target device
- that were previously backed up to a remote server using FTP, SFTP, TFTP,
- or SCP. The first step is to create a directory from where the remote
- server can be reached. The next step is to provide the full file path of
- he backup configuration's location. Authentication details required by the
- remote server must be provided as well.
- By default, this method overwrites the switch's configuration file with
- the newly downloaded file. This module uses SSH to manage network device
- configuration. The results of the operation will be placed in a directory
- named 'results' that must be created by the user in their local directory
- to where the playbook is run.
-extends_documentation_fragment:
-- community.general.cnos
-
-options:
- configType:
- description:
- - This refers to the type of configuration which will be used for
- the rolling back process. The choices are the running or startup
- configurations. There is no default value, so it will result
- in an error if the input is incorrect.
- required: Yes
- default: Null
- choices: [running-config, startup-config]
- protocol:
- description:
- - This refers to the protocol used by the network device to
- interact with the remote server from where to download the backup
- configuration. The choices are FTP, SFTP, TFTP, or SCP. Any other
- protocols will result in error. If this parameter is not
- specified, there is no default value to be used.
- required: Yes
- default: Null
- choices: [SFTP, SCP, FTP, TFTP]
- rcserverip:
- description:
- - This specifies the IP Address of the remote server from where the
- backup configuration will be downloaded.
- required: Yes
- default: Null
- rcpath:
- description:
- - This specifies the full file path of the configuration file
- located on the remote server. In case the relative path is used as
- the variable value, the root folder for the user of the server
- needs to be specified.
- required: Yes
- default: Null
- serverusername:
- description:
- - Specify username for the server relating to the protocol used.
- required: Yes
- default: Null
- serverpassword:
- description:
- - Specify password for the server relating to the protocol used.
- required: Yes
- default: Null
-'''
-EXAMPLES = '''
-Tasks : The following are examples of using the module cnos_rollback.
- These are written in the main.yml file of the tasks directory.
----
-
-- name: Test Rollback of config - Running config
- cnos_rolback:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_rollback_{{ inventory_hostname }}_output.txt"
- configType: running-config
- protocol: "sftp"
- serverip: "10.241.106.118"
- rcpath: "/root/cnos/G8272-running-config.txt"
- serverusername: "root"
- serverpassword: "root123"
-
-- name: Test Rollback of config - Startup config
- cnos_rolback:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_rollback_{{ inventory_hostname }}_output.txt"
- configType: startup-config
- protocol: "sftp"
- serverip: "10.241.106.118"
- rcpath: "/root/cnos/G8272-startup-config.txt"
- serverusername: "root"
- serverpassword: "root123"
-
-- name: Test Rollback of config - Running config - TFTP
- cnos_rolback:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_rollback_{{ inventory_hostname }}_output.txt"
- configType: running-config
- protocol: "tftp"
- serverip: "10.241.106.118"
- rcpath: "/anil/G8272-running-config.txt"
- serverusername: "root"
- serverpassword: "root123"
-
-- name: Test Rollback of config - Startup config - TFTP
- cnos_rolback:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_rollback_{{ inventory_hostname }}_output.txt"
- configType: startup-config
- protocol: "tftp"
- serverip: "10.241.106.118"
- rcpath: "/anil/G8272-startup-config.txt"
- serverusername: "root"
- serverpassword: "root123"
-
-'''
-RETURN = '''
-msg:
- description: Success or failure message
- returned: always
- type: str
- sample: "Config file transferred to Device"
-'''
-
-import sys
-import time
-import socket
-import array
-import json
-import time
-import re
-import os
-try:
- from ansible_collections.community.general.plugins.module_utils.network.cnos import cnos
- HAS_LIB = True
-except Exception:
- HAS_LIB = False
-from ansible.module_utils.basic import AnsibleModule
-from collections import defaultdict
-
-
-# Utility Method to rollback the running config or start up config
-# This method supports only SCP or SFTP or FTP or TFTP
-def doConfigRollBack(module, prompt, answer):
- host = module.params['host']
- server = module.params['serverip']
- username = module.params['serverusername']
- password = module.params['serverpassword']
- protocol = module.params['protocol'].lower()
- rcPath = module.params['rcpath']
- configType = module.params['configType']
- confPath = rcPath
- retVal = ''
-
- command = "copy " + protocol + " " + protocol + "://"
- command = command + username + "@" + server + "/" + confPath
- command = command + " " + configType + " vrf management\n"
- cnos.debugOutput(command + "\n")
- # cnos.checkForFirstTimeAccess(module, command, 'yes/no', 'yes')
- cmd = []
- if(protocol == "scp"):
- scp_cmd1 = [{'command': command, 'prompt': 'timeout:', 'answer': '0'}]
- scp_cmd2 = [{'command': '\n', 'prompt': 'Password:',
- 'answer': password}]
- cmd.extend(scp_cmd1)
- cmd.extend(scp_cmd2)
- if(configType == 'startup-config'):
- scp_cmd3 = [{'command': 'y', 'prompt': None, 'answer': None}]
- cmd.extend(scp_cmd3)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- elif(protocol == "sftp"):
- sftp_cmd = [{'command': command, 'prompt': 'Password:',
- 'answer': password}]
- cmd.extend(sftp_cmd)
- # cnos.debugOutput(configType + "\n")
- if(configType == 'startup-config'):
- sftp_cmd2 = [{'command': 'y', 'prompt': None, 'answer': None}]
- cmd.extend(sftp_cmd2)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- elif(protocol == "ftp"):
- ftp_cmd = [{'command': command, 'prompt': 'Password:',
- 'answer': password}]
- cmd.extend(ftp_cmd)
- if(configType == 'startup-config'):
- ftp_cmd2 = [{'command': 'y', 'prompt': None, 'answer': None}]
- cmd.extend(ftp_cmd2)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- elif(protocol == "tftp"):
- command = "copy " + protocol + " " + protocol
- command = command + "://" + server + "/" + confPath
- command = command + " " + configType + " vrf management\n"
- cnos.debugOutput(command)
- tftp_cmd = [{'command': command, 'prompt': None, 'answer': None}]
- cmd.extend(tftp_cmd)
- if(configType == 'startup-config'):
- tftp_cmd2 = [{'command': 'y', 'prompt': None, 'answer': None}]
- cmd.extend(tftp_cmd2)
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- else:
- return "Error-110"
-
- return retVal
-# EOM
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- outputfile=dict(required=True),
- host=dict(required=False),
- username=dict(required=False),
- password=dict(required=False, no_log=True),
- enablePassword=dict(required=False, no_log=True),
- deviceType=dict(required=True),
- configType=dict(required=True),
- protocol=dict(required=True),
- serverip=dict(required=True),
- rcpath=dict(required=True),
- serverusername=dict(required=False),
- serverpassword=dict(required=False, no_log=True),),
- supports_check_mode=False)
-
- outputfile = module.params['outputfile']
- protocol = module.params['protocol'].lower()
- output = ''
- if protocol in ('tftp', 'ftp', 'sftp', 'scp'):
- transfer_status = doConfigRollBack(module, None, None)
- else:
- transfer_status = 'Invalid Protocol option'
- output = output + "\n Config Transfer status \n" + transfer_status
-
- # Save it into the file
- if '/' in outputfile:
- path = outputfile.rsplit('/', 1)
- # cnos.debugOutput(path[0])
- if not os.path.exists(path[0]):
- os.makedirs(path[0])
- file = open(outputfile, "a")
- file.write(output)
- file.close()
-
- # need to add logic to check when changes occur or not
- errorMsg = cnos.checkOutputForError(output)
- if(errorMsg is None):
- module.exit_json(changed=True, msg="Config file transferred to Device")
- else:
- module.fail_json(msg=errorMsg)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_save.py b/plugins/modules/network/cnos/cnos_save.py
deleted file mode 100644
index 2d03be1fb8..0000000000
--- a/plugins/modules/network/cnos/cnos_save.py
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2017 Lenovo, Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to save running config to start up config to Lenovo Switches
-# Lenovo Networking
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_save
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Save the running configuration as the startup configuration
- on devices running Lenovo CNOS
-description:
- - This module allows you to copy the running configuration of a switch over
- its startup configuration. It is recommended to use this module shortly
- after any major configuration changes so they persist after a switch
- restart. This module uses SSH to manage network device configuration.
- The results of the operation will be placed in a directory named 'results'
- that must be created by the user in their local directory to where the
- playbook is run.
-extends_documentation_fragment:
-- community.general.cnos
-
-options: {}
-
-'''
-EXAMPLES = '''
-Tasks : The following are examples of using the module cnos_save. These are
- written in the main.yml file of the tasks directory.
----
-- name: Test Save
- cnos_save:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_save_{{ inventory_hostname }}_output.txt"
-'''
-RETURN = '''
-msg:
- description: Success or failure message
- returned: always
- type: str
- sample: "Switch Running Config is Saved to Startup Config"
-'''
-
-import sys
-import time
-import socket
-import array
-import json
-import time
-import re
-try:
- from ansible_collections.community.general.plugins.module_utils.network.cnos import cnos
- HAS_LIB = True
-except Exception:
- HAS_LIB = False
-from ansible.module_utils.basic import AnsibleModule
-from collections import defaultdict
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- outputfile=dict(required=True),
- host=dict(required=False),
- username=dict(required=False),
- password=dict(required=False, no_log=True),
- enablePassword=dict(required=False, no_log=True),
- deviceType=dict(required=True),),
- supports_check_mode=False)
-
- command = 'write memory'
- outputfile = module.params['outputfile']
- output = ''
- cmd = [{'command': command, 'prompt': None, 'answer': None}]
- output = output + str(cnos.run_cnos_commands(module, cmd))
-
- # Save it into the file
- file = open(outputfile, "a")
- file.write(output)
- file.close()
-
- errorMsg = cnos.checkOutputForError(output)
- if(errorMsg is None):
- module.exit_json(changed=True,
- msg="Switch Running Config is Saved to Startup Config ")
- else:
- module.fail_json(msg=errorMsg)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_showrun.py b/plugins/modules/network/cnos/cnos_showrun.py
deleted file mode 100644
index 3f161f5028..0000000000
--- a/plugins/modules/network/cnos/cnos_showrun.py
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2017 Lenovo, Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to display running config of Switches
-# Lenovo Networking
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_showrun
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Collect the current running configuration on devices running on CNOS
-description:
- - This module allows you to view the switch running configuration. It
- executes the display running-config CLI command on a switch and returns a
- file containing the current running configuration of the target network
- device. This module uses SSH to manage network device configuration.
- The results of the operation will be placed in a directory named 'results'
- that must be created by the user in their local directory to where the
- playbook is run.
-extends_documentation_fragment:
-- community.general.cnos
-
-options: {}
-
-'''
-EXAMPLES = '''
-Tasks : The following are examples of using the module cnos_showrun. These are
- written in the main.yml file of the tasks directory.
----
-- name: Run show running-config
- cnos_showrun:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- outputfile: "./results/test_showrun_{{ inventory_hostname }}_output.txt"
-
-'''
-RETURN = '''
-msg:
- description: Success or failure message
- returned: always
- type: str
- sample: "Running Configuration saved in file"
-'''
-
-import sys
-import time
-import socket
-import array
-import json
-import time
-import re
-try:
- from ansible_collections.community.general.plugins.module_utils.network.cnos import cnos
- HAS_LIB = True
-except Exception:
- HAS_LIB = False
-from ansible.module_utils.basic import AnsibleModule
-from collections import defaultdict
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- outputfile=dict(required=True),
- host=dict(required=False),
- username=dict(required=False),
- password=dict(required=False, no_log=True),
- enablePassword=dict(required=False, no_log=True),),
- supports_check_mode=False)
-
- command = 'show running-config'
- outputfile = module.params['outputfile']
- output = ''
- cmd = [{'command': command, 'prompt': None, 'answer': None}]
- output = output + str(cnos.run_cnos_commands(module, cmd))
- # Save it into the file
- file = open(outputfile, "a")
- file.write(output)
- file.close()
-
- errorMsg = cnos.checkOutputForError(output)
- if(errorMsg is None):
- module.exit_json(changed=True,
- msg="Running Configuration saved in file ")
- else:
- module.fail_json(msg=errorMsg)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_static_route.py b/plugins/modules/network/cnos/cnos_static_route.py
deleted file mode 100644
index 0195831c5b..0000000000
--- a/plugins/modules/network/cnos/cnos_static_route.py
+++ /dev/null
@@ -1,288 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2019 Lenovo, Inc.
-# (c) 2017, Ansible by Red Hat, inc
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to work on Link Aggregation with Lenovo Switches
-# Lenovo Networking
-#
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: cnos_static_route
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Manage static IP routes on Lenovo CNOS network devices
-description:
- - This module provides declarative management of static
- IP routes on Lenovo CNOS network devices.
-notes:
- - Tested against CNOS 10.10.1
-options:
- prefix:
- description:
- - Network prefix of the static route.
- mask:
- description:
- - Network prefix mask of the static route.
- next_hop:
- description:
- - Next hop IP of the static route.
- interface:
- description:
- - Interface of the static route.
- description:
- description:
- - Name of the static route
- aliases: ['description']
- admin_distance:
- description:
- - Admin distance of the static route.
- default: 1
- tag:
- description:
- - Set tag of the static route.
- aggregate:
- description: List of static route definitions.
- state:
- description:
- - State of the static route configuration.
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = """
-- name: configure static route
- cnos_static_route:
- prefix: 10.241.107.0
- mask: 255.255.255.0
- next_hop: 10.241.106.1
-
-- name: configure ultimate route with name and tag
- cnos_static_route:
- prefix: 10.241.107.0
- mask: 255.255.255.0
- interface: Ethernet1/13
- description: hello world
- tag: 100
-
-- name: remove configuration
- cnos_static_route:
- prefix: 10.241.107.0
- mask: 255.255.255.0
- next_hop: 10.241.106.0
- state: absent
-
-- name: Add static route aggregates
- cnos_static_route:
- aggregate:
- - { prefix: 10.241.107.0, mask: 255.255.255.0, next_hop: 10.241.105.0 }
- - { prefix: 10.241.106.0, mask: 255.255.255.0, next_hop: 10.241.104.0 }
-
-- name: Remove static route aggregates
- cnos_static_route:
- aggregate:
- - { prefix: 10.241.107.0, mask: 255.255.255.0, next_hop: 10.241.105.0 }
- - { prefix: 10.241.106.0, mask: 255.255.255.0, next_hop: 10.241.104.0 }
- state: absent
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always
- type: list
- sample:
- - ip route 10.241.107.0 255.255.255.0 10.241.106.0
-"""
-from copy import deepcopy
-from re import findall
-from ansible_collections.ansible.netcommon.plugins.module_utils.compat import ipaddress
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import validate_ip_address
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import get_config, load_config
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import check_args
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import cnos_argument_spec
-
-
-def map_obj_to_commands(want, have):
- commands = list()
-
- for w in want:
- state = w['state']
- command = 'ip route'
- prefix = w['prefix']
- mask = w['mask']
- command = ' '.join((command, prefix, mask))
-
- for key in ['interface', 'next_hop', 'admin_distance', 'tag',
- 'description']:
- if w.get(key):
- if key == 'description' and len(w.get(key).split()) > 1:
- # name with multiple words needs to be quoted
- command = ' '.join((command, key, '"%s"' % w.get(key)))
- elif key in ('description', 'tag'):
- command = ' '.join((command, key, w.get(key)))
- else:
- command = ' '.join((command, w.get(key)))
-
- if state == 'absent':
- commands.append('no %s' % command)
- elif state == 'present':
- commands.append(command)
-
- return commands
-
-
-def map_config_to_obj(module):
- obj = []
-
- out = get_config(module, flags='| include ip route')
- for line in out.splitlines():
- # Split by whitespace but do not split quotes, needed for description
- splitted_line = findall(r'[^"\s]\S*|".+?"', line)
- route = {}
- prefix_with_mask = splitted_line[2]
- prefix = None
- mask = None
- iface = None
- nhop = None
- if validate_ip_address(prefix_with_mask) is True:
- my_net = ipaddress.ip_network(prefix_with_mask)
- prefix = str(my_net.network_address)
- mask = str(my_net.netmask)
- route.update({'prefix': prefix,
- 'mask': mask, 'admin_distance': '1'})
- if splitted_line[3] is not None:
- if validate_ip_address(splitted_line[3]) is False:
- iface = str(splitted_line[3])
- route.update(interface=iface)
- if validate_ip_address(splitted_line[4]) is True:
- nhop = str(splitted_line[4])
- route.update(next_hop=nhop)
- if splitted_line[5].isdigit():
- route.update(admin_distance=str(splitted_line[5]))
- elif splitted_line[4].isdigit():
- route.update(admin_distance=str(splitted_line[4]))
- else:
- if splitted_line[6] is not None and splitted_line[6].isdigit():
- route.update(admin_distance=str(splitted_line[6]))
- else:
- nhop = str(splitted_line[3])
- route.update(next_hop=nhop)
- if splitted_line[4].isdigit():
- route.update(admin_distance=str(splitted_line[4]))
-
- index = 0
- for word in splitted_line:
- if word in ('tag', 'description'):
- route.update(word=splitted_line[index + 1])
- index = index + 1
- obj.append(route)
-
- return obj
-
-
-def map_params_to_obj(module, required_together=None):
- keys = ['prefix', 'mask', 'state', 'next_hop', 'interface', 'description',
- 'admin_distance', 'tag']
- obj = []
-
- aggregate = module.params.get('aggregate')
- if aggregate:
- for item in aggregate:
- route = item.copy()
- for key in keys:
- if route.get(key) is None:
- route[key] = module.params.get(key)
-
- route = dict((k, v) for k, v in route.items() if v is not None)
- module._check_required_together(required_together, route)
- obj.append(route)
- else:
- module._check_required_together(required_together, module.params)
- route = dict()
- for key in keys:
- if module.params.get(key) is not None:
- route[key] = module.params.get(key)
- obj.append(route)
-
- return obj
-
-
-def main():
- """ main entry point for module execution
- """
- element_spec = dict(
- prefix=dict(type='str'),
- mask=dict(type='str'),
- next_hop=dict(type='str'),
- interface=dict(type='str'),
- description=dict(type='str'),
- admin_distance=dict(type='str', default='1'),
- tag=dict(type='str'),
- state=dict(default='present', choices=['present', 'absent'])
- )
-
- aggregate_spec = deepcopy(element_spec)
- aggregate_spec['prefix'] = dict(required=True)
-
- # remove default in aggregate spec, to handle common arguments
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec),
- )
- argument_spec.update(element_spec)
-
- required_one_of = [['aggregate', 'prefix']]
- required_together = [['prefix', 'mask']]
- mutually_exclusive = [['aggregate', 'prefix']]
-
- module = AnsibleModule(argument_spec=argument_spec,
- required_one_of=required_one_of,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
-
- warnings = list()
- check_args(module, warnings)
-
- result = {'changed': False}
- if warnings:
- result['warnings'] = warnings
- want = map_params_to_obj(module, required_together=required_together)
- have = map_config_to_obj(module)
-
- commands = map_obj_to_commands(want, have)
- result['commands'] = commands
- if commands:
- if not module.check_mode:
- load_config(module, commands)
-
- result['changed'] = True
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_system.py b/plugins/modules/network/cnos/cnos_system.py
deleted file mode 100644
index 6c72c44a43..0000000000
--- a/plugins/modules/network/cnos/cnos_system.py
+++ /dev/null
@@ -1,387 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2019 Lenovo.
-# (c) 2017, Ansible by Red Hat, inc
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to work on System Configuration with Lenovo Switches
-# Lenovo Networking
-#
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: cnos_system
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Manage the system attributes on Lenovo CNOS devices
-description:
- - This module provides declarative management of node system attributes
- on Lenovo CNOS devices. It provides an option to configure host system
- parameters or remove those parameters from the device active
- configuration.
-options:
- hostname:
- description:
- - Configure the device hostname parameter. This option takes an
- ASCII string value or keyword 'default'
- domain_name:
- description:
- - Configures the default domain
- name suffix to be used when referencing this node by its
- FQDN. This argument accepts either a list of domain names or
- a list of dicts that configure the domain name and VRF name or
- keyword 'default'. See examples.
- lookup_enabled:
- description:
- - Administrative control for enabling or disabling DNS lookups.
- When this argument is set to True, lookups are performed and
- when it is set to False, lookups are not performed.
- type: bool
- domain_search:
- description:
- - Configures a list of domain
- name suffixes to search when performing DNS name resolution.
- This argument accepts either a list of domain names or
- a list of dicts that configure the domain name and VRF name or
- keyword 'default'. See examples.
- name_servers:
- description:
- - List of DNS name servers by IP address to use to perform name resolution
- lookups. This argument accepts either a list of DNS servers or
- a list of hashes that configure the name server and VRF name or
- keyword 'default'. See examples.
- lookup_source:
- description:
- - Provides one or more source interfaces to use for performing DNS
- lookups. The interface must be a valid interface configured.
- on the device.
- state:
- description:
- - State of the configuration
- values in the device's current active configuration. When set
- to I(present), the values should be configured in the device active
- configuration and when set to I(absent) the values should not be
- in the device active configuration
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = """
-- name: configure hostname and domain-name
- cnos_system:
- hostname: cnos01
- domain_name: test.example.com
-
-- name: remove configuration
- cnos_system:
- state: absent
-
-- name: configure name servers
- cnos_system:
- name_servers:
- - 8.8.8.8
- - 8.8.4.4
-
-- name: configure DNS Lookup sources
- cnos_system:
- lookup_source: MgmtEth0/0/CPU0/0
- lookup_enabled: yes
-
-- name: configure name servers with VRF support
- nxos_system:
- name_servers:
- - { server: 8.8.8.8, vrf: mgmt }
- - { server: 8.8.4.4, vrf: mgmt }
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always
- type: list
- sample:
- - hostname cnos01
- - ip domain-name test.example.com vrf default
-"""
-import re
-
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import get_config, load_config
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import cnos_argument_spec
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import check_args, debugOutput
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.six import iteritems
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ComplexList
-
-_CONFIGURED_VRFS = None
-
-
-def map_obj_to_commands(want, have, module):
- commands = list()
- state = module.params['state']
-
- def needs_update(x):
- return want.get(x) and (want.get(x) != have.get(x))
-
- def difference(x, y, z):
- return [item for item in x[z] if item not in y[z]]
-
- if state == 'absent':
- if have['hostname']:
- commands.append('no hostname')
-
- for item in have['domain_name']:
- my_vrf = 'default'
- if item['vrf'] is not None:
- my_vrf = item['vrf']
- cmd = 'no ip domain-name {0} vrf {1}'.format(item['name'], my_vrf)
- commands.append(cmd)
-
- for item in have['domain_search']:
- my_vrf = 'default'
- if item['vrf'] is not None:
- my_vrf = item['vrf']
- cmd = 'no ip domain-list {0} vrf {1}'.format(item['name'], my_vrf)
- commands.append(cmd)
-
- for item in have['name_servers']:
- my_vrf = 'default'
- if item['vrf'] is not None:
- my_vrf = item['vrf']
- cmd = 'no ip name-server {0} vrf {1}'.format(item['server'], my_vrf)
- commands.append(cmd)
-
- if state == 'present':
- if needs_update('hostname'):
- if want['hostname'] == 'default':
- if have['hostname']:
- commands.append('no hostname')
- else:
- commands.append('hostname %s' % want['hostname'])
-
- if want.get('lookup_enabled') is not None:
- if have.get('lookup_enabled') != want.get('lookup_enabled'):
- cmd = 'ip domain-lookup'
- if want['lookup_enabled'] is False:
- cmd = 'no %s' % cmd
- commands.append(cmd)
-
- if want['domain_name']:
- if want.get('domain_name')[0]['name'] == 'default':
- if have['domain_name']:
- for item in have['domain_name']:
- my_vrf = 'default'
- if item['vrf'] is not None:
- my_vrf = item['vrf']
- cmd = 'no ip domain-name {0} vrf {1}'.format(item['name'], my_vrf)
- commands.append(cmd)
- else:
- for item in difference(have, want, 'domain_name'):
- my_vrf = 'default'
- if item['vrf'] is not None:
- my_vrf = item['vrf']
- cmd = 'no ip domain-name {0} vrf {1}'.format(item['name'], my_vrf)
- commands.append(cmd)
- for item in difference(want, have, 'domain_name'):
- my_vrf = 'default'
- if item['vrf'] is not None:
- my_vrf = item['vrf']
- cmd = 'ip domain-name {0} vrf {1}'.format(item['name'], my_vrf)
- commands.append(cmd)
-
- if want['domain_search']:
- if want.get('domain_search')[0]['name'] == 'default':
- if have['domain_search']:
- for item in have['domain_search']:
- my_vrf = 'default'
- if item['vrf'] is not None:
- my_vrf = item['vrf']
- cmd = 'no ip domain-list {0} vrf {1}'.format(item['name'], my_vrf)
- commands.append(cmd)
- else:
- for item in difference(have, want, 'domain_search'):
- my_vrf = 'default'
- if item['vrf'] is not None:
- my_vrf = item['vrf']
- cmd = 'no ip domain-list {0} vrf {1}'.format(item['name'], my_vrf)
- commands.append(cmd)
- for item in difference(want, have, 'domain_search'):
- my_vrf = 'default'
- if item['vrf'] is not None:
- my_vrf = item['vrf']
- cmd = 'ip domain-list {0} vrf {1}'.format(item['name'], my_vrf)
- commands.append(cmd)
-
- if want['name_servers']:
- if want.get('name_servers')[0]['server'] == 'default':
- if have['name_servers']:
- for item in have['name_servers']:
- my_vrf = 'default'
- if item['vrf'] is not None:
- my_vrf = item['vrf']
- cmd = 'no ip name-server {0} vrf {1}'.format(item['server'], my_vrf)
- commands.append(cmd)
- else:
- for item in difference(have, want, 'name_servers'):
- my_vrf = 'default'
- if item['vrf'] is not None:
- my_vrf = item['vrf']
- cmd = 'no ip name-server {0} vrf {1}'.format(item['server'], my_vrf)
- commands.append(cmd)
- for item in difference(want, have, 'name_servers'):
- my_vrf = 'default'
- if item['vrf'] is not None:
- my_vrf = item['vrf']
- cmd = 'ip name-server {0} vrf {1}'.format(item['server'], my_vrf)
- commands.append(cmd)
-
- return commands
-
-
-def parse_hostname(config):
- match = re.search(r'^hostname (\S+)', config, re.M)
- if match:
- return match.group(1)
-
-
-def parse_domain_name(config):
- objects = list()
- myconf = config.splitlines()
- for line in myconf:
- if 'ip domain-name' in line:
- datas = line.split()
- objects.append({'name': datas[2], 'vrf': datas[4]})
-
- return objects
-
-
-def parse_domain_search(config):
- objects = list()
- myconf = config.splitlines()
- for line in myconf:
- if 'ip domain-list' in line:
- datas = line.split()
- objects.append({'name': datas[2], 'vrf': datas[4]})
-
- return objects
-
-
-def parse_name_servers(config):
- objects = list()
- myconf = config.splitlines()
- for line in myconf:
- if 'ip name-server' in line:
- datas = line.split()
- objects.append({'server': datas[2], 'vrf': datas[4]})
-
- return objects
-
-
-def map_config_to_obj(module):
- config = get_config(module)
- configobj = NetworkConfig(indent=2, contents=config)
-
- return {
- 'hostname': parse_hostname(config),
- 'lookup_enabled': 'no ip domain-lookup' not in config,
- 'domain_name': parse_domain_name(config),
- 'domain_search': parse_domain_search(config),
- 'name_servers': parse_name_servers(config),
- }
-
-
-def map_params_to_obj(module):
- obj = {
- 'hostname': module.params['hostname'],
- 'lookup_enabled': module.params['lookup_enabled'],
- }
-
- domain_name = ComplexList(dict(
- name=dict(key=True),
- vrf=dict()
- ), module)
-
- domain_search = ComplexList(dict(
- name=dict(key=True),
- vrf=dict()
- ), module)
-
- name_servers = ComplexList(dict(
- server=dict(key=True),
- vrf=dict()
- ), module)
-
- for arg, cast in [('domain_name', domain_name),
- ('domain_search', domain_search),
- ('name_servers', name_servers)]:
- if module.params[arg] is not None:
- obj[arg] = cast(module.params[arg])
- else:
- obj[arg] = None
-
- return obj
-
-
-def main():
- """ main entry point for module execution
- """
- argument_spec = dict(
- hostname=dict(),
- lookup_enabled=dict(type='bool'),
-
- # { name: , vrf: }
- domain_name=dict(type='list'),
-
- # {name: , vrf: }
- domain_search=dict(type='list'),
-
- # { server: ; vrf: }
- name_servers=dict(type='list'),
-
- lookup_source=dict(type='str'),
- state=dict(default='present', choices=['present', 'absent'])
- )
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- warnings = list()
- check_args(module, warnings)
-
- result = {'changed': False}
- if warnings:
- result['warnings'] = warnings
-
- want = map_params_to_obj(module)
- have = map_config_to_obj(module)
-
- commands = map_obj_to_commands(want, have, module)
- result['commands'] = commands
- if commands:
- if not module.check_mode:
- load_config(module, commands)
- result['changed'] = True
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_template.py b/plugins/modules/network/cnos/cnos_template.py
deleted file mode 100644
index 1e1bc2dd61..0000000000
--- a/plugins/modules/network/cnos/cnos_template.py
+++ /dev/null
@@ -1,151 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2017 Lenovo, Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to send CLI templates to Lenovo Switches
-# Lenovo Networking
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_template
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Manage switch configuration using templates on devices running Lenovo CNOS
-description:
- - This module allows you to work with the running configuration of a switch. It provides a way
- to execute a set of CNOS commands on a switch by evaluating the current running configuration
- and executing the commands only if the specific settings have not been already configured.
- The configuration source can be a set of commands or a template written in the Jinja2 templating language.
- This module uses SSH to manage network device configuration.
- The results of the operation will be placed in a directory named 'results'
- that must be created by the user in their local directory to where the playbook is run.
-extends_documentation_fragment:
-- community.general.cnos
-
-options:
- commandfile:
- description:
- - This specifies the path to the CNOS command file which needs to be applied. This usually
- comes from the commands folder. Generally this file is the output of the variables applied
- on a template file. So this command is preceded by a template module.
- Note The command file must contain the Ansible keyword {{ inventory_hostname }} in its
- filename to ensure that the command file is unique for each switch and condition.
- If this is omitted, the command file will be overwritten during iteration. For example,
- commandfile=./commands/clos_leaf_bgp_{{ inventory_hostname }}_commands.txt
- required: true
- default: Null
-'''
-EXAMPLES = '''
-Tasks : The following are examples of using the module cnos_template. These are written in the main.yml file of the tasks directory.
----
-- name: Replace Config CLI command template with values
- template:
- src: demo_template.j2
- dest: "./commands/demo_template_{{ inventory_hostname }}_commands.txt"
- vlanid1: 13
- slot_chassis_number1: "1/2"
- portchannel_interface_number1: 100
- portchannel_mode1: "active"
-
-- name: Applying CLI commands on Switches
- cnos_template:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
- commandfile: "./commands/demo_template_{{ inventory_hostname }}_commands.txt"
- outputfile: "./results/demo_template_command_{{ inventory_hostname }}_output.txt"
-
-'''
-RETURN = '''
-msg:
- description: Success or failure message
- returned: always
- type: str
- sample: "Template Applied."
-'''
-
-import sys
-import time
-import socket
-import array
-import json
-import time
-import re
-import os
-try:
- from ansible_collections.community.general.plugins.module_utils.network.cnos import cnos
- HAS_LIB = True
-except Exception:
- HAS_LIB = False
-from ansible.module_utils.basic import AnsibleModule
-from collections import defaultdict
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- commandfile=dict(required=True),
- outputfile=dict(required=True),
- host=dict(required=False),
- deviceType=dict(required=True),
- username=dict(required=False),
- password=dict(required=False, no_log=True),
- enablePassword=dict(required=False, no_log=True),),
- supports_check_mode=False)
- commandfile = module.params['commandfile']
- outputfile = module.params['outputfile']
- output = ''
-
- # Send commands one by one to the device
- f = open(commandfile, "r")
- cmd = []
- for line in f:
- # Omit the comment lines in template file
- if not line.startswith("#"):
- command = line.strip()
- inner_cmd = [{'command': command, 'prompt': None, 'answer': None}]
- cmd.extend(inner_cmd)
- # Write to memory
- save_cmd = [{'command': 'save', 'prompt': None, 'answer': None}]
- cmd.extend(save_cmd)
- output = output + str(cnos.run_cnos_commands(module, cmd))
- # Write output to file
- path = outputfile.rsplit('/', 1)
- # cnos.debugOutput(path[0])
- if not os.path.exists(path[0]):
- os.makedirs(path[0])
- file = open(outputfile, "a")
- file.write(output)
- file.close()
-
- # Logic to check when changes occur or not
- errorMsg = cnos.checkOutputForError(output)
- if(errorMsg is None):
- module.exit_json(changed=True, msg="Template Applied")
- else:
- module.fail_json(msg=errorMsg)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_user.py b/plugins/modules/network/cnos/cnos_user.py
deleted file mode 100644
index 98a4552c83..0000000000
--- a/plugins/modules/network/cnos/cnos_user.py
+++ /dev/null
@@ -1,390 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2019 Lenovo.
-# (c) 2017, Ansible by Red Hat, inc
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to work on management of local users on Lenovo CNOS Switches
-# Lenovo Networking
-#
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: cnos_user
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Manage the collection of local users on Lenovo CNOS devices
-description:
- - This module provides declarative management of the local usernames
- configured on Lenovo CNOS devices. It allows playbooks to manage
- either individual usernames or the collection of usernames in the
- current running config. It also supports purging usernames from the
- configuration that are not explicitly defined.
-options:
- aggregate:
- description:
- - The set of username objects to be configured on the remote
- Lenovo CNOS device. The list entries can either be the username
- or a hash of username and properties. This argument is mutually
- exclusive with the C(name) argument.
- aliases: ['users', 'collection']
- name:
- description:
- - The username to be configured on the remote Lenovo CNOS
- device. This argument accepts a string value and is mutually
- exclusive with the C(aggregate) argument.
- configured_password:
- description:
- - The password to be configured on the network device. The
- password needs to be provided in cleartext and it will be encrypted
- on the device.
- Please note that this option is not same as C(provider password).
- update_password:
- description:
- - Since passwords are encrypted in the device running config, this
- argument will instruct the module when to change the password. When
- set to C(always), the password will always be updated in the device
- and when set to C(on_create) the password will be updated only if
- the username is created.
- default: always
- choices: ['on_create', 'always']
- role:
- description:
- - The C(role) argument configures the role for the username in the
- device running configuration. The argument accepts a string value
- defining the role name. This argument does not check if the role
- has been configured on the device.
- aliases: ['roles']
- sshkey:
- description:
- - The C(sshkey) argument defines the SSH public key to configure
- for the username. This argument accepts a valid SSH key value.
- purge:
- description:
- - The C(purge) argument instructs the module to consider the
- resource definition absolute. It will remove any previously
- configured usernames on the device with the exception of the
- `admin` user which cannot be deleted per cnos constraints.
- type: bool
- default: 'no'
- state:
- description:
- - The C(state) argument configures the state of the username definition
- as it relates to the device operational configuration. When set
- to I(present), the username(s) should be configured in the device active
- configuration and when set to I(absent) the username(s) should not be
- in the device active configuration
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = """
-- name: create a new user
- cnos_user:
- name: ansible
- sshkey: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
- state: present
-
-- name: remove all users except admin
- cnos_user:
- purge: yes
-
-- name: set multiple users role
- aggregate:
- - name: netop
- - name: netend
- role: network-operator
- state: present
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always
- type: list
- sample:
- - name ansible
- - name ansible password password
-start:
- description: The time the job started
- returned: always
- type: str
- sample: "2016-11-16 10:38:15.126146"
-end:
- description: The time the job ended
- returned: always
- type: str
- sample: "2016-11-16 10:38:25.595612"
-delta:
- description: The time elapsed to perform all operations
- returned: always
- type: str
- sample: "0:00:10.469466"
-"""
-import re
-
-from copy import deepcopy
-from functools import partial
-
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import run_commands, load_config
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import get_config
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import cnos_argument_spec
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.six import string_types, iteritems
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import get_user_roles
-
-
-def validate_roles(value, module):
- for item in value:
- if item not in get_user_roles():
- module.fail_json(msg='invalid role specified')
-
-
-def map_obj_to_commands(updates, module):
- commands = list()
- state = module.params['state']
- update_password = module.params['update_password']
-
- for update in updates:
- want, have = update
-
- def needs_update(x):
- return want.get(x) and (want.get(x) != have.get(x))
-
- def add(x):
- return commands.append('username %s %s' % (want['name'], x))
-
- def remove(x):
- return commands.append('no username %s %s' % (want['name'], x))
-
- if want['state'] == 'absent':
- commands.append('no username %s' % want['name'])
- continue
-
- if want['state'] == 'present' and not have:
- commands.append('username %s' % want['name'])
-
- if needs_update('configured_password'):
- if update_password == 'always' or not have:
- add('password %s' % want['configured_password'])
-
- if needs_update('sshkey'):
- add('sshkey %s' % want['sshkey'])
-
- if want['roles']:
- if have:
- for item in set(have['roles']).difference(want['roles']):
- remove('role %s' % item)
-
- for item in set(want['roles']).difference(have['roles']):
- add('role %s' % item)
- else:
- for item in want['roles']:
- add('role %s' % item)
-
- return commands
-
-
-def parse_password(data):
- if 'no password set' in data:
- return None
- return ''
-
-
-def parse_roles(data):
- roles = list()
- if 'role:' in data:
- items = data.split()
- my_item = items[items.index('role:') + 1]
- roles.append(my_item)
- return roles
-
-
-def parse_username(data):
- name = data.split(' ', 1)[0]
- username = name[1:]
- return username
-
-
-def parse_sshkey(data):
- key = None
- if 'sskkey:' in data:
- items = data.split()
- key = items[items.index('sshkey:') + 1]
- return key
-
-
-def map_config_to_obj(module):
- out = run_commands(module, ['show user-account'])
- data = out[0]
- objects = list()
- datum = data.split('User')
-
- for item in datum:
- objects.append({
- 'name': parse_username(item),
- 'configured_password': parse_password(item),
- 'sshkey': parse_sshkey(item),
- 'roles': parse_roles(item),
- 'state': 'present'
- })
- return objects
-
-
-def get_param_value(key, item, module):
- # if key doesn't exist in the item, get it from module.params
- if not item.get(key):
- value = module.params[key]
-
- # if key does exist, do a type check on it to validate it
- else:
- value_type = module.argument_spec[key].get('type', 'str')
- type_checker = module._CHECK_ARGUMENT_TYPES_DISPATCHER[value_type]
- type_checker(item[key])
- value = item[key]
-
- return value
-
-
-def map_params_to_obj(module):
- aggregate = module.params['aggregate']
- if not aggregate:
- if not module.params['name'] and module.params['purge']:
- return list()
- elif not module.params['name']:
- module.fail_json(msg='username is required')
- else:
- collection = [{'name': module.params['name']}]
- else:
- collection = list()
- for item in aggregate:
- if not isinstance(item, dict):
- collection.append({'name': item})
- elif 'name' not in item:
- module.fail_json(msg='name is required')
- else:
- collection.append(item)
-
- objects = list()
-
- for item in collection:
- get_value = partial(get_param_value, item=item, module=module)
- item.update({
- 'configured_password': get_value('configured_password'),
- 'sshkey': get_value('sshkey'),
- 'roles': get_value('roles'),
- 'state': get_value('state')
- })
-
- for key, value in iteritems(item):
- if value:
- # validate the param value (if validator func exists)
- validator = globals().get('validate_%s' % key)
- if all((value, validator)):
- validator(value, module)
-
- objects.append(item)
-
- return objects
-
-
-def update_objects(want, have):
- updates = list()
- for entry in want:
- item = next((i for i in have if i['name'] == entry['name']), None)
- if all((item is None, entry['state'] == 'present')):
- updates.append((entry, {}))
- elif item:
- for key, value in iteritems(entry):
- if value and value != item[key]:
- updates.append((entry, item))
- return updates
-
-
-def main():
- """ main entry point for module execution
- """
- element_spec = dict(
- name=dict(),
- configured_password=dict(no_log=True),
- update_password=dict(default='always', choices=['on_create', 'always']),
- roles=dict(type='list', aliases=['role']),
- sshkey=dict(),
- state=dict(default='present', choices=['present', 'absent'])
- )
-
- aggregate_spec = deepcopy(element_spec)
-
- # remove default in aggregate spec, to handle common arguments
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict',
- options=aggregate_spec, aliases=['collection', 'users']),
- purge=dict(type='bool', default=False)
- )
-
- argument_spec.update(element_spec)
-
- mutually_exclusive = [('name', 'aggregate')]
-
- module = AnsibleModule(argument_spec=argument_spec,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
-
- warnings = list()
-
- result = {'changed': False}
- result['warnings'] = warnings
-
- want = map_params_to_obj(module)
- have = map_config_to_obj(module)
-
- commands = map_obj_to_commands(update_objects(want, have), module)
-
- if module.params['purge']:
- want_users = [x['name'] for x in want]
- have_users = [x['name'] for x in have]
- for item in set(have_users).difference(want_users):
- if item != 'admin':
- if not item.strip():
- continue
- item = item.replace("\\", "\\\\")
- commands.append('no username %s' % item)
-
- result['commands'] = commands
-
- # the cnos cli prevents this by rule but still
- if 'no username admin' in commands:
- module.fail_json(msg='Cannot delete the `admin` account')
-
- if commands:
- if not module.check_mode:
- load_config(module, commands)
- result['changed'] = True
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_vlag.py b/plugins/modules/network/cnos/cnos_vlag.py
deleted file mode 100644
index 8568f7fb42..0000000000
--- a/plugins/modules/network/cnos/cnos_vlag.py
+++ /dev/null
@@ -1,446 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2017 Lenovo, Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to send VLAG commands to Lenovo Switches
-# Lenovo Networking
-#
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: cnos_vlag
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Manage VLAG resources and attributes on devices running
- Lenovo CNOS
-description:
- - This module allows you to work with virtual Link Aggregation Groups
- (vLAG) related configurations. The operators used are overloaded to ensure
- control over switch vLAG configurations. Apart from the regular device
- connection related attributes, there are four vLAG arguments which are
- overloaded variables that will perform further configurations. They are
- vlagArg1, vlagArg2, vlagArg3, and vlagArg4. For more details on how to use
- these arguments, see [Overloaded Variables].
- This module uses SSH to manage network device configuration.
- The results of the operation will be placed in a directory named 'results'
- that must be created by the user in their local directory to where the
- playbook is run.
-extends_documentation_fragment:
-- community.general.cnos
-
-options:
- vlagArg1:
- description:
- - This is an overloaded vlag first argument. Usage of this argument can
- be found is the User Guide referenced above.
- required: Yes
- default: Null
- choices: [enable, auto-recovery,config-consistency,isl,mac-address-table,
- peer-gateway,priority,startup-delay,tier-id,vrrp,instance,hlthchk]
- vlagArg2:
- description:
- - This is an overloaded vlag second argument. Usage of this argument can
- be found is the User Guide referenced above.
- required: No
- default: Null
- choices: [Interval in seconds,disable or strict,Port Aggregation Number,
- VLAG priority,Delay time in seconds,VLAG tier-id value,
- VLAG instance number,keepalive-attempts,keepalive-interval,
- retry-interval,peer-ip]
- vlagArg3:
- description:
- - This is an overloaded vlag third argument. Usage of this argument can
- be found is the User Guide referenced above.
- required: No
- default: Null
- choices: [enable or port-aggregation,Number of keepalive attempts,
- Interval in seconds,Interval in seconds,
- VLAG health check peer IP4 address]
- vlagArg4:
- description:
- - This is an overloaded vlag fourth argument. Usage of this argument can
- be found is the User Guide referenced above.
- required: No
- default: Null
- choices: [Port Aggregation Number,default or management]
-
-'''
-EXAMPLES = '''
-
-Tasks : The following are examples of using the module cnos_vlag. These are
- written in the main.yml file of the tasks directory.
----
-- name: Test Vlag - enable
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "enable"
-
-- name: Test Vlag - autorecovery
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "auto-recovery"
- vlagArg2: 266
-
-- name: Test Vlag - config-consistency
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "config-consistency"
- vlagArg2: "strict"
-
-- name: Test Vlag - isl
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "isl"
- vlagArg2: 23
-
-- name: Test Vlag - mac-address-table
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "mac-address-table"
-
-- name: Test Vlag - peer-gateway
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "peer-gateway"
-
-- name: Test Vlag - priority
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "priority"
- vlagArg2: 1313
-
-- name: Test Vlag - startup-delay
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "startup-delay"
- vlagArg2: 323
-
-- name: Test Vlag - tier-id
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "tier-id"
- vlagArg2: 313
-
-- name: Test Vlag - vrrp
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "vrrp"
-
-- name: Test Vlag - instance
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "instance"
- vlagArg2: 33
- vlagArg3: 333
-
-- name: Test Vlag - instance2
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "instance"
- vlagArg2: "33"
-
-- name: Test Vlag - keepalive-attempts
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "hlthchk"
- vlagArg2: "keepalive-attempts"
- vlagArg3: 13
-
-- name: Test Vlag - keepalive-interval
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "hlthchk"
- vlagArg2: "keepalive-interval"
- vlagArg3: 131
-
-- name: Test Vlag - retry-interval
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "hlthchk"
- vlagArg2: "retry-interval"
- vlagArg3: 133
-
-- name: Test Vlag - peer ip
- cnos_vlag:
- deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
- outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
- vlagArg1: "hlthchk"
- vlagArg2: "peer-ip"
- vlagArg3: "1.2.3.4"
-
-'''
-RETURN = '''
-msg:
- description: Success or failure message
- returned: always
- type: str
- sample: "vLAG configurations accomplished"
-'''
-
-import sys
-import time
-import socket
-import array
-import json
-import time
-import re
-try:
- from ansible_collections.community.general.plugins.module_utils.network.cnos import cnos
- HAS_LIB = True
-except Exception:
- HAS_LIB = False
-
-from ansible.module_utils.basic import AnsibleModule
-from collections import defaultdict
-
-
-def vlagConfig(module, prompt, answer):
-
- retVal = ''
- # vlag config command happens here.
- command = 'vlag '
-
- vlagArg1 = module.params['vlagArg1']
- vlagArg2 = module.params['vlagArg2']
- vlagArg3 = module.params['vlagArg3']
- vlagArg4 = module.params['vlagArg4']
- deviceType = module.params['deviceType']
-
- if(vlagArg1 == "enable"):
- # debugOutput("enable")
- command = command + vlagArg1 + " "
-
- elif(vlagArg1 == "auto-recovery"):
- # debugOutput("auto-recovery")
- command = command + vlagArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "vlag_auto_recovery", vlagArg2)
- if(value == "ok"):
- command = command + vlagArg2
- else:
- retVal = "Error-160"
- return retVal
-
- elif(vlagArg1 == "config-consistency"):
- # debugOutput("config-consistency")
- command = command + vlagArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "vlag_config_consistency", vlagArg2)
- if(value == "ok"):
- command = command + vlagArg2
- else:
- retVal = "Error-161"
- return retVal
-
- elif(vlagArg1 == "isl"):
- # debugOutput("isl")
- command = command + vlagArg1 + " port-channel "
- value = cnos.checkSanityofVariable(
- deviceType, "vlag_port_aggregation", vlagArg2)
- if(value == "ok"):
- command = command + vlagArg2
- else:
- retVal = "Error-162"
- return retVal
-
- elif(vlagArg1 == "mac-address-table"):
- # debugOutput("mac-address-table")
- command = command + vlagArg1 + " refresh"
-
- elif(vlagArg1 == "peer-gateway"):
- # debugOutput("peer-gateway")
- command = command + vlagArg1 + " "
-
- elif(vlagArg1 == "priority"):
- # debugOutput("priority")
- command = command + vlagArg1 + " "
- value = cnos.checkSanityofVariable(deviceType, "vlag_priority",
- vlagArg2)
- if(value == "ok"):
- command = command + vlagArg2
- else:
- retVal = "Error-163"
- return retVal
-
- elif(vlagArg1 == "startup-delay"):
- # debugOutput("startup-delay")
- command = command + vlagArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "vlag_startup_delay", vlagArg2)
- if(value == "ok"):
- command = command + vlagArg2
- else:
- retVal = "Error-164"
- return retVal
-
- elif(vlagArg1 == "tier-id"):
- # debugOutput("tier-id")
- command = command + vlagArg1 + " "
- value = cnos.checkSanityofVariable(deviceType, "vlag_tier_id", vlagArg2)
- if(value == "ok"):
- command = command + vlagArg2
- else:
- retVal = "Error-165"
- return retVal
-
- elif(vlagArg1 == "vrrp"):
- # debugOutput("vrrp")
- command = command + vlagArg1 + " active"
-
- elif(vlagArg1 == "instance"):
- # debugOutput("instance")
- command = command + vlagArg1 + " "
- value = cnos.checkSanityofVariable(deviceType, "vlag_instance",
- vlagArg2)
- if(value == "ok"):
- command = command + vlagArg2
- if(vlagArg3 is not None):
- command = command + " port-channel "
- value = cnos.checkSanityofVariable(
- deviceType, "vlag_port_aggregation", vlagArg3)
- if(value == "ok"):
- command = command + vlagArg3
- else:
- retVal = "Error-162"
- return retVal
- else:
- command = command + " enable "
- else:
- retVal = "Error-166"
- return retVal
-
- elif(vlagArg1 == "hlthchk"):
- # debugOutput("hlthchk")
- command = command + vlagArg1 + " "
- value = cnos.checkSanityofVariable(
- deviceType, "vlag_hlthchk_options", vlagArg2)
- if(value == "ok"):
- if(vlagArg2 == "keepalive-attempts"):
- value = cnos.checkSanityofVariable(
- deviceType, "vlag_keepalive_attempts", vlagArg3)
- if(value == "ok"):
- command = command + vlagArg2 + " " + vlagArg3
- else:
- retVal = "Error-167"
- return retVal
- elif(vlagArg2 == "keepalive-interval"):
- value = cnos.checkSanityofVariable(
- deviceType, "vlag_keepalive_interval", vlagArg3)
- if(value == "ok"):
- command = command + vlagArg2 + " " + vlagArg3
- else:
- retVal = "Error-168"
- return retVal
- elif(vlagArg2 == "retry-interval"):
- value = cnos.checkSanityofVariable(
- deviceType, "vlag_retry_interval", vlagArg3)
- if(value == "ok"):
- command = command + vlagArg2 + " " + vlagArg3
- else:
- retVal = "Error-169"
- return retVal
- elif(vlagArg2 == "peer-ip"):
- # Here I am not taking care of IPV6 option.
- value = cnos.checkSanityofVariable(
- deviceType, "vlag_peerip", vlagArg3)
- if(value == "ok"):
- command = command + vlagArg2 + " " + vlagArg3
- if(vlagArg4 is not None):
- value = cnos.checkSanityofVariable(
- deviceType, "vlag_peerip_vrf", vlagArg4)
- if(value == "ok"):
- command = command + " vrf " + vlagArg4
- else:
- retVal = "Error-170"
- return retVal
- else:
- retVal = "Error-171"
- return retVal
-
- else:
- retVal = "Error-172"
- return retVal
-
- # debugOutput(command)
- cmd = [{'command': command, 'prompt': None, 'answer': None}]
- retVal = retVal + str(cnos.run_cnos_commands(module, cmd))
- return retVal
-# EOM
-
-
-def main():
- #
- # Define parameters for vlag creation entry
- #
- module = AnsibleModule(
- argument_spec=dict(
- outputfile=dict(required=True),
- host=dict(required=False),
- username=dict(required=False),
- password=dict(required=False, no_log=True),
- enablePassword=dict(required=False, no_log=True),
- deviceType=dict(required=True),
- vlagArg1=dict(required=True),
- vlagArg2=dict(required=False),
- vlagArg3=dict(required=False),
- vlagArg4=dict(required=False),),
- supports_check_mode=False)
-
- outputfile = module.params['outputfile']
- output = ""
-
- # Send the CLi command
- output = output + str(vlagConfig(module, '(config)#', None))
-
- # Save it into the file
- file = open(outputfile, "a")
- file.write(output)
- file.close()
-
- # need to add logic to check when changes occur or not
- errorMsg = cnos.checkOutputForError(output)
- if(errorMsg is None):
- module.exit_json(changed=True, msg="VLAG configurations accomplished")
- else:
- module.fail_json(msg=errorMsg)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_vlan.py b/plugins/modules/network/cnos/cnos_vlan.py
deleted file mode 100644
index ce336c2ccb..0000000000
--- a/plugins/modules/network/cnos/cnos_vlan.py
+++ /dev/null
@@ -1,409 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright (C) 2017 Lenovo, Inc.
-# (c) 2017, Ansible by Red Hat, inc
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to send VLAN commands to Lenovo Switches
-# Overloading aspect of vlan creation in a range is pending
-# Lenovo Networking
-
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: cnos_vlan
-author: "Anil Kumar Mureleedharan(@amuraleedhar)"
-short_description: Manage VLANs on CNOS network devices
-description:
- - This module provides declarative management of VLANs
- on Lenovo CNOS network devices.
-notes:
- - Tested against CNOS 10.8.1
-options:
- name:
- description:
- - Name of the VLAN.
- vlan_id:
- description:
- - ID of the VLAN. Range 1-4094.
- required: true
- interfaces:
- description:
- - List of interfaces that should be associated to the VLAN.
- required: true
- associated_interfaces:
- description:
- - This is a intent option and checks the operational state of the for
- given vlan C(name) for associated interfaces. If the value in the
- C(associated_interfaces) does not match with the operational state of
- vlan interfaces on device it will result in failure.
- delay:
- description:
- - Delay the play should wait to check for declarative intent params
- values.
- default: 10
- aggregate:
- description: List of VLANs definitions.
- purge:
- description:
- - Purge VLANs not defined in the I(aggregate) parameter.
- default: no
- type: bool
- state:
- description:
- - State of the VLAN configuration.
- default: present
- choices: ['present', 'absent', 'active', 'suspend']
- provider:
- description:
- - B(Deprecated)
- - "Starting with Ansible 2.5 we recommend using C(connection: network_cli)."
- - For more information please see the L(CNOS Platform Options guide, ../network/user_guide/platform_cnos.html).
- - HORIZONTALLINE
- - A dict object containing connection details.
- suboptions:
- host:
- description:
- - Specifies the DNS host name or address for connecting to the remote
- device over the specified transport. The value of host is used as
- the destination address for the transport.
- required: true
- port:
- description:
- - Specifies the port to use when building the connection to the remote device.
- default: 22
- username:
- description:
- - Configures the username to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_USERNAME) will be used instead.
- password:
- description:
- - Specifies the password to use to authenticate the connection to
- the remote device. This value is used to authenticate
- the SSH session. If the value is not specified in the task, the
- value of environment variable C(ANSIBLE_NET_PASSWORD) will be used instead.
- timeout:
- description:
- - Specifies the timeout in seconds for communicating with the network device
- for either connecting or sending commands. If the timeout is
- exceeded before the operation is completed, the module will error.
- default: 10
- ssh_keyfile:
- description:
- - Specifies the SSH key to use to authenticate the connection to
- the remote device. This value is the path to the
- key used to authenticate the SSH session. If the value is not specified
- in the task, the value of environment variable C(ANSIBLE_NET_SSH_KEYFILE)
- will be used instead.
- authorize:
- description:
- - Instructs the module to enter privileged mode on the remote device
- before sending any commands. If not specified, the device will
- attempt to execute all commands in non-privileged mode. If the value
- is not specified in the task, the value of environment variable
- C(ANSIBLE_NET_AUTHORIZE) will be used instead.
- type: bool
- default: 'no'
- auth_pass:
- description:
- - Specifies the password to use if required to enter privileged mode
- on the remote device. If I(authorize) is false, then this argument
- does nothing. If the value is not specified in the task, the value of
- environment variable C(ANSIBLE_NET_AUTH_PASS) will be used instead.
-'''
-
-EXAMPLES = """
-- name: Create vlan
- cnos_vlan:
- vlan_id: 100
- name: test-vlan
- state: present
-
-- name: Add interfaces to VLAN
- cnos_vlan:
- vlan_id: 100
- interfaces:
- - Ethernet1/33
- - Ethernet1/44
-
-- name: Check if interfaces is assigned to VLAN
- cnos_vlan:
- vlan_id: 100
- associated_interfaces:
- - Ethernet1/33
- - Ethernet1/44
-
-- name: Delete vlan
- cnos_vlan:
- vlan_id: 100
- state: absent
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always
- type: list
- sample:
- - vlan 100
- - name test-vlan
-"""
-
-import re
-import time
-
-from copy import deepcopy
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import load_config, run_commands
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import debugOutput, check_args
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import cnos_argument_spec
-from ansible.module_utils._text import to_text
-
-
-def search_obj_in_list(vlan_id, lst):
- obj = list()
- for o in lst:
- if o['vlan_id'] == vlan_id:
- return o
-
-
-def map_obj_to_commands(updates, module):
- commands = list()
- want, have = updates
- purge = module.params['purge']
-
- for w in want:
- vlan_id = w['vlan_id']
- name = w['name']
- interfaces = w['interfaces']
- state = w['state']
-
- obj_in_have = search_obj_in_list(vlan_id, have)
-
- if state == 'absent':
- if obj_in_have:
- commands.append('no vlan {0}'.format(vlan_id))
-
- elif state == 'present':
- if not obj_in_have:
- commands.append('vlan {0}'.format(vlan_id))
- if name:
- commands.append('name {0}'.format(name))
-
- if interfaces:
- for i in interfaces:
- commands.append('interface {0}'.format(i))
- commands.append('switchport mode access')
- commands.append('switchport access vlan {0}'.format(vlan_id))
-
- else:
- if name:
- if name != obj_in_have['name']:
- commands.append('vlan {0}'.format(vlan_id))
- commands.append('name {0}'.format(name))
-
- if interfaces:
- if not obj_in_have['interfaces']:
- for i in interfaces:
- commands.append('vlan {0}'.format(vlan_id))
- commands.append('interface {0}'.format(i))
- commands.append('switchport mode access')
- commands.append('switchport access vlan {0}'.format(vlan_id))
-
- elif set(interfaces) != set(obj_in_have['interfaces']):
- missing_interfaces = list(set(interfaces) - set(obj_in_have['interfaces']))
- for i in missing_interfaces:
- commands.append('vlan {0}'.format(vlan_id))
- commands.append('interface {0}'.format(i))
- commands.append('switchport mode access')
- commands.append('switchport access vlan {0}'.format(vlan_id))
-
- superfluous_interfaces = list(set(obj_in_have['interfaces']) - set(interfaces))
- for i in superfluous_interfaces:
- commands.append('vlan {0}'.format(vlan_id))
- commands.append('interface {0}'.format(i))
- commands.append('switchport mode access')
- commands.append('no switchport access vlan')
- else:
- commands.append('vlan {0}'.format(vlan_id))
- if name:
- commands.append('name {0}'.format(name))
- commands.append('state {0}'.format(state))
-
- if purge:
- for h in have:
- obj_in_want = search_obj_in_list(h['vlan_id'], want)
- if not obj_in_want and h['vlan_id'] != '1':
- commands.append('no vlan {0}'.format(h['vlan_id']))
-
- return commands
-
-
-def map_params_to_obj(module):
- obj = []
- aggregate = module.params.get('aggregate')
- if aggregate:
- for item in aggregate:
- for key in item:
- if item.get(key) is None:
- item[key] = module.params[key]
-
- d = item.copy()
- d['vlan_id'] = str(d['vlan_id'])
-
- obj.append(d)
- else:
- obj.append({
- 'vlan_id': str(module.params['vlan_id']),
- 'name': module.params['name'],
- 'interfaces': module.params['interfaces'],
- # 'associated_interfaces': module.params['associated_interfaces'],
- 'state': module.params['state']
- })
-
- return obj
-
-
-def parse_to_logical_rows(out):
- relevant_data = False
- cur_row = []
- for line in out.splitlines():
- if not line:
- """Skip empty lines."""
- continue
- if '0' < line[0] <= '9':
- """Line starting with a number."""
- if len(cur_row) > 0:
- yield cur_row
- cur_row = [] # Reset it to hold a next chunk
- relevant_data = True
- if relevant_data:
- data = line.strip().split('(')
- cur_row.append(data[0])
- yield cur_row
-
-
-def parse_to_obj(logical_rows):
- first_row = logical_rows[0]
- rest_rows = logical_rows[1:]
- vlan_data = first_row.split()
- obj = {}
- obj['vlan_id'] = vlan_data[0]
- obj['name'] = vlan_data[1]
- obj['state'] = vlan_data[2]
- obj['interfaces'] = rest_rows
- return obj
-
-
-def parse_vlan_brief(vlan_out):
- return [parse_to_obj(r) for r in parse_to_logical_rows(vlan_out)]
-
-
-def map_config_to_obj(module):
- return parse_vlan_brief(run_commands(module, ['show vlan brief'])[0])
-
-
-def check_declarative_intent_params(want, module, result):
-
- have = None
- is_delay = False
-
- for w in want:
- if w.get('associated_interfaces') is None:
- continue
-
- if result['changed'] and not is_delay:
- time.sleep(module.params['delay'])
- is_delay = True
-
- if have is None:
- have = map_config_to_obj(module)
-
- for i in w['associated_interfaces']:
- obj_in_have = search_obj_in_list(w['vlan_id'], have)
- if obj_in_have and 'interfaces' in obj_in_have and i not in obj_in_have['interfaces']:
- module.fail_json(msg="Interface %s not configured on vlan %s" % (i, w['vlan_id']))
-
-
-def main():
- """ main entry point for module execution
- """
- element_spec = dict(
- vlan_id=dict(type='int'),
- name=dict(),
- interfaces=dict(type='list'),
- associated_interfaces=dict(type='list'),
- delay=dict(default=10, type='int'),
- state=dict(default='present',
- choices=['present', 'absent', 'active', 'suspend'])
- )
-
- aggregate_spec = deepcopy(element_spec)
- aggregate_spec['vlan_id'] = dict(required=True)
-
- # remove default in aggregate spec, to handle common arguments
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec),
- purge=dict(default=False, type='bool')
- )
-
- argument_spec.update(element_spec)
- argument_spec.update(cnos_argument_spec)
-
- required_one_of = [['vlan_id', 'aggregate']]
- mutually_exclusive = [['vlan_id', 'aggregate']]
-
- module = AnsibleModule(argument_spec=argument_spec,
- required_one_of=required_one_of,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
- warnings = list()
- result = {'changed': False}
- if warnings:
- result['warnings'] = warnings
-
- want = map_params_to_obj(module)
- have = map_config_to_obj(module)
- commands = map_obj_to_commands((want, have), module)
- result['commands'] = commands
-
- if commands:
- if not module.check_mode:
- load_config(module, commands)
- result['changed'] = True
-
- check_declarative_intent_params(want, module, result)
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cnos/cnos_vrf.py b/plugins/modules/network/cnos/cnos_vrf.py
deleted file mode 100644
index 1d8ffc5d6b..0000000000
--- a/plugins/modules/network/cnos/cnos_vrf.py
+++ /dev/null
@@ -1,369 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-#
-# Copyright (C) 2019 Lenovo.
-# (c) 2017, Ansible by Red Hat, inc
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-# Module to work on management of local users on Lenovo CNOS Switches
-# Lenovo Networking
-#
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: cnos_vrf
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Manage VRFs on Lenovo CNOS network devices
-description:
- - This module provides declarative management of VRFs
- on Lenovo CNOS network devices.
-notes:
- - Tested against CNOS 10.9.1
-options:
- name:
- description:
- - Name of the VRF.
- required: true
- rd:
- description:
- - Route distinguisher of the VRF
- interfaces:
- description:
- - Identifies the set of interfaces that
- should be configured in the VRF. Interfaces must be routed
- interfaces in order to be placed into a VRF. The name of interface
- should be in expanded format and not abbreviated.
- associated_interfaces:
- description:
- - This is a intent option and checks the operational state of the for
- given vrf C(name) for associated interfaces. If the value in the
- C(associated_interfaces) does not match with the operational state of
- vrf interfaces on device it will result in failure.
- aggregate:
- description: List of VRFs contexts
- purge:
- description:
- - Purge VRFs not defined in the I(aggregate) parameter.
- default: no
- type: bool
- delay:
- description:
- - Time in seconds to wait before checking for the operational state on
- remote device. This wait is applicable for operational state arguments.
- default: 10
- state:
- description:
- - State of the VRF configuration.
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = """
-- name: Create vrf
- cnos_vrf:
- name: test
- rd: 1:200
- interfaces:
- - Ethernet1/33
- state: present
-
-- name: Delete VRFs
- cnos_vrf:
- name: test
- state: absent
-
-- name: Create aggregate of VRFs with purge
- cnos_vrf:
- aggregate:
- - { name: test4, rd: "1:204" }
- - { name: test5, rd: "1:205" }
- state: present
- purge: yes
-
-- name: Delete aggregate of VRFs
- cnos_vrf:
- aggregate:
- - name: test2
- - name: test3
- - name: test4
- - name: test5
- state: absent
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always
- type: list
- sample:
- - vrf context test
- - rd 1:100
- - interface Ethernet1/44
- - vrf member test
-"""
-import re
-import time
-
-from copy import deepcopy
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import load_config, run_commands
-from ansible_collections.community.general.plugins.module_utils.network.cnos.cnos import cnos_argument_spec, check_args
-
-
-def search_obj_in_list(name, lst):
- for o in lst:
- if o['name'] == name:
- return o
-
-
-def get_interface_type(interface):
- intf_type = 'unknown'
- if interface.upper()[:2] in ('ET', 'GI', 'FA', 'TE', 'FO', 'HU', 'TWE'):
- intf_type = 'ethernet'
- elif interface.upper().startswith('VL'):
- intf_type = 'svi'
- elif interface.upper().startswith('LO'):
- intf_type = 'loopback'
- elif interface.upper()[:2] in ('MG', 'MA'):
- intf_type = 'management'
- elif interface.upper().startswith('PO'):
- intf_type = 'portchannel'
- elif interface.upper().startswith('NV'):
- intf_type = 'nve'
-
- return intf_type
-
-
-def is_switchport(name, module):
- intf_type = get_interface_type(name)
-
- if intf_type in ('ethernet', 'portchannel'):
- config = run_commands(module,
- ['show interface {0} switchport'.format(name)])[0]
- match = re.search(r'Switchport : enabled', config)
- return bool(match)
- return False
-
-
-def map_obj_to_commands(updates, module):
- commands = list()
- want, have = updates
- state = module.params['state']
- purge = module.params['purge']
-
- for w in want:
- name = w['name']
- rd = w['rd']
- interfaces = w['interfaces']
-
- obj_in_have = search_obj_in_list(name, have)
-
- if name == 'default':
- module.fail_json(msg='VRF context default is reserved')
- elif len(name) > 63:
- module.fail_json(msg='VRF name is too long')
- if state == 'absent':
- if name == 'management':
- module.fail_json(msg='Management VRF context cannot be deleted')
- if obj_in_have:
- commands.append('no vrf context %s' % name)
- elif state == 'present':
- if not obj_in_have:
- commands.append('vrf context %s' % name)
-
- if rd is not None:
- commands.append('rd %s' % rd)
-
- if w['interfaces']:
- for i in w['interfaces']:
- commands.append('interface %s' % i)
- commands.append('vrf member %s' % w['name'])
- else:
- if w['rd'] is not None and w['rd'] != obj_in_have['rd']:
- commands.append('vrf context %s' % w['name'])
- commands.append('rd %s' % w['rd'])
-
- if w['interfaces']:
- if not obj_in_have['interfaces']:
- for i in w['interfaces']:
- commands.append('interface %s' % i)
- commands.append('vrf member %s' % w['name'])
- elif set(w['interfaces']) != obj_in_have['interfaces']:
- missing_interfaces = list(set(w['interfaces']) - set(obj_in_have['interfaces']))
-
- for i in missing_interfaces:
- commands.append('interface %s' % i)
- commands.append('vrf member %s' % w['name'])
-
- if purge:
- for h in have:
- obj_in_want = search_obj_in_list(h['name'], want)
- if not obj_in_want:
- commands.append('no vrf context %s' % h['name'])
-
- return commands
-
-
-def map_config_to_obj(module):
- objs = []
- output = run_commands(module, {'command': 'show vrf'})
- if output is not None:
- vrfText = output[0].strip()
- vrfList = vrfText.split('VRF')
- for vrfItem in vrfList:
- if 'FIB ID' in vrfItem:
- obj = dict()
- list_of_words = vrfItem.split()
- vrfName = list_of_words[0]
- obj['name'] = vrfName[:-1]
- obj['rd'] = list_of_words[list_of_words.index('RD') + 1]
- start = False
- obj['interfaces'] = []
- for intName in list_of_words:
- if 'Interfaces' in intName:
- start = True
- if start is True:
- if '!' not in intName and 'Interfaces' not in intName:
- obj['interfaces'].append(intName.strip().lower())
- objs.append(obj)
- else:
- module.fail_json(msg='Could not fetch VRF details from device')
- return objs
-
-
-def map_params_to_obj(module):
- obj = []
- aggregate = module.params.get('aggregate')
- if aggregate:
- for item in aggregate:
- for key in item:
- if item.get(key) is None:
- item[key] = module.params[key]
-
- if item.get('interfaces'):
- item['interfaces'] = [intf.replace(" ", "").lower() for intf in item.get('interfaces') if intf]
-
- if item.get('associated_interfaces'):
- item['associated_interfaces'] = [intf.replace(" ", "").lower() for intf in item.get('associated_interfaces') if intf]
-
- obj.append(item.copy())
- else:
- obj.append({
- 'name': module.params['name'],
- 'state': module.params['state'],
- 'rd': module.params['rd'],
- 'interfaces': [intf.replace(" ", "").lower() for intf in module.params['interfaces']] if module.params['interfaces'] else [],
- 'associated_interfaces': [intf.replace(" ", "").lower() for intf in
- module.params['associated_interfaces']] if module.params['associated_interfaces'] else []
-
- })
-
- return obj
-
-
-def check_declarative_intent_params(want, module, result):
- have = None
- is_delay = False
-
- for w in want:
- if w.get('associated_interfaces') is None:
- continue
-
- if result['changed'] and not is_delay:
- time.sleep(module.params['delay'])
- is_delay = True
-
- if have is None:
- have = map_config_to_obj(module)
-
- for i in w['associated_interfaces']:
- obj_in_have = search_obj_in_list(w['name'], have)
-
- if obj_in_have:
- interfaces = obj_in_have.get('interfaces')
- if interfaces is not None and i not in interfaces:
- module.fail_json(msg="Interface %s not configured on vrf %s" % (i, w['name']))
-
-
-def main():
- """ main entry point for module execution
- """
- element_spec = dict(
- name=dict(),
- interfaces=dict(type='list'),
- associated_interfaces=dict(type='list'),
- delay=dict(default=10, type='int'),
- rd=dict(),
- state=dict(default='present', choices=['present', 'absent'])
- )
-
- aggregate_spec = deepcopy(element_spec)
-
- # remove default in aggregate spec, to handle common arguments
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec),
- purge=dict(default=False, type='bool')
- )
-
- argument_spec.update(element_spec)
-
- required_one_of = [['name', 'aggregate']]
- mutually_exclusive = [['name', 'aggregate']]
- module = AnsibleModule(argument_spec=argument_spec,
- required_one_of=required_one_of,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
-
- warnings = list()
- check_args(module, warnings)
-
- result = {'changed': False}
-
- if warnings:
- result['warnings'] = warnings
-
- want = map_params_to_obj(module)
- for w in want:
- name = w['name']
- name = name.lower()
- if is_switchport(name, module):
- module.fail_json(msg='Ensure interface is configured to be a L3'
- '\nport first before using this module. You can use'
- '\nthe cnos_interface module for this.')
- have = map_config_to_obj(module)
-
- commands = map_obj_to_commands((want, have), module)
- result['commands'] = commands
-
- if commands:
- if not module.check_mode:
- load_config(module, commands)
- result['changed'] = True
- check_declarative_intent_params(want, module, result)
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/cumulus/nclu.py b/plugins/modules/network/cumulus/nclu.py
deleted file mode 100644
index 85a1af6f89..0000000000
--- a/plugins/modules/network/cumulus/nclu.py
+++ /dev/null
@@ -1,254 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2016-2018, Cumulus Networks
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: nclu
-author: "Cumulus Networks (@isharacomix)"
-short_description: Configure network interfaces using NCLU
-description:
- - Interface to the Network Command Line Utility, developed to make it easier
- to configure operating systems running ifupdown2 and Quagga, such as
- Cumulus Linux. Command documentation is available at
- U(https://docs.cumulusnetworks.com/cumulus-linux/System-Configuration/Network-Command-Line-Utility-NCLU/)
-options:
- commands:
- description:
- - A list of strings containing the net commands to run. Mutually
- exclusive with I(template).
- template:
- description:
- - A single, multi-line string with jinja2 formatting. This string
- will be broken by lines, and each line will be run through net.
- Mutually exclusive with I(commands).
- commit:
- description:
- - When true, performs a 'net commit' at the end of the block.
- Mutually exclusive with I(atomic).
- default: false
- type: bool
- abort:
- description:
- - Boolean. When true, perform a 'net abort' before the block.
- This cleans out any uncommitted changes in the buffer.
- Mutually exclusive with I(atomic).
- default: false
- type: bool
- atomic:
- description:
- - When true, equivalent to both I(commit) and I(abort) being true.
- Mutually exclusive with I(commit) and I(atomic).
- default: false
- type: bool
- description:
- description:
- - Commit description that will be recorded to the commit log if
- I(commit) or I(atomic) are true.
- default: "Ansible-originated commit"
-'''
-
-EXAMPLES = '''
-
-- name: Add two interfaces without committing any changes
- nclu:
- commands:
- - add int swp1
- - add int swp2
-
-- name: Modify hostname to Cumulus-1 and commit the change
- nclu:
- commands:
- - add hostname Cumulus-1
- commit: true
-
-- name: Add 48 interfaces and commit the change.
- nclu:
- template: |
- {% for iface in range(1,49) %}
- add int swp{{iface}}
- {% endfor %}
- commit: true
- description: "Ansible - add swps1-48"
-
-- name: Fetch Status Of Interface
- nclu:
- commands:
- - show interface swp1
- register: output
-
-- name: Print Status Of Interface
- debug:
- var: output
-
-- name: Fetch Details From All Interfaces In JSON Format
- nclu:
- commands:
- - show interface json
- register: output
-
-- name: Print Interface Details
- debug:
- var: output["msg"]
-
-- name: Atomically add an interface
- nclu:
- commands:
- - add int swp1
- atomic: true
- description: "Ansible - add swp1"
-
-- name: Remove IP address from interface swp1
- nclu:
- commands:
- - del int swp1 ip address 1.1.1.1/24
-
-- name: Configure BGP AS and add 2 EBGP neighbors using BGP Unnumbered
- nclu:
- commands:
- - add bgp autonomous-system 65000
- - add bgp neighbor swp51 interface remote-as external
- - add bgp neighbor swp52 interface remote-as external
- commit: true
-
-- name: Configure BGP AS and Add 2 EBGP neighbors Using BGP Unnumbered via Template
- nclu:
- template: |
- {% for neighbor in range(51,53) %}
- add bgp neighbor swp{{neighbor}} interface remote-as external
- add bgp autonomous-system 65000
- {% endfor %}
- atomic: true
-
-- name: Check BGP Status
- nclu:
- commands:
- - show bgp summary json
- register: output
-
-- name: Print BGP Status In JSON
- debug:
- var: output["msg"]
-'''
-
-RETURN = '''
-changed:
- description: whether the interface was changed
- returned: changed
- type: bool
- sample: True
-msg:
- description: human-readable report of success or failure
- returned: always
- type: str
- sample: "interface bond0 config updated"
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-
-
-def command_helper(module, command, errmsg=None):
- """Run a command, catch any nclu errors"""
- (_rc, output, _err) = module.run_command("/usr/bin/net %s" % command)
- if _rc or 'ERROR' in output or 'ERROR' in _err:
- module.fail_json(msg=errmsg or output)
- return str(output)
-
-
-def check_pending(module):
- """Check the pending diff of the nclu buffer."""
- pending = command_helper(module, "pending", "Error in pending config. You may want to view `net pending` on this target.")
-
- delimeter1 = "net add/del commands since the last 'net commit'"
- color1 = '\x1b[94m'
- if delimeter1 in pending:
- pending = pending.split(delimeter1)[0]
- pending = pending.replace(color1, '')
- return pending.strip()
-
-
-def run_nclu(module, command_list, command_string, commit, atomic, abort, description):
- _changed = False
-
- commands = []
- if command_list:
- commands = command_list
- elif command_string:
- commands = command_string.splitlines()
-
- do_commit = False
- do_abort = abort
- if commit or atomic:
- do_commit = True
- if atomic:
- do_abort = True
-
- if do_abort:
- command_helper(module, "abort")
-
- # First, look at the staged commands.
- before = check_pending(module)
- # Run all of the net commands
- output_lines = []
- for line in commands:
- if line.strip():
- output_lines += [command_helper(module, line.strip(), "Failed on line %s" % line)]
- output = "\n".join(output_lines)
-
- # If pending changes changed, report a change.
- after = check_pending(module)
- if before == after:
- _changed = False
- else:
- _changed = True
-
- # Do the commit.
- if do_commit:
- result = command_helper(module, "commit description '%s'" % description)
- if "commit ignored" in result:
- _changed = False
- command_helper(module, "abort")
- elif command_helper(module, "show commit last") == "":
- _changed = False
-
- return _changed, output
-
-
-def main(testing=False):
- module = AnsibleModule(argument_spec=dict(
- commands=dict(required=False, type='list'),
- template=dict(required=False, type='str'),
- description=dict(required=False, type='str', default="Ansible-originated commit"),
- abort=dict(required=False, type='bool', default=False),
- commit=dict(required=False, type='bool', default=False),
- atomic=dict(required=False, type='bool', default=False)),
- mutually_exclusive=[('commands', 'template'),
- ('commit', 'atomic'),
- ('abort', 'atomic')]
- )
- command_list = module.params.get('commands', None)
- command_string = module.params.get('template', None)
- commit = module.params.get('commit')
- atomic = module.params.get('atomic')
- abort = module.params.get('abort')
- description = module.params.get('description')
-
- _changed, output = run_nclu(module, command_list, command_string, commit, atomic, abort, description)
- if not testing:
- module.exit_json(changed=_changed, msg=output)
- elif testing:
- return {"changed": _changed, "msg": output}
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/edgeos/edgeos_command.py b/plugins/modules/network/edgeos/edgeos_command.py
deleted file mode 100644
index 944be74108..0000000000
--- a/plugins/modules/network/edgeos/edgeos_command.py
+++ /dev/null
@@ -1,176 +0,0 @@
-#!/usr/bin/python
-
-# Copyright: (c) 2018, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
-module: edgeos_command
-author:
- - Chad Norgan (@beardymcbeards)
- - Sam Doran (@samdoran)
-short_description: Run one or more commands on EdgeOS devices
-description:
- - This command module allows running one or more commands on a remote
- device running EdgeOS, such as the Ubiquiti EdgeRouter.
- - This module does not support running commands in configuration mode.
- - Certain C(show) commands in EdgeOS produce many lines of output and
- use a custom pager that can cause this module to hang. If the
- value of the environment variable C(ANSIBLE_EDGEOS_TERMINAL_LENGTH)
- is not set, the default number of 10000 is used.
- - "This is a network module and requires C(connection: network_cli)
- in order to work properly."
- - For more information please see the L(Network Guide,../network/getting_started/index.html).
-options:
- commands:
- description:
- - The commands or ordered set of commands that should be run against the
- remote device. The output of the command is returned to the playbook.
- If the C(wait_for) argument is provided, the module is not returned
- until the condition is met or the number of retries is exceeded.
- required: True
- wait_for:
- description:
- - Causes the task to wait for a specific condition to be met before
- moving forward. If the condition is not met before the specified
- number of retries is exceeded, the task will fail.
- required: False
- match:
- description:
- - Used in conjunction with C(wait_for) to create match policy. If set to
- C(all), then all conditions in C(wait_for) must be met. If set to
- C(any), then only one condition must match.
- required: False
- default: 'all'
- choices: ['any', 'all']
- retries:
- description:
- - Number of times a command should be tried before it is considered failed.
- The command is run on the target device and evaluated against the
- C(wait_for) conditionals.
- required: False
- default: 10
- interval:
- description:
- - The number of seconds to wait between C(retries) of the command.
- required: False
- default: 1
-
-notes:
- - Tested against EdgeOS 1.9.7
- - Running C(show system boot-messages all) will cause the module to hang since
- EdgeOS is using a custom pager setting to display the output of that command.
-'''
-
-EXAMPLES = """
-tasks:
- - name: Reboot the device
- edgeos_command:
- commands: reboot now
-
- - name: Show the configuration for eth0 and eth1
- edgeos_command:
- commands: show interfaces ethernet {{ item }}
- loop:
- - eth0
- - eth1
-"""
-
-RETURN = """
-stdout:
- description: The set of responses from the commands
- returned: always apart from low level errors (such as action plugin)
- type: list
- sample: ['...', '...']
-stdout_lines:
- description: The value of stdout split into a list
- returned: always
- type: list
- sample: [['...', '...'], ['...'], ['...']]
-"""
-import time
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import Conditional
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import transform_commands, to_lines
-from ansible_collections.community.general.plugins.module_utils.network.edgeos.edgeos import run_commands
-
-
-def parse_commands(module, warnings):
- commands = transform_commands(module)
-
- if module.check_mode:
- for item in list(commands):
- if not item['command'].startswith('show'):
- warnings.append(
- 'Only show commands are supported when using check mode, not '
- 'executing %s' % item['command']
- )
- commands.remove(item)
-
- return commands
-
-
-def main():
- spec = dict(
- commands=dict(type='list', required=True),
- wait_for=dict(type='list'),
- match=dict(default='all', choices=['all', 'any']),
- retries=dict(default=10, type='int'),
- interval=dict(default=1, type='int')
- )
-
- module = AnsibleModule(argument_spec=spec, supports_check_mode=True)
-
- warnings = list()
- result = {'changed': False, 'warnings': warnings}
- commands = parse_commands(module, warnings)
- wait_for = module.params['wait_for'] or list()
-
- try:
- conditionals = [Conditional(c) for c in wait_for]
- except AttributeError as exc:
- module.fail_json(msg=to_text(exc))
-
- retries = module.params['retries']
- interval = module.params['interval']
- match = module.params['match']
-
- while retries > 0:
- responses = run_commands(module, commands)
-
- for item in list(conditionals):
- if item(responses):
- if match == 'any':
- conditionals = list()
- break
- conditionals.remove(item)
-
- if not conditionals:
- break
-
- time.sleep(interval)
- retries -= 1
-
- if conditionals:
- failed_conditions = [item.raw for item in conditionals]
- msg = 'One or more conditional statements have not been satisfied'
- module.fail_json(msg=msg, failed_conditions=failed_conditions)
-
- result.update({
- 'stdout': responses,
- 'stdout_lines': list(to_lines(responses)),
- })
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/edgeos/edgeos_config.py b/plugins/modules/network/edgeos/edgeos_config.py
deleted file mode 100644
index cc3b4f17aa..0000000000
--- a/plugins/modules/network/edgeos/edgeos_config.py
+++ /dev/null
@@ -1,317 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: edgeos_config
-author:
- - "Nathaniel Case (@Qalthos)"
- - "Sam Doran (@samdoran)"
-short_description: Manage EdgeOS configuration on remote device
-description:
- - This module provides configuration file management of EdgeOS
- devices. It provides arguments for managing both the
- configuration file and state of the active configuration. All
- configuration statements are based on `set` and `delete` commands
- in the device configuration.
- - "This is a network module and requires the C(connection: network_cli) in order
- to work properly."
- - For more information please see the L(Network Guide,../network/getting_started/index.html).
-notes:
- - Tested against EdgeOS 1.9.7
- - Setting C(ANSIBLE_PERSISTENT_COMMAND_TIMEOUT) to 30 is recommended since
- the save command can take longer than the default of 10 seconds on
- some EdgeOS hardware.
-options:
- lines:
- description:
- - The ordered set of configuration lines to be managed and
- compared with the existing configuration on the remote
- device.
- src:
- description:
- - The C(src) argument specifies the path to the source config
- file to load. The source config file can either be in
- bracket format or set format. The source file can include
- Jinja2 template variables.
- match:
- description:
- - The C(match) argument controls the method used to match
- against the current active configuration. By default, the
- desired config is matched against the active config and the
- deltas are loaded. If the C(match) argument is set to C(none)
- the active configuration is ignored and the configuration is
- always loaded.
- default: line
- choices: ['line', 'none']
- backup:
- description:
- - The C(backup) argument will backup the current device's active
- configuration to the Ansible control host prior to making any
- changes. If the C(backup_options) value is not given, the backup
- file will be located in the backup folder in the playbook root
- directory or role root directory if the playbook is part of an
- ansible role. If the directory does not exist, it is created.
- type: bool
- default: 'no'
- comment:
- description:
- - Allows a commit description to be specified to be included
- when the configuration is committed. If the configuration is
- not changed or committed, this argument is ignored.
- default: 'configured by edgeos_config'
- config:
- description:
- - The C(config) argument specifies the base configuration to use
- to compare against the desired configuration. If this value
- is not specified, the module will automatically retrieve the
- current active configuration from the remote device.
- save:
- description:
- - The C(save) argument controls whether or not changes made
- to the active configuration are saved to disk. This is
- independent of committing the config. When set to C(True), the
- active configuration is saved.
- type: bool
- default: 'no'
- backup_options:
- description:
- - This is a dict object containing configurable options related to backup file path.
- The value of this option is read only when C(backup) is set to I(yes), if C(backup) is set
- to I(no) this option will be silently ignored.
- suboptions:
- filename:
- description:
- - The filename to be used to store the backup configuration. If the filename
- is not given it will be generated based on the hostname, current time and date
- in format defined by _config.@
- dir_path:
- description:
- - This option provides the path ending with directory name in which the backup
- configuration file will be stored. If the directory does not exist it will be first
- created and the filename is either the value of C(filename) or default filename
- as described in C(filename) options description. If the path value is not given
- in that case a I(backup) directory will be created in the current working directory
- and backup configuration will be copied in C(filename) within I(backup) directory.
- type: path
- type: dict
-'''
-
-EXAMPLES = """
-- name: configure the remote device
- edgeos_config:
- lines:
- - set system host-name {{ inventory_hostname }}
- - set service lldp
- - delete service dhcp-server
-
-- name: backup and load from file
- edgeos_config:
- src: edgeos.cfg
- backup: yes
-
-- name: configurable backup path
- edgeos_config:
- src: edgeos.cfg
- backup: yes
- backup_options:
- filename: backup.cfg
- dir_path: /home/user
-"""
-
-RETURN = """
-commands:
- description: The list of configuration commands sent to the device
- returned: always
- type: list
- sample: ['...', '...']
-backup_path:
- description: The full path to the backup file
- returned: when backup is yes
- type: str
- sample: /playbooks/ansible/backup/edgeos_config.2016-07-16@22:28:34
-"""
-
-import re
-
-from ansible.module_utils._text import to_native
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig
-from ansible_collections.community.general.plugins.module_utils.network.edgeos.edgeos import load_config, get_config, run_commands
-
-
-DEFAULT_COMMENT = 'configured by edgeos_config'
-
-
-def config_to_commands(config):
- set_format = config.startswith('set') or config.startswith('delete')
- candidate = NetworkConfig(indent=4, contents=config)
- if not set_format:
- candidate = [c.line for c in candidate.items]
- commands = list()
- # this filters out less specific lines
- for item in candidate:
- for index, entry in enumerate(commands):
- if item.startswith(entry):
- del commands[index]
- break
- commands.append(item)
-
- commands = ['set %s' % cmd.replace(' {', '') for cmd in commands]
-
- else:
- commands = to_native(candidate).split('\n')
-
- return commands
-
-
-def get_candidate(module):
- contents = module.params['src'] or module.params['lines']
-
- if module.params['lines']:
- contents = '\n'.join(contents)
-
- return config_to_commands(contents)
-
-
-def check_command(module, command):
- """Tests against a command line to be valid otherwise raise errors
-
- Error on uneven single quote which breaks ansible waiting for further input. Ansible
- will handle even single quote failures correctly.
-
- :param command: the command line from current or new config
- :type command: string
- :raises ValueError:
- * if contains odd number of single quotes
- :return: command string unchanged
- :rtype: string
- """
- if command.count("'") % 2 != 0:
- module.fail_json(msg="Unmatched single (') quote found in command: " + command)
-
- return command
-
-
-def diff_config(module, commands, config):
- config = [to_native(check_command(module, c)) for c in config.splitlines()]
-
- updates = list()
- visited = set()
- delete_commands = [line for line in commands if line.startswith('delete')]
-
- for line in commands:
- item = to_native(check_command(module, line))
-
- if not item.startswith('set') and not item.startswith('delete'):
- raise ValueError('line must start with either `set` or `delete`')
-
- elif item.startswith('set'):
-
- if item not in config:
- updates.append(line)
-
- # If there is a corresponding delete command in the desired config, make sure to append
- # the set command even though it already exists in the running config
- else:
- ditem = re.sub('set', 'delete', item)
- for line in delete_commands:
- if ditem.startswith(line):
- updates.append(item)
-
- elif item.startswith('delete'):
- if not config:
- updates.append(line)
- else:
- item = re.sub(r'delete', 'set', item)
- for entry in config:
- if entry.startswith(item) and line not in visited:
- updates.append(line)
- visited.add(line)
-
- return list(updates)
-
-
-def run(module, result):
- # get the current active config from the node or passed in via
- # the config param
- config = module.params['config'] or get_config(module)
-
- # create the candidate config object from the arguments
- candidate = get_candidate(module)
-
- # create loadable config that includes only the configuration updates
- commands = diff_config(module, candidate, config)
-
- result['commands'] = commands
-
- commit = not module.check_mode
- comment = module.params['comment']
-
- if commands:
- load_config(module, commands, commit=commit, comment=comment)
-
- result['changed'] = True
-
-
-def main():
-
- backup_spec = dict(
- filename=dict(),
- dir_path=dict(type='path')
- )
- spec = dict(
- src=dict(type='path'),
- lines=dict(type='list'),
-
- match=dict(default='line', choices=['line', 'none']),
-
- comment=dict(default=DEFAULT_COMMENT),
-
- config=dict(),
-
- backup=dict(type='bool', default=False),
- backup_options=dict(type='dict', options=backup_spec),
- save=dict(type='bool', default=False),
- )
-
- mutually_exclusive = [('lines', 'src')]
-
- module = AnsibleModule(
- argument_spec=spec,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True
- )
-
- warnings = list()
-
- result = dict(changed=False, warnings=warnings)
-
- if module.params['backup']:
- result['__backup__'] = get_config(module=module)
-
- if any((module.params['src'], module.params['lines'])):
- run(module, result)
-
- if module.params['save']:
- diff = run_commands(module, commands=['configure', 'compare saved'])[1]
- if diff != '[edit]':
- run_commands(module, commands=['save'])
- result['changed'] = True
- run_commands(module, commands=['exit'])
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/edgeos/edgeos_facts.py b/plugins/modules/network/edgeos/edgeos_facts.py
deleted file mode 100644
index 104061829a..0000000000
--- a/plugins/modules/network/edgeos/edgeos_facts.py
+++ /dev/null
@@ -1,310 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: edgeos_facts
-author:
- - Nathaniel Case (@Qalthos)
- - Sam Doran (@samdoran)
-short_description: Collect facts from remote devices running EdgeOS
-description:
- - Collects a base set of device facts from a remote device that
- is running EdgeOS. This module prepends all of the
- base network fact keys with U(ansible_net_). The facts
- module will always collect a base set of facts from the device
- and can enable or disable collection of additional facts.
-notes:
- - Tested against EdgeOS 1.9.7
-options:
- gather_subset:
- description:
- - When supplied, this argument will restrict the facts collected
- to a given subset. Possible values for this argument include
- all, default, config, and neighbors. Can specify a list of
- values to include a larger subset. Values can also be used
- with an initial C(M(!)) to specify that a specific subset should
- not be collected.
- required: false
- default: "!config"
-'''
-
-EXAMPLES = """
-- name: collect all facts from the device
- edgeos_facts:
- gather_subset: all
-
-- name: collect only the config and default facts
- edgeos_facts:
- gather_subset: config
-
-- name: collect everything exception the config
- edgeos_facts:
- gather_subset: "!config"
-"""
-
-RETURN = """
-ansible_net_config:
- description: The running-config from the device
- returned: when config is configured
- type: str
-ansible_net_commits:
- description: The set of available configuration revisions
- returned: when present
- type: list
-ansible_net_hostname:
- description: The configured system hostname
- returned: always
- type: str
-ansible_net_model:
- description: The device model string
- returned: always
- type: str
-ansible_net_serialnum:
- description: The serial number of the device
- returned: always
- type: str
-ansible_net_version:
- description: The version of the software running
- returned: always
- type: str
-ansible_net_neighbors:
- description: The set of LLDP neighbors
- returned: when interface is configured
- type: list
-ansible_net_gather_subset:
- description: The list of subsets gathered by the module
- returned: always
- type: list
-"""
-
-import re
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.six import iteritems
-from ansible_collections.community.general.plugins.module_utils.network.edgeos.edgeos import run_commands
-
-
-class FactsBase(object):
-
- COMMANDS = frozenset()
-
- def __init__(self, module):
- self.module = module
- self.facts = dict()
- self.responses = None
-
- def populate(self):
- self.responses = run_commands(self.module, list(self.COMMANDS))
-
-
-class Default(FactsBase):
-
- COMMANDS = [
- 'show version',
- 'show host name',
- ]
-
- def populate(self):
- super(Default, self).populate()
- data = self.responses[0]
-
- self.facts['version'] = self.parse_version(data)
- self.facts['serialnum'] = self.parse_serialnum(data)
- self.facts['model'] = self.parse_model(data)
-
- self.facts['hostname'] = self.responses[1]
-
- def parse_version(self, data):
- match = re.search(r'Version:\s*v(\S+)', data)
- if match:
- return match.group(1)
-
- def parse_model(self, data):
- match = re.search(r'HW model:\s*([A-Za-z0-9- ]+)', data)
- if match:
- return match.group(1)
-
- def parse_serialnum(self, data):
- match = re.search(r'HW S/N:\s+(\S+)', data)
- if match:
- return match.group(1)
-
-
-class Config(FactsBase):
-
- COMMANDS = [
- 'show configuration commands',
- 'show system commit',
- ]
-
- def populate(self):
- super(Config, self).populate()
-
- self.facts['config'] = self.responses
-
- commits = self.responses[1]
- entries = list()
- entry = None
-
- for line in commits.split('\n'):
- match = re.match(r'(\d+)\s+(.+)by(.+)via(.+)', line)
- if match:
- if entry:
- entries.append(entry)
-
- entry = dict(revision=match.group(1),
- datetime=match.group(2),
- by=str(match.group(3)).strip(),
- via=str(match.group(4)).strip(),
- comment=None)
- elif entry:
- entry['comment'] = line.strip()
-
- self.facts['commits'] = entries
-
-
-class Neighbors(FactsBase):
-
- COMMANDS = [
- 'show lldp neighbors',
- 'show lldp neighbors detail',
- ]
-
- def populate(self):
- super(Neighbors, self).populate()
-
- all_neighbors = self.responses[0]
- if 'LLDP not configured' not in all_neighbors:
- neighbors = self.parse(
- self.responses[1]
- )
- self.facts['neighbors'] = self.parse_neighbors(neighbors)
-
- def parse(self, data):
- parsed = list()
- values = None
- for line in data.split('\n'):
- if not line:
- continue
- elif line[0] == ' ':
- values += '\n%s' % line
- elif line.startswith('Interface'):
- if values:
- parsed.append(values)
- values = line
- if values:
- parsed.append(values)
- return parsed
-
- def parse_neighbors(self, data):
- facts = dict()
- for item in data:
- interface = self.parse_interface(item)
- host = self.parse_host(item)
- port = self.parse_port(item)
- if interface not in facts:
- facts[interface] = list()
- facts[interface].append(dict(host=host, port=port))
- return facts
-
- def parse_interface(self, data):
- match = re.search(r'^Interface:\s+(\S+),', data)
- return match.group(1)
-
- def parse_host(self, data):
- match = re.search(r'SysName:\s+(.+)$', data, re.M)
- if match:
- return match.group(1)
-
- def parse_port(self, data):
- match = re.search(r'PortDescr:\s+(.+)$', data, re.M)
- if match:
- return match.group(1)
-
-
-FACT_SUBSETS = dict(
- default=Default,
- neighbors=Neighbors,
- config=Config
-)
-
-VALID_SUBSETS = frozenset(FACT_SUBSETS.keys())
-
-
-def main():
- spec = dict(
- gather_subset=dict(default=['!config'], type='list')
- )
-
- module = AnsibleModule(argument_spec=spec,
- supports_check_mode=True)
-
- warnings = list()
-
- gather_subset = module.params['gather_subset']
-
- runable_subsets = set()
- exclude_subsets = set()
-
- for subset in gather_subset:
- if subset == 'all':
- runable_subsets.update(VALID_SUBSETS)
- continue
-
- if subset.startswith('!'):
- subset = subset[1:]
- if subset == 'all':
- exclude_subsets.update(VALID_SUBSETS)
- continue
- exclude = True
- else:
- exclude = False
-
- if subset not in VALID_SUBSETS:
- module.fail_json(msg='Subset must be one of [%s], got %s' %
- (', '.join(VALID_SUBSETS), subset))
-
- if exclude:
- exclude_subsets.add(subset)
- else:
- runable_subsets.add(subset)
-
- if not runable_subsets:
- runable_subsets.update(VALID_SUBSETS)
-
- runable_subsets.difference_update(exclude_subsets)
- runable_subsets.add('default')
-
- facts = dict()
- facts['gather_subset'] = list(runable_subsets)
-
- instances = list()
- for key in runable_subsets:
- instances.append(FACT_SUBSETS[key](module))
-
- for inst in instances:
- inst.populate()
- facts.update(inst.facts)
-
- ansible_facts = dict()
- for key, value in iteritems(facts):
- key = 'ansible_net_%s' % key
- ansible_facts[key] = value
-
- module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/edgeswitch/edgeswitch_facts.py b/plugins/modules/network/edgeswitch/edgeswitch_facts.py
deleted file mode 100644
index 9d6969ecb6..0000000000
--- a/plugins/modules/network/edgeswitch/edgeswitch_facts.py
+++ /dev/null
@@ -1,270 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: edgeswitch_facts
-author: "Frederic Bor (@f-bor)"
-short_description: Collect facts from remote devices running Edgeswitch
-description:
- - Collects a base set of device facts from a remote device that
- is running Ubiquiti Edgeswitch. This module prepends all of the
- base network fact keys with C(ansible_net_). The facts
- module will always collect a base set of facts from the device
- and can enable or disable collection of additional facts.
-notes:
- - Tested against Edgeswitch 1.7.4
-options:
- gather_subset:
- description:
- - When supplied, this argument will restrict the facts collected
- to a given subset. Possible values for this argument include
- all, config, and interfaces. Can specify a list of
- values to include a larger subset. Values can also be used
- with an initial C(M(!)) to specify that a specific subset should
- not be collected.
- required: false
- default: '!config'
-'''
-
-EXAMPLES = """
-# Collect all facts from the device
-- edgeswitch_facts:
- gather_subset: all
-
-# Collect only the config and default facts
-- edgeswitch_facts:
- gather_subset:
- - config
-
-"""
-
-RETURN = """
-ansible_net_gather_subset:
- description: The list of fact subsets collected from the device
- returned: always
- type: list
-
-# default
-ansible_net_model:
- description: The model name returned from the device
- returned: always
- type: str
-ansible_net_serialnum:
- description: The serial number of the remote device
- returned: always
- type: str
-ansible_net_version:
- description: The operating system version running on the remote device
- returned: always
- type: str
-ansible_net_hostname:
- description: The configured hostname of the device
- returned: always
- type: str
-
-# config
-ansible_net_config:
- description: The current active config from the device
- returned: when config is configured
- type: str
-
-# interfaces
-ansible_net_interfaces:
- description: A hash of all interfaces running on the system
- returned: when interfaces is configured
- type: dict
-"""
-import re
-
-from ansible_collections.community.general.plugins.module_utils.network.edgeswitch.edgeswitch import run_commands
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.six import iteritems
-
-
-class FactsBase(object):
-
- COMMANDS = list()
-
- def __init__(self, module):
- self.module = module
- self.facts = dict()
- self.responses = None
-
- def populate(self):
- self.responses = run_commands(self.module, commands=self.COMMANDS, check_rc=False)
-
- def run(self, cmd):
- return run_commands(self.module, commands=cmd, check_rc=False)
-
-
-class Default(FactsBase):
-
- COMMANDS = ['show version', 'show sysinfo']
-
- def populate(self):
- super(Default, self).populate()
- data = self.responses[0]
- if data:
- self.facts['version'] = self.parse_version(data)
- self.facts['serialnum'] = self.parse_serialnum(data)
- self.facts['model'] = self.parse_model(data)
- self.facts['hostname'] = self.parse_hostname(self.responses[1])
-
- def parse_version(self, data):
- match = re.search(r'Software Version\.+ (.*)', data)
- if match:
- return match.group(1)
-
- def parse_hostname(self, data):
- match = re.search(r'System Name\.+ (.*)', data)
- if match:
- return match.group(1)
-
- def parse_model(self, data):
- match = re.search(r'Machine Model\.+ (.*)', data)
- if match:
- return match.group(1)
-
- def parse_serialnum(self, data):
- match = re.search(r'Serial Number\.+ (.*)', data)
- if match:
- return match.group(1)
-
-
-class Config(FactsBase):
-
- COMMANDS = ['show running-config']
-
- def populate(self):
- super(Config, self).populate()
- data = self.responses[0]
- if data:
- self.facts['config'] = data
-
-
-class Interfaces(FactsBase):
-
- COMMANDS = [
- 'show interfaces description',
- 'show interfaces status all'
- ]
-
- def populate(self):
- super(Interfaces, self).populate()
-
- interfaces = {}
-
- data = self.responses[0]
- self.parse_interfaces_description(data, interfaces)
-
- data = self.responses[1]
- self.parse_interfaces_status(data, interfaces)
-
- self.facts['interfaces'] = interfaces
-
- def parse_interfaces_description(self, data, interfaces):
- for line in data.split('\n'):
- match = re.match(r'(\d\/\d+)\s+(\w+)\s+(\w+)', line)
- if match:
- name = match.group(1)
- interface = {}
- interface['operstatus'] = match.group(2)
- interface['lineprotocol'] = match.group(3)
- interface['description'] = line[30:]
- interfaces[name] = interface
-
- def parse_interfaces_status(self, data, interfaces):
- for line in data.split('\n'):
- match = re.match(r'(\d\/\d+)', line)
- if match:
- name = match.group(1)
- interface = interfaces[name]
- interface['physicalstatus'] = line[61:71].strip()
- interface['mediatype'] = line[73:91].strip()
-
-
-FACT_SUBSETS = dict(
- default=Default,
- config=Config,
- interfaces=Interfaces,
-)
-
-VALID_SUBSETS = frozenset(FACT_SUBSETS.keys())
-
-
-def main():
- """main entry point for module execution
- """
- argument_spec = dict(
- gather_subset=dict(default=['!config'], type='list')
- )
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- gather_subset = module.params['gather_subset']
-
- runable_subsets = set()
- exclude_subsets = set()
-
- for subset in gather_subset:
- if subset == 'all':
- runable_subsets.update(VALID_SUBSETS)
- continue
-
- if subset.startswith('!'):
- subset = subset[1:]
- if subset == 'all':
- exclude_subsets.update(VALID_SUBSETS)
- continue
- exclude = True
- else:
- exclude = False
-
- if subset not in VALID_SUBSETS:
- module.fail_json(msg='Bad subset')
-
- if exclude:
- exclude_subsets.add(subset)
- else:
- runable_subsets.add(subset)
-
- if not runable_subsets:
- runable_subsets.update(VALID_SUBSETS)
-
- runable_subsets.difference_update(exclude_subsets)
- runable_subsets.add('default')
-
- facts = dict()
- facts['gather_subset'] = list(runable_subsets)
-
- instances = list()
- for key in runable_subsets:
- instances.append(FACT_SUBSETS[key](module))
-
- for inst in instances:
- inst.populate()
- facts.update(inst.facts)
-
- ansible_facts = dict()
- for key, value in iteritems(facts):
- key = 'ansible_net_%s' % key
- ansible_facts[key] = value
-
- module.exit_json(ansible_facts=ansible_facts)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/edgeswitch/edgeswitch_vlan.py b/plugins/modules/network/edgeswitch/edgeswitch_vlan.py
deleted file mode 100644
index a367ffd3d7..0000000000
--- a/plugins/modules/network/edgeswitch/edgeswitch_vlan.py
+++ /dev/null
@@ -1,497 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2018, Ansible by Red Hat, inc
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: edgeswitch_vlan
-author: "Frederic Bor (@f-bor)"
-short_description: Manage VLANs on Ubiquiti Edgeswitch network devices
-description:
- - This module provides declarative management of VLANs
- on Ubiquiti Edgeswitch network devices.
-notes:
- - Tested against edgeswitch 1.7.4
- - This module use native Ubiquiti vlan syntax and does not support switchport compatibility syntax.
- For clarity, it is strongly advised to not use both syntaxes on the same interface.
- - Edgeswitch does not support deleting or changing name of VLAN 1
- - As auto_tag, auto_untag and auto_exclude are a kind of default setting for all interfaces, they are mutually exclusive
-
-options:
- name:
- description:
- - Name of the VLAN.
- vlan_id:
- description:
- - ID of the VLAN. Range 1-4093.
- tagged_interfaces:
- description:
- - List of interfaces that should accept and transmit tagged frames for the VLAN.
- Accept range of interfaces.
- untagged_interfaces:
- description:
- - List of interfaces that should accept untagged frames and transmit them tagged for the VLAN.
- Accept range of interfaces.
- excluded_interfaces:
- description:
- - List of interfaces that should be excluded of the VLAN.
- Accept range of interfaces.
- auto_tag:
- description:
- - Each of the switch interfaces will be set to accept and transmit
- untagged frames for I(vlan_id) unless defined in I(*_interfaces).
- This is a default setting for all switch interfaces.
- type: bool
- auto_untag:
- description:
- - Each of the switch interfaces will be set to accept untagged frames and
- transmit them tagged for I(vlan_id) unless defined in I(*_interfaces).
- This is a default setting for all switch interfaces.
- type: bool
- auto_exclude:
- description:
- - Each of the switch interfaces will be excluded from I(vlan_id)
- unless defined in I(*_interfaces).
- This is a default setting for all switch interfaces.
- type: bool
- aggregate:
- description: List of VLANs definitions.
- purge:
- description:
- - Purge VLANs not defined in the I(aggregate) parameter.
- default: no
- type: bool
- state:
- description:
- - action on the VLAN configuration.
- default: present
- choices: ['present', 'absent']
-'''
-
-EXAMPLES = """
-- name: Create vlan
- edgeswitch_vlan:
- vlan_id: 100
- name: voice
- action: present
-
-- name: Add interfaces to VLAN
- edgeswitch_vlan:
- vlan_id: 100
- tagged_interfaces:
- - 0/1
- - 0/4-0/6
-
-- name: setup three vlans and delete the rest
- edgeswitch_vlan:
- purge: true
- aggregate:
- - { vlan_id: 1, name: default, auto_untag: true, excluded_interfaces: 0/45-0/48 }
- - { vlan_id: 100, name: voice, auto_tag: true }
- - { vlan_id: 200, name: video, auto_exclude: true, untagged_interfaces: 0/45-0/48, tagged_interfaces: 0/49 }
-
-- name: Delete vlan
- edgeswitch_vlan:
- vlan_id: 100
- state: absent
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always
- type: list
- sample:
- - vlan database
- - vlan 100
- - vlan name 100 "test vlan"
- - exit
- - interface 0/1
- - vlan pvid 50
- - vlan participation include 50,100
- - vlan tagging 100
- - vlan participation exclude 200
- - no vlan tagging 200
-"""
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.edgeswitch.edgeswitch import load_config, run_commands
-from ansible_collections.community.general.plugins.module_utils.network.edgeswitch.edgeswitch import build_aggregate_spec, map_params_to_obj
-from ansible_collections.community.general.plugins.module_utils.network.edgeswitch.edgeswitch_interface import InterfaceConfiguration, merge_interfaces
-
-
-def search_obj_in_list(vlan_id, lst):
- for o in lst:
- if o['vlan_id'] == vlan_id:
- return o
-
-
-def map_vlans_to_commands(want, have, module):
- commands = []
- vlans_added = []
- vlans_removed = []
- vlans_names = []
-
- for w in want:
- vlan_id = w['vlan_id']
- name = w['name']
- state = w['state']
-
- obj_in_have = search_obj_in_list(vlan_id, have)
-
- if state == 'absent':
- if obj_in_have:
- vlans_removed.append(vlan_id)
-
- elif state == 'present':
- if not obj_in_have:
- vlans_added.append(vlan_id)
- if name:
- vlans_names.append('vlan name {0} "{1}"'.format(vlan_id, name))
- else:
- if name:
- if name != obj_in_have['name']:
- vlans_names.append('vlan name {0} "{1}"'.format(vlan_id, name))
-
- if module.params['purge']:
- for h in have:
- obj_in_want = search_obj_in_list(h['vlan_id'], want)
- # you can't delete vlan 1 on Edgeswitch
- if not obj_in_want and h['vlan_id'] != '1':
- vlans_removed.append(h['vlan_id'])
-
- if vlans_removed:
- commands.append('no vlan {0}'.format(','.join(vlans_removed)))
-
- if vlans_added:
- commands.append('vlan {0}'.format(','.join(vlans_added)))
-
- if vlans_names:
- commands.extend(vlans_names)
-
- if commands:
- commands.insert(0, 'vlan database')
- commands.append('exit')
-
- return commands
-
-
-class VlanInterfaceConfiguration(InterfaceConfiguration):
- """ class holding vlan definitions for a given interface
- """
- def __init__(self):
- InterfaceConfiguration.__init__(self)
- self.tagged = []
- self.untagged = []
- self.excluded = []
-
- def set_vlan(self, vlan_id, type):
- try:
- self.tagged.remove(vlan_id)
- except ValueError:
- pass
-
- try:
- self.untagged.remove(vlan_id)
- except ValueError:
- pass
-
- try:
- self.excluded.remove(vlan_id)
- except ValueError:
- pass
-
- f = getattr(self, type)
- f.append(vlan_id)
-
- def gen_commands(self, port, module):
- """ to reduce commands generated by this module
- we group vlans changes to have a max of 5 vlan commands by interface
- """
- exclude = []
- include = []
- tag = []
- untag = []
- pvid = []
-
- for vlan_id in self.excluded:
- if vlan_id not in port['forbidden_vlans']:
- exclude.append(vlan_id)
-
- if vlan_id in port['tagged_vlans']:
- untag.append(vlan_id)
-
- for vlan_id in self.untagged:
- if vlan_id in port['forbidden_vlans'] or vlan_id not in port['untagged_vlans'] and vlan_id not in port['tagged_vlans']:
- include.append(vlan_id)
-
- if vlan_id in port['tagged_vlans']:
- untag.append(vlan_id)
-
- if vlan_id != port['pvid_mode']:
- pvid.append(vlan_id)
-
- for vlan_id in self.tagged:
- if vlan_id not in port['tagged_vlans']:
- tag.append(vlan_id)
- include.append(vlan_id)
-
- if include:
- self.commands.append('vlan participation include {0}'.format(','.join(include)))
-
- if pvid:
- if len(pvid) > 1:
- module.fail_json(msg='{0} can\'t have more than one untagged vlan')
- return
- self.commands.append('vlan pvid {0}'.format(pvid[0]))
-
- if untag:
- self.commands.append('no vlan tagging {0}'.format(','.join(untag)))
-
- if tag:
- self.commands.append('vlan tagging {0}'.format(','.join(tag)))
-
- if exclude:
- self.commands.append('vlan participation exclude {0}'.format(','.join(exclude)))
-
-
-def set_interfaces_vlan(interfaces_param, interfaces, vlan_id, type):
- """ set vlan_id type for each interface in interfaces_param on interfaces
- unrange interfaces_param if needed
- """
- if interfaces_param:
- for i in interfaces_param:
- match = re.search(r'(\d+)\/(\d+)-(\d+)\/(\d+)', i)
- if match:
- group = match.group(1)
- start = int(match.group(2))
- end = int(match.group(4))
- for x in range(start, end + 1):
- key = '{0}/{1}'.format(group, x)
- interfaces[key].set_vlan(vlan_id, type)
- else:
- interfaces[i].set_vlan(vlan_id, type)
-
-
-def map_interfaces_to_commands(want, ports, module):
- commands = list()
-
- # generate a configuration for each interface
- interfaces = {}
- for key, value in ports.items():
- interfaces[key] = VlanInterfaceConfiguration()
-
- for w in want:
- state = w['state']
- if state != 'present':
- continue
-
- auto_tag = w['auto_tag']
- auto_untag = w['auto_untag']
- auto_exclude = w['auto_exclude']
- vlan_id = w['vlan_id']
- tagged_interfaces = w['tagged_interfaces']
- untagged_interfaces = w['untagged_interfaces']
- excluded_interfaces = w['excluded_interfaces']
-
- # set the default type, if any
- for key, value in ports.items():
- if auto_tag:
- interfaces[key].tagged.append(vlan_id)
- elif auto_exclude:
- interfaces[key].excluded.append(vlan_id)
- elif auto_untag:
- interfaces[key].untagged.append(vlan_id)
-
- # set explicit definitions
- set_interfaces_vlan(tagged_interfaces, interfaces, vlan_id, 'tagged')
- set_interfaces_vlan(untagged_interfaces, interfaces, vlan_id, 'untagged')
- set_interfaces_vlan(excluded_interfaces, interfaces, vlan_id, 'excluded')
-
- # generate commands for each interface
- for i, interface in interfaces.items():
- port = ports[i]
- interface.gen_commands(port, module)
-
- # reduce them using range syntax when possible
- interfaces = merge_interfaces(interfaces)
-
- # final output
- for i, interface in interfaces.items():
- if len(interface.commands) > 0:
- commands.append('interface {0}'.format(i))
- commands.extend(interface.commands)
-
- return commands
-
-
-def parse_vlan_brief(vlan_out):
- have = []
- for line in vlan_out.split('\n'):
- obj = re.match(r'(?P\d+)\s+(?P[^\s]+)\s+', line)
- if obj:
- have.append(obj.groupdict())
- return have
-
-
-def unrange(vlans):
- res = []
- for vlan in vlans:
- match = re.match(r'(\d+)-(\d+)', vlan)
- if match:
- start = int(match.group(1))
- end = int(match.group(2))
- for vlan_id in range(start, end + 1):
- res.append(str(vlan_id))
- else:
- res.append(vlan)
- return res
-
-
-def parse_interfaces_switchport(cmd_out):
- ports = dict()
- objs = re.findall(
- r'Port: (\d+\/\d+)\n'
- 'VLAN Membership Mode:(.*)\n'
- 'Access Mode VLAN:(.*)\n'
- 'General Mode PVID:(.*)\n'
- 'General Mode Ingress Filtering:(.*)\n'
- 'General Mode Acceptable Frame Type:(.*)\n'
- 'General Mode Dynamically Added VLANs:(.*)\n'
- 'General Mode Untagged VLANs:(.*)\n'
- 'General Mode Tagged VLANs:(.*)\n'
- 'General Mode Forbidden VLANs:(.*)\n', cmd_out)
- for o in objs:
- port = {
- 'interface': o[0],
- 'pvid_mode': o[3].replace("(default)", "").strip(),
- 'untagged_vlans': unrange(o[7].strip().split(',')),
- 'tagged_vlans': unrange(o[8].strip().split(',')),
- 'forbidden_vlans': unrange(o[9].strip().split(','))
- }
- ports[port['interface']] = port
- return ports
-
-
-def map_ports_to_obj(module):
- return parse_interfaces_switchport(run_commands(module, ['show interfaces switchport'])[0])
-
-
-def map_config_to_obj(module):
- return parse_vlan_brief(run_commands(module, ['show vlan brief'])[0])
-
-
-def check_params(module, want):
- """ Deeper checks on parameters
- """
- def check_parmams_interface(interfaces):
- if interfaces:
- for i in interfaces:
- match = re.search(r'(\d+)\/(\d+)-(\d+)\/(\d+)', i)
- if match:
- if match.group(1) != match.group(3):
- module.fail_json(msg="interface range must be within same group: " + i)
- else:
- match = re.search(r'(\d+)\/(\d+)', i)
- if not match:
- module.fail_json(msg="wrong interface format: " + i)
-
- for w in want:
- auto_tag = w['auto_tag']
- auto_untag = w['auto_untag']
- auto_exclude = w['auto_exclude']
-
- c = 0
- if auto_tag:
- c = c + 1
-
- if auto_untag:
- c = c + 1
-
- if auto_exclude:
- c = c + 1
-
- if c > 1:
- module.fail_json(msg="parameters are mutually exclusive: auto_tag, auto_untag, auto_exclude")
- return
-
- check_parmams_interface(w['tagged_interfaces'])
- check_parmams_interface(w['untagged_interfaces'])
- check_parmams_interface(w['excluded_interfaces'])
- w['vlan_id'] = str(w['vlan_id'])
-
-
-def main():
- """ main entry point for module execution
- """
- element_spec = dict(
- vlan_id=dict(type='int'),
- name=dict(),
- tagged_interfaces=dict(type='list'),
- untagged_interfaces=dict(type='list'),
- excluded_interfaces=dict(type='list'),
- auto_tag=dict(type='bool'),
- auto_exclude=dict(type='bool'),
- auto_untag=dict(type='bool'),
- state=dict(default='present',
- choices=['present', 'absent'])
- )
-
- argument_spec = build_aggregate_spec(
- element_spec,
- ['vlan_id'],
- dict(purge=dict(default=False, type='bool'))
- )
-
- required_one_of = [['vlan_id', 'aggregate']]
- mutually_exclusive = [
- ['vlan_id', 'aggregate'],
- ['auto_tag', 'auto_untag', 'auto_exclude']]
-
- module = AnsibleModule(argument_spec=argument_spec,
- required_one_of=required_one_of,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
- result = {'changed': False}
-
- want = map_params_to_obj(module)
- have = map_config_to_obj(module)
-
- check_params(module, want)
-
- # vlans are not created/deleted in configure mode
- commands = map_vlans_to_commands(want, have, module)
- result['commands'] = commands
-
- if commands:
- if not module.check_mode:
- run_commands(module, commands, check_rc=False)
- result['changed'] = True
-
- ports = map_ports_to_obj(module)
-
- # interfaces vlan are set in configure mode
- commands = map_interfaces_to_commands(want, ports, module)
- result['commands'].extend(commands)
-
- if commands:
- if not module.check_mode:
- load_config(module, commands)
- result['changed'] = True
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/enos/enos_command.py b/plugins/modules/network/enos/enos_command.py
deleted file mode 100644
index 2da3ebe868..0000000000
--- a/plugins/modules/network/enos/enos_command.py
+++ /dev/null
@@ -1,228 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# (C) 2017 Red Hat Inc.
-# Copyright (C) 2017 Lenovo.
-#
-# GNU General Public License v3.0+
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-# Module to execute ENOS Commands on Lenovo Switches.
-# Lenovo Networking
-#
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: enos_command
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Run arbitrary commands on Lenovo ENOS devices
-description:
- - Sends arbitrary commands to an ENOS node and returns the results
- read from the device. The C(enos_command) module includes an
- argument that will cause the module to wait for a specific condition
- before returning or timing out if the condition is not met.
-extends_documentation_fragment:
-- community.general.enos
-
-options:
- commands:
- description:
- - List of commands to send to the remote device over the
- configured provider. The resulting output from the command
- is returned. If the I(wait_for) argument is provided, the
- module is not returned until the condition is satisfied or
- the number of retires as expired.
- required: true
- wait_for:
- description:
- - List of conditions to evaluate against the output of the
- command. The task will wait for each condition to be true
- before moving forward. If the conditional is not true
- within the configured number of retries, the task fails.
- See examples.
- match:
- description:
- - The I(match) argument is used in conjunction with the
- I(wait_for) argument to specify the match policy. Valid
- values are C(all) or C(any). If the value is set to C(all)
- then all conditionals in the wait_for must be satisfied. If
- the value is set to C(any) then only one of the values must be
- satisfied.
- default: all
- choices: ['any', 'all']
- retries:
- description:
- - Specifies the number of retries a command should by tried
- before it is considered failed. The command is run on the
- target device every retry and evaluated against the
- I(wait_for) conditions.
- default: 10
- interval:
- description:
- - Configures the interval in seconds to wait between retries
- of the command. If the command does not pass the specified
- conditions, the interval indicates how long to wait before
- trying the command again.
- default: 1
-'''
-
-EXAMPLES = """
-# Note: examples below use the following provider dict to handle
-# transport and authentication to the node.
----
-vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: 22
- username: admin
- password: admin
- timeout: 30
-
----
-- name: test contains operator
- enos_command:
- commands:
- - show version
- - show system memory
- wait_for:
- - "result[0] contains 'Lenovo'"
- - "result[1] contains 'MemFree'"
- provider: "{{ cli }}"
- register: result
-
-- assert:
- that:
- - "result.changed == false"
- - "result.stdout is defined"
-
-- name: get output for single command
- enos_command:
- commands: ['show version']
- provider: "{{ cli }}"
- register: result
-
-- assert:
- that:
- - "result.changed == false"
- - "result.stdout is defined"
-
-- name: get output for multiple commands
- enos_command:
- commands:
- - show version
- - show interface information
- provider: "{{ cli }}"
- register: result
-
-- assert:
- that:
- - "result.changed == false"
- - "result.stdout is defined"
- - "result.stdout | length == 2"
-"""
-
-RETURN = """
-stdout:
- description: the set of responses from the commands
- returned: always
- type: list
- sample: ['...', '...']
-stdout_lines:
- description: The value of stdout split into a list
- returned: always
- type: list
- sample: [['...', '...'], ['...'], ['...']]
-failed_conditions:
- description: the conditionals that failed
- returned: failed
- type: list
- sample: ['...', '...']
-"""
-
-import time
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.enos.enos import run_commands, check_args
-from ansible_collections.community.general.plugins.module_utils.network.enos.enos import enos_argument_spec
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import Conditional
-from ansible.module_utils.six import string_types
-
-
-def to_lines(stdout):
- for item in stdout:
- if isinstance(item, string_types):
- item = str(item).split('\n')
- yield item
-
-
-def main():
- spec = dict(
- # { command: , prompt: , response: }
- commands=dict(type='list', required=True),
-
- wait_for=dict(type='list'),
- match=dict(default='all', choices=['all', 'any']),
-
- retries=dict(default=10, type='int'),
- interval=dict(default=1, type='int')
- )
-
- spec.update(enos_argument_spec)
-
- module = AnsibleModule(argument_spec=spec, supports_check_mode=True)
- result = {'changed': False}
-
- wait_for = module.params['wait_for'] or list()
- conditionals = [Conditional(c) for c in wait_for]
-
- commands = module.params['commands']
- retries = module.params['retries']
- interval = module.params['interval']
- match = module.params['match']
-
- while retries > 0:
- responses = run_commands(module, commands)
-
- for item in list(conditionals):
- if item(responses):
- if match == 'any':
- conditionals = list()
- break
- conditionals.remove(item)
-
- if not conditionals:
- break
-
- time.sleep(interval)
- retries -= 1
-
- if conditionals:
- failed_conditions = [item.raw for item in conditionals]
- msg = 'One or more conditional statements have not been satisfied'
- module.fail_json(msg=msg, failed_conditions=failed_conditions)
-
- result.update({
- 'changed': False,
- 'stdout': responses,
- 'stdout_lines': list(to_lines(responses))
- })
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/enos/enos_config.py b/plugins/modules/network/enos/enos_config.py
deleted file mode 100644
index 3aecf6b7c5..0000000000
--- a/plugins/modules/network/enos/enos_config.py
+++ /dev/null
@@ -1,310 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# (C) 2017 Red Hat Inc.
-# Copyright (C) 2017 Lenovo.
-#
-# GNU General Public License v3.0+
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-# Module to configure Lenovo Switches.
-# Lenovo Networking
-#
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: enos_config
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Manage Lenovo ENOS configuration sections
-description:
- - Lenovo ENOS configurations use a simple block indent file syntax
- for segmenting configuration into sections. This module provides
- an implementation for working with ENOS configuration sections in
- a deterministic way.
-extends_documentation_fragment:
-- community.general.enos
-
-notes:
- - Tested against ENOS 8.4.1
-options:
- lines:
- description:
- - The ordered set of commands that should be configured in the
- section. The commands must be the exact same commands as found
- in the device running-config. Be sure to note the configuration
- command syntax as some commands are automatically modified by the
- device config parser.
- aliases: ['commands']
- parents:
- description:
- - The ordered set of parents that uniquely identify the section
- the commands should be checked against. If the parents argument
- is omitted, the commands are checked against the set of top
- level or global commands.
- src:
- description:
- - Specifies the source path to the file that contains the configuration
- or configuration template to load. The path to the source file can
- either be the full path on the Ansible control host or a relative
- path from the playbook or role root directory. This argument is
- mutually exclusive with I(lines), I(parents).
- before:
- description:
- - The ordered set of commands to push on to the command stack if
- a change needs to be made. This allows the playbook designer
- the opportunity to perform configuration commands prior to pushing
- any changes without affecting how the set of commands are matched
- against the system.
- after:
- description:
- - The ordered set of commands to append to the end of the command
- stack if a change needs to be made. Just like with I(before) this
- allows the playbook designer to append a set of commands to be
- executed after the command set.
- match:
- description:
- - Instructs the module on the way to perform the matching of
- the set of commands against the current device config. If
- match is set to I(line), commands are matched line by line. If
- match is set to I(strict), command lines are matched with respect
- to position. If match is set to I(exact), command lines
- must be an equal match. Finally, if match is set to I(none), the
- module will not attempt to compare the source configuration with
- the running configuration on the remote device.
- default: line
- choices: ['line', 'strict', 'exact', 'none']
- replace:
- description:
- - Instructs the module on the way to perform the configuration
- on the device. If the replace argument is set to I(line) then
- the modified lines are pushed to the device in configuration
- mode. If the replace argument is set to I(block) then the entire
- command block is pushed to the device in configuration mode if any
- line is not correct.
- default: line
- choices: ['line', 'block', 'config']
- config:
- description:
- - The module, by default, will connect to the remote device and
- retrieve the current running-config to use as a base for comparing
- against the contents of source. There are times when it is not
- desirable to have the task get the current running-config for
- every task in a playbook. The I(config) argument allows the
- implementer to pass in the configuration to use as the base
- config for comparison.
- backup:
- description:
- - This argument will cause the module to create a full backup of
- the current C(running-config) from the remote device before any
- changes are made. If the C(backup_options) value is not given,
- the backup file is written to the C(backup) folder in the playbook
- root directory. If the directory does not exist, it is created.
- type: bool
- default: 'no'
- comment:
- description:
- - Allows a commit description to be specified to be included
- when the configuration is committed. If the configuration is
- not changed or committed, this argument is ignored.
- default: 'configured by enos_config'
- admin:
- description:
- - Enters into administration configuration mode for making config
- changes to the device.
- type: bool
- default: 'no'
- backup_options:
- description:
- - This is a dict object containing configurable options related to backup file path.
- The value of this option is read only when C(backup) is set to I(yes), if C(backup) is set
- to I(no) this option will be silently ignored.
- suboptions:
- filename:
- description:
- - The filename to be used to store the backup configuration. If the filename
- is not given it will be generated based on the hostname, current time and date
- in format defined by _config.@
- dir_path:
- description:
- - This option provides the path ending with directory name in which the backup
- configuration file will be stored. If the directory does not exist it will be first
- created and the filename is either the value of C(filename) or default filename
- as described in C(filename) options description. If the path value is not given
- in that case a I(backup) directory will be created in the current working directory
- and backup configuration will be copied in C(filename) within I(backup) directory.
- type: path
- type: dict
-'''
-
-EXAMPLES = """
-- name: configure top level configuration
- enos_config:
- "lines: hostname {{ inventory_hostname }}"
-
-- name: configure interface settings
- enos_config:
- lines:
- - enable
- - ip ospf enable
- parents: interface ip 13
-
-- name: load a config from disk and replace the current config
- enos_config:
- src: config.cfg
- backup: yes
-
-- name: configurable backup path
- enos_config:
- src: config.cfg
- backup: yes
- backup_options:
- filename: backup.cfg
- dir_path: /home/user
-"""
-
-RETURN = """
-updates:
- description: The set of commands that will be pushed to the remote device
- returned: Only when lines is specified.
- type: list
- sample: ['...', '...']
-backup_path:
- description: The full path to the backup file
- returned: when backup is yes
- type: str
- sample: /playbooks/ansible/backup/enos01.2016-07-16@22:28:34
-"""
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.enos.enos import load_config, get_config
-from ansible_collections.community.general.plugins.module_utils.network.enos.enos import enos_argument_spec
-from ansible_collections.community.general.plugins.module_utils.network.enos.enos import check_args
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, dumps
-
-
-DEFAULT_COMMIT_COMMENT = 'configured by enos_config'
-
-
-def get_running_config(module):
- contents = module.params['config']
- if not contents:
- contents = get_config(module)
- return NetworkConfig(indent=1, contents=contents)
-
-
-def get_candidate(module):
- candidate = NetworkConfig(indent=1)
- if module.params['src']:
- candidate.load(module.params['src'])
- elif module.params['lines']:
- parents = module.params['parents'] or list()
- candidate.add(module.params['lines'], parents=parents)
- return candidate
-
-
-def run(module, result):
- match = module.params['match']
- replace = module.params['replace']
- replace_config = replace == 'config'
- path = module.params['parents']
- comment = module.params['comment']
- admin = module.params['admin']
- check_mode = module.check_mode
-
- candidate = get_candidate(module)
-
- if match != 'none' and replace != 'config':
- contents = get_running_config(module)
- configobj = NetworkConfig(contents=contents, indent=1)
- commands = candidate.difference(configobj, path=path, match=match,
- replace=replace)
- else:
- commands = candidate.items
-
- if commands:
- commands = dumps(commands, 'commands').split('\n')
-
- if any((module.params['lines'], module.params['src'])):
- if module.params['before']:
- commands[:0] = module.params['before']
-
- if module.params['after']:
- commands.extend(module.params['after'])
-
- result['commands'] = commands
-
- diff = load_config(module, commands)
- if diff:
- result['diff'] = dict(prepared=diff)
- result['changed'] = True
-
-
-def main():
- """main entry point for module execution
- """
- backup_spec = dict(
- filename=dict(),
- dir_path=dict(type='path')
- )
- argument_spec = dict(
- src=dict(type='path'),
-
- lines=dict(aliases=['commands'], type='list'),
- parents=dict(type='list'),
-
- before=dict(type='list'),
- after=dict(type='list'),
-
- match=dict(default='line', choices=['line', 'strict', 'exact', 'none']),
- replace=dict(default='line', choices=['line', 'block', 'config']),
-
- config=dict(),
- backup=dict(type='bool', default=False),
- backup_options=dict(type='dict', options=backup_spec),
- comment=dict(default=DEFAULT_COMMIT_COMMENT),
- admin=dict(type='bool', default=False)
- )
-
- argument_spec.update(enos_argument_spec)
-
- mutually_exclusive = [('lines', 'src'),
- ('parents', 'src')]
-
- required_if = [('match', 'strict', ['lines']),
- ('match', 'exact', ['lines']),
- ('replace', 'block', ['lines']),
- ('replace', 'config', ['src'])]
-
- module = AnsibleModule(argument_spec=argument_spec,
- mutually_exclusive=mutually_exclusive,
- required_if=required_if,
- supports_check_mode=True)
-
- warnings = list()
- check_args(module, warnings)
-
- result = dict(changed=False, warnings=warnings)
-
- if module.params['backup']:
- result['__backup__'] = get_config(module)
-
- run(module, result)
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/enos/enos_facts.py b/plugins/modules/network/enos/enos_facts.py
deleted file mode 100644
index dda2653101..0000000000
--- a/plugins/modules/network/enos/enos_facts.py
+++ /dev/null
@@ -1,507 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# (C) 2017 Red Hat Inc.
-# Copyright (C) 2017 Lenovo.
-#
-# GNU General Public License v3.0+
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-# Module to Collect facts from Lenovo Switches running Lenovo ENOS commands
-# Lenovo Networking
-#
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: enos_facts
-author: "Anil Kumar Muraleedharan (@amuraleedhar)"
-short_description: Collect facts from remote devices running Lenovo ENOS
-description:
- - Collects a base set of device facts from a remote Lenovo device
- running on ENOS. This module prepends all of the
- base network fact keys with C(ansible_net_). The facts
- module will always collect a base set of facts from the device
- and can enable or disable collection of additional facts.
-extends_documentation_fragment:
-- community.general.enos
-
-notes:
- - Tested against ENOS 8.4.1
-options:
- gather_subset:
- description:
- - When supplied, this argument will restrict the facts collected
- to a given subset. Possible values for this argument include
- all, hardware, config, and interfaces. Can specify a list of
- values to include a larger subset. Values can also be used
- with an initial C(M(!)) to specify that a specific subset should
- not be collected.
- required: false
- default: '!config'
-'''
-EXAMPLES = '''
-Tasks: The following are examples of using the module enos_facts.
----
-- name: Test Enos Facts
- enos_facts:
- provider={{ cli }}
-
- vars:
- cli:
- host: "{{ inventory_hostname }}"
- port: 22
- username: admin
- password: admin
- transport: cli
- timeout: 30
- authorize: True
- auth_pass:
-
----
-# Collect all facts from the device
-- enos_facts:
- gather_subset: all
- provider: "{{ cli }}"
-
-# Collect only the config and default facts
-- enos_facts:
- gather_subset:
- - config
- provider: "{{ cli }}"
-
-# Do not collect hardware facts
-- enos_facts:
- gather_subset:
- - "!hardware"
- provider: "{{ cli }}"
-
-'''
-RETURN = '''
- ansible_net_gather_subset:
- description: The list of fact subsets collected from the device
- returned: always
- type: list
-# default
- ansible_net_model:
- description: The model name returned from the Lenovo ENOS device
- returned: always
- type: str
- ansible_net_serialnum:
- description: The serial number of the Lenovo ENOS device
- returned: always
- type: str
- ansible_net_version:
- description: The ENOS operating system version running on the remote device
- returned: always
- type: str
- ansible_net_hostname:
- description: The configured hostname of the device
- returned: always
- type: str
- ansible_net_image:
- description: Indicates the active image for the device
- returned: always
- type: str
-# hardware
- ansible_net_memfree_mb:
- description: The available free memory on the remote device in MB
- returned: when hardware is configured
- type: int
-# config
- ansible_net_config:
- description: The current active config from the device
- returned: when config is configured
- type: str
-# interfaces
- ansible_net_all_ipv4_addresses:
- description: All IPv4 addresses configured on the device
- returned: when interfaces is configured
- type: list
- ansible_net_all_ipv6_addresses:
- description: All IPv6 addresses configured on the device
- returned: when interfaces is configured
- type: list
- ansible_net_interfaces:
- description: A hash of all interfaces running on the system.
- This gives information on description, mac address, mtu, speed,
- duplex and operstatus
- returned: when interfaces is configured
- type: dict
- ansible_net_neighbors:
- description: The list of LLDP neighbors from the remote device
- returned: when interfaces is configured
- type: dict
-'''
-
-import re
-
-from ansible_collections.community.general.plugins.module_utils.network.enos.enos import run_commands, enos_argument_spec, check_args
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.six import iteritems
-from ansible.module_utils.six.moves import zip
-
-
-class FactsBase(object):
-
- COMMANDS = list()
-
- def __init__(self, module):
- self.module = module
- self.facts = dict()
- self.responses = None
- self.PERSISTENT_COMMAND_TIMEOUT = 60
-
- def populate(self):
- self.responses = run_commands(self.module, self.COMMANDS,
- check_rc=False)
-
- def run(self, cmd):
- return run_commands(self.module, cmd, check_rc=False)
-
-
-class Default(FactsBase):
-
- COMMANDS = ['show version', 'show run']
-
- def populate(self):
- super(Default, self).populate()
- data = self.responses[0]
- data_run = self.responses[1]
- if data:
- self.facts['version'] = self.parse_version(data)
- self.facts['serialnum'] = self.parse_serialnum(data)
- self.facts['model'] = self.parse_model(data)
- self.facts['image'] = self.parse_image(data)
- if data_run:
- self.facts['hostname'] = self.parse_hostname(data_run)
-
- def parse_version(self, data):
- match = re.search(r'^Software Version (.*?) ', data, re.M | re.I)
- if match:
- return match.group(1)
-
- def parse_hostname(self, data_run):
- for line in data_run.split('\n'):
- line = line.strip()
- match = re.match(r'hostname (.*?)', line, re.M | re.I)
- if match:
- hosts = line.split()
- hostname = hosts[1].strip('\"')
- return hostname
- return "NA"
-
- def parse_model(self, data):
- match = re.search(r'^Lenovo RackSwitch (\S+)', data, re.M | re.I)
- if match:
- return match.group(1)
-
- def parse_image(self, data):
- match = re.search(r'(.*) image1(.*)', data, re.M | re.I)
- if match:
- return "Image1"
- else:
- return "Image2"
-
- def parse_serialnum(self, data):
- match = re.search(r'^Switch Serial No: (\S+)', data, re.M | re.I)
- if match:
- return match.group(1)
-
-
-class Hardware(FactsBase):
-
- COMMANDS = [
- 'show system memory'
- ]
-
- def populate(self):
- super(Hardware, self).populate()
- data = self.run(['show system memory'])
- data = to_text(data, errors='surrogate_or_strict').strip()
- data = data.replace(r"\n", "\n")
- if data:
- self.facts['memtotal_mb'] = self.parse_memtotal(data)
- self.facts['memfree_mb'] = self.parse_memfree(data)
-
- def parse_memtotal(self, data):
- match = re.search(r'^MemTotal:\s*(.*) kB', data, re.M | re.I)
- if match:
- return int(match.group(1)) / 1024
-
- def parse_memfree(self, data):
- match = re.search(r'^MemFree:\s*(.*) kB', data, re.M | re.I)
- if match:
- return int(match.group(1)) / 1024
-
-
-class Config(FactsBase):
-
- COMMANDS = ['show running-config']
-
- def populate(self):
- super(Config, self).populate()
- data = self.responses[0]
- if data:
- self.facts['config'] = data
-
-
-class Interfaces(FactsBase):
-
- COMMANDS = ['show interface status']
-
- def populate(self):
- super(Interfaces, self).populate()
-
- self.facts['all_ipv4_addresses'] = list()
- self.facts['all_ipv6_addresses'] = list()
-
- data1 = self.run(['show interface status'])
- data1 = to_text(data1, errors='surrogate_or_strict').strip()
- data1 = data1.replace(r"\n", "\n")
- data2 = self.run(['show lldp port'])
- data2 = to_text(data2, errors='surrogate_or_strict').strip()
- data2 = data2.replace(r"\n", "\n")
- lines1 = None
- lines2 = None
- if data1:
- lines1 = self.parse_interfaces(data1)
- if data2:
- lines2 = self.parse_interfaces(data2)
- if lines1 is not None and lines2 is not None:
- self.facts['interfaces'] = self.populate_interfaces(lines1, lines2)
- data3 = self.run(['show lldp remote-device port'])
- data3 = to_text(data3, errors='surrogate_or_strict').strip()
- data3 = data3.replace(r"\n", "\n")
-
- lines3 = None
- if data3:
- lines3 = self.parse_neighbors(data3)
- if lines3 is not None:
- self.facts['neighbors'] = self.populate_neighbors(lines3)
-
- data4 = self.run(['show interface ip'])
- data4 = data4[0].split('\n')
- lines4 = None
- if data4:
- lines4 = self.parse_ipaddresses(data4)
- ipv4_interfaces = self.set_ipv4_interfaces(lines4)
- self.facts['all_ipv4_addresses'] = ipv4_interfaces
- ipv6_interfaces = self.set_ipv6_interfaces(lines4)
- self.facts['all_ipv6_addresses'] = ipv6_interfaces
-
- def parse_ipaddresses(self, data4):
- parsed = list()
- for line in data4:
- if len(line) == 0:
- continue
- else:
- line = line.strip()
- if len(line) == 0:
- continue
- match = re.search(r'IP4', line, re.M | re.I)
- if match:
- key = match.group()
- parsed.append(line)
- match = re.search(r'IP6', line, re.M | re.I)
- if match:
- key = match.group()
- parsed.append(line)
- return parsed
-
- def set_ipv4_interfaces(self, line4):
- ipv4_addresses = list()
- for line in line4:
- ipv4Split = line.split()
- if ipv4Split[1] == "IP4":
- ipv4_addresses.append(ipv4Split[2])
- return ipv4_addresses
-
- def set_ipv6_interfaces(self, line4):
- ipv6_addresses = list()
- for line in line4:
- ipv6Split = line.split()
- if ipv6Split[1] == "IP6":
- ipv6_addresses.append(ipv6Split[2])
- return ipv6_addresses
-
- def populate_neighbors(self, lines3):
- neighbors = dict()
- for line in lines3:
- neighborSplit = line.split("|")
- innerData = dict()
- innerData['Remote Chassis ID'] = neighborSplit[2].strip()
- innerData['Remote Port'] = neighborSplit[3].strip()
- sysName = neighborSplit[4].strip()
- if sysName is not None:
- innerData['Remote System Name'] = neighborSplit[4].strip()
- else:
- innerData['Remote System Name'] = "NA"
- neighbors[neighborSplit[0].strip()] = innerData
- return neighbors
-
- def populate_interfaces(self, lines1, lines2):
- interfaces = dict()
- for line1, line2 in zip(lines1, lines2):
- line = line1 + " " + line2
- intfSplit = line.split()
- innerData = dict()
- innerData['description'] = intfSplit[6].strip()
- innerData['macaddress'] = intfSplit[8].strip()
- innerData['mtu'] = intfSplit[9].strip()
- innerData['speed'] = intfSplit[1].strip()
- innerData['duplex'] = intfSplit[2].strip()
- innerData['operstatus'] = intfSplit[5].strip()
- if("up" not in intfSplit[5].strip()) and ("down" not in intfSplit[5].strip()):
- innerData['description'] = intfSplit[7].strip()
- innerData['macaddress'] = intfSplit[9].strip()
- innerData['mtu'] = intfSplit[10].strip()
- innerData['operstatus'] = intfSplit[6].strip()
- interfaces[intfSplit[0].strip()] = innerData
- return interfaces
-
- def parse_neighbors(self, neighbors):
- parsed = list()
- for line in neighbors.split('\n'):
- if len(line) == 0:
- continue
- else:
- line = line.strip()
- match = re.match(r'^([0-9]+)', line)
- if match:
- key = match.group(1)
- parsed.append(line)
- match = re.match(r'^(INT+)', line)
- if match:
- key = match.group(1)
- parsed.append(line)
- match = re.match(r'^(EXT+)', line)
- if match:
- key = match.group(1)
- parsed.append(line)
- match = re.match(r'^(MGT+)', line)
- if match:
- key = match.group(1)
- parsed.append(line)
- return parsed
-
- def parse_interfaces(self, data):
- parsed = list()
- for line in data.split('\n'):
- if len(line) == 0:
- continue
- else:
- line = line.strip()
- match = re.match(r'^([0-9]+)', line)
- if match:
- key = match.group(1)
- parsed.append(line)
- match = re.match(r'^(INT+)', line)
- if match:
- key = match.group(1)
- parsed.append(line)
- match = re.match(r'^(EXT+)', line)
- if match:
- key = match.group(1)
- parsed.append(line)
- match = re.match(r'^(MGT+)', line)
- if match:
- key = match.group(1)
- parsed.append(line)
- return parsed
-
-
-FACT_SUBSETS = dict(
- default=Default,
- hardware=Hardware,
- interfaces=Interfaces,
- config=Config,
-)
-
-VALID_SUBSETS = frozenset(FACT_SUBSETS.keys())
-
-PERSISTENT_COMMAND_TIMEOUT = 60
-
-
-def main():
- """main entry point for module execution
- """
- argument_spec = dict(
- gather_subset=dict(default=['!config'], type='list')
- )
-
- argument_spec.update(enos_argument_spec)
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- gather_subset = module.params['gather_subset']
-
- runable_subsets = set()
- exclude_subsets = set()
-
- for subset in gather_subset:
- if subset == 'all':
- runable_subsets.update(VALID_SUBSETS)
- continue
-
- if subset.startswith('!'):
- subset = subset[1:]
- if subset == 'all':
- exclude_subsets.update(VALID_SUBSETS)
- continue
- exclude = True
- else:
- exclude = False
-
- if subset not in VALID_SUBSETS:
- module.fail_json(msg='Bad subset')
-
- if exclude:
- exclude_subsets.add(subset)
- else:
- runable_subsets.add(subset)
-
- if not runable_subsets:
- runable_subsets.update(VALID_SUBSETS)
-
- runable_subsets.difference_update(exclude_subsets)
- runable_subsets.add('default')
-
- facts = dict()
- facts['gather_subset'] = list(runable_subsets)
-
- instances = list()
- for key in runable_subsets:
- instances.append(FACT_SUBSETS[key](module))
-
- for inst in instances:
- inst.populate()
- facts.update(inst.facts)
-
- ansible_facts = dict()
- for key, value in iteritems(facts):
- key = 'ansible_net_%s' % key
- ansible_facts[key] = value
-
- warnings = list()
- check_args(module, warnings)
-
- module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/eric_eccli/eric_eccli_command.py b/plugins/modules/network/eric_eccli/eric_eccli_command.py
deleted file mode 100644
index 8b226feee0..0000000000
--- a/plugins/modules/network/eric_eccli/eric_eccli_command.py
+++ /dev/null
@@ -1,213 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2019 Ericsson AB.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = """
----
-module: eric_eccli_command
-author: Ericsson IPOS OAM team (@itercheng)
-short_description: Run commands on remote devices running ERICSSON ECCLI
-description:
- - Sends arbitrary commands to an ERICSSON eccli node and returns the results
- read from the device. This module includes an
- argument that will cause the module to wait for a specific condition
- before returning or timing out if the condition is not met.
- - This module also support running commands in configuration mode
- in raw command style.
-options:
- commands:
- description:
- - List of commands to send to the remote ECCLI device over the
- configured provider. The resulting output from the command
- is returned. If the I(wait_for) argument is provided, the
- module is not returned until the condition is satisfied or
- the number of retries has expired. If a command sent to the
- device requires answering a prompt, it is possible to pass
- a dict containing I(command), I(answer) and I(prompt).
- Common answers are 'y' or "\\r" (carriage return, must be
- double quotes). See examples.
- type: list
- required: true
- wait_for:
- description:
- - List of conditions to evaluate against the output of the
- command. The task will wait for each condition to be true
- before moving forward. If the conditional is not true
- within the configured number of retries, the task fails.
- See examples.
- type: list
- aliases: ['waitfor']
- match:
- description:
- - The I(match) argument is used in conjunction with the
- I(wait_for) argument to specify the match policy. Valid
- values are C(all) or C(any). If the value is set to C(all)
- then all conditionals in the wait_for must be satisfied. If
- the value is set to C(any) then only one of the values must be
- satisfied.
- type: str
- default: all
- choices: ['any', 'all']
- retries:
- description:
- - Specifies the number of retries a command should by tried
- before it is considered failed. The command is run on the
- target device every retry and evaluated against the
- I(wait_for) conditions.
- type: int
- default: 10
- interval:
- description:
- - Configures the interval in seconds to wait between retries
- of the command. If the command does not pass the specified
- conditions, the interval indicates how long to wait before
- trying the command again.
- type: int
- default: 1
-notes:
- - Tested against IPOS 19.3
- - For more information on using Ansible to manage network devices see the :ref:`Ansible Network Guide `
- - For more information on using Ansible to manage Ericsson devices see the Ericsson documents.
- - "Starting with Ansible 2.5 we recommend using C(connection: network_cli)."
- - For more information please see the L(ERIC_ECCLI Platform Options guide,../network/user_guide/platform_eric_eccli.html).
-"""
-
-EXAMPLES = r"""
-tasks:
- - name: run show version on remote devices
- eric_eccli_command:
- commands: show version
-
- - name: run show version and check to see if output contains IPOS
- eric_eccli_command:
- commands: show version
- wait_for: result[0] contains IPOS
-
- - name: run multiple commands on remote nodes
- eric_eccli_command:
- commands:
- - show version
- - show running-config interfaces
-
- - name: run multiple commands and evaluate the output
- eric_eccli_command:
- commands:
- - show version
- - show running-config interfaces
- wait_for:
- - result[0] contains IPOS
- - result[1] contains management
-"""
-
-RETURN = """
-stdout:
- description: The set of responses from the commands
- returned: always apart from low level errors (such as action plugin)
- type: list
- sample: ['...', '...']
-stdout_lines:
- description: The value of stdout split into a list
- returned: always apart from low level errors (such as action plugin)
- type: list
- sample: [['...', '...'], ['...'], ['...']]
-failed_conditions:
- description: The list of conditionals that have failed
- returned: failed
- type: list
- sample: ['...', '...']
-"""
-import re
-import time
-
-from ansible_collections.community.general.plugins.module_utils.network.eric_eccli.eric_eccli import run_commands
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import transform_commands
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import Conditional
-from ansible.module_utils.six import string_types
-
-
-def parse_commands(module, warnings):
- commands = transform_commands(module)
-
- for item in list(commands):
- if module.check_mode:
- if item['command'].startswith('conf'):
- warnings.append(
- 'only non-config commands are supported when using check mode, not '
- 'executing %s' % item['command']
- )
- commands.remove(item)
- return commands
-
-
-def main():
- """main entry point for module execution
- """
- argument_spec = dict(
- commands=dict(type='list', required=True),
-
- wait_for=dict(type='list', aliases=['waitfor']),
- match=dict(default='all', choices=['all', 'any']),
-
- retries=dict(default=10, type='int'),
- interval=dict(default=1, type='int')
- )
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- result = {'changed': False}
-
- warnings = list()
- commands = parse_commands(module, warnings)
- result['warnings'] = warnings
-
- wait_for = module.params['wait_for'] or list()
- conditionals = [Conditional(c) for c in wait_for]
-
- retries = module.params['retries']
- interval = module.params['interval']
- match = module.params['match']
-
- while retries > 0:
- responses = run_commands(module, commands)
-
- for item in list(conditionals):
- if item(responses):
- if match == 'any':
- conditionals = list()
- break
- conditionals.remove(item)
-
- if not conditionals:
- break
-
- time.sleep(interval)
- retries -= 1
-
- if conditionals:
- failed_conditions = [item.raw for item in conditionals]
- msg = 'One or more conditional statements have not been satisfied'
- module.fail_json(msg=msg, failed_conditions=failed_conditions)
-
- result.update({
- 'changed': False,
- 'stdout': responses,
- 'stdout_lines': list()
- })
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/exos/exos_command.py b/plugins/modules/network/exos/exos_command.py
deleted file mode 100644
index 3282c512a7..0000000000
--- a/plugins/modules/network/exos/exos_command.py
+++ /dev/null
@@ -1,220 +0,0 @@
-#!/usr/bin/python
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: exos_command
-author: "Rafael D. Vencioneck (@rdvencioneck)"
-short_description: Run commands on remote devices running Extreme EXOS
-description:
- - Sends arbitrary commands to an Extreme EXOS device and returns the results
- read from the device. This module includes an argument that will cause the
- module to wait for a specific condition before returning or timing out if
- the condition is not met.
- - This module does not support running configuration commands.
- Please use M(exos_config) to configure EXOS devices.
-notes:
- - If a command sent to the device requires answering a prompt, it is possible
- to pass a dict containing I(command), I(answer) and I(prompt). See examples.
-options:
- commands:
- description:
- - List of commands to send to the remote EXOS device over the
- configured provider. The resulting output from the command
- is returned. If the I(wait_for) argument is provided, the
- module is not returned until the condition is satisfied or
- the number of retries has expired.
- required: true
- wait_for:
- description:
- - List of conditions to evaluate against the output of the
- command. The task will wait for each condition to be true
- before moving forward. If the conditional is not true
- within the configured number of retries, the task fails.
- See examples.
- match:
- description:
- - The I(match) argument is used in conjunction with the
- I(wait_for) argument to specify the match policy. Valid
- values are C(all) or C(any). If the value is set to C(all)
- then all conditionals in the wait_for must be satisfied. If
- the value is set to C(any) then only one of the values must be
- satisfied.
- default: all
- choices: ['any', 'all']
- retries:
- description:
- - Specifies the number of retries a command should by tried
- before it is considered failed. The command is run on the
- target device every retry and evaluated against the
- I(wait_for) conditions.
- default: 10
- interval:
- description:
- - Configures the interval in seconds to wait between retries
- of the command. If the command does not pass the specified
- conditions, the interval indicates how long to wait before
- trying the command again.
- default: 1
-'''
-
-EXAMPLES = """
-tasks:
- - name: run show version on remote devices
- exos_command:
- commands: show version
- - name: run show version and check to see if output contains ExtremeXOS
- exos_command:
- commands: show version
- wait_for: result[0] contains ExtremeXOS
- - name: run multiple commands on remote nodes
- exos_command:
- commands:
- - show version
- - show ports no-refresh
- - name: run multiple commands and evaluate the output
- exos_command:
- commands:
- - show version
- - show ports no-refresh
- wait_for:
- - result[0] contains ExtremeXOS
- - result[1] contains 20
- - name: run command that requires answering a prompt
- exos_command:
- commands:
- - command: 'clear license-info'
- prompt: 'Are you sure.*'
- answer: 'Yes'
-"""
-
-RETURN = """
-stdout:
- description: The set of responses from the commands
- returned: always apart from low level errors (such as action plugin)
- type: list
- sample: ['...', '...']
-stdout_lines:
- description: The value of stdout split into a list
- returned: always apart from low level errors (such as action plugin)
- type: list
- sample: [['...', '...'], ['...'], ['...']]
-failed_conditions:
- description: The list of conditionals that have failed
- returned: failed
- type: list
- sample: ['...', '...']
-"""
-import re
-import time
-
-from ansible_collections.community.general.plugins.module_utils.network.exos.exos import run_commands
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ComplexList
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import Conditional
-from ansible.module_utils.six import string_types
-
-
-def to_lines(stdout):
- for item in stdout:
- if isinstance(item, string_types):
- item = str(item).split('\n')
- yield item
-
-
-def parse_commands(module, warnings):
- command = ComplexList(dict(
- command=dict(key=True),
- prompt=dict(),
- answer=dict()
- ), module)
- commands = command(module.params['commands'])
- for item in list(commands):
- command_split = re.match(r'^(\w*)(.*)$', item['command'])
- if module.check_mode and not item['command'].startswith('show'):
- warnings.append(
- 'only show commands are supported when using check mode, not '
- 'executing `%s`' % item['command']
- )
- commands.remove(item)
- elif command_split and command_split.group(1) not in ('check', 'clear', 'debug', 'history',
- 'ls', 'mrinfo', 'mtrace', 'nslookup',
- 'ping', 'rtlookup', 'show', 'traceroute'):
- module.fail_json(
- msg='some commands were not recognized. exos_command can only run read-only'
- 'commands. For configuration commands, please use exos_config instead'
- )
- return commands
-
-
-def main():
- """main entry point for module execution
- """
- argument_spec = dict(
- commands=dict(type='list', required=True),
-
- wait_for=dict(type='list'),
- match=dict(default='all', choices=['all', 'any']),
-
- retries=dict(default=10, type='int'),
- interval=dict(default=1, type='int')
- )
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- result = {'changed': False}
-
- warnings = list()
- commands = parse_commands(module, warnings)
- result['warnings'] = warnings
-
- wait_for = module.params['wait_for'] or list()
- conditionals = [Conditional(c) for c in wait_for]
-
- retries = module.params['retries']
- interval = module.params['interval']
- match = module.params['match']
-
- while retries > 0:
- responses = run_commands(module, commands)
-
- for item in list(conditionals):
- if item(responses):
- if match == 'any':
- conditionals = list()
- break
- conditionals.remove(item)
-
- if not conditionals:
- break
-
- time.sleep(interval)
- retries -= 1
-
- if conditionals:
- failed_conditions = [item.raw for item in conditionals]
- msg = 'One or more conditional statements have not be satisfied'
- module.fail_json(msg=msg, failed_conditions=failed_conditions)
-
- result.update({
- 'changed': False,
- 'stdout': responses,
- 'stdout_lines': list(to_lines(responses))
- })
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/exos/exos_config.py b/plugins/modules/network/exos/exos_config.py
deleted file mode 100644
index d9ab02fd30..0000000000
--- a/plugins/modules/network/exos/exos_config.py
+++ /dev/null
@@ -1,436 +0,0 @@
-#!/usr/bin/python
-
-# Copyright: (c) 2018, Extreme Networks Inc.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: exos_config
-author: "Lance Richardson (@hlrichardson)"
-short_description: Manage Extreme Networks EXOS configuration sections
-description:
- - Extreme EXOS configurations use a simple flat text file syntax.
- This module provides an implementation for working with EXOS
- configuration lines in a deterministic way.
-notes:
- - Tested against EXOS version 22.6.0b19
-options:
- lines:
- description:
- - The ordered set of commands that should be configured in the
- section. The commands must be the exact same commands as found
- in the device running-config. Be sure to note the configuration
- command syntax as some commands are automatically modified by the
- device config parser.
- aliases: ['commands']
- src:
- description:
- - Specifies the source path to the file that contains the configuration
- or configuration template to load. The path to the source file can
- either be the full path on the Ansible control host or a relative
- path from the playbook or role root directory. This argument is mutually
- exclusive with I(lines).
- before:
- description:
- - The ordered set of commands to push on to the command stack if
- a change needs to be made. This allows the playbook designer
- the opportunity to perform configuration commands prior to pushing
- any changes without affecting how the set of commands are matched
- against the system.
- after:
- description:
- - The ordered set of commands to append to the end of the command
- stack if a change needs to be made. Just like with I(before) this
- allows the playbook designer to append a set of commands to be
- executed after the command set.
- match:
- description:
- - Instructs the module on the way to perform the matching of
- the set of commands against the current device config. If
- match is set to I(line), commands are matched line by line. If
- match is set to I(strict), command lines are matched with respect
- to position. If match is set to I(exact), command lines
- must be an equal match. Finally, if match is set to I(none), the
- module will not attempt to compare the source configuration with
- the running configuration on the remote device.
- default: line
- choices: ['line', 'strict', 'exact', 'none']
- replace:
- description:
- - Instructs the module on the way to perform the configuration
- on the device. If the replace argument is set to I(line) then
- the modified lines are pushed to the device in configuration
- mode. If the replace argument is set to I(block) then the entire
- command block is pushed to the device in configuration mode if any
- line is not correct.
- default: line
- choices: ['line', 'block']
- backup:
- description:
- - This argument will cause the module to create a full backup of
- the current C(running-config) from the remote device before any
- changes are made. If the C(backup_options) value is not given,
- the backup file is written to the C(backup) folder in the playbook
- root directory. If the directory does not exist, it is created.
- type: bool
- default: 'no'
- running_config:
- description:
- - The module, by default, will connect to the remote device and
- retrieve the current running-config to use as a base for comparing
- against the contents of source. There are times when it is not
- desirable to have the task get the current running-config for
- every task in a playbook. The I(running_config) argument allows the
- implementer to pass in the configuration to use as the base
- config for comparison.
- aliases: ['config']
- defaults:
- description:
- - This argument specifies whether or not to collect all defaults
- when getting the remote device running config. When enabled,
- the module will get the current config by issuing the command
- C(show running-config all).
- type: bool
- default: 'no'
- save_when:
- description:
- - When changes are made to the device running-configuration, the
- changes are not copied to non-volatile storage by default. Using
- this argument will change that behavior. If the argument is set to
- I(always), then the running-config will always be copied to the
- startup-config and the I(modified) flag will always be set to
- True. If the argument is set to I(modified), then the running-config
- will only be copied to the startup-config if it has changed since
- the last save to startup-config. If the argument is set to
- I(never), the running-config will never be copied to the
- startup-config. If the argument is set to I(changed), then the running-config
- will only be copied to the startup-config if the task has made a change.
- default: never
- choices: ['always', 'never', 'modified', 'changed']
- diff_against:
- description:
- - When using the C(ansible-playbook --diff) command line argument
- the module can generate diffs against different sources.
- - When this option is configure as I(startup), the module will return
- the diff of the running-config against the startup-config.
- - When this option is configured as I(intended), the module will
- return the diff of the running-config against the configuration
- provided in the C(intended_config) argument.
- - When this option is configured as I(running), the module will
- return the before and after diff of the running-config with respect
- to any changes made to the device configuration.
- default: running
- choices: ['running', 'startup', 'intended']
- diff_ignore_lines:
- description:
- - Use this argument to specify one or more lines that should be
- ignored during the diff. This is used for lines in the configuration
- that are automatically updated by the system. This argument takes
- a list of regular expressions or exact line matches.
- intended_config:
- description:
- - The C(intended_config) provides the master configuration that
- the node should conform to and is used to check the final
- running-config against. This argument will not modify any settings
- on the remote device and is strictly used to check the compliance
- of the current device's configuration against. When specifying this
- argument, the task should also modify the C(diff_against) value and
- set it to I(intended).
- backup_options:
- description:
- - This is a dict object containing configurable options related to backup file path.
- The value of this option is read only when C(backup) is set to I(yes), if C(backup) is set
- to I(no) this option will be silently ignored.
- suboptions:
- filename:
- description:
- - The filename to be used to store the backup configuration. If the filename
- is not given it will be generated based on the hostname, current time and date
- in format defined by _config.@
- dir_path:
- description:
- - This option provides the path ending with directory name in which the backup
- configuration file will be stored. If the directory does not exist it will be first
- created and the filename is either the value of C(filename) or default filename
- as described in C(filename) options description. If the path value is not given
- in that case a I(backup) directory will be created in the current working directory
- and backup configuration will be copied in C(filename) within I(backup) directory.
- type: path
- type: dict
-'''
-
-EXAMPLES = """
-- name: configure SNMP system name
- exos_config:
- lines: configure snmp sysName "{{ inventory_hostname }}"
-
-- name: configure interface settings
- exos_config:
- lines:
- - configure ports 2 description-string "Master Uplink"
- backup: yes
-
-- name: check the running-config against master config
- exos_config:
- diff_against: intended
- intended_config: "{{ lookup('file', 'master.cfg') }}"
-
-- name: check the startup-config against the running-config
- exos_config:
- diff_against: startup
- diff_ignore_lines:
- - ntp clock .*
-
-- name: save running to startup when modified
- exos_config:
- save_when: modified
-
-- name: configurable backup path
- exos_config:
- lines:
- - configure ports 2 description-string "Master Uplink"
- backup: yes
- backup_options:
- filename: backup.cfg
- dir_path: /home/user
-"""
-
-RETURN = """
-updates:
- description: The set of commands that will be pushed to the remote device
- returned: always
- type: list
- sample: ['switch-attributes hostname foo', 'router ospf', 'area 0']
-commands:
- description: The set of commands that will be pushed to the remote device
- returned: always
- type: list
- sample: ['create vlan "foo"', 'configure snmp sysName "x620-red"']
-backup_path:
- description: The full path to the backup file
- returned: when backup is yes
- type: str
- sample: /playbooks/ansible/backup/x870_config.2018-08-08@15:00:21
-
-"""
-import re
-
-from ansible_collections.community.general.plugins.module_utils.network.exos.exos import run_commands, get_config, load_config, get_diff
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, dumps
-from ansible.module_utils._text import to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
-
-__metaclass__ = type
-
-
-def get_running_config(module, current_config=None, flags=None):
- contents = module.params['running_config']
- if not contents:
- if current_config:
- contents = current_config.config_text
- else:
- contents = get_config(module, flags=flags)
- return contents
-
-
-def get_startup_config(module, flags=None):
- reply = run_commands(module, {'command': 'show switch', 'output': 'text'})
- match = re.search(r'Config Selected: +(\S+)\.cfg', to_text(reply, errors='surrogate_or_strict').strip(), re.MULTILINE)
- if match:
- cfgname = match.group(1).strip()
- command = ' '.join(['debug cfgmgr show configuration file', cfgname])
- if flags:
- command += ' '.join(to_list(flags)).strip()
- reply = run_commands(module, {'command': command, 'output': 'text'})
- data = reply[0]
- else:
- data = ''
- return data
-
-
-def get_candidate(module):
- candidate = NetworkConfig(indent=1)
-
- if module.params['src']:
- candidate.load(module.params['src'])
- elif module.params['lines']:
- candidate.add(module.params['lines'])
- candidate = dumps(candidate, 'raw')
- return candidate
-
-
-def save_config(module, result):
- result['changed'] = True
- if not module.check_mode:
- command = {"command": "save configuration",
- "prompt": "Do you want to save configuration", "answer": "y"}
- run_commands(module, command)
- else:
- module.warn('Skipping command `save configuration` '
- 'due to check_mode. Configuration not copied to '
- 'non-volatile storage')
-
-
-def main():
- """ main entry point for module execution
- """
- backup_spec = dict(
- filename=dict(),
- dir_path=dict(type='path')
- )
- argument_spec = dict(
- src=dict(type='path'),
-
- lines=dict(aliases=['commands'], type='list'),
-
- before=dict(type='list'),
- after=dict(type='list'),
-
- match=dict(default='line', choices=['line', 'strict', 'exact', 'none']),
- replace=dict(default='line', choices=['line', 'block']),
-
- running_config=dict(aliases=['config']),
- intended_config=dict(),
-
- defaults=dict(type='bool', default=False),
- backup=dict(type='bool', default=False),
- backup_options=dict(type='dict', options=backup_spec),
-
- save_when=dict(choices=['always', 'never', 'modified', 'changed'], default='never'),
-
- diff_against=dict(choices=['startup', 'intended', 'running'], default='running'),
- diff_ignore_lines=dict(type='list'),
- )
-
- mutually_exclusive = [('lines', 'src')]
-
- required_if = [('match', 'strict', ['lines']),
- ('match', 'exact', ['lines']),
- ('replace', 'block', ['lines']),
- ('diff_against', 'intended', ['intended_config'])]
-
- module = AnsibleModule(argument_spec=argument_spec,
- mutually_exclusive=mutually_exclusive,
- required_if=required_if,
- supports_check_mode=True)
-
- result = {'changed': False}
-
- warnings = list()
- if warnings:
- result['warnings'] = warnings
-
- config = None
- flags = ['detail'] if module.params['defaults'] else []
- diff_ignore_lines = module.params['diff_ignore_lines']
-
- if module.params['backup'] or (module._diff and module.params['diff_against'] == 'running'):
- contents = get_config(module, flags=flags)
- config = NetworkConfig(indent=1, contents=contents)
- if module.params['backup']:
- result['__backup__'] = contents
-
- if any((module.params['lines'], module.params['src'])):
- match = module.params['match']
- replace = module.params['replace']
-
- candidate = get_candidate(module)
- running = get_running_config(module, config)
-
- try:
- response = get_diff(module, candidate=candidate, running=running, diff_match=match, diff_ignore_lines=diff_ignore_lines, diff_replace=replace)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
-
- config_diff = response.get('config_diff')
-
- if config_diff:
- commands = config_diff.split('\n')
-
- if module.params['before']:
- commands[:0] = module.params['before']
-
- if module.params['after']:
- commands.extend(module.params['after'])
-
- result['commands'] = commands
- result['updates'] = commands
-
- # send the configuration commands to the device and merge
- # them with the current running config
- if not module.check_mode:
- if commands:
- load_config(module, commands)
-
- result['changed'] = True
-
- running_config = None
- startup_config = None
-
- if module.params['save_when'] == 'always':
- save_config(module, result)
- elif module.params['save_when'] == 'modified':
- running = get_running_config(module)
- startup = get_startup_config(module)
-
- running_config = NetworkConfig(indent=1, contents=running, ignore_lines=diff_ignore_lines)
- startup_config = NetworkConfig(indent=1, contents=startup, ignore_lines=diff_ignore_lines)
-
- if running_config.sha1 != startup_config.sha1:
- save_config(module, result)
- elif module.params['save_when'] == 'changed' and result['changed']:
- save_config(module, result)
-
- if module._diff:
- if not running_config:
- contents = get_running_config(module)
- else:
- contents = running_config.config_text
-
- # recreate the object in order to process diff_ignore_lines
- running_config = NetworkConfig(indent=1, contents=contents, ignore_lines=diff_ignore_lines)
-
- if module.params['diff_against'] == 'running':
- if module.check_mode:
- module.warn("unable to perform diff against running-config due to check mode")
- contents = None
- else:
- contents = config.config_text
-
- elif module.params['diff_against'] == 'startup':
- if not startup_config:
- contents = get_startup_config(module)
- else:
- contents = startup_config.config_text
-
- elif module.params['diff_against'] == 'intended':
- contents = module.params['intended_config']
-
- if contents is not None:
- base_config = NetworkConfig(indent=1, contents=contents, ignore_lines=diff_ignore_lines)
-
- if running_config.sha1 != base_config.sha1:
- if module.params['diff_against'] == 'intended':
- before = running_config
- after = base_config
- elif module.params['diff_against'] in ('startup', 'running'):
- before = base_config
- after = running_config
-
- result.update({
- 'changed': True,
- 'diff': {'before': str(before), 'after': str(after)}
- })
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/exos/exos_facts.py b/plugins/modules/network/exos/exos_facts.py
deleted file mode 100644
index b5f79708d8..0000000000
--- a/plugins/modules/network/exos/exos_facts.py
+++ /dev/null
@@ -1,189 +0,0 @@
-#!/usr/bin/python
-#
-# (c) 2018 Extreme Networks Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: exos_facts
-author:
- - "Lance Richardson (@hlrichardson)"
- - "Ujwal Koamrla (@ujwalkomarla)"
-short_description: Collect facts from devices running Extreme EXOS
-description:
- - Collects a base set of device facts from a remote device that
- is running EXOS. This module prepends all of the base network
- fact keys with C(ansible_net_). The facts module will
- always collect a base set of facts from the device and can
- enable or disable collection of additional facts.
-notes:
- - Tested against EXOS 22.5.1.7
-options:
- gather_subset:
- description:
- - When supplied, this argument will restrict the facts collected
- to a given subset. Possible values for this argument include
- all, hardware, config, and interfaces. Can specify a list of
- values to include a larger subset. Values can also be used
- with an initial C(M(!)) to specify that a specific subset should
- not be collected.
- required: false
- type: list
- default: ['!config']
- gather_network_resources:
- description:
- - When supplied, this argument will restrict the facts collected
- to a given subset. Possible values for this argument include
- all and the resources like interfaces, vlans etc.
- Can specify a list of values to include a larger subset.
- Values can also be used with an initial C(M(!)) to specify that
- a specific subset should not be collected.
- Valid subsets are 'all', 'lldp_global'.
- type: list
-'''
-
-EXAMPLES = """
- - name: Gather all legacy facts
- exos_facts:
- gather_subset: all
-
- - name: Gather only the config and default facts
- exos_facts:
- gather_subset: config
-
- - name: do not gather hardware facts
- exos_facts:
- gather_subset: "!hardware"
-
- - name: Gather legacy and resource facts
- exos_facts:
- gather_subset: all
- gather_network_resources: all
-
- - name: Gather only the lldp global resource facts and no legacy facts
- exos_facts:
- gather_subset:
- - '!all'
- - '!min'
- gather_network_resource:
- - lldp_global
-
- - name: Gather lldp global resource and minimal legacy facts
- exos_facts:
- gather_subset: min
- gather_network_resource: lldp_global
-"""
-
-RETURN = """
-ansible_net_gather_subset:
- description: The list of fact subsets collected from the device
- returned: always
- type: list
-
-ansible_net_gather_network_resources:
- description: The list of fact for network resource subsets collected from the device
- returned: when the resource is configured
- type: list
-
-# default
-ansible_net_model:
- description: The model name returned from the device
- returned: always
- type: str
-ansible_net_serialnum:
- description: The serial number of the remote device
- returned: always
- type: str
-ansible_net_version:
- description: The operating system version running on the remote device
- returned: always
- type: str
-ansible_net_hostname:
- description: The configured hostname of the device
- returned: always
- type: str
-
-# hardware
-ansible_net_memfree_mb:
- description: The available free memory on the remote device in Mb
- returned: when hardware is configured
- type: int
-ansible_net_memtotal_mb:
- description: The total memory on the remote device in Mb
- returned: when hardware is configured
- type: int
-
-# config
-ansible_net_config:
- description: The current active config from the device
- returned: when config is configured
- type: str
-
-# interfaces
-ansible_net_all_ipv4_addresses:
- description: All IPv4 addresses configured on the device
- returned: when interfaces is configured
- type: list
-ansible_net_all_ipv6_addresses:
- description: All Primary IPv6 addresses configured on the device
- returned: when interfaces is configured
- type: list
-ansible_net_interfaces:
- description: A hash of all interfaces running on the system
- returned: when interfaces is configured
- type: dict
-ansible_net_neighbors:
- description: The list of LLDP neighbors from the remote device
- returned: when interfaces is configured
- type: dict
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.exos.argspec.facts.facts import FactsArgs
-from ansible_collections.community.general.plugins.module_utils.network.exos.facts.facts import Facts
-
-
-def main():
- """Main entry point for AnsibleModule
- """
- argument_spec = FactsArgs.argument_spec
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- warnings = ['default value for `gather_subset` '
- 'will be changed to `min` from `!config` v2.11 onwards']
-
- result = Facts(module).get_facts()
-
- ansible_facts, additional_warnings = result
- warnings.extend(additional_warnings)
-
- module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/exos/exos_l2_interfaces.py b/plugins/modules/network/exos/exos_l2_interfaces.py
deleted file mode 100644
index 199e53f38f..0000000000
--- a/plugins/modules/network/exos/exos_l2_interfaces.py
+++ /dev/null
@@ -1,1136 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-"""
-The module file for exos_l2_interfaces
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- 'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'
-}
-
-DOCUMENTATION = '''
----
-module: exos_l2_interfaces
-short_description: Manage L2 interfaces on Extreme Networks EXOS devices.
-description: This module provides declarative management of L2 interfaces on Extreme Networks EXOS network devices.
-author: Jayalakshmi Viswanathan (@jayalakshmiV)
-notes:
- - Tested against EXOS 30.2.1.8
- - This module works with connection C(httpapi).
- See L(EXOS Platform Options,../network/user_guide/platform_exos.html)
-options:
- config:
- description: A dictionary of L2 interfaces options
- type: list
- elements: dict
- suboptions:
- name:
- description:
- - Name of the interface
- type: str
- required: True
- access:
- description:
- - Switchport mode access command to configure the interface as a layer 2 access.
- type: dict
- suboptions:
- vlan:
- description:
- - Configure given VLAN in access port. It's used as the access VLAN ID.
- type: int
- trunk:
- description:
- - Switchport mode trunk command to configure the interface as a Layer 2 trunk.
- type: dict
- suboptions:
- native_vlan:
- description:
- - Native VLAN to be configured in trunk port. It's used as the trunk native VLAN ID.
- type: int
- trunk_allowed_vlans:
- description:
- - List of allowed VLANs in a given trunk port. These are the only VLANs that will be configured on the trunk.
- type: list
- state:
- description:
- - The state the configuration should be left in
- type: str
- choices:
- - merged
- - replaced
- - overridden
- - deleted
- default: merged
-'''
-EXAMPLES = """
-# Using deleted
-
-# Before state:
-# -------------
-# path: /rest/restconf/data/openconfig-interfaces:interfaces/
-# method: GET
-# data:
-# {
-# "openconfig-interfaces:interfaces": {
-# "interface": [
-# {
-# "name": "1",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 10
-# }
-# }
-# }
-# },
-# {
-# "name": "2",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "TRUNK",
-# "native-vlan": 1,
-# "trunk-vlans": [
-# 10
-# ]
-# }
-# }
-# }
-# },
-# {
-# "name": "3",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "TRUNK",
-# "native-vlan": 10,
-# "trunk-vlans": [
-# 20,
-# 30
-# ]
-# }
-# }
-# }
-# }
-# ]
-# }
-# }
-
-- name: Delete L2 interface configuration for the given arguments
- exos_l2_interfaces:
- config:
- - name: '3'
- state: deleted
-
-# Module Execution Results:
-# -------------------------
-#
-# "before": [
-# {
-# "access": {
-# "vlan": 10
-# },
-# "name": "1",
-# "trunk": null
-# },
-# {
-# "access": null,
-# "name": "2",
-# "trunk": {
-# "native_vlan": 1,
-# "trunk_allowed_vlans": [
-# 10
-# ]
-# }
-# },
-# {
-# "access": null,
-# "name": "3",
-# "trunk": {
-# "native_vlan": 10,
-# "trunk_allowed_vlans": [
-# 20,
-# 30
-# ]
-# }
-# }
-# ],
-#
-# "requests": [
-# {
-# "data": {
-# "openconfig-vlan:config": {
-# "access-vlan": 1,
-# "interface-mode": "ACCESS"
-# }
-# }
-# "method": "PATCH",
-# "path": "rest/restconf/data/openconfig-interfaces:interfaces/interface=3/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
-# }
-# ],
-#
-# "after": [
-# {
-# "access": {
-# "vlan": 10
-# },
-# "name": "1",
-# "trunk": null
-# },
-# {
-# "access": null,
-# "name": "2",
-# "trunk": {
-# "native_vlan": 1,
-# "trunk_allowed_vlans": [
-# 10
-# ]
-# }
-# },
-# {
-# "access": {
-# "vlan": 1
-# },
-# "name": "3",
-# "trunk": null
-# }
-# ]
-#
-# After state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-interfaces:interfaces/
-# method: GET
-# data:
-# {
-# "openconfig-interfaces:interfaces": {
-# "interface": [
-# {
-# "name": "1",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 10
-# }
-# }
-# }
-# },
-# {
-# "name": "2",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "TRUNK",
-# "native-vlan": 1,
-# "trunk-vlans": [
-# 10
-# ]
-# }
-# }
-# }
-# },
-# {
-# "name": "3",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 1
-# }
-# }
-# }
-# }
-# ]
-# }
-# }
-
-
-# Using deleted without any config passed
-#"(NOTE: This will delete all of configured resource module attributes from each configured interface)"
-
-# Before state:
-# -------------
-# path: /rest/restconf/data/openconfig-interfaces:interfaces/
-# method: GET
-# data:
-# {
-# "openconfig-interfaces:interfaces": {
-# "interface": [
-# {
-# "name": "1",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 10
-# }
-# }
-# }
-# },
-# {
-# "name": "2",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "TRUNK",
-# "native-vlan": 1,
-# "trunk-vlans": [
-# 10
-# ]
-# }
-# }
-# }
-# },
-# {
-# "name": "3",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "TRUNK",
-# "native-vlan": 10,
-# "trunk-vlans": [
-# 20,
-# 30
-# ]
-# }
-# }
-# }
-# }
-# ]
-# }
-# }
-
-- name: Delete L2 interface configuration for the given arguments
- exos_l2_interfaces:
- state: deleted
-
-# Module Execution Results:
-# -------------------------
-#
-# "before": [
-# {
-# "access": {
-# "vlan": 10
-# },
-# "name": "1",
-# "trunk": null
-# },
-# {
-# "access": null,
-# "name": "2",
-# "trunk": {
-# "native_vlan": 1,
-# "trunk_allowed_vlans": [
-# 10
-# ]
-# }
-# },
-# {
-# "access": null,
-# "name": "3",
-# "trunk": {
-# "native_vlan": 10,
-# "trunk_allowed_vlans": [
-# 20,
-# 30
-# ]
-# }
-# }
-# ],
-#
-# "requests": [
-# {
-# "data": {
-# "openconfig-vlan:config": {
-# "access-vlan": 1,
-# "interface-mode": "ACCESS"
-# }
-# }
-# "method": "PATCH",
-# "path": "rest/restconf/data/openconfig-interfaces:interfaces/interface=1/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
-# },
-# {
-# "data": {
-# "openconfig-vlan:config": {
-# "access-vlan": 1,
-# "interface-mode": "ACCESS"
-# }
-# }
-# "method": "PATCH",
-# "path": "rest/restconf/data/openconfig-interfaces:interfaces/interface=2/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
-# },
-# {
-# "data": {
-# "openconfig-vlan:config": {
-# "access-vlan": 1,
-# "interface-mode": "ACCESS"
-# }
-# }
-# "method": "PATCH",
-# "path": "rest/restconf/data/openconfig-interfaces:interfaces/interface=3/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
-# }
-# ],
-#
-# "after": [
-# {
-# "access": {
-# "vlan": 1
-# },
-# "name": "1",
-# "trunk": null
-# },
-# {
-# "access": {
-# "vlan": 1
-# },
-# "name": "2",
-# "trunk": null
-# },
-# {
-# "access": {
-# "vlan": 1
-# },
-# "name": "3",
-# "trunk": null
-# }
-# ]
-#
-# After state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-interfaces:interfaces/
-# method: GET
-# data:
-# {
-# "openconfig-interfaces:interfaces": {
-# "interface": [
-# {
-# "name": "1",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 1
-# }
-# }
-# }
-# },
-# {
-# "name": "2",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 1
-# }
-# }
-# }
-# },
-# {
-# "name": "3",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 1
-# }
-# }
-# }
-# }
-# ]
-# }
-# }
-
-
-# Using merged
-
-# Before state:
-# -------------
-# path: /rest/restconf/data/openconfig-interfaces:interfaces/
-# method: GET
-# data:
-# {
-# "openconfig-interfaces:interfaces": {
-# "interface": [
-# {
-# "name": "1",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 1
-# },
-# }
-# }
-# },
-# {
-# "name": "2",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 1
-# },
-# }
-# }
-# },
-# {
-# "name": "3",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 1
-# },
-# }
-# }
-# },
-# ]
-# }
-# }
-
-- name: Merge provided configuration with device configuration
- exos_l2_interfaces:
- config:
- - access:
- vlan: 10
- name: '1'
- - name: '2'
- trunk:
- trunk_allowed_vlans: 10
- - name: '3'
- trunk:
- native_vlan: 10
- trunk_allowed_vlans: 20
- state: merged
-
-# Module Execution Results:
-# -------------------------
-#
-# "before": [
-# {
-# "access": {
-# "vlan": 1
-# },
-# "name": "1",
-# "trunk": null
-# },
-# {
-# "access": {
-# "vlan": 1
-# },
-# "name": "2",
-# "trunk": null
-# },
-# {
-# "access": {
-# "vlan": 1
-# },
-# "name": "3",
-# "trunk": null
-# }
-# ],
-#
-# "requests": [
-# {
-# "data": {
-# "openconfig-vlan:config": {
-# "access-vlan": 10,
-# "interface-mode": "ACCESS"
-# }
-# }
-# "method": "PATCH",
-# "path": "rest/restconf/data/openconfig-interfaces:interfaces/interface=1/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
-# },
-# {
-# "data": {
-# "openconfig-vlan:config": {
-# "trunk-vlans": [10],
-# "interface-mode": "TRUNK"
-# }
-# }
-# "method": "PATCH",
-# "path": "rest/restconf/data/openconfig-interfaces:interfaces/interface=2/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
-# },
-# {
-# "data": {
-# "openconfig-vlan:config": {
-# "native-vlan": 10,
-# "trunk-vlans": [20],
-# "interface-mode": "TRUNK"
-# }
-# }
-# "method": "PATCH",
-# "path": "rest/restconf/data/openconfig-interfaces:interfaces/interface=3/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
-# }
-# ],
-#
-# "after": [
-# {
-# "access": {
-# "vlan": 10
-# },
-# "name": "1",
-# "trunk": null
-# },
-# {
-# "access": null,
-# "name": "2",
-# "trunk": {
-# "native_vlan": 1,
-# "trunk_allowed_vlans": [
-# 10
-# ]
-# }
-# },
-# {
-# "access": null,
-# "name": "3",
-# "trunk": {
-# "native_vlan": 10,
-# "trunk_allowed_vlans": [
-# 20
-# ]
-# }
-# }
-# ]
-#
-# After state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-interfaces:interfaces/
-# method: GET
-# data:
-# {
-# "openconfig-interfaces:interfaces": {
-# "interface": [
-# {
-# "name": "1",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 10
-# }
-# }
-# }
-# },
-# {
-# "name": "2",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "TRUNK",
-# "native-vlan": 1,
-# "trunk-vlans": [
-# 10
-# ]
-# }
-# }
-# }
-# },
-# {
-# "name": "3",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "TRUNK",
-# "native-vlan": 10,
-# "trunk-vlans": [
-# 20
-# ]
-# }
-# }
-# }
-# },
-# ]
-# }
-# }
-
-
-# Using overridden
-
-# Before state:
-# -------------
-# path: /rest/restconf/data/openconfig-interfaces:interfaces/
-# method: GET
-# data:
-# {
-# "openconfig-interfaces:interfaces": {
-# "interface": [
-# {
-# "name": "1",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 10
-# }
-# }
-# }
-# },
-# {
-# "name": "2",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "TRUNK",
-# "native-vlan": 1,
-# "trunk-vlans": [
-# 10
-# ]
-# }
-# }
-# }
-# },
-# {
-# "name": "3",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "TRUNK",
-# "native-vlan": 10,
-# "trunk-vlans": [
-# 20,
-# 30
-# ]
-# }
-# }
-# }
-# }
-# ]
-# }
-# }
-
-- name: Overrride device configuration of all L2 interfaces with provided configuration
- exos_l2_interfaces:
- config:
- - access:
- vlan: 10
- name: '2'
- state: overridden
-
-# Module Execution Results:
-# -------------------------
-#
-# "before": [
-# {
-# "access": {
-# "vlan": 10
-# },
-# "name": "1",
-# "trunk": null
-# },
-# {
-# "access": null,
-# "name": "2",
-# "trunk": {
-# "native_vlan": 1,
-# "trunk_allowed_vlans": [
-# 10
-# ]
-# }
-# },
-# {
-# "access": null,
-# "name": "3",
-# "trunk": {
-# "native_vlan": 10,
-# "trunk_allowed_vlans": [
-# 20,
-# 30
-# ]
-# }
-# }
-# ],
-#
-# "requests": [
-# {
-# "data": {
-# "openconfig-vlan:config": {
-# "access-vlan": 1,
-# "interface-mode": "ACCESS"
-# }
-# }
-# "method": "PATCH",
-# "path": "rest/restconf/data/openconfig-interfaces:interfaces/interface=1/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
-# },
-# {
-# "data": {
-# "openconfig-vlan:config": {
-# "access-vlan": 10,
-# "interface-mode": "ACCESS"
-# }
-# }
-# "method": "PATCH",
-# "path": "rest/restconf/data/openconfig-interfaces:interfaces/interface=2/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
-# }
-# {
-# "data": {
-# "openconfig-vlan:config": {
-# "access-vlan": 1,
-# "interface-mode": "ACCESS"
-# }
-# }
-# "method": "PATCH",
-# "path": "rest/restconf/data/openconfig-interfaces:interfaces/interface=3/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
-# }
-# ],
-#
-# "after": [
-# {
-# "access": {
-# "vlan": 1
-# },
-# "name": "1",
-# "trunk": null
-# },
-# {
-# "access": {
-# "vlan": 10
-# },
-# "name": "2",
-# "trunk": null
-# },
-# {
-# "access": {
-# "vlan": 1
-# },
-# "name": "3",
-# "trunk": null
-# }
-# ]
-#
-# After state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-interfaces:interfaces/
-# method: GET
-# data:
-# {
-# "openconfig-interfaces:interfaces": {
-# "interface": [
-# {
-# "name": "1",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 1
-# }
-# }
-# }
-# },
-# {
-# "name": "2",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 10
-# }
-# }
-# }
-# },
-# {
-# "name": "3",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 1
-# }
-# }
-# }
-# }
-# ]
-# }
-# }
-
-
-# Using replaced
-
-# Before state:
-# -------------
-# path: /rest/restconf/data/openconfig-interfaces:interfaces/
-# method: GET
-# data:
-# {
-# "openconfig-interfaces:interfaces": {
-# "interface": [
-# {
-# "name": "1",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 10
-# }
-# }
-# }
-# },
-# {
-# "name": "2",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 20
-# }
-# }
-# }
-# },
-# {
-# "name": "3",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "TRUNK",
-# "native-vlan": 1,
-# "trunk-vlans": [
-# 10
-# ]
-# }
-# }
-# }
-# }
-# ]
-# }
-# }
-
-- name: Replace device configuration of listed L2 interfaces with provided configuration
- exos_l2_interfaces:
- config:
- - access:
- vlan: 20
- name: '1'
- - name: '2'
- trunk:
- trunk_allowed_vlans: 10
- - name: '3'
- trunk:
- native_vlan: 10
- trunk_allowed_vlan: 20,30
- state: replaced
-
-# Module Execution Results:
-# -------------------------
-#
-# "before": [
-# {
-# "access": {
-# "vlan": 10
-# },
-# "name": "1",
-# "trunk": null
-# },
-# {
-# "access": {
-# "vlan": 20
-# },
-# "name": "2",
-# "trunk": null
-# },
-# {
-# "access": null,
-# "name": "3",
-# "trunk": {
-# "native_vlan": 1,
-# "trunk_allowed_vlans": [
-# 10
-# ]
-# }
-# }
-# ],
-#
-# "requests": [
-# {
-# "data": {
-# "openconfig-vlan:config": {
-# "access-vlan": 20,
-# "interface-mode": "ACCESS"
-# }
-# }
-# "method": "PATCH",
-# "path": "rest/restconf/data/openconfig-interfaces:interfaces/interface=1/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
-# },
-# {
-# "data": {
-# "openconfig-vlan:config": {
-# "trunk-vlans": [10],
-# "interface-mode": "TRUNK"
-# }
-# }
-# "method": "PATCH",
-# "path": "rest/restconf/data/openconfig-interfaces:interfaces/interface=2/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
-# },
-# {
-# "data": {
-# "openconfig-vlan:config": {
-# "native-vlan": 10,
-# "trunk-vlans": [20, 30]
-# "interface-mode": "TRUNK"
-# }
-# }
-# "method": "PATCH",
-# "path": "rest/restconf/data/openconfig-interfaces:interfaces/interface=3/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config"
-# }
-# ],
-#
-# "after": [
-# {
-# "access": {
-# "vlan": 20
-# },
-# "name": "1",
-# "trunk": null
-# },
-# {
-# "access": null,
-# "name": "2",
-# "trunk": {
-# "native_vlan": null,
-# "trunk_allowed_vlans": [
-# 10
-# ]
-# }
-# },
-# {
-# "access": null,
-# "name": "3",
-# "trunk": {
-# "native_vlan": 10,
-# "trunk_allowed_vlans": [
-# 20,
-# 30
-# ]
-# }
-# }
-# ]
-#
-# After state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-interfaces:interfaces/
-# method: GET
-# data:
-# {
-# "openconfig-interfaces:interfaces": {
-# "interface": [
-# {
-# "name": "1",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "ACCESS",
-# "access-vlan": 20
-# }
-# }
-# }
-# },
-# {
-# "name": "2",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "TRUNK",
-# "trunk-vlans": [
-# 10
-# ]
-# }
-# }
-# }
-# },
-# {
-# "name": "3",
-# "openconfig-if-ethernet:ethernet": {
-# "openconfig-vlan:switched-vlan": {
-# "config": {
-# "interface-mode": "TRUNK",
-# "native-vlan": 10,
-# "trunk-vlans": [
-# 20,
-# 30
-# ]
-# }
-# }
-# }
-# }
-# ]
-# }
-# }
-
-
-"""
-RETURN = """
-before:
- description: The configuration prior to the model invocation.
- returned: always
- sample: >
- The configuration returned will always be in the same format
- of the parameters above.
- type: list
-after:
- description: The resulting configuration model invocation.
- returned: when changed
- sample: >
- The configuration returned will always be in the same format
- of the parameters above.
- type: list
-requests:
- description: The set of requests pushed to the remote device.
- returned: always
- type: list
- sample: [{"data": "...", "method": "...", "path": "..."}, {"data": "...", "method": "...", "path": "..."}, {"data": "...", "method": "...", "path": "..."}]
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.exos.argspec.l2_interfaces.l2_interfaces import L2_interfacesArgs
-from ansible_collections.community.general.plugins.module_utils.network.exos.config.l2_interfaces.l2_interfaces import L2_interfaces
-
-
-def main():
- """
- Main entry point for module execution
-
- :returns: the result form module invocation
- """
- required_if = [('state', 'merged', ('config', )),
- ('state', 'replaced', ('config', ))]
- module = AnsibleModule(argument_spec=L2_interfacesArgs.argument_spec, required_if=required_if,
- supports_check_mode=True)
-
- result = L2_interfaces(module).execute_module()
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/exos/exos_lldp_global.py b/plugins/modules/network/exos/exos_lldp_global.py
deleted file mode 100644
index 8ed421aa2b..0000000000
--- a/plugins/modules/network/exos/exos_lldp_global.py
+++ /dev/null
@@ -1,429 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-
-"""
-The module file for exos_lldp_global
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- 'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'
-}
-
-DOCUMENTATION = '''
----
-module: exos_lldp_global
-short_description: Configure and manage Link Layer Discovery Protocol(LLDP) attributes on EXOS platforms.
-description: This module configures and manages the Link Layer Discovery Protocol(LLDP) attributes on Extreme Networks EXOS platforms.
-author: Ujwal Komarla (@ujwalkomarla)
-notes:
-- Tested against Extreme Networks EXOS version 30.2.1.8 on x460g2.
-- This module works with connection C(httpapi).
- See L(EXOS Platform Options,../network/user_guide/platform_exos.html)
-options:
- config:
- description: A dictionary of LLDP options
- type: dict
- suboptions:
- interval:
- description:
- - Frequency at which LLDP advertisements are sent (in seconds). By default - 30 seconds.
- type: int
- default: 30
- tlv_select:
- description:
- - This attribute can be used to specify the TLVs that need to be sent in the LLDP packets. By default, only system name and system description is sent
- type: dict
- suboptions:
- management_address:
- description:
- - Used to specify the management address in TLV messages
- type: bool
- port_description:
- description:
- - Used to specify the port description TLV
- type: bool
- system_capabilities:
- description:
- - Used to specify the system capabilities TLV
- type: bool
- system_description:
- description:
- - Used to specify the system description TLV
- type: bool
- default: true
- system_name:
- description:
- - Used to specify the system name TLV
- type: bool
- default: true
-
- state:
- description:
- - The state of the configuration after module completion.
- type: str
- choices:
- - merged
- - replaced
- - deleted
- default: merged
-'''
-EXAMPLES = """
-# Using merged
-
-
-# Before state:
-# -------------
-# path: /rest/restconf/data/openconfig_lldp:lldp/config
-# method: GET
-# data:
-# {
-# "openconfig_lldp:config": {
-# "enabled": true,
-# "hello-timer": 30,
-# "suppress-tlv-advertisement": [
-# "PORT_DESCRIPTION",
-# "SYSTEM_CAPABILITIES",
-# "MANAGEMENT_ADDRESS"
-# ],
-# "system-description": "ExtremeXOS (X460G2-24t-10G4) version 30.2.1.8"
-# "system-name": "X460G2-24t-10G4"
-# }
-# }
-
-- name: Merge provided LLDP configuration with device configuration
- exos_lldp_global:
- config:
- interval: 10000
- tlv_select:
- system_capabilities: true
- state: merged
-
-# Module Execution Results:
-# -------------------------
-#
-# "before": [
-# {
-# "interval": 30,
-# "tlv_select": {
-# "system_name": true,
-# "system_description": true
-# "port_description": false,
-# "management_address": false,
-# "system_capabilities": false
-# }
-# }
-# ]
-#
-# "requests": [
-# {
-# "data": {
-# "openconfig_lldp:config": {
-# "hello-timer": 10000,
-# "suppress-tlv-advertisement": [
-# "PORT_DESCRIPTION",
-# "MANAGEMENT_ADDRESS"
-# ]
-# }
-# },
-# "method": "PATCH",
-# "path": "/rest/restconf/data/openconfig_lldp:lldp/config"
-# }
-# ]
-#
-# "after": [
-# {
-# "interval": 10000,
-# "tlv_select": {
-# "system_name": true,
-# "system_description": true,
-# "port_description": false,
-# "management_address": false,
-# "system_capabilities": true
-# }
-# }
-# ]
-
-
-# After state:
-# -------------
-# path: /rest/restconf/data/openconfig_lldp:lldp/config
-# method: GET
-# data:
-# {
-# "openconfig_lldp:config": {
-# "enabled": true,
-# "hello-timer": 10000,
-# "suppress-tlv-advertisement": [
-# "PORT_DESCRIPTION",
-# "MANAGEMENT_ADDRESS"
-# ],
-# "system-description": "ExtremeXOS (X460G2-24t-10G4) version 30.2.1.8"
-# "system-name": "X460G2-24t-10G4"
-# }
-# }
-
-
-# Using replaced
-
-
-# Before state:
-# -------------
-# path: /rest/restconf/data/openconfig_lldp:lldp/config
-# method: GET
-# data:
-# {
-# "openconfig_lldp:config": {
-# "enabled": true,
-# "hello-timer": 30,
-# "suppress-tlv-advertisement": [
-# "PORT_DESCRIPTION",
-# "SYSTEM_CAPABILITIES",
-# "MANAGEMENT_ADDRESS"
-# ],
-# "system-description": "ExtremeXOS (X460G2-24t-10G4) version 30.2.1.8"
-# "system-name": "X460G2-24t-10G4"
-# }
-# }
-
-- name: Replace device configuration with provided LLDP configuration
- exos_lldp_global:
- config:
- interval: 10000
- tlv_select:
- system_capabilities: true
- state: replaced
-
-# Module Execution Results:
-# -------------------------
-#
-# "before": [
-# {
-# "interval": 30,
-# "tlv_select": {
-# "system_name": true,
-# "system_description": true
-# "port_description": false,
-# "management_address": false,
-# "system_capabilities": false
-# }
-# }
-# ]
-#
-# "requests": [
-# {
-# "data": {
-# "openconfig_lldp:config": {
-# "hello-timer": 10000,
-# "suppress-tlv-advertisement": [
-# "SYSTEM_NAME",
-# "SYSTEM_DESCRIPTION",
-# "PORT_DESCRIPTION",
-# "MANAGEMENT_ADDRESS"
-# ]
-# }
-# },
-# "method": "PATCH",
-# "path": "/rest/restconf/data/openconfig_lldp:lldp/config"
-# }
-# ]
-#
-# "after": [
-# {
-# "interval": 10000,
-# "tlv_select": {
-# "system_name": false,
-# "system_description": false,
-# "port_description": false,
-# "management_address": false,
-# "system_capabilities": true
-# }
-# }
-# ]
-
-
-# After state:
-# -------------
-# path: /rest/restconf/data/openconfig_lldp:lldp/config
-# method: GET
-# data:
-# {
-# "openconfig_lldp:config": {
-# "enabled": true,
-# "hello-timer": 10000,
-# "suppress-tlv-advertisement": [
-# "SYSTEM_NAME",
-# "SYSTEM_DESCRIPTION",
-# "PORT_DESCRIPTION",
-# "MANAGEMENT_ADDRESS"
-# ],
-# "system-description": "ExtremeXOS (X460G2-24t-10G4) version 30.2.1.8"
-# "system-name": "X460G2-24t-10G4"
-# }
-# }
-
-
-# Using deleted
-
-
-# Before state:
-# -------------
-# path: /rest/restconf/data/openconfig_lldp:lldp/config
-# method: GET
-# data:
-# {
-# "openconfig_lldp:config": {
-# "enabled": true,
-# "hello-timer": 10000,
-# "suppress-tlv-advertisement": [
-# "SYSTEM_CAPABILITIES",
-# "MANAGEMENT_ADDRESS"
-# ],
-# "system-description": "ExtremeXOS (X460G2-24t-10G4) version 30.2.1.8"
-# "system-name": "X460G2-24t-10G4"
-# }
-# }
-
-- name: Delete attributes of given LLDP service (This won't delete the LLDP service itself)
- exos_lldp_global:
- config:
- state: deleted
-
-# Module Execution Results:
-# -------------------------
-#
-# "before": [
-# {
-# "interval": 10000,
-# "tlv_select": {
-# "system_name": true,
-# "system_description": true,
-# "port_description": true,
-# "management_address": false,
-# "system_capabilities": false
-# }
-# }
-# ]
-#
-# "requests": [
-# {
-# "data": {
-# "openconfig_lldp:config": {
-# "hello-timer": 30,
-# "suppress-tlv-advertisement": [
-# "SYSTEM_CAPABILITIES",
-# "PORT_DESCRIPTION",
-# "MANAGEMENT_ADDRESS"
-# ]
-# }
-# },
-# "method": "PATCH",
-# "path": "/rest/restconf/data/openconfig_lldp:lldp/config"
-# }
-# ]
-#
-# "after": [
-# {
-# "interval": 30,
-# "tlv_select": {
-# "system_name": true,
-# "system_description": true,
-# "port_description": false,
-# "management_address": false,
-# "system_capabilities": false
-# }
-# }
-# ]
-
-
-# After state:
-# -------------
-# path: /rest/restconf/data/openconfig_lldp:lldp/config
-# method: GET
-# data:
-# {
-# "openconfig_lldp:config": {
-# "enabled": true,
-# "hello-timer": 30,
-# "suppress-tlv-advertisement": [
-# "SYSTEM_CAPABILITIES",
-# "PORT_DESCRIPTION",
-# "MANAGEMENT_ADDRESS"
-# ],
-# "system-description": "ExtremeXOS (X460G2-24t-10G4) version 30.2.1.8"
-# "system-name": "X460G2-24t-10G4"
-# }
-# }
-
-
-"""
-RETURN = """
-before:
- description: The configuration as structured data prior to module invocation.
- returned: always
- sample: >
- The configuration returned will always be in the same format
- of the parameters above.
- type: list
-after:
- description: The configuration as structured data after module completion.
- returned: when changed
- sample: >
- The configuration returned will always be in the same format
- of the parameters above.
- type: list
-requests:
- description: The set of requests pushed to the remote device.
- returned: always
- type: list
- sample: [{"data": "...", "method": "...", "path": "..."}, {"data": "...", "method": "...", "path": "..."}, {"data": "...", "method": "...", "path": "..."}]
-"""
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.exos.argspec.lldp_global.lldp_global import Lldp_globalArgs
-from ansible_collections.community.general.plugins.module_utils.network.exos.config.lldp_global.lldp_global import Lldp_global
-
-
-def main():
- """
- Main entry point for module execution
-
- :returns: the result form module invocation
- """
- required_if = [('state', 'merged', ('config',)),
- ('state', 'replaced', ('config',))]
- module = AnsibleModule(argument_spec=Lldp_globalArgs.argument_spec, required_if=required_if,
- supports_check_mode=True)
-
- result = Lldp_global(module).execute_module()
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/exos/exos_lldp_interfaces.py b/plugins/modules/network/exos/exos_lldp_interfaces.py
deleted file mode 100644
index 744f76c24b..0000000000
--- a/plugins/modules/network/exos/exos_lldp_interfaces.py
+++ /dev/null
@@ -1,679 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-"""
-The module file for exos_lldp_interfaces
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- 'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'
-}
-
-DOCUMENTATION = '''
----
-module: exos_lldp_interfaces
-short_description: Manage link layer discovery protocol (LLDP) attributes of interfaces on EXOS platforms.
-description:
- - This module manages link layer discovery protocol (LLDP) attributes of interfaces on Extreme Networks EXOS platforms.
-author: Jayalakshmi Viswanathan (@JayalakshmiV)
-options:
- config:
- description: The list of link layer discovery protocol interface attribute configurations
- type: list
- elements: dict
- suboptions:
- name:
- description:
- - Name of the interface LLDP needs to be configured on.
- type: str
- required: True
- enabled:
- description:
- - This is a boolean value to control disabling of LLDP on the interface C(name)
- type: bool
- state:
- description:
- - The state the configuration should be left in.
- type: str
- choices:
- - merged
- - replaced
- - overridden
- - deleted
- default: merged
-'''
-EXAMPLES = """
-# Using merged
-
-# Before state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-lldp:lldp/interfaces?depth=4
-# method: GET
-# data:
-# {
-# "openconfig-lldp:interfaces": {
-# "interface": [
-# {
-# "config": {
-# "enabled": true,
-# "name": "1"
-# }
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "2"
-# }
-# },
-# {
-# "config": {
-# "enabled": false,
-# "name": "3"
-# }
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "4"
-# }
-# },
-# {
-# "config": {
-# "enabled": false,
-# "name": "5"
-# }
-# }
-# ]
-# }
-# }
-
-- name: Merge provided configuration with device configuration
- exos_lldp_interfaces:
- config:
- - name: '2'
- enabled: false
- - name: '5'
- enabled: true
- state: merged
-
-# Module Execution Results:
-# -------------------------
-#
-# "before":
-# - name: '1'
-# enabled: True
-# - name: '2'
-# enabled: True
-# - name: '3'
-# enabled: False
-# - name: '4'
-# enabled: True
-# - name: '5'
-# enabled: False
-#
-# "requests": [
-# {
-# "data": |
-# {
-# "openconfig-lldp:config": {
-# "enabled": false,
-# "name": "2"
-# }
-# }
-# "method": "PATCH",
-# "path": "/rest/restconf/data/openconfig-lldp:lldp/interfaces/interface=2/config"
-# },
-# {
-# "data": |
-# {
-# "openconfig-lldp:config": {
-# "enabled": true,
-# "name": "5"
-# }
-# }
-# "method": "PATCH",
-# "path": "/rest/restconf/data/openconfig-lldp:lldp/interfaces/interface=5/config"
-# }
-# ]
-#
-# "after":
-# - name: '1'
-# enabled: True
-# - name: '2'
-# enabled: False
-# - name: '3'
-# enabled: False
-# - name: '4'
-# enabled: True
-# - name: '5'
-# enabled: True
-
-# After state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-lldp:lldp/interfaces?depth=4
-# method: GET
-# data:
-# {
-# "openconfig-lldp:interfaces": {
-# "interface": [
-# {
-# "config": {
-# "enabled": true,
-# "name": "1"
-# }
-# },
-# {
-# "config": {
-# "enabled": false,
-# "name": "2"
-# }
-# },
-# {
-# "config": {
-# "enabled": false,
-# "name": "3"
-# }
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "4"
-# }
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "5"
-# }
-# }
-# ]
-# }
-# }
-
-
-# Using replaced
-
-# Before state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-lldp:lldp/interfaces?depth=4
-# method: GET
-# data:
-# {
-# "openconfig-lldp:interfaces": {
-# "interface": [
-# {
-# "config": {
-# "enabled": true,
-# "name": "1"
-# }
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "2"
-# }
-# },
-# {
-# "config": {
-# "enabled": false,
-# "name": "3"
-# }
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "4"
-# }
-# },
-# {
-# "config": {
-# "enabled": false,
-# "name": "5"
-# }
-# }
-# ]
-# }
-# }
-
-- name: Replaces device configuration of listed lldp_interfaces with provided configuration
- exos_lldp_interfaces:
- config:
- - name: '1'
- enabled: false
- - name: '3'
- enabled: true
- state: merged
-
-# Module Execution Results:
-# -------------------------
-#
-# "before":
-# - name: '1'
-# enabled: True
-# - name: '2'
-# enabled: True
-# - name: '3'
-# enabled: False
-# - name: '4'
-# enabled: True
-# - name: '5'
-# enabled: False
-#
-# "requests": [
-# {
-# "data": |
-# {
-# "openconfig-lldp:config": {
-# "enabled": false,
-# "name": "1"
-# }
-# }
-# "method": "PATCH",
-# "path": "/rest/restconf/data/openconfig-lldp:lldp/interfaces/interface=1/config"
-# },
-# {
-# "data": |
-# {
-# "openconfig-lldp:config": {
-# "enabled": true,
-# "name": "3"
-# }
-# }
-# "method": "PATCH",
-# "path": "/rest/restconf/data/openconfig-lldp:lldp/interfaces/interface=3/config"
-# }
-# ]
-#
-# "after":
-# - name: '1'
-# enabled: False
-# - name: '2'
-# enabled: True
-# - name: '3'
-# enabled: True
-# - name: '4'
-# enabled: True
-# - name: '5'
-# enabled: False
-
-# After state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-lldp:lldp/interfaces?depth=4
-# method: GET
-# data:
-# {
-# "openconfig-lldp:interfaces": {
-# "interface": [
-# {
-# "config": {
-# "enabled": false,
-# "name": "1"
-# }
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "2"
-# }
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "3"
-# }
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "4"
-# }
-# },
-# {
-# "config": {
-# "enabled": false,
-# "name": "5"
-# }
-# }
-# ]
-# }
-# }
-
-
-# Using deleted
-
-# Before state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-lldp:lldp/interfaces?depth=4
-# method: GET
-# data:
-# {
-# "openconfig-lldp:interfaces": {
-# "interface": [
-# {
-# "config": {
-# "enabled": false,
-# "name": "1"
-# },
-# },
-# {
-# "config": {
-# "enabled": false,
-# "name": "2"
-# },
-# },
-# {
-# "config": {
-# "enabled": false,
-# "name": "3"
-# },
-# }
-# ]
-# }
-# }
-
-- name: Delete lldp interface configuration (this will not delete other lldp configuration)
- exos_lldp_interfaces:
- config:
- - name: '1'
- - name: '3'
- state: deleted
-
-# Module Execution Results:
-# -------------------------
-#
-# "before":
-# - name: '1'
-# enabled: False
-# - name: '2'
-# enabled: False
-# - name: '3'
-# enabled: False
-#
-# "requests": [
-# {
-# "data": |
-# {
-# "openconfig-lldp:config": {
-# "enabled": true,
-# "name": "1"
-# }
-# }
-# "method": "PATCH",
-# "path": "/rest/restconf/data/openconfig-lldp:lldp/interfaces/interface=1/config"
-# },
-# {
-# "data": |
-# {
-# "openconfig-lldp:config": {
-# "enabled": true,
-# "name": "3"
-# }
-# }
-# "method": "PATCH",
-# "path": "/rest/restconf/data/openconfig-lldp:lldp/interfaces/interface=3/config"
-# }
-# ]
-#
-# "after":
-# - name: '1'
-# enabled: True
-# - name: '2'
-# enabled: False
-# - name: '3'
-# enabled: True
-#
-# After state:
-# -------------
-# path: /rest/restconf/data/openconfig-lldp:lldp/interfaces?depth=4
-# method: GET
-# data:
-# {
-# "openconfig-lldp:interfaces": {
-# "interface": [
-# {
-# "config": {
-# "enabled": true,
-# "name": "1"
-# },
-# },
-# {
-# "config": {
-# "enabled": false,
-# "name": "2"
-# },
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "3"
-# },
-# }
-# ]
-# }
-# }
-
-
-# Using overridden
-
-# Before state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-lldp:lldp/interfaces?depth=4
-# method: GET
-# data:
-# {
-# "openconfig-lldp:interfaces": {
-# "interface": [
-# {
-# "config": {
-# "enabled": true,
-# "name": "1"
-# }
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "2"
-# }
-# },
-# {
-# "config": {
-# "enabled": false,
-# "name": "3"
-# }
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "4"
-# }
-# },
-# {
-# "config": {
-# "enabled": false,
-# "name": "5"
-# }
-# }
-# ]
-# }
-# }
-
-- name: Override device configuration of all lldp_interfaces with provided configuration
- exos_lldp_interfaces:
- config:
- - name: '3'
- enabled: true
- state: overridden
-
-# Module Execution Results:
-# -------------------------
-#
-# "before":
-# - name: '1'
-# enabled: True
-# - name: '2'
-# enabled: True
-# - name: '3'
-# enabled: False
-# - name: '4'
-# enabled: True
-# - name: '5'
-# enabled: False
-#
-# "requests": [
-# {
-# "data": |
-# {
-# "openconfig-lldp:config": {
-# "enabled": true,
-# "name": "5"
-# }
-# }
-# "method": "PATCH",
-# "path": "/rest/restconf/data/openconfig-lldp:lldp/interfaces/interface=5/config"
-# },
-# {
-# "data": |
-# {
-# "openconfig-lldp:config": {
-# "enabled": true,
-# "name": "3"
-# }
-# }
-# "method": "PATCH",
-# "path": "/rest/restconf/data/openconfig-lldp:lldp/interfaces/interface=3/config"
-# }
-# ]
-#
-# "after":
-# - name: '1'
-# enabled: True
-# - name: '2'
-# enabled: True
-# - name: '3'
-# enabled: True
-# - name: '4'
-# enabled: True
-# - name: '5'
-# enabled: True
-
-# After state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-lldp:lldp/interfaces?depth=4
-# method: GET
-# data:
-# {
-# "openconfig-lldp:interfaces": {
-# "interface": [
-# {
-# "config": {
-# "enabled": true,
-# "name": "1"
-# }
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "2"
-# }
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "3"
-# }
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "4"
-# }
-# },
-# {
-# "config": {
-# "enabled": true,
-# "name": "5"
-# }
-# }
-# ]
-# }
-# }
-
-
-"""
-RETURN = """
-before:
- description: The configuration prior to the model invocation.
- returned: always
- sample: >
- The configuration returned will always be in the same format
- of the parameters above.
- type: list
-after:
- description: The resulting configuration model invocation.
- returned: when changed
- sample: >
- The configuration returned will always be in the same format
- of the parameters above.
- type: list
-requests:
- description: The set of requests pushed to the remote device.
- returned: always
- type: list
- sample: [{"data": "...", "method": "...", "path": "..."}, {"data": "...", "method": "...", "path": "..."}, {"data": "...", "method": "...", "path": "..."}]
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.exos.argspec.lldp_interfaces.lldp_interfaces import Lldp_interfacesArgs
-from ansible_collections.community.general.plugins.module_utils.network.exos.config.lldp_interfaces.lldp_interfaces import Lldp_interfaces
-
-
-def main():
- """
- Main entry point for module execution
-
- :returns: the result form module invocation
- """
- required_if = [('state', 'merged', ('config', )),
- ('state', 'replaced', ('config', ))]
- module = AnsibleModule(argument_spec=Lldp_interfacesArgs.argument_spec,
- required_if=required_if,
- supports_check_mode=True)
-
- result = Lldp_interfaces(module).execute_module()
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/exos/exos_vlans.py b/plugins/modules/network/exos/exos_vlans.py
deleted file mode 100644
index d828c7cd70..0000000000
--- a/plugins/modules/network/exos/exos_vlans.py
+++ /dev/null
@@ -1,758 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-
-"""
-The module file for exos_vlans
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- 'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'
-}
-
-DOCUMENTATION = '''
----
-module: exos_vlans
-short_description: Manage VLANs on Extreme Networks EXOS devices.
-description: This module provides declarative management of VLANs on Extreme Networks EXOS network devices.
-author: Jayalakshmi Viswanathan (@jayalakshmiV)
-notes:
- - Tested against EXOS 30.2.1.8
- - This module works with connection C(httpapi).
- See L(EXOS Platform Options,../network/user_guide/platform_exos.html)
-options:
- config:
- description: A dictionary of VLANs options
- type: list
- elements: dict
- suboptions:
- name:
- description:
- - Ascii name of the VLAN.
- type: str
- vlan_id:
- description:
- - ID of the VLAN. Range 1-4094
- type: int
- required: True
- state:
- description:
- - Operational state of the VLAN
- type: str
- choices:
- - active
- - suspend
- default: active
- state:
- description:
- - The state the configuration should be left in
- type: str
- choices:
- - merged
- - replaced
- - overridden
- - deleted
- default: merged
-'''
-EXAMPLES = """
-# Using deleted
-
-# Before state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-vlan:vlans/
-# method: GET
-# data:
-# {
-# "openconfig-vlan:vlans": {
-# "vlan": [
-# {
-# "config": {
-# "name": "Default",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 1
-# },
-# },
-# {
-# "config": {
-# "name": "vlan_10",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 10
-# },
-# },
-# {
-# "config": {
-# "name": "vlan_20",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 20
-# },
-# },
-# {
-# "config": {
-# "name": "vlan_30",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 30
-# },
-# }
-# ]
-# }
-# }
-
-- name: Delete attributes of given VLANs
- exos_vlans:
- config:
- - vlan_id: 10
- - vlan_id: 20
- - vlan_id: 30
- state: deleted
-
-# Module Execution Results:
-# -------------------------
-#
-# "after": [
-# {
-# "name": "Default",
-# "state": "active",
-# "vlan_id": 1
-# }
-# ],
-#
-# "before": [
-# {
-# "name": "Default",
-# "state": "active",
-# "vlan_id": 1
-# },
-# {
-# "name": "vlan_10",
-# "state": "active",
-# "vlan_id": 10
-# },
-# {
-# "name": "vlan_20",
-# "state": "active",
-# "vlan_id": 20
-# }
-# {
-# "name": "vlan_30",
-# "state": "active",
-# "vlan_id": 30
-# }
-# ],
-#
-# "requests": [
-# {
-# "data": null,
-# "method": "DELETE",
-# "path": "/rest/restconf/data/openconfig-vlan:vlans/vlan=10"
-# },
-# {
-# "data": null,
-# "method": "DELETE",
-# "path": "/rest/restconf/data/openconfig-vlan:vlans/vlan=20"
-# },
-# {
-# "data": null,
-# "method": "DELETE",
-# "path": "/rest/restconf/data/openconfig-vlan:vlans/vlan=30"
-# }
-# ]
-#
-#
-# After state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-vlan:vlans/
-# method: GET
-# data:
-# {
-# "openconfig-vlan:vlans": {
-# "vlan": [
-# {
-# "config": {
-# "name": "Default",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 1
-# },
-# }
-# ]
-# }
-# }
-
-
-# Using merged
-
-# Before state:
-# -------------
-# path: /rest/restconf/data/openconfig-vlan:vlans/
-# method: GET
-# data:
-# {
-# "openconfig-vlan:vlans": {
-# "vlan": [
-# {
-# "config": {
-# "name": "Default",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 1
-# },
-# }
-# ]
-# }
-# }
-
-- name: Merge provided configuration with device configuration
- exos_vlans:
- config:
- - name: vlan_10
- vlan_id: 10
- state: active
- - name: vlan_20
- vlan_id: 20
- state: active
- - name: vlan_30
- vlan_id: 30
- state: active
- state: merged
-
-# Module Execution Results:
-# -------------------------
-#
-# "after": [
-# {
-# "name": "Default",
-# "state": "active",
-# "vlan_id": 1
-# },
-# {
-# "name": "vlan_10",
-# "state": "active",
-# "vlan_id": 10
-# },
-# {
-# "name": "vlan_20",
-# "state": "active",
-# "vlan_id": 20
-# },
-# {
-# "name": "vlan_30",
-# "state": "active",
-# "vlan_id": 30
-# }
-# ],
-#
-# "before": [
-# {
-# "name": "Default",
-# "state": "active",
-# "vlan_id": 1
-# }
-# ],
-#
-# "requests": [
-# {
-# "data": {
-# "openconfig-vlan:vlan": [
-# {
-# "config": {
-# "name": "vlan_10",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 10
-# }
-# }
-# ]
-# },
-# "method": "POST",
-# "path": "/rest/restconf/data/openconfig-vlan:vlans/"
-# },
-# {
-# "data": {
-# "openconfig-vlan:vlan": [
-# {
-# "config": {
-# "name": "vlan_20",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 20
-# }
-# }
-# ]
-# },
-# "method": "POST",
-# "path": "/rest/restconf/data/openconfig-vlan:vlans/"
-# },
-# "data": {
-# "openconfig-vlan:vlan": [
-# {
-# "config": {
-# "name": "vlan_30",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 30
-# }
-# }
-# ]
-# },
-# "method": "POST",
-# "path": "/rest/restconf/data/openconfig-vlan:vlans/"
-# }
-# ]
-#
-#
-# After state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-vlan:vlans/
-# method: GET
-# data:
-# {
-# "openconfig-vlan:vlans": {
-# "vlan": [
-# {
-# "config": {
-# "name": "Default",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 1
-# },
-# },
-# {
-# "config": {
-# "name": "vlan_10",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 10
-# },
-# },
-# {
-# "config": {
-# "name": "vlan_20",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 20
-# },
-# },
-# {
-# "config": {
-# "name": "vlan_30",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 30
-# },
-# }
-# ]
-# }
-# }
-
-
-# Using overridden
-
-# Before state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-vlan:vlans/
-# method: GET
-# data:
-# {
-# "openconfig-vlan:vlans": {
-# "vlan": [
-# {
-# "config": {
-# "name": "Default",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 1
-# },
-# },
-# {
-# "config": {
-# "name": "vlan_10",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 10
-# },
-# },
-# {
-# "config": {
-# "name": "vlan_20",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 20
-# },
-# },
-# {
-# "config": {
-# "name": "vlan_30",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 30
-# },
-# }
-# ]
-# }
-# }
-
-- name: Override device configuration of all VLANs with provided configuration
- exos_vlans:
- config:
- - name: TEST_VLAN10
- vlan_id: 10
- state: overridden
-
-# Module Execution Results:
-# -------------------------
-#
-# "after": [
-# {
-# "name": "Default",
-# "state": "active",
-# "vlan_id": 1
-# },
-# {
-# "name": "TEST_VLAN10",
-# "state": "active",
-# "vlan_id": 10
-# },
-# ],
-#
-# "before": [
-# {
-# "name": "Default",
-# "state": "active",
-# "vlan_id": 1
-# },
-# {
-# "name": "vlan_10",
-# "state": "active",
-# "vlan_id": 10
-# },
-# {
-# "name": "vlan_20",
-# "state": "active",
-# "vlan_id": 20
-# },
-# {
-# "name": "vlan_30",
-# "state": "active",
-# "vlan_id": 30
-# }
-# ],
-#
-# "requests": [
-# {
-# "data": {
-# "openconfig-vlan:vlan": {
-# "vlan": [
-# {
-# "config": {
-# "name": "TEST_VLAN10",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 10
-# }
-# }
-# ]
-# }
-# }
-# },
-# "method": "PATCH",
-# "path": "/rest/restconf/data/openconfig-vlan:vlans/"
-# },
-# {
-# "data": null,
-# "method": "DELETE",
-# "path": "/rest/restconf/data/openconfig-vlan:vlans/vlan=20"
-# },
-# {
-# "data": null,
-# "method": "DELETE",
-# "path": "/rest/restconf/data/openconfig-vlan:vlans/vlan=30"
-# }
-# ]
-#
-#
-# After state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-vlan:vlans/
-# method: GET
-# data:
-# {
-# "openconfig-vlan:vlans": {
-# "vlan": [
-# {
-# "config": {
-# "name": "Default",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 1
-# },
-# },
-# {
-# "config": {
-# "name": "TEST_VLAN10",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 10
-# },
-# }
-# ]
-# }
-# }
-
-
-# Using replaced
-
-# Before state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-vlan:vlans/
-# method: GET
-# data:
-# {
-# "openconfig-vlan:vlans": {
-# "vlan": [
-# {
-# "config": {
-# "name": "Default",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 1
-# },
-# },
-# {
-# "config": {
-# "name": "vlan_10",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 10
-# },
-# },
-# {
-# "config": {
-# "name": "vlan_20",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 20
-# },
-# },
-# {
-# "config": {
-# "name": "vlan_30",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 30
-# },
-# }
-# ]
-# }
-# }
-
-- name: Replaces device configuration of listed VLANs with provided configuration
- exos_vlans:
- config:
- - name: Test_VLAN20
- vlan_id: 20
- - name: Test_VLAN30
- vlan_id: 30
- state: replaced
-
-# Module Execution Results:
-# -------------------------
-#
-# "after": [
-# {
-# "name": "Default",
-# "state": "active",
-# "vlan_id": 1
-# },
-# {
-# "name": "vlan_10",
-# "state": "active",
-# "vlan_id": 10
-# },
-# {
-# "name": "TEST_VLAN20",
-# "state": "active",
-# "vlan_id": 20
-# },
-# {
-# "name": "TEST_VLAN30",
-# "state": "active",
-# "vlan_id": 30
-# }
-# ],
-#
-# "before": [
-# {
-# "name": "Default",
-# "state": "active",
-# "vlan_id": 1
-# },
-# {
-# "name": "vlan_10",
-# "state": "active",
-# "vlan_id": 10
-# },
-# {
-# "name": "vlan_20",
-# "state": "active",
-# "vlan_id": 20
-# },
-# {
-# "name": "vlan_30",
-# "state": "active",
-# "vlan_id": 30
-# }
-# ],
-#
-# "requests": [
-# {
-# "data": {
-# "openconfig-vlan:vlan": {
-# "vlan": [
-# {
-# "config": {
-# "name": "TEST_VLAN20",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 20
-# }
-# "config": {
-# "name": "TEST_VLAN30",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 30
-# }
-# }
-# ]
-# },
-# "method": "PATCH",
-# "path": "/rest/restconf/data/openconfig-vlan:vlans/"
-# }
-# ]
-#
-# After state:
-# -------------
-#
-# path: /rest/restconf/data/openconfig-vlan:vlans/
-# method: GET
-# data:
-# {
-# "openconfig-vlan:vlans": {
-# "vlan": [
-# {
-# "config": {
-# "name": "Default",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 1
-# },
-# },
-# {
-# "config": {
-# "name": "vlan_10",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 10
-# },
-# },
-# {
-# "config": {
-# "name": "TEST_VLAN20",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 20
-# },
-# },
-# {
-# "config": {
-# "name": "TEST_VLAN30",
-# "status": "ACTIVE",
-# "tpid": "oc-vlan-types:TPID_0x8100",
-# "vlan-id": 30
-# },
-# }
-# ]
-# }
-# }
-
-
-"""
-RETURN = """
-before:
- description: The configuration prior to the model invocation.
- returned: always
- sample: >
- The configuration returned will always be in the same format
- of the parameters above.
- type: list
-after:
- description: The resulting configuration model invocation.
- returned: when changed
- sample: >
- The configuration returned will always be in the same format
- of the parameters above.
- type: list
-requests:
- description: The set of requests pushed to the remote device.
- returned: always
- type: list
- sample: [{"data": "...", "method": "...", "path": "..."}, {"data": "...", "method": "...", "path": "..."}, {"data": "...", "method": "...", "path": "..."}]
-"""
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.exos.argspec.vlans.vlans import VlansArgs
-from ansible_collections.community.general.plugins.module_utils.network.exos.config.vlans.vlans import Vlans
-
-
-def main():
- """
- Main entry point for module execution
-
- :returns: the result form module invocation
- """
- required_if = [('state', 'merged', ('config',)),
- ('state', 'replaced', ('config',))]
- module = AnsibleModule(argument_spec=VlansArgs.argument_spec, required_if=required_if,
- supports_check_mode=True)
-
- result = Vlans(module).execute_module()
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/f5/bigip_asm_policy.py b/plugins/modules/network/f5/bigip_asm_policy.py
deleted file mode 100644
index 2217f0d780..0000000000
--- a/plugins/modules/network/f5/bigip_asm_policy.py
+++ /dev/null
@@ -1,1062 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright: (c) 2017, F5 Networks Inc.
-# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['deprecated'],
- 'supported_by': 'certified'}
-
-DOCUMENTATION = r'''
----
-module: bigip_asm_policy
-short_description: Manage BIG-IP ASM policies
-description:
- - Manage BIG-IP ASM policies.
-deprecated:
- removed_in: '2.12'
- alternative: bigip_asm_policy_manage
- why: >
- The bigip_asm_policy module has been split into three new modules to handle import, export and general policy
- management. This will allow scalability of the asm policy management as well as ease of maintenance.
- Additionally to further reduce the burden of having multiple smaller module F5 has created asm_policy
- role in Ansible Galaxy for a more declarative way of ASM policy management.
-options:
- active:
- description:
- - If C(yes) will apply and activate existing inactive policy. If C(no), it will
- deactivate existing active policy. Generally should be C(yes) only in cases where
- you want to activate new or existing policy.
- default: no
- type: bool
- name:
- description:
- - The ASM policy to manage or create.
- required: True
- state:
- description:
- - When C(state) is C(present), and C(file) or C(template) parameter is provided,
- new ASM policy is imported and created with the given C(name).
- - When C(state) is present and no C(file) or C(template) parameter is provided
- new blank ASM policy is created with the given C(name).
- - When C(state) is C(absent), ensures that the policy is removed, even if it is
- currently active.
- choices:
- - present
- - absent
- default: present
- file:
- description:
- - Full path to a policy file to be imported into the BIG-IP ASM.
- - Policy files exported from newer versions of BIG-IP cannot be imported into older
- versions of BIG-IP. The opposite, however, is true; you can import older into
- newer.
- template:
- description:
- - An ASM policy built-in template. If the template does not exist we will raise an error.
- - Once the policy has been created, this value cannot change.
- - The C(Comprehensive), C(Drupal), C(Fundamental), C(Joomla),
- C(Vulnerability Assessment Baseline), and C(Wordpress) templates are only available
- on BIG-IP versions >= 13.
- choices:
- - ActiveSync v1.0 v2.0 (http)
- - ActiveSync v1.0 v2.0 (https)
- - Comprehensive
- - Drupal
- - Fundamental
- - Joomla
- - LotusDomino 6.5 (http)
- - LotusDomino 6.5 (https)
- - OWA Exchange 2003 (http)
- - OWA Exchange 2003 (https)
- - OWA Exchange 2003 with ActiveSync (http)
- - OWA Exchange 2003 with ActiveSync (https)
- - OWA Exchange 2007 (http)
- - OWA Exchange 2007 (https)
- - OWA Exchange 2007 with ActiveSync (http)
- - OWA Exchange 2007 with ActiveSync (https)
- - OWA Exchange 2010 (http)
- - OWA Exchange 2010 (https)
- - Oracle 10g Portal (http)
- - Oracle 10g Portal (https)
- - Oracle Applications 11i (http)
- - Oracle Applications 11i (https)
- - PeopleSoft Portal 9 (http)
- - PeopleSoft Portal 9 (https)
- - Rapid Deployment Policy
- - SAP NetWeaver 7 (http)
- - SAP NetWeaver 7 (https)
- - SharePoint 2003 (http)
- - SharePoint 2003 (https)
- - SharePoint 2007 (http)
- - SharePoint 2007 (https)
- - SharePoint 2010 (http)
- - SharePoint 2010 (https)
- - Vulnerability Assessment Baseline
- - Wordpress
- partition:
- description:
- - Device partition to manage resources on.
- default: Common
-extends_documentation_fragment:
-- f5networks.f5_modules.f5
-
-author:
- - Wojciech Wypior (@wojtek0806)
- - Tim Rupp (@caphrim007)
-'''
-
-EXAMPLES = r'''
-- name: Import and activate ASM policy
- bigip_asm_policy:
- name: new_asm_policy
- file: /root/asm_policy.xml
- active: yes
- state: present
- provider:
- server: lb.mydomain.com
- user: admin
- password: secret
- delegate_to: localhost
-
-- name: Import ASM policy from template
- bigip_asm_policy:
- name: new_sharepoint_policy
- template: SharePoint 2007 (http)
- state: present
- provider:
- server: lb.mydomain.com
- user: admin
- password: secret
- delegate_to: localhost
-
-- name: Create blank ASM policy
- bigip_asm_policy:
- name: new_blank_policy
- state: present
- provider:
- server: lb.mydomain.com
- user: admin
- password: secret
- delegate_to: localhost
-
-- name: Create blank ASM policy and activate
- bigip_asm_policy:
- name: new_blank_policy
- active: yes
- state: present
- provider:
- server: lb.mydomain.com
- user: admin
- password: secret
- delegate_to: localhost
-
-- name: Activate ASM policy
- bigip_asm_policy:
- name: inactive_policy
- active: yes
- state: present
- provider:
- server: lb.mydomain.com
- user: admin
- password: secret
- delegate_to: localhost
-
-- name: Deactivate ASM policy
- bigip_asm_policy:
- name: active_policy
- state: present
- provider:
- server: lb.mydomain.com
- user: admin
- password: secret
- delegate_to: localhost
-
-- name: Import and activate ASM policy in Role
- bigip_asm_policy:
- name: new_asm_policy
- file: "{{ role_path }}/files/asm_policy.xml"
- active: yes
- state: present
- provider:
- server: lb.mydomain.com
- user: admin
- password: secret
- delegate_to: localhost
-
-- name: Import ASM binary policy
- bigip_asm_policy:
- name: new_asm_policy
- file: "/root/asm_policy.plc"
- active: yes
- state: present
- provider:
- server: lb.mydomain.com
- user: admin
- password: secret
- delegate_to: localhost
-'''
-
-RETURN = r'''
-active:
- description: Set when activating/deactivating ASM policy
- returned: changed
- type: bool
- sample: yes
-state:
- description: Action performed on the target device.
- returned: changed
- type: str
- sample: absent
-file:
- description: Local path to ASM policy file.
- returned: changed
- type: str
- sample: /root/some_policy.xml
-template:
- description: Name of the built-in ASM policy template
- returned: changed
- type: str
- sample: OWA Exchange 2007 (https)
-name:
- description: Name of the ASM policy to be managed/created
- returned: changed
- type: str
- sample: Asm_APP1_Transparent
-'''
-
-import os
-import time
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.basic import env_fallback
-from distutils.version import LooseVersion
-
-
-try:
- from library.module_utils.network.f5.bigip import F5RestClient
- from library.module_utils.network.f5.common import F5ModuleError
- from library.module_utils.network.f5.common import AnsibleF5Parameters
- from library.module_utils.network.f5.common import fq_name
- from library.module_utils.network.f5.common import f5_argument_spec
- from library.module_utils.network.f5.icontrol import upload_file
- from library.module_utils.network.f5.icontrol import tmos_version
- from library.module_utils.network.f5.icontrol import module_provisioned
-except ImportError:
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.bigip import F5RestClient
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import F5ModuleError
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import AnsibleF5Parameters
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import fq_name
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import f5_argument_spec
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.icontrol import upload_file
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.icontrol import tmos_version
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.icontrol import module_provisioned
-
-
-class Parameters(AnsibleF5Parameters):
- updatables = [
- 'active',
- ]
-
- returnables = [
- 'name',
- 'template',
- 'file',
- 'active',
- ]
-
- api_attributes = [
- 'name',
- 'file',
- 'active',
- ]
- api_map = {
- 'filename': 'file',
- }
-
- @property
- def template_link(self):
- if self._values['template_link'] is not None:
- return self._values['template_link']
- collection = self._templates_from_device()
- for resource in collection['items']:
- if resource['name'] == self.template.upper():
- return dict(link=resource['selfLink'])
- return None
-
- @property
- def full_path(self):
- return fq_name(self.name)
-
- def _templates_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/asm/policy-templates/".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- return response
-
- def to_return(self):
- result = {}
- for returnable in self.returnables:
- result[returnable] = getattr(self, returnable)
- result = self._filter_params(result)
- return result
-
-
-class V1Parameters(Parameters):
- @property
- def template(self):
- if self._values['template'] is None:
- return None
- template_map = {
- 'ActiveSync v1.0 v2.0 (http)': 'POLICY_TEMPLATE_ACTIVESYNC_V1_0_V2_0_HTTP',
- 'ActiveSync v1.0 v2.0 (https)': 'POLICY_TEMPLATE_ACTIVESYNC_V1_0_V2_0_HTTPS',
- 'LotusDomino 6.5 (http)': 'POLICY_TEMPLATE_LOTUSDOMINO_6_5_HTTP',
- 'LotusDomino 6.5 (https)': 'POLICY_TEMPLATE_LOTUSDOMINO_6_5_HTTPS',
- 'OWA Exchange 2003 (http)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2003_HTTP',
- 'OWA Exchange 2003 (https)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2003_HTTPS',
- 'OWA Exchange 2003 with ActiveSync (http)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2003_WITH_ACTIVESYNC_HTTP',
- 'OWA Exchange 2003 with ActiveSync (https)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2003_WITH_ACTIVESYNC_HTTPS',
- 'OWA Exchange 2007 (http)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2007_HTTP',
- 'OWA Exchange 2007 (https)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2007_HTTPS',
- 'OWA Exchange 2007 with ActiveSync (http)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2007_WITH_ACTIVESYNC_HTTP',
- 'OWA Exchange 2007 with ActiveSync (https)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2007_WITH_ACTIVESYNC_HTTPS',
- 'OWA Exchange 2010 (http)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2010_HTTP',
- 'OWA Exchange 2010 (https)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2010_HTTPS',
- 'Oracle 10g Portal (http)': 'POLICY_TEMPLATE_ORACLE_10G_PORTAL_HTTP',
- 'Oracle 10g Portal (https)': 'POLICY_TEMPLATE_ORACLE_10G_PORTAL_HTTPS',
- 'Oracle Applications 11i (http)': 'POLICY_TEMPLATE_ORACLE_APPLICATIONS_11I_HTTP',
- 'Oracle Applications 11i (https)': 'POLICY_TEMPLATE_ORACLE_APPLICATIONS_11I_HTTPS',
- 'PeopleSoft Portal 9 (http)': 'POLICY_TEMPLATE_PEOPLESOFT_PORTAL_9_HTTP',
- 'PeopleSoft Portal 9 (https)': 'POLICY_TEMPLATE_PEOPLESOFT_PORTAL_9_HTTPS',
- 'Rapid Deployment Policy': 'POLICY_TEMPLATE_RAPID_DEPLOYMENT',
- 'SAP NetWeaver 7 (http)': 'POLICY_TEMPLATE_SAP_NETWEAVER_7_HTTP',
- 'SAP NetWeaver 7 (https)': 'POLICY_TEMPLATE_SAP_NETWEAVER_7_HTTPS',
- 'SharePoint 2003 (http)': 'POLICY_TEMPLATE_SHAREPOINT_2003_HTTP',
- 'SharePoint 2003 (https)': 'POLICY_TEMPLATE_SHAREPOINT_2003_HTTPS',
- 'SharePoint 2007 (http)': 'POLICY_TEMPLATE_SHAREPOINT_2007_HTTP',
- 'SharePoint 2007 (https)': 'POLICY_TEMPLATE_SHAREPOINT_2007_HTTPS',
- 'SharePoint 2010 (http)': 'POLICY_TEMPLATE_SHAREPOINT_2010_HTTP',
- 'SharePoint 2010 (https)': 'POLICY_TEMPLATE_SHAREPOINT_2010_HTTPS'
- }
- if self._values['template'] in template_map:
- return template_map[self._values['template']]
- else:
- raise F5ModuleError(
- "The specified template is not valid for this version of BIG-IP."
- )
-
-
-class V2Parameters(Parameters):
- @property
- def template(self):
- if self._values['template'] is None:
- return None
- template_map = {
- 'ActiveSync v1.0 v2.0 (http)': 'POLICY_TEMPLATE_ACTIVESYNC_V1_0_V2_0_HTTP',
- 'ActiveSync v1.0 v2.0 (https)': 'POLICY_TEMPLATE_ACTIVESYNC_V1_0_V2_0_HTTPS',
- 'Comprehensive': 'POLICY_TEMPLATE_COMPREHENSIVE', # v13
- 'Drupal': 'POLICY_TEMPLATE_DRUPAL', # v13
- 'Fundamental': 'POLICY_TEMPLATE_FUNDAMENTAL', # v13
- 'Joomla': 'POLICY_TEMPLATE_JOOMLA', # v13
- 'LotusDomino 6.5 (http)': 'POLICY_TEMPLATE_LOTUSDOMINO_6_5_HTTP',
- 'LotusDomino 6.5 (https)': 'POLICY_TEMPLATE_LOTUSDOMINO_6_5_HTTPS',
- 'OWA Exchange 2003 (http)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2003_HTTP',
- 'OWA Exchange 2003 (https)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2003_HTTPS',
- 'OWA Exchange 2003 with ActiveSync (http)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2003_WITH_ACTIVESYNC_HTTP',
- 'OWA Exchange 2003 with ActiveSync (https)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2003_WITH_ACTIVESYNC_HTTPS',
- 'OWA Exchange 2007 (http)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2007_HTTP',
- 'OWA Exchange 2007 (https)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2007_HTTPS',
- 'OWA Exchange 2007 with ActiveSync (http)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2007_WITH_ACTIVESYNC_HTTP',
- 'OWA Exchange 2007 with ActiveSync (https)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2007_WITH_ACTIVESYNC_HTTPS',
- 'OWA Exchange 2010 (http)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2010_HTTP',
- 'OWA Exchange 2010 (https)': 'POLICY_TEMPLATE_OWA_EXCHANGE_2010_HTTPS',
- 'Oracle 10g Portal (http)': 'POLICY_TEMPLATE_ORACLE_10G_PORTAL_HTTP',
- 'Oracle 10g Portal (https)': 'POLICY_TEMPLATE_ORACLE_10G_PORTAL_HTTPS',
- 'Oracle Applications 11i (http)': 'POLICY_TEMPLATE_ORACLE_APPLICATIONS_11I_HTTP',
- 'Oracle Applications 11i (https)': 'POLICY_TEMPLATE_ORACLE_APPLICATIONS_11I_HTTPS',
- 'PeopleSoft Portal 9 (http)': 'POLICY_TEMPLATE_PEOPLESOFT_PORTAL_9_HTTP',
- 'PeopleSoft Portal 9 (https)': 'POLICY_TEMPLATE_PEOPLESOFT_PORTAL_9_HTTPS',
- 'Rapid Deployment Policy': 'POLICY_TEMPLATE_RAPID_DEPLOYMENT',
- 'SAP NetWeaver 7 (http)': 'POLICY_TEMPLATE_SAP_NETWEAVER_7_HTTP',
- 'SAP NetWeaver 7 (https)': 'POLICY_TEMPLATE_SAP_NETWEAVER_7_HTTPS',
- 'SharePoint 2003 (http)': 'POLICY_TEMPLATE_SHAREPOINT_2003_HTTP',
- 'SharePoint 2003 (https)': 'POLICY_TEMPLATE_SHAREPOINT_2003_HTTPS',
- 'SharePoint 2007 (http)': 'POLICY_TEMPLATE_SHAREPOINT_2007_HTTP',
- 'SharePoint 2007 (https)': 'POLICY_TEMPLATE_SHAREPOINT_2007_HTTPS',
- 'SharePoint 2010 (http)': 'POLICY_TEMPLATE_SHAREPOINT_2010_HTTP',
- 'SharePoint 2010 (https)': 'POLICY_TEMPLATE_SHAREPOINT_2010_HTTPS',
- 'Vulnerability Assessment Baseline': 'POLICY_TEMPLATE_VULNERABILITY_ASSESSMENT', # v13
- 'Wordpress': 'POLICY_TEMPLATE_WORDPRESS' # v13
- }
- return template_map[self._values['template']]
-
-
-class Changes(Parameters):
- @property
- def template(self):
- if self._values['template'] is None:
- return None
- template_map = {
- 'POLICY_TEMPLATE_ACTIVESYNC_V1_0_V2_0_HTTP': 'ActiveSync v1.0 v2.0 (http)',
- 'POLICY_TEMPLATE_ACTIVESYNC_V1_0_V2_0_HTTPS': 'ActiveSync v1.0 v2.0 (https)',
- 'POLICY_TEMPLATE_COMPREHENSIVE': 'Comprehensive',
- 'POLICY_TEMPLATE_DRUPAL': 'Drupal',
- 'POLICY_TEMPLATE_FUNDAMENTAL': 'Fundamental',
- 'POLICY_TEMPLATE_JOOMLA': 'Joomla',
- 'POLICY_TEMPLATE_LOTUSDOMINO_6_5_HTTP': 'LotusDomino 6.5 (http)',
- 'POLICY_TEMPLATE_LOTUSDOMINO_6_5_HTTPS': 'LotusDomino 6.5 (https)',
- 'POLICY_TEMPLATE_OWA_EXCHANGE_2003_HTTP': 'OWA Exchange 2003 (http)',
- 'POLICY_TEMPLATE_OWA_EXCHANGE_2003_HTTPS': 'OWA Exchange 2003 (https)',
- 'POLICY_TEMPLATE_OWA_EXCHANGE_2003_WITH_ACTIVESYNC_HTTP': 'OWA Exchange 2003 with ActiveSync (http)',
- 'POLICY_TEMPLATE_OWA_EXCHANGE_2003_WITH_ACTIVESYNC_HTTPS': 'OWA Exchange 2003 with ActiveSync (https)',
- 'POLICY_TEMPLATE_OWA_EXCHANGE_2007_HTTP': 'OWA Exchange 2007 (http)',
- 'POLICY_TEMPLATE_OWA_EXCHANGE_2007_HTTPS': 'OWA Exchange 2007 (https)',
- 'POLICY_TEMPLATE_OWA_EXCHANGE_2007_WITH_ACTIVESYNC_HTTP': 'OWA Exchange 2007 with ActiveSync (http)',
- 'POLICY_TEMPLATE_OWA_EXCHANGE_2007_WITH_ACTIVESYNC_HTTPS': 'OWA Exchange 2007 with ActiveSync (https)',
- 'POLICY_TEMPLATE_OWA_EXCHANGE_2010_HTTP': 'OWA Exchange 2010 (http)',
- 'POLICY_TEMPLATE_OWA_EXCHANGE_2010_HTTPS': 'OWA Exchange 2010 (https)',
- 'POLICY_TEMPLATE_ORACLE_10G_PORTAL_HTTP': 'Oracle 10g Portal (http)',
- 'POLICY_TEMPLATE_ORACLE_10G_PORTAL_HTTPS': 'Oracle 10g Portal (https)',
- 'POLICY_TEMPLATE_ORACLE_APPLICATIONS_11I_HTTP': 'Oracle Applications 11i (http)',
- 'POLICY_TEMPLATE_ORACLE_APPLICATIONS_11I_HTTPS': 'Oracle Applications 11i (https)',
- 'POLICY_TEMPLATE_PEOPLESOFT_PORTAL_9_HTTP': 'PeopleSoft Portal 9 (http)',
- 'POLICY_TEMPLATE_PEOPLESOFT_PORTAL_9_HTTPS': 'PeopleSoft Portal 9 (https)',
- 'POLICY_TEMPLATE_RAPID_DEPLOYMENT': 'Rapid Deployment Policy',
- 'POLICY_TEMPLATE_SAP_NETWEAVER_7_HTTP': 'SAP NetWeaver 7 (http)',
- 'POLICY_TEMPLATE_SAP_NETWEAVER_7_HTTPS': 'SAP NetWeaver 7 (https)',
- 'POLICY_TEMPLATE_SHAREPOINT_2003_HTTP': 'SharePoint 2003 (http)',
- 'POLICY_TEMPLATE_SHAREPOINT_2003_HTTPS': 'SharePoint 2003 (https)',
- 'POLICY_TEMPLATE_SHAREPOINT_2007_HTTP': 'SharePoint 2007 (http)',
- 'POLICY_TEMPLATE_SHAREPOINT_2007_HTTPS': 'SharePoint 2007 (https)',
- 'POLICY_TEMPLATE_SHAREPOINT_2010_HTTP': 'SharePoint 2010 (http)',
- 'POLICY_TEMPLATE_SHAREPOINT_2010_HTTPS': 'SharePoint 2010 (https)',
- 'POLICY_TEMPLATE_VULNERABILITY_ASSESSMENT': 'Vulnerability Assessment Baseline',
- 'POLICY_TEMPLATE_WORDPRESS': 'Wordpress',
- }
- return template_map[self._values['template']]
-
-
-class Difference(object):
- def __init__(self, want, have=None):
- self.want = want
- self.have = have
-
- def compare(self, param):
- try:
- result = getattr(self, param)
- return result
- except AttributeError:
- return self.__default(param)
-
- def __default(self, param):
- attr1 = getattr(self.want, param)
- try:
- attr2 = getattr(self.have, param)
- if attr1 != attr2:
- return attr1
- except AttributeError:
- return attr1
-
- @property
- def active(self):
- if self.want.active is True and self.have.active is False:
- return True
- if self.want.active is False and self.have.active is True:
- return False
-
-
-class BaseManager(object):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- self.have = None
- self.changes = Changes()
-
- def exec_module(self):
- changed = False
- result = dict()
- state = self.want.state
-
- if state == "present":
- changed = self.present()
- elif state == "absent":
- changed = self.absent()
-
- changes = self.changes.to_return()
- result.update(**changes)
- result.update(dict(changed=changed))
- self._announce_deprecations(result)
- return result
-
- def _announce_deprecations(self, result):
- warnings = result.pop('__warnings', [])
- for warning in warnings:
- self.client.module.deprecate(
- msg=warning['msg'],
- version=warning['version']
- )
-
- def _set_changed_options(self):
- changed = {}
- for key in Parameters.returnables:
- if getattr(self.want, key) is not None:
- changed[key] = getattr(self.want, key)
- if changed:
- self.changes = Changes(params=changed)
-
- def should_update(self):
- result = self._update_changed_options()
- if result:
- return True
- return False
-
- def _update_changed_options(self):
- diff = Difference(self.want, self.have)
- updatables = Parameters.updatables
- changed = dict()
- for k in updatables:
- change = diff.compare(k)
- if change is None:
- continue
- else:
- if isinstance(change, dict):
- changed.update(change)
- else:
- changed[k] = change
- if changed:
- self.changes = Changes(params=changed)
- return True
- return False
-
- def present(self):
- if self.exists():
- return self.update()
- else:
- return self.create()
-
- def absent(self):
- if not self.exists():
- return False
- else:
- return self.remove()
-
- def exists(self):
- uri = "https://{0}:{1}/mgmt/tm/asm/policies/".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if any(p['name'] == self.want.name and p['partition'] == self.want.partition for p in response['items']):
- return True
- return False
-
- def _file_is_missing(self):
- if self.want.template and self.want.file is None:
- return False
- if self.want.template is None and self.want.file is None:
- return False
- if not os.path.exists(self.want.file):
- return True
- return False
-
- def create(self):
- if self.want.active is None:
- self.want.update(dict(active=False))
- if self._file_is_missing():
- raise F5ModuleError(
- "The specified ASM policy file does not exist"
- )
- self._set_changed_options()
- if self.module.check_mode:
- return True
-
- if self.want.template is None and self.want.file is None:
- self.create_blank()
- else:
- if self.want.template is not None:
- self.create_from_template()
- elif self.want.file is not None:
- self.create_from_file()
-
- if self.want.active:
- self.activate()
- return True
- else:
- return True
-
- def update(self):
- self.have = self.read_current_from_device()
- if not self.should_update():
- return False
- if self.module.check_mode:
- return True
- self.update_on_device()
- if self.changes.active:
- self.activate()
- return True
-
- def activate(self):
- self.have = self.read_current_from_device()
- task_id = self.apply_on_device()
- if self.wait_for_task(task_id, 'apply'):
- return True
- else:
- raise F5ModuleError('Apply policy task failed.')
-
- def wait_for_task(self, task_id, task):
- uri = ''
- if task == 'apply':
- uri = "https://{0}:{1}/mgmt/tm/asm/tasks/apply-policy/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- task_id
- )
- elif task == 'import':
- uri = "https://{0}:{1}/mgmt/tm/asm/tasks/import-policy/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- task_id
- )
- while True:
- resp = self.client.api.get(uri)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- if response['status'] in ['COMPLETED', 'FAILURE']:
- break
- time.sleep(1)
-
- if response['status'] == 'FAILURE':
- return False
- if response['status'] == 'COMPLETED':
- return True
-
- def _get_policy_id(self):
- name = self.want.name
- partition = self.want.partition
- uri = "https://{0}:{1}/mgmt/tm/asm/policies/".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- policy_id = next(
- (p['id'] for p in response['items'] if p['name'] == name and p['partition'] == partition), None
- )
-
- if not policy_id:
- raise F5ModuleError("The policy was not found")
- return policy_id
-
- def update_on_device(self):
- params = self.changes.api_params()
- policy_id = self._get_policy_id()
- uri = "https://{0}:{1}/mgmt/tm/asm/policies/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- policy_id
- )
- if not params['active']:
- resp = self.client.api.patch(uri, json=params)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- def create_blank(self):
- self.create_on_device()
- if self.exists():
- return True
- else:
- raise F5ModuleError(
- 'Failed to create ASM policy: {0}'.format(self.want.name)
- )
-
- def remove(self):
- if self.module.check_mode:
- return True
- self.remove_from_device()
- if self.exists():
- raise F5ModuleError(
- 'Failed to delete ASM policy: {0}'.format(self.want.name)
- )
- return True
-
- def is_activated(self):
- if self.want.active is True:
- return True
- else:
- return False
-
- def read_current_from_device(self):
- policy_id = self._get_policy_id()
- uri = "https://{0}:{1}/mgmt/tm/asm/policies/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- policy_id
- )
- resp = self.client.api.get(uri)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- response.update((dict(self_link=response['selfLink'])))
-
- return Parameters(params=response)
-
- def upload_file_to_device(self, content, name):
- url = 'https://{0}:{1}/mgmt/shared/file-transfer/uploads'.format(
- self.client.provider['server'],
- self.client.provider['server_port']
- )
- try:
- upload_file(self.client, url, content, name)
- except F5ModuleError:
- raise F5ModuleError(
- "Failed to upload the file."
- )
-
- def import_to_device(self):
- name = os.path.split(self.want.file)[1]
- self.upload_file_to_device(self.want.file, name)
- time.sleep(2)
-
- full_name = fq_name(self.want.partition, self.want.name)
- cmd = 'tmsh load asm policy {0} file /var/config/rest/downloads/{1}'.format(full_name, name)
-
- uri = "https://{0}:{1}/mgmt/tm/util/bash/".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- args = dict(
- command='run',
- utilCmdArgs='-c "{0}"'.format(cmd)
- )
- resp = self.client.api.post(uri, json=args)
-
- try:
- response = resp.json()
- if 'commandResult' in response:
- if 'Unexpected Error' in response['commandResult']:
- raise F5ModuleError(response['commandResult'])
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- return True
-
- def remove_temp_policy_from_device(self):
- name = os.path.split(self.want.file)[1]
- tpath_name = '/var/config/rest/downloads/{0}'.format(name)
- uri = "https://{0}:{1}/mgmt/tm/util/unix-rm/".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- args = dict(
- command='run',
- utilCmdArgs=tpath_name
- )
- resp = self.client.api.post(uri, json=args)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- def apply_on_device(self):
- uri = "https://{0}:{1}/mgmt/tm/asm/tasks/apply-policy/".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- params = dict(policyReference={'link': self.have.self_link})
- resp = self.client.api.post(uri, json=params)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] in [400, 403]:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- return response['id']
-
- def create_from_template_on_device(self):
- full_name = fq_name(self.want.partition, self.want.name)
- cmd = 'tmsh create asm policy {0} policy-template {1}'.format(full_name, self.want.template)
- uri = "https://{0}:{1}/mgmt/tm/util/bash/".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- args = dict(
- command='run',
- utilCmdArgs='-c "{0}"'.format(cmd)
- )
- resp = self.client.api.post(uri, json=args)
-
- try:
- response = resp.json()
- if 'commandResult' in response:
- if 'Unexpected Error' in response['commandResult']:
- raise F5ModuleError(response['commandResult'])
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- def create_on_device(self):
- params = self.changes.api_params()
- params['name'] = self.want.name
- params['partition'] = self.want.partition
- # we need to remove active from params as API will raise an error if the active is set to True,
- # policies can only be activated via apply-policy task endpoint.
- params.pop('active')
- uri = "https://{0}:{1}/mgmt/tm/asm/policies/".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.post(uri, json=params)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] in [400, 401, 403]:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- time.sleep(2)
- return response['selfLink']
-
- def remove_from_device(self):
- policy_id = self._get_policy_id()
- uri = "https://{0}:{1}/mgmt/tm/asm/policies/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- policy_id
- )
- response = self.client.api.delete(uri)
- if response.status in [200, 201]:
- return True
- raise F5ModuleError(response.content)
-
-
-class ModuleManager(object):
- def __init__(self, *args, **kwargs):
- self.module = kwargs.get('module', None)
- self.client = F5RestClient(**self.module.params)
- self.kwargs = kwargs
-
- def exec_module(self):
- if not module_provisioned(self.client, 'asm'):
- raise F5ModuleError(
- "ASM must be provisioned to use this module."
- )
- if self.version_is_less_than_13():
- manager = self.get_manager('v1')
- else:
- manager = self.get_manager('v2')
- return manager.exec_module()
-
- def get_manager(self, type):
- if type == 'v1':
- return V1Manager(**self.kwargs)
- elif type == 'v2':
- return V2Manager(**self.kwargs)
-
- def version_is_less_than_13(self):
- version = tmos_version(self.client)
- if LooseVersion(version) < LooseVersion('13.0.0'):
- return True
- else:
- return False
-
-
-class V1Manager(BaseManager):
- def __init__(self, *args, **kwargs):
- module = kwargs.get('module', None)
- client = F5RestClient(**module.params)
- super(V1Manager, self).__init__(client=client, module=module)
- self.want = V1Parameters(params=module.params, client=client)
-
- def create_from_file(self):
- self.import_to_device()
- self.remove_temp_policy_from_device()
-
- def create_from_template(self):
- self.create_from_template_on_device()
-
-
-class V2Manager(BaseManager):
- def __init__(self, *args, **kwargs):
- module = kwargs.get('module', None)
- client = F5RestClient(**module.params)
- super(V2Manager, self).__init__(client=client, module=module)
- self.want = V2Parameters(params=module.params, client=client)
-
- def create_from_template(self):
- if not self.create_from_template_on_device():
- return False
-
- def create_from_file(self):
- if not self.import_to_device():
- return False
- self.remove_temp_policy_from_device()
-
-
-class ArgumentSpec(object):
- def __init__(self):
- self.template_map = [
- 'ActiveSync v1.0 v2.0 (http)',
- 'ActiveSync v1.0 v2.0 (https)',
- 'Comprehensive',
- 'Drupal',
- 'Fundamental',
- 'Joomla',
- 'LotusDomino 6.5 (http)',
- 'LotusDomino 6.5 (https)',
- 'OWA Exchange 2003 (http)',
- 'OWA Exchange 2003 (https)',
- 'OWA Exchange 2003 with ActiveSync (http)',
- 'OWA Exchange 2003 with ActiveSync (https)',
- 'OWA Exchange 2007 (http)',
- 'OWA Exchange 2007 (https)',
- 'OWA Exchange 2007 with ActiveSync (http)',
- 'OWA Exchange 2007 with ActiveSync (https)',
- 'OWA Exchange 2010 (http)',
- 'OWA Exchange 2010 (https)',
- 'Oracle 10g Portal (http)',
- 'Oracle 10g Portal (https)',
- 'Oracle Applications 11i (http)',
- 'Oracle Applications 11i (https)',
- 'PeopleSoft Portal 9 (http)',
- 'PeopleSoft Portal 9 (https)',
- 'Rapid Deployment Policy',
- 'SAP NetWeaver 7 (http)',
- 'SAP NetWeaver 7 (https)',
- 'SharePoint 2003 (http)',
- 'SharePoint 2003 (https)',
- 'SharePoint 2007 (http)',
- 'SharePoint 2007 (https)',
- 'SharePoint 2010 (http)',
- 'SharePoint 2010 (https)',
- 'Vulnerability Assessment Baseline',
- 'Wordpress',
- ]
- self.supports_check_mode = True
- argument_spec = dict(
- name=dict(
- required=True,
- ),
- file=dict(type='path'),
- template=dict(
- choices=self.template_map
- ),
- active=dict(
- type='bool'
- ),
- state=dict(
- default='present',
- choices=['present', 'absent']
- ),
- partition=dict(
- default='Common',
- fallback=(env_fallback, ['F5_PARTITION'])
- )
- )
- self.argument_spec = {}
- self.argument_spec.update(f5_argument_spec)
- self.argument_spec.update(argument_spec)
-
-
-def main():
- spec = ArgumentSpec()
-
- module = AnsibleModule(
- argument_spec=spec.argument_spec,
- supports_check_mode=spec.supports_check_mode,
- mutually_exclusive=[
- ['file', 'template']
- ]
- )
-
- client = F5RestClient(**module.params)
-
- try:
- mm = ModuleManager(module=module)
- results = mm.exec_module()
- module.exit_json(**results)
- except F5ModuleError as ex:
- module.fail_json(msg=str(ex))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/f5/bigip_device_facts.py b/plugins/modules/network/f5/bigip_device_facts.py
deleted file mode 120000
index 0b7da78370..0000000000
--- a/plugins/modules/network/f5/bigip_device_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-bigip_device_info.py
\ No newline at end of file
diff --git a/plugins/modules/network/f5/bigip_device_info.py b/plugins/modules/network/f5/bigip_device_info.py
deleted file mode 100644
index 957ecbd2be..0000000000
--- a/plugins/modules/network/f5/bigip_device_info.py
+++ /dev/null
@@ -1,16267 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright: (c) 2017, F5 Networks Inc.
-# Copyright: (c) 2013, Matt Hite
-# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'certified'}
-
-DOCUMENTATION = r'''
----
-module: bigip_device_info
-short_description: Collect information from F5 BIG-IP devices
-description:
- - Collect information from F5 BIG-IP devices.
- - This module was called C(bigip_device_facts) before Ansible 2.9. The usage did not change.
-options:
- gather_subset:
- description:
- - When supplied, this argument will restrict the information returned to a given subset.
- - Can specify a list of values to include a larger subset.
- - Values can also be used with an initial C(!) to specify that a specific subset
- should not be collected.
- type: list
- required: True
- choices:
- - all
- - monitors
- - profiles
- - asm-policy-stats
- - asm-policies
- - asm-server-technologies
- - asm-signature-sets
- - client-ssl-profiles
- - devices
- - device-groups
- - external-monitors
- - fasthttp-profiles
- - fastl4-profiles
- - gateway-icmp-monitors
- - gtm-pools
- - gtm-servers
- - gtm-wide-ips
- - gtm-a-pools
- - gtm-a-wide-ips
- - gtm-aaaa-pools
- - gtm-aaaa-wide-ips
- - gtm-cname-pools
- - gtm-cname-wide-ips
- - gtm-mx-pools
- - gtm-mx-wide-ips
- - gtm-naptr-pools
- - gtm-naptr-wide-ips
- - gtm-srv-pools
- - gtm-srv-wide-ips
- - http-monitors
- - https-monitors
- - http-profiles
- - iapp-services
- - iapplx-packages
- - icmp-monitors
- - interfaces
- - internal-data-groups
- - irules
- - ltm-pools
- - ltm-policies
- - nodes
- - oneconnect-profiles
- - partitions
- - provision-info
- - self-ips
- - server-ssl-profiles
- - software-volumes
- - software-images
- - software-hotfixes
- - ssl-certs
- - ssl-keys
- - system-db
- - system-info
- - tcp-monitors
- - tcp-half-open-monitors
- - tcp-profiles
- - traffic-groups
- - trunks
- - udp-profiles
- - users
- - vcmp-guests
- - virtual-addresses
- - virtual-servers
- - vlans
- - "!all"
- - "!monitors"
- - "!profiles"
- - "!asm-policy-stats"
- - "!asm-policies"
- - "!asm-server-technologies"
- - "!asm-signature-sets"
- - "!client-ssl-profiles"
- - "!devices"
- - "!device-groups"
- - "!external-monitors"
- - "!fasthttp-profiles"
- - "!fastl4-profiles"
- - "!gateway-icmp-monitors"
- - "!gtm-pools"
- - "!gtm-servers"
- - "!gtm-wide-ips"
- - "!gtm-a-pools"
- - "!gtm-a-wide-ips"
- - "!gtm-aaaa-pools"
- - "!gtm-aaaa-wide-ips"
- - "!gtm-cname-pools"
- - "!gtm-cname-wide-ips"
- - "!gtm-mx-pools"
- - "!gtm-mx-wide-ips"
- - "!gtm-naptr-pools"
- - "!gtm-naptr-wide-ips"
- - "!gtm-srv-pools"
- - "!gtm-srv-wide-ips"
- - "!http-monitors"
- - "!https-monitors"
- - "!http-profiles"
- - "!iapp-services"
- - "!iapplx-packages"
- - "!icmp-monitors"
- - "!interfaces"
- - "!internal-data-groups"
- - "!irules"
- - "!ltm-pools"
- - "!ltm-policies"
- - "!nodes"
- - "!oneconnect-profiles"
- - "!partitions"
- - "!provision-info"
- - "!self-ips"
- - "!server-ssl-profiles"
- - "!software-volumes"
- - "!software-images"
- - "!software-hotfixes"
- - "!ssl-certs"
- - "!ssl-keys"
- - "!system-db"
- - "!system-info"
- - "!tcp-monitors"
- - "!tcp-half-open-monitors"
- - "!tcp-profiles"
- - "!traffic-groups"
- - "!trunks"
- - "!udp-profiles"
- - "!users"
- - "!vcmp-guests"
- - "!virtual-addresses"
- - "!virtual-servers"
- - "!vlans"
- aliases: ['include']
-extends_documentation_fragment:
-- f5networks.f5_modules.f5
-
-author:
- - Tim Rupp (@caphrim007)
- - Wojciech Wypior (@wojtek0806)
-'''
-
-EXAMPLES = r'''
-- name: Collect BIG-IP information
- bigip_device_info:
- gather_subset:
- - interfaces
- - vlans
- provider:
- server: lb.mydomain.com
- user: admin
- password: secret
- delegate_to: localhost
-
-- name: Collect all BIG-IP information
- bigip_device_info:
- gather_subset:
- - all
- provider:
- server: lb.mydomain.com
- user: admin
- password: secret
- delegate_to: localhost
-
-- name: Collect all BIG-IP information except trunks
- bigip_device_info:
- gather_subset:
- - all
- - "!trunks"
- provider:
- server: lb.mydomain.com
- user: admin
- password: secret
- delegate_to: localhost
-'''
-
-RETURN = r'''
-asm_policy_stats:
- description: Miscellaneous ASM policy related information.
- returned: When C(asm-policy-stats) is specified in C(gather_subset).
- type: complex
- contains:
- policies:
- description:
- - The total number of ASM policies on the device.
- returned: queried
- type: int
- sample: 3
- policies_active:
- description:
- - The number of ASM policies that are marked as active.
- returned: queried
- type: int
- sample: 3
- policies_attached:
- description:
- - The number of ASM policies that are attached to virtual servers.
- returned: queried
- type: int
- sample: 1
- policies_inactive:
- description:
- - The number of ASM policies that are marked as inactive.
- returned: queried
- type: int
- sample: 0
- policies_unattached:
- description:
- - The number of ASM policies that are not attached to a virtual server.
- returned: queried
- type: int
- sample: 3
- sample: hash/dictionary of values
-asm_policies:
- description: Detailed information for ASM policies present on device.
- returned: When C(asm-policies) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/foo_policy
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: foo_policy
- policy_id:
- description:
- - Generated ID of the ASM policy resource.
- returned: queried
- type: str
- sample: l0Ckxe-7yHsXp8U5tTgbFQ
- active:
- description:
- - Indicates if an ASM policy is active.
- returned: queried
- type: bool
- sample: yes
- protocol_independent:
- description:
- - Indicates if the ASM policy differentiates between HTTP/WS and HTTPS/WSS URLs.
- returned: queried
- type: bool
- sample: no
- has_parent:
- description:
- - Indicates if the ASM policy is a child of another ASM policy.
- returned: queried
- type: bool
- sample: no
- type:
- description:
- - The type of policy, can be C(Security) or C(Parent).
- returned: queried
- type: str
- sample: security
- virtual_servers:
- description:
- - Virtual server or servers which have this policy assigned to them.
- returned: queried
- type: list
- sample: ['/Common/foo_VS/']
- allowed_response_codes:
- description:
- - Lists the response status codes between 400 and 599 that the security profile considers legal.
- returned: queried
- type: list
- sample: ['400', '404']
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: Significant Policy Description
- learning_mode:
- description:
- - Determine how the policy is built.
- returned: queried
- type: str
- sample: manual
- enforcement_mode:
- description:
- - Specifies whether blocking is active or inactive for the ASM policy.
- returned: queried
- type: str
- sample: blocking
- trust_xff:
- description:
- - Indicates the system has confidence in an XFF (X-Forwarded-For) header in the request.
- returned: queried
- type: bool
- sample: yes
- custom_xff_headers:
- description:
- - List of custom XFF headers trusted by the system.
- returned: queried
- type: str
- sample: asm-proxy1
- case_insensitive:
- description:
- - Indicates if the ASM policy treats file types, URLs, and parameters as case sensitive.
- returned: queried
- type: bool
- sample: yes
- signature_staging:
- description:
- - Specifies if the staging feature is active on the ASM policy.
- returned: queried
- type: bool
- sample: yes
- place_signatures_in_staging:
- description:
- - Specifies if the system places new or updated signatures in staging
- for the number of days specified in the enforcement readiness period.
- returned: queried
- type: bool
- sample: no
- enforcement_readiness_period:
- description:
- - Period in days both security policy entities and attack signatures
- remain in staging mode before the system suggests to enforce them.
- returned: queried
- type: int
- sample: 8
- path_parameter_handling:
- description:
- - Specifies how the system handles path parameters that are attached to path segments in URIs.
- returned: queried
- type: str
- sample: ignore
- trigger_asm_irule_event:
- description:
- - Indicates if iRule event is enabled.
- returned: queried
- type: str
- sample: disabled
- inspect_http_uploads:
- description:
- - Specify if the system should inspect all http uploads.
- returned: queried
- type: bool
- sample: yes
- mask_credit_card_numbers_in_request:
- description:
- - Indicates if the system masks credit card numbers.
- returned: queried
- type: bool
- sample: no
- maximum_http_header_length:
- description:
- - Maximum length of an HTTP header name and value that the system processes.
- returned: queried
- type: int
- sample: 8192
- use_dynamic_session_id_in_url:
- description:
- - Specifies how the security policy processes URLs that use dynamic sessions.
- returned: queried
- type: bool
- sample: no
- maximum_cookie_header_length:
- description:
- - Maximum length of a cookie header name and value that the system processes.
- returned: queried
- type: int
- sample: 8192
- application_language:
- description:
- - The language encoding for the web application.
- returned: queried
- type: str
- sample: utf-8
- disallowed_geolocations:
- description:
- - Displays countries that may not access the web application.
- returned: queried
- type: str
- sample: Argentina
- csrf_protection_enabled:
- description:
- - Specifies if CSRF protection is active on the ASM policy.
- returned: queried
- type: bool
- sample: yes
- csrf_protection_ssl_only:
- description:
- - Specifies that only HTTPS URLs will be checked for CSRF protection.
- returned: queried
- type: bool
- sample: yes
- csrf_protection_expiration_time_in_seconds:
- description:
- - Specifies how long, in seconds, a configured CSRF token is valid before it expires.
- returned: queried
- type: int
- sample: 600
- csrf_urls:
- description:
- - Specifies a list of URLs for CSRF token verification.
- - In version 13.0.0 and above this has become a sub-collection and a list of dictionaries.
- - In version 12.x this is a list of simple strings.
- returned: queried
- type: complex
- contains:
- csrf_url_required_parameters:
- description:
- - Indicates whether to ignore or require one of the specified parameters is present
- in a request when checking if the URL entry matches the request.
- returned: queried
- type: str
- sample: ignore
- csrf_url_parameters_list:
- description:
- - List of parameters to look for in a request when checking if the URL entry matches the request.
- returned: queried
- type: list
- sample: ['fooparam']
- csrf_url:
- description:
- - Specifies an URL to protect.
- returned: queried
- type: str
- sample: ['/foo.html']
- csrf_url_method:
- description:
- - Method for the specified URL.
- returned: queried
- type: str
- sample: POST
- csrf_url_enforcement_action:
- description:
- - Indicates the action specified for the system to take when the URL entry matches.
- returned: queried
- type: str
- sample: none
- csrf_url_id:
- description:
- - Specified the generated ID for the configured CSRF url resource.
- returned: queried
- type: str
- sample: l0Ckxe-7yHsXp8U5tTgbFQ
- csrf_url_wildcard_order:
- description:
- - Specified the order in which the wildcard URLs are enforced.
- returned: queried
- type: str
- sample: 1
- sample: hash/dictionary of values
-asm_server_technologies:
- description: Detailed information for ASM server technologies present on device.
- returned: When C(asm-server-technologies) is specified in C(gather_subset).
- type: complex
- contains:
- id:
- description:
- - Displays the generated ID for the server technology resource.
- returned: queried
- type: str
- sample: l0Ckxe-7yHsXp8U5tTgbFQ
- server_technology_name:
- description:
- - Human friendly name of the server technology resource.
- returned: queried
- type: str
- sample: Wordpress
- server_technology_references:
- description:
- - List of dictionaries containing API self links of the associated technology resources.
- returned: queried
- type: complex
- contains:
- link:
- description:
- - A self link to an associated server technology.
- sample: https://localhost/mgmt/tm/asm/server-technologies/NQG7CT02OBC2cQWbnP7T-A?ver=13.1.0
- sample: hash/dictionary of values
-asm_signature_sets:
- description: Detailed information for ASM signature sets present on device.
- returned: When C(asm-signature-sets) is specified in C(gather_subset).
- type: complex
- contains:
- name:
- description:
- - Name of the signature set
- returned: queried
- type: str
- sample: WebSphere signatures
- id:
- description:
- - Displays the generated ID for the signature set resource.
- returned: queried
- type: str
- sample: l0Ckxe-7yHsXp8U5tTgbFQ
- type:
- description:
- - The method used to select signatures to be a part of the signature set.
- returned: queried
- type: str
- sample: filter-based
- category:
- description:
- - Displays the category of the signature set.
- returned: queried
- type: str
- sample: filter-based
- is_user_defined:
- description:
- - Specifies that this signature set was added by a user.
- returned: queried
- type: bool
- sample: no
- assign_to_policy_by_default:
- description:
- - Indicates whether the system assigns this signature set to a new created security policy by default.
- returned: queried
- type: bool
- sample: yes
- default_alarm:
- description:
- - Displays whether the security policy logs the request data in the Statistics
- screen if a request matches a signature that is included in the signature set
- returned: queried
- type: bool
- sample: yes
- default_block:
- description:
- - Displays, when the security policy's enforcement mode is Blocking,
- how the system treats requests that match a signature included in the signature set.
- returned: queried
- type: bool
- sample: yes
- default_learn:
- description:
- - Displays whether the security policy learns all requests that match a signature
- that is included in the signature set.
- returned: queried
- type: bool
- sample: yes
- sample: hash/dictionary of values
-client_ssl_profiles:
- description: Client SSL Profile related information.
- returned: When C(client-ssl-profiles) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/bigip02.internal
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: bigip02.internal
- alert_timeout:
- description:
- - Maximum time period in seconds to keep the SSL session active after alert
- message is sent, or indefinite.
- returned: queried
- type: int
- sample: 0
- allow_non_ssl:
- description:
- - Enables or disables non-SSL connections.
- returned: queried
- type: bool
- sample: yes
- authenticate_depth:
- description:
- - Specifies the authenticate depth. This is the client certificate chain maximum traversal depth.
- returned: queried
- type: int
- sample: 9
- authenticate_frequency:
- description:
- - Specifies how often the system authenticates a user.
- returned: queried
- type: str
- sample: once
- ca_file:
- description:
- - Specifies the certificate authority (CA) file name.
- returned: queried
- type: str
- sample: /Common/default-ca.crt
- cache_size:
- description:
- - Specifies the SSL session cache size.
- returned: queried
- type: int
- sample: 262144
- cache_timeout:
- description:
- - Specifies the SSL session cache timeout value.
- returned: queried
- type: int
- sample: 3600
- certificate_file:
- description:
- - Specifies the name of the certificate installed on the traffic
- management system for the purpose of terminating or initiating
- an SSL connection.
- returned: queried
- type: str
- sample: /Common/default.crt
- chain_file:
- description:
- - Specifies or builds a certificate chain file that a client can
- use to authenticate the profile.
- returned: queried
- type: str
- sample: /Common/ca-chain.crt
- ciphers:
- description:
- - Specifies a list of cipher names.
- returned: queried
- type: str
- sample: ['DEFAULT']
- crl_file:
- description:
- - Specifies the certificate revocation list file name.
- returned: queried
- type: str
- sample: /Common/default.crl
- parent:
- description:
- - Parent of the profile
- returned: queried
- type: str
- sample: /Common/clientssl
- description:
- description:
- - Description of the profile.
- returned: queried
- type: str
- sample: My profile
- modssl_methods:
- description:
- - Enables or disables ModSSL method emulation.
- returned: queried
- type: bool
- sample: no
- peer_certification_mode:
- description:
- - Specifies the peer certificate mode.
- returned: queried
- type: str
- sample: ignore
- sni_require:
- description:
- - When this option is C(yes), a client connection that does not
- specify a known server name or does not support SNI extension will
- be rejected.
- returned: queried
- type: bool
- sample: no
- sni_default:
- description:
- - When C(yes), this profile is the default SSL profile when the server
- name in a client connection does not match any configured server
- names, or a client connection does not specify any server name at
- all.
- returned: queried
- type: bool
- sample: yes
- strict_resume:
- description:
- - Enables or disables strict-resume.
- returned: queried
- type: bool
- sample: yes
- profile_mode_enabled:
- description:
- - Specifies the profile mode, which enables or disables SSL
- processing.
- returned: queried
- type: bool
- sample: yes
- renegotiation_maximum_record_delay:
- description:
- - Maximum number of SSL records that the traffic
- management system can receive before it renegotiates an SSL
- session.
- returned: queried
- type: int
- sample: 0
- renegotiation_period:
- description:
- - Number of seconds required to renegotiate an SSL
- session.
- returned: queried
- type: int
- sample: 0
- renegotiation:
- description:
- - Specifies whether renegotiations are enabled.
- returned: queried
- type: bool
- sample: yes
- server_name:
- description:
- - Specifies the server names to be matched with SNI (server name
- indication) extension information in ClientHello from a client
- connection.
- returned: queried
- type: str
- sample: bigip01
- session_ticket:
- description:
- - Enables or disables session-ticket.
- returned: queried
- type: bool
- sample: no
- unclean_shutdown:
- description:
- - Whether to force the SSL profile to perform a clean shutdown of all SSL
- connections or not
- returned: queried
- type: bool
- sample: no
- retain_certificate:
- description:
- - APM module requires storing certificate in SSL session. When
- C(no), certificate will not be stored in SSL session.
- returned: queried
- type: bool
- sample: yes
- secure_renegotiation_mode:
- description:
- - Specifies the secure renegotiation mode.
- returned: queried
- type: str
- sample: require
- handshake_timeout:
- description:
- - Specifies the handshake timeout in seconds.
- returned: queried
- type: int
- sample: 10
- forward_proxy_certificate_extension_include:
- description:
- - Specifies the extensions of the web server certificates to be
- included in the generated certificates using SSL Forward Proxy.
- returned: queried
- type: list
- sample: ["basic-constraints", "subject-alternative-name"]
- forward_proxy_certificate_lifespan:
- description:
- - Specifies the lifespan of the certificate generated using the SSL
- forward proxy feature.
- returned: queried
- type: int
- sample: 30
- forward_proxy_lookup_by_ipaddr_port:
- description:
- - Specifies whether to perform certificate look up by IP address and
- port number.
- returned: queried
- type: bool
- sample: no
- forward_proxy_enabled:
- description:
- - Enables or disables SSL forward proxy feature.
- returned: queried
- type: bool
- sample: yes
- forward_proxy_ca_passphrase:
- description:
- - Specifies the passphrase of the key file that is used as the
- certification authority key when SSL forward proxy feature is
- enabled.
- returned: queried
- type: str
- forward_proxy_ca_certificate_file:
- description:
- - Specifies the name of the certificate file that is used as the
- certification authority certificate when SSL forward proxy feature
- is enabled.
- returned: queried
- type: str
- forward_proxy_ca_key_file:
- description:
- - Specifies the name of the key file that is used as the
- certification authority key when SSL forward proxy feature is
- enabled.
- returned: queried
- type: str
- sample: hash/dictionary of values
-devices:
- description: Device related information.
- returned: When C(devices) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/bigip02.internal
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: bigip02.internal
- active_modules:
- description:
- - The currently licensed and provisioned modules on the device.
- returned: queried
- type: list
- sample: ["DNS Services (LAB)", "PSM, VE"]
- base_mac_address:
- description:
- - Media Access Control address (MAC address) of the device.
- returned: queried
- type: str
- sample: "fa:16:3e:c3:42:6f"
- build:
- description:
- - The minor version information of the total product version.
- returned: queried
- type: str
- sample: 0.0.1
- chassis_id:
- description:
- - Serial number of the device.
- returned: queried
- type: str
- sample: 11111111-2222-3333-444444444444
- chassis_type:
- description:
- - Displays the chassis type. The possible values are C(individual) and C(viprion).
- returned: queried
- type: str
- sample: individual
- comment:
- description:
- - User comments about the device.
- returned: queried
- type: str
- sample: My device
- configsync_address:
- description:
- - IP address used for configuration synchronization.
- returned: queried
- type: str
- sample: 10.10.10.10
- contact:
- description:
- - Administrator contact information.
- returned: queried
- type: str
- sample: The User
- description:
- description:
- - Description of the device.
- returned: queried
- type: str
- sample: My device
- edition:
- description:
- - Displays the software edition.
- returned: queried
- type: str
- sample: Point Release 7
- failover_state:
- description:
- - Device failover state.
- returned: queried
- type: str
- sample: active
- hostname:
- description:
- - Device hostname
- returned: queried
- type: str
- sample: bigip02.internal
- location:
- description:
- - Specifies the physical location of the device.
- returned: queried
- type: str
- sample: London
- management_address:
- description:
- - IP address of the management interface.
- returned: queried
- type: str
- sample: 3.3.3.3
- marketing_name:
- description:
- - Marketing name of the device platform.
- returned: queried
- type: str
- sample: BIG-IP Virtual Edition
- multicast_address:
- description:
- - Specifies the multicast IP address used for failover.
- returned: queried
- type: str
- sample: 4.4.4.4
- optional_modules:
- description:
- - Modules that are available for the current platform, but are not currently licensed.
- returned: queried
- type: list
- sample: ["App Mode (TMSH Only, No Root/Bash)", "BIG-IP VE, Multicast Routing"]
- platform_id:
- description:
- - Displays the device platform identifier.
- returned: queried
- type: str
- sample: Z100
- primary_mirror_address:
- description:
- - Specifies the IP address used for state mirroring.
- returned: queried
- type: str
- sample: 5.5.5.5
- product:
- description:
- - Displays the software product name.
- returned: queried
- type: str
- sample: BIG-IP
- secondary_mirror_address:
- description:
- - Secondary IP address used for state mirroring.
- returned: queried
- type: str
- sample: 2.2.2.2
- self:
- description:
- - Whether this device is the one that was queried for information, or not.
- returned: queried
- type: bool
- sample: yes
- software_version:
- description:
- - Displays the software version number.
- returned: queried
- type: str
- sample: 13.1.0.7
- timelimited_modules:
- description:
- - Displays the licensed modules that are time-limited.
- returned: queried
- type: list
- sample: ["IP Intelligence, 3Yr, ...", "PEM URL Filtering, 3Yr, ..."]
- timezone:
- description:
- - Displays the time zone configured on the device.
- returned: queried
- type: str
- sample: UTC
- unicast_addresses:
- description:
- - Specifies the entire set of unicast addresses used for failover.
- returned: queried
- type: complex
- contains:
- effective_ip:
- description:
- - The IP address that peers can use to reach this unicast address IP.
- returned: queried
- type: str
- sample: 5.4.3.5
- effective_port:
- description:
- - The port that peers can use to reach this unicast address.
- returned: queried
- type: int
- sample: 1026
- ip:
- description:
- - The IP address that the failover daemon will listen on for packets from its peers.
- returned: queried
- type: str
- sample: 5.4.3.5
- port:
- description:
- - The IP port that the failover daemon uses to accept packets from its peers.
- returned: queried
- type: int
- sample: 1026
- sample: hash/dictionary of values
-device_groups:
- description: Device group related information.
- returned: When C(device-groups) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/fasthttp
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: fasthttp
- autosync_enabled:
- description:
- - Whether the device group automatically synchronizes configuration data to its members.
- returned: queried
- type: bool
- sample: no
- description:
- description:
- - Description of the device group.
- returned: queried
- type: str
- sample: My device group
- devices:
- description:
- - List of devices that are in the group. Devices are listed by their C(full_path).
- returned: queried
- type: list
- sample: [/Common/bigip02.internal]
- full_load_on_sync:
- description:
- - Specifies that the entire configuration for a device group is sent when configuration
- synchronization is performed.
- returned: queried
- type: bool
- sample: yes
- incremental_config_sync_size_maximum:
- description:
- - Specifies the maximum size (in KB) to devote to incremental config sync cached transactions.
- returned: queried
- type: int
- sample: 1024
- network_failover_enabled:
- description:
- - Specifies whether network failover is used.
- returned: queried
- type: bool
- sample: yes
- type:
- description:
- - Specifies the type of device group.
- returned: queried
- type: str
- sample: sync-only
- asm_sync_enabled:
- description:
- - Specifies whether to synchronize ASM configurations of device group members.
- returned: queried
- type: bool
- sample: yes
- sample: hash/dictionary of values
-external_monitors:
- description: External monitor related information.
- returned: When C(external-monitors) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/external
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: external
- parent:
- description:
- - Profile from which this profile inherits settings.
- returned: queried
- type: str
- sample: external
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: My monitor
- destination:
- description:
- - Specifies the IP address and service port of the resource that is
- the destination of this monitor.
- returned: queried
- type: str
- sample: "*:*"
- args:
- description:
- - Specifies any command-line arguments that the script requires.
- returned: queried
- type: str
- sample: arg1 arg2 arg3
- external_program:
- description:
- - Specifies the name of the file for the monitor to use.
- returned: queried
- type: str
- sample: /Common/arg_example
- variables:
- description:
- - Specifies any variables that the script requires.
- type: complex
- sample: { "key1": "val", "key_2": "val 2" }
- interval:
- description:
- - Specifies, in seconds, the frequency at which the system issues
- the monitor check when either the resource is down or the status
- of the resource is unknown.
- returned: queried
- type: int
- sample: 5
- manual_resume:
- description:
- - Specifies whether the system automatically changes the status of a
- resource to up at the next successful monitor check.
- returned: queried
- type: bool
- sample: yes
- time_until_up:
- description:
- - Specifies the amount of time, in seconds, after the first
- successful response before a node is marked up.
- returned: queried
- type: int
- sample: 0
- timeout:
- description:
- - Specifies the number of seconds the target has in which to respond
- to the monitor request.
- returned: queried
- type: int
- sample: 16
- up_interval:
- description:
- - Specifies, in seconds, the frequency at which the system issues
- the monitor check when the resource is up.
- returned: queried
- type: int
- sample: 0
- sample: hash/dictionary of values
-fasthttp_profiles:
- description: FastHTTP profile related information.
- returned: When C(fasthttp-profiles) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/fasthttp
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: fasthttp
- client_close_timeout:
- description:
- - Number of seconds after which the system closes a client connection, when
- the system either receives a client FIN packet or sends a FIN packet to the client.
- returned: queried
- type: int
- sample: 5
- oneconnect_idle_timeout_override:
- description:
- - Number of seconds after which a server-side connection in a OneConnect pool
- is eligible for deletion, when the connection has no traffic.
- returned: queried
- type: int
- sample: 0
- oneconnect_maximum_reuse:
- description:
- - Maximum number of times that the system can re-use a current connection.
- returned: queried
- type: int
- sample: 0
- oneconnect_maximum_pool_size:
- description:
- - Maximum number of connections to a load balancing pool.
- returned: queried
- type: int
- sample: 2048
- oneconnect_minimum_pool_size:
- description:
- - Minimum number of connections to a load balancing pool.
- returned: queried
- type: int
- sample: 0
- oneconnect_replenish':
- description:
- - Specifies, when C(yes), that the system will not keep a steady-state maximum of
- connections to the back-end unless the number of connections to the pool have
- dropped beneath the C(minimum_pool_size) specified in the profile.
- returned: queried
- type: bool
- sample: yes
- oneconnect_ramp_up_increment:
- description:
- - The increment in which the system makes additional connections available, when
- all available connections are in use.
- returned: queried
- type: int
- sample: 4
- parent:
- description:
- - Profile from which this profile inherits settings.
- returned: queried
- type: str
- sample: fasthttp
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: My profile
- force_http_1_0_response:
- description:
- - Specifies, when C(yes), that the server sends responses to clients in the HTTP/1.0
- format.
- returned: queried
- type: bool
- sample: no
- request_header_insert:
- description:
- - A string that the system inserts as a header in an HTTP request. If the header
- exists already, the system does not replace it.
- returned: queried
- type: str
- sample: "X-F5-Authentication: foo"
- http_1_1_close_workarounds:
- description:
- - Specifies, when C(yes), that the server uses workarounds for HTTP 1.1 close issues.
- returned: queried
- type: bool
- sample: no
- idle_timeout:
- description:
- - Length of time that a connection is idle (has no traffic) before the connection
- is eligible for deletion.
- returned: queried
- type: int
- sample: 300
- insert_x_forwarded_for:
- description:
- - Whether the system inserts the X-Forwarded-For header in an HTTP request with the
- client IP address, to use with connection pooling.
- returned: queried
- type: bool
- sample: no
- maximum_header_size:
- description:
- - Maximum amount of HTTP header data that the system buffers before making a load
- balancing decision.
- returned: queried
- type: int
- sample: 32768
- maximum_requests:
- description:
- - Maximum number of requests that the system can receive on a client-side connection,
- before the system closes the connection.
- returned: queried
- type: int
- sample: 0
- maximum_segment_size_override:
- description:
- - Maximum segment size (MSS) override for server-side connections.
- returned: queried
- type: int
- sample: 0
- receive_window_size:
- description:
- - Amount of data the BIG-IP system can accept without acknowledging the server.
- returned: queried
- type: int
- sample: 0
- reset_on_timeout:
- description:
- - Specifies, when C(yes), that the system sends a reset packet (RST) in addition to
- deleting the connection, when a connection exceeds the idle timeout value.
- returned: queried
- type: bool
- sample: yes
- server_close_timeout:
- description:
- - Number of seconds after which the system closes a client connection, when the system
- either receives a server FIN packet or sends a FIN packet to the server.
- returned: queried
- type: int
- sample: 5
- server_sack:
- description:
- - Whether the BIG-IP system processes Selective ACK (Sack) packets in cookie responses
- from the server.
- returned: queried
- type: bool
- sample: no
- server_timestamp:
- description:
- - Whether the BIG-IP system processes timestamp request packets in cookie responses
- from the server.
- returned: queried
- type: bool
- sample: no
- unclean_shutdown:
- description:
- - How the system handles closing connections. Values provided may be C(enabled), C(disabled),
- or C(fast).
- returned: queried
- type: str
- sample: enabled
- sample: hash/dictionary of values
-fastl4_profiles:
- description: FastL4 profile related information.
- returned: When C(fastl4-profiles) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/fastl4
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: fastl4
- client_timeout:
- description:
- - Specifies late binding client timeout in seconds.
- - This is the number of seconds allowed for a client to transmit enough data to
- select a server pool.
- - If this timeout expires, the timeout-recovery option dictates whether
- to drop the connection or fallback to the normal FastL4 load-balancing method
- to pick a server pool.
- returned: queried
- type: int
- sample: 30
- parent:
- description:
- - Profile from which this profile inherits settings.
- returned: queried
- type: str
- sample: fastl4
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: My profile
- explicit_flow_migration:
- description:
- - Specifies whether to have the iRule code determine exactly when
- the FIX stream drops down to the ePVA hardware.
- returned: queried
- type: bool
- sample: yes
- hardware_syn_cookie:
- description:
- - Enables or disables hardware SYN cookie support when PVA10 is present on the system.
- - This option is deprecated in version 13.0.0 and is replaced by C(syn-cookie-enable).
- returned: queried
- type: bool
- sample: no
- idle_timeout:
- description:
- - Specifies the number of seconds that a connection is idle before the connection is
- eligible for deletion.
- - Values will be in the range of 0 to 4294967295 (inclusive).
- - C(0) is equivalent to the TMUI value "immediate".
- - C(4294967295) is equivalent to the TMUI value "indefinite".
- returned: queried
- type: int
- sample: 300
- dont_fragment_flag:
- description:
- - Describes the Don't Fragment (DF) bit setting in the IP Header of
- the outgoing TCP packet.
- - When C(pmtu), sets the outgoing IP Header DF bit based on IP pmtu
- setting(tm.pathmtudiscovery).
- - When C(preserve), sets the outgoing Packet's IP Header DF bit to be same as incoming
- IP Header DF bit.
- - When C(set), sets the outgoing packet's IP Header DF bit.
- - When C(clear), clears the outgoing packet's IP Header DF bit.
- returned: queried
- type: str
- sample: pmtu
- ip_tos_to_client:
- description:
- - Specifies an IP Type of Service (ToS) number for the client-side.
- - This option specifies the ToS level that the traffic management
- system assigns to IP packets when sending them to clients.
- returned: queried
- type: str or int
- sample: 200
- ip_tos_to_server:
- description:
- - Specifies an IP ToS number for the server side.
- - This option specifies the ToS level that the traffic management system assigns
- to IP packets when sending them to servers.
- returned: queried
- type: str or int
- sample: pass-through
- ttl_mode:
- description:
- - Describe the outgoing TCP packet's IP Header TTL mode.
- - When C(proxy), sets the outgoing IP Header TTL value to 255/64 for ipv4/ipv6
- respectively.
- - When C(preserve), sets the outgoing IP Header TTL value to be same as the
- incoming IP Header TTL value.
- - When C(decrement), sets the outgoing IP Header TTL value to be one less than
- the incoming TTL value.
- - When C(set), sets the outgoing IP Header TTL value to a specific value(as
- specified by C(ttl_v4) or C(ttl_v6).
- returned: queried
- type: str
- sample: preserve
- ttl_v4:
- description:
- - Specify the outgoing packet's IP Header TTL value for IPv4 traffic.
- - Maximum value that can be specified is 255.
- returned: queried
- type: int
- sample: 200
- ttl_v6:
- description:
- - Specify the outgoing packet's IP Header TTL value for IPv6
- traffic.
- - Maximum value that can be specified is 255.
- returned: queried
- type: int
- sample: 300
- keep_alive_interval:
- description:
- - Specifies the keep-alive probe interval, in seconds.
- - A value of 0 indicates keep-alive is disabled.
- returned: queried
- type: int
- sample: 10
- late_binding:
- description:
- - Specifies whether to enable or disable intelligent selection of a
- back-end server pool.
- returned: queried
- type: bool
- sample: yes
- link_qos_to_client:
- description:
- - Specifies a Link Quality of Service (QoS) (VLAN priority) number
- for the client side.
- - This option specifies the QoS level that the system assigns to packets
- when sending them to clients.
- returned: queried
- type: int or string
- sample: 7
- link_qos_to_server:
- description:
- - Specifies a Link QoS (VLAN priority) number for the server side.
- - This option specifies the QoS level that the system assigns to
- packets when sending them to servers.
- returned: queried
- type: int or string
- sample: 5
- loose_close:
- description:
- - Specifies that the system closes a loosely-initiated connection
- when the system receives the first FIN packet from either the
- client or the server.
- returned: queried
- type: bool
- sample: no
- loose_init:
- description:
- - Specifies that the system initializes a connection when it
- receives any Transmission Control Protocol (TCP) packet, rather
- than requiring a SYN packet for connection initiation.
- returned: queried
- type: bool
- sample: yes
- mss_override:
- description:
- - Specifies a maximum segment size (MSS) override for server
- connections. Note that this is also the MSS advertised to a client
- when a client first connects.
- - C(0) (zero), means the option is disabled. Otherwise, the value will be
- between 256 and 9162.
- returned: queried
- type: int
- sample: 500
- priority_to_client:
- description:
- - Specifies internal packet priority for the client side.
- - This option specifies the internal packet priority that the system
- assigns to packets when sending them to clients.
- returned: queried
- type: int or string
- sample: 300
- priority_to_server:
- description:
- - Specifies internal packet priority for the server side.
- - This option specifies the internal packet priority that the system
- assigns to packets when sending them to servers.
- returned: queried
- type: int or string
- sample: 200
- pva_acceleration:
- description:
- - Specifies the Packet Velocity(r) ASIC acceleration policy.
- returned: queried
- type: str
- sample: full
- pva_dynamic_client_packets:
- description:
- - Specifies the number of client packets before dynamic ePVA
- hardware re-offloading occurs.
- - Values will be between 0 and 10.
- returned: queried
- type: int
- sample: 8
- pva_dynamic_server_packets:
- description:
- - Specifies the number of server packets before dynamic ePVA
- hardware re-offloading occurs.
- - Values will be between 0 and 10.
- returned: queried
- type: int
- sample: 5
- pva_flow_aging:
- description:
- - Specifies if automatic aging from ePVA flow cache is enabled or not.
- returned: queried
- type: bool
- sample: yes
- pva_flow_evict:
- description:
- - Specifies if this flow can be evicted upon hash collision with a
- new flow learn snoop request.
- returned: queried
- type: bool
- sample: no
- pva_offload_dynamic:
- description:
- - Specifies whether PVA flow dynamic offloading is enabled or not.
- returned: queried
- type: bool
- sample: yes
- pva_offload_state:
- description:
- - Specifies at what stage the ePVA performs hardware offload.
- - When C(embryonic), implies at TCP CSYN or the first client UDP packet.
- - When C(establish), implies TCP 3WAY handshaking or UDP CS round trip are
- confirmed.
- returned: queried
- type: str
- sample: embryonic
- reassemble_fragments:
- description:
- - Specifies whether to reassemble fragments.
- returned: queried
- type: bool
- sample: yes
- receive_window:
- description:
- - Specifies the window size to use, in bytes.
- - The maximum is 2^31 for window scale enabling.
- returned: queried
- type: int
- sample: 1000
- reset_on_timeout:
- description:
- - Specifies whether you want to reset connections on timeout.
- returned: queried
- type: bool
- sample: yes
- rtt_from_client:
- description:
- - Enables or disables the TCP timestamp options to measure the round
- trip time to the client.
- returned: queried
- type: bool
- sample: no
- rtt_from_server:
- description:
- - Enables or disables the TCP timestamp options to measure the round
- trip time to the server.
- returned: queried
- type: bool
- sample: yes
- server_sack:
- description:
- - Specifies whether to support server sack option in cookie response
- by default.
- returned: queried
- type: bool
- sample: no
- server_timestamp:
- description:
- - Specifies whether to support server timestamp option in cookie
- response by default.
- returned: queried
- type: bool
- sample: yes
- software_syn_cookie:
- description:
- - Enables or disables software SYN cookie support when PVA10 is not present
- on the system.
- - This option is deprecated in version 13.0.0 and is replaced by
- C(syn_cookie_enabled).
- returned: queried
- type: bool
- sample: yes
- syn_cookie_enabled:
- description:
- - Enables syn-cookies capability on this virtual server.
- returned: queried
- type: bool
- sample: no
- syn_cookie_mss:
- description:
- - Specifies a maximum segment size (MSS) for server connections when
- SYN Cookie is enabled.
- returned: queried
- type: int
- sample: 2000
- syn_cookie_whitelist:
- description:
- - Specifies whether or not to use a SYN Cookie WhiteList when doing
- software SYN Cookies.
- returned: queried
- type: bool
- sample: no
- tcp_close_timeout:
- description:
- - Specifies a TCP close timeout in seconds.
- returned: queried
- type: int
- sample: 100
- generate_init_seq_number:
- description:
- - Specifies whether you want to generate TCP sequence numbers on all
- SYNs that conform with RFC1948, and allow timestamp recycling.
- returned: queried
- type: bool
- sample: yes
- tcp_handshake_timeout:
- description:
- - Specifies a TCP handshake timeout in seconds.
- returned: queried
- type: int
- sample: 5
- strip_sack:
- description:
- - Specifies whether you want to block the TCP SackOK option from
- passing to the server on an initiating SYN.
- returned: queried
- type: bool
- sample: yes
- tcp_time_wait_timeout:
- description:
- - Specifies a TCP time_wait timeout in milliseconds.
- returned: queried
- type: int
- sample: 60
- tcp_timestamp_mode:
- description:
- - Specifies how you want to handle the TCP timestamp.
- returned: queried
- type: str
- sample: preserve
- tcp_window_scale_mode:
- description:
- - Specifies how you want to handle the TCP window scale.
- returned: queried
- type: str
- sample: preserve
- timeout_recovery:
- description:
- - Specifies late binding timeout recovery mode. This is the action
- to take when late binding timeout occurs on a connection.
- - When C(disconnect), only the L7 iRule actions are acceptable to
- pick a server.
- - When C(fallback), the normal FastL4 load-balancing methods are acceptable
- to pick a server.
- returned: queried
- type: str
- sample: fallback
- sample: hash/dictionary of values
-gateway_icmp_monitors:
- description: Gateway ICMP monitor related information.
- returned: When C(gateway-icmp-monitors) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/gateway_icmp
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: gateway_icmp
- parent:
- description:
- - Profile from which this profile inherits settings.
- returned: queried
- type: str
- sample: gateway_icmp
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: My monitor
- adaptive:
- description:
- - Whether adaptive response time monitoring is enabled for this monitor.
- returned: queried
- type: bool
- sample: no
- adaptive_divergence_type:
- description:
- - Specifies whether the adaptive-divergence-value is C(relative) or
- C(absolute).
- returned: queried
- type: str
- sample: relative
- adaptive_divergence_value:
- description:
- - Specifies how far from mean latency each monitor probe is allowed
- to be.
- returned: queried
- type: int
- sample: 25
- adaptive_limit:
- description:
- - Specifies the hard limit, in milliseconds, which the probe is not
- allowed to exceed, regardless of the divergence value.
- returned: queried
- type: int
- sample: 200
- adaptive_sampling_timespan:
- description:
- - Specifies the size of the sliding window, in seconds, which
- records probe history.
- returned: queried
- type: int
- sample: 300
- destination:
- description:
- - Specifies the IP address and service port of the resource that is
- the destination of this monitor.
- returned: queried
- type: str
- sample: "*:*"
- interval:
- description:
- - Specifies, in seconds, the frequency at which the system issues
- the monitor check when either the resource is down or the status
- of the resource is unknown.
- returned: queried
- type: int
- sample: 5
- manual_resume:
- description:
- - Specifies whether the system automatically changes the status of a
- resource to up at the next successful monitor check.
- returned: queried
- type: bool
- sample: yes
- time_until_up:
- description:
- - Specifies the amount of time, in seconds, after the first
- successful response before a node is marked up.
- returned: queried
- type: int
- sample: 0
- timeout:
- description:
- - Specifies the number of seconds the target has in which to respond
- to the monitor request.
- returned: queried
- type: int
- sample: 16
- transparent:
- description:
- - Specifies whether the monitor operates in transparent mode.
- returned: queried
- type: bool
- sample: no
- up_interval:
- description:
- - Specifies, in seconds, the frequency at which the system issues
- the monitor check when the resource is up.
- returned: queried
- type: int
- sample: 0
- sample: hash/dictionary of values
-gtm_pools:
- description:
- - GTM pool related information.
- - Every "type" of pool has the exact same list of possible information. Therefore,
- the list of information here is presented once instead of 6 times.
- returned: When any of C(gtm-pools) or C(gtm-*-pools) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/pool1
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: pool1
- alternate_mode:
- description:
- - The load balancing mode that the system uses to load balance name resolution
- requests among the members of the pool.
- returned: queried
- type: str
- sample: drop-packet
- dynamic_ratio:
- description:
- - Whether or not the dynamic ratio load balancing algorithm is enabled for this
- pool.
- returned: queried
- type: bool
- sample: yes
- enabled:
- description:
- - Is the pool enabled.
- returned: queried
- type: bool
- disabled:
- description:
- - Is the pool disabled.
- returned: queried
- type: bool
- fallback_mode:
- description:
- - Specifies the load balancing mode that the system uses to load balance
- name resolution amongst the pool members if the preferred and alternate
- modes are unsuccessful in picking a pool.
- returned: queried
- type: str
- load_balancing_mode:
- description:
- - Specifies the preferred load balancing mode that the system uses to load
- balance requests across pool members.
- returned: queried
- type: str
- manual_resume:
- description:
- - Whether manual resume is enabled for this pool.
- returned: queried
- type: bool
- max_answers_returned:
- description:
- - Maximum number of available virtual servers that the system lists in a
- response.
- returned: queried
- type: int
- members:
- description:
- - Lists of members (and their configurations) in the pool.
- returned: queried
- type: complex
- partition:
- description:
- - Partition the pool exists on.
- returned: queried
- qos_hit_ratio:
- description:
- - Weight of the Hit Ratio performance factor for the QoS dynamic load
- balancing method.
- returned: queried
- type: int
- qos_hops:
- description:
- - Weight of the Hops performance factor when load balancing mode or fallback mode
- is QoS.
- returned: queried
- type: int
- qos_kilobytes_second:
- description:
- - Weight assigned to Kilobytes per Second performance factor when load balancing
- option is QoS.
- returned: queried
- type: int
- qos_lcs:
- description:
- - Weight assign to the Link Capacity performance factor when load balancing option
- is QoS.
- returned: queried
- type: int
- qos_packet_rate:
- description:
- - Weight assign to the Packet Rate performance factor when load balancing option
- is QoS.
- returned: queried
- type: int
- qos_rtt:
- description:
- - Weight assign to the Round Trip Time performance factor when load balancing option
- is QoS.
- returned: queried
- type: int
- qos_topology:
- description:
- - Weight assign to the Topology performance factor when load balancing option
- is QoS.
- returned: queried
- type: int
- qos_vs_capacity:
- description:
- - Weight assign to the Virtual Server performance factor when load balancing option
- is QoS.
- returned: queried
- type: int
- qos_vs_score:
- description:
- - Weight assign to the Virtual Server Score performance factor when load balancing
- option is QoS.
- returned: queried
- type: int
- ttl:
- description:
- - Number of seconds that the IP address, once found, is valid.
- returned: queried
- type: int
- verify_member_availability:
- description:
- - Whether or not the system verifies the availability of the members before
- sending a connection to them.
- returned: queried
- type: bool
- sample: hash/dictionary of values
-gtm_servers:
- description:
- - GTM server related information.
- returned: When C(gtm-servers) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/server1
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: server1
- datacenter:
- description:
- - Full name of the datacenter this server belongs to.
- returned: queried
- type: str
- enabled:
- description:
- - Whether the server is enabled.
- returned: queried
- type: bool
- disabled:
- description:
- - Whether the server is disabled.
- returned: queried
- type: bool
- expose_route_domains:
- description:
- - Allow the GTM server to auto-discover the LTM virtual servers from all
- route domains.
- returned: queried
- type: bool
- iq_allow_path:
- description:
- - Whether the GTM uses this BIG-IP system to conduct a path probe before
- delegating traffic to it.
- returned: queried
- type: bool
- iq_allow_service_check:
- description:
- - Whether the GTM uses this BIG-IP system to conduct a service check probe
- before delegating traffic to it.
- returned: queried
- type: bool
- iq_allow_snmp:
- description:
- - Whether the GTM uses this BIG-IP system to conduct an SNMP probe
- before delegating traffic to it.
- returned: queried
- type: bool
- limit_cpu_usage:
- description:
- - For a server configured as a generic host, specifies the percent of CPU
- usage, otherwise has no effect.
- returned: queried
- type: int
- limit_cpu_usage_status:
- description:
- - Whether C(limit_cpu_usage) is enabled for this server.
- returned: queried
- type: bool
- limit_max_bps:
- description:
- - Maximum allowable data throughput rate in bits per second for this server.
- returned: queried
- type: int
- limit_max_bps_status:
- description:
- - Whether C(limit_max_bps) is enabled for this server.
- returned: queried
- type: bool
- limit_max_connections:
- description:
- - Maximum number of concurrent connections, combined, for this server.
- returned: queried
- type: int
- limit_max_connections_status:
- description:
- - Whether C(limit_max_connections) is enabled for this server.
- type: bool
- limit_max_pps:
- description:
- - Maximum allowable data transfer rate, in packets per second, for this server.
- returned: queried
- type: int
- limit_max_pps_status:
- description:
- - Whether C(limit_max_pps) is enabled for this server.
- returned: queried
- type: bool
- limit_mem_available:
- description:
- - For a server configured as a generic host, specifies the available memory
- required by the virtual servers on the server.
- - If available memory falls below this limit, the system marks the server as
- unavailable.
- returned: queried
- type: int
- limit_mem_available_status:
- description:
- - Whether C(limit_mem_available) is enabled for this server.
- returned: queried
- type: bool
- link_discovery:
- description:
- - Specifies whether the system auto-discovers the links for this server.
- returned: queried
- type: str
- monitors:
- description:
- - Specifies health monitors that the system uses to determine whether this
- server is available for load balancing.
- returned: queried
- type: list
- sample: ['/Common/https_443', '/Common/icmp']
- monitor_type:
- description:
- - Whether one or monitors need to pass, or all monitors need to pass.
- returned: queried
- type: str
- sample: and_list
- product:
- description:
- - Specifies the server type.
- returned: queried
- type: str
- prober_fallback:
- description:
- - The type of prober to use to monitor this servers resources when the
- preferred type is not available.
- returned: queried
- type: str
- prober_preference:
- description:
- - Specifies the type of prober to use to monitor this servers resources.
- returned: queried
- type: str
- virtual_server_discovery:
- description:
- - Whether the system auto-discovers the virtual servers for this server.
- returned: queried
- type: str
- addresses:
- description:
- - Specifies the server IP addresses for the server.
- returned: queried
- type: complex
- devices:
- description:
- - Specifies the names of the devices that represent this server.
- returned: queried
- type: complex
- virtual_servers:
- description:
- - Virtual servers that are resources for this server.
- returned: queried
- type: complex
- sample: hash/dictionary of values
-gtm_wide_ips:
- description:
- - GTM Wide IP related information.
- - Every "type" of wide-ip has the exact same list of possible information. Therefore,
- the list of information here is presented once instead of 6 times.
- returned: When any of C(gtm-wide-ips) or C(gtm-*-wide-ips) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/wide1
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: wide1
- description:
- description:
- - Description of the wide ip.
- returned: queried
- type: str
- enabled:
- description:
- - Whether the Wide IP is enabled.
- returned: queried
- type: bool
- disabled:
- description:
- - Whether the Wide IP is disabled.
- returned: queried
- type: bool
- failure_rcode:
- description:
- - Specifies the DNS RCODE used when C(failure_rcode_response) is C(yes).
- returned: queried
- type: int
- failure_rcode_response:
- description:
- - When C(yes), specifies that the system returns a RCODE response to
- Wide IP requests after exhausting all load-balancing methods.
- returned: queried
- type: bool
- failure_rcode_ttl:
- description:
- - Specifies the negative caching TTL of the SOA for the RCODE response.
- returned: queried
- type: int
- last_resort_pool:
- description:
- - Specifies which pool, as listed in Pool List, for the system to use as
- the last resort pool for the wide IP.
- returned: queried
- type: str
- minimal_response:
- description:
- - Specifies that the system forms the smallest allowable DNS response to
- a query.
- returned: queried
- type: str
- persist_cidr_ipv4:
- description:
- - Specifies the number of bits the system uses to identify IPv4 addresses
- when persistence is enabled.
- returned: queried
- type: int
- persist_cidr_ipv6:
- description:
- - Specifies the number of bits the system uses to identify IPv6 addresses
- when persistence is enabled.
- returned: queried
- type: int
- pool_lb_mode:
- description:
- - Specifies the load balancing method used to select a pool in this wide IP.
- returned: queried
- type: str
- ttl_persistence:
- description:
- - Specifies, in seconds, the length of time for which the persistence
- entry is valid.
- returned: queried
- type: int
- pools:
- description:
- - Specifies the pools that this wide IP uses for load balancing.
- returned: queried
- type: complex
- sample: hash/dictionary of values
-http_monitors:
- description: HTTP monitor related information.
- returned: When C(http-monitors) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/http
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: http
- parent:
- description:
- - Profile from which this profile inherits settings.
- returned: queried
- type: str
- sample: http
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: My monitor
- adaptive:
- description:
- - Whether adaptive response time monitoring is enabled for this monitor.
- returned: queried
- type: bool
- sample: no
- adaptive_divergence_type:
- description:
- - Specifies whether the adaptive-divergence-value is C(relative) or
- C(absolute).
- returned: queried
- type: str
- sample: relative
- adaptive_divergence_value:
- description:
- - Specifies how far from mean latency each monitor probe is allowed
- to be.
- returned: queried
- type: int
- sample: 25
- adaptive_limit:
- description:
- - Specifies the hard limit, in milliseconds, which the probe is not
- allowed to exceed, regardless of the divergence value.
- returned: queried
- type: int
- sample: 200
- adaptive_sampling_timespan:
- description:
- - Specifies the size of the sliding window, in seconds, which
- records probe history.
- returned: queried
- type: int
- sample: 300
- destination:
- description:
- - Specifies the IP address and service port of the resource that is
- the destination of this monitor.
- returned: queried
- type: str
- sample: "*:*"
- interval:
- description:
- - Specifies, in seconds, the frequency at which the system issues
- the monitor check when either the resource is down or the status
- of the resource is unknown.
- returned: queried
- type: int
- sample: 5
- ip_dscp:
- description:
- - Specifies the differentiated services code point (DSCP).
- returned: queried
- type: int
- sample: 0
- manual_resume:
- description:
- - Specifies whether the system automatically changes the status of a
- resource to up at the next successful monitor check.
- returned: queried
- type: bool
- sample: yes
- receive_string:
- description:
- - Specifies the text string that the monitor looks for in the
- returned resource.
- returned: queried
- type: str
- sample: check string
- receive_disable_string:
- description:
- - Specifies a text string that the monitor looks for in the returned
- resource. If the text string is matched in the returned resource,
- the corresponding node or pool member is marked session disabled.
- returned: queried
- type: str
- sample: check disable string
- reverse:
- description:
- - Specifies whether the monitor operates in reverse mode. When the
- monitor is in reverse mode, a successful check marks the monitored
- object down instead of up.
- returned: queried
- type: bool
- sample: no
- send_string:
- description:
- - Specifies the text string that the monitor sends to the target
- object.
- returned: queried
- type: str
- sample: "GET /\\r\\n"
- time_until_up:
- description:
- - Specifies the amount of time, in seconds, after the first
- successful response before a node is marked up.
- returned: queried
- type: int
- sample: 0
- timeout:
- description:
- - Specifies the number of seconds the target has in which to respond
- to the monitor request.
- returned: queried
- type: int
- sample: 16
- transparent:
- description:
- - Specifies whether the monitor operates in transparent mode.
- returned: queried
- type: bool
- sample: no
- up_interval:
- description:
- - Specifies, in seconds, the frequency at which the system issues
- the monitor check when the resource is up.
- returned: queried
- type: int
- sample: 0
- username:
- description:
- - Specifies the username, if the monitored target requires
- authentication.
- returned: queried
- type: str
- sample: user1
- sample: hash/dictionary of values
-https_monitors:
- description: HTTPS monitor related information.
- returned: When C(https-monitors) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/http
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: http
- parent:
- description:
- - Profile from which this profile inherits settings.
- returned: queried
- type: str
- sample: http
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: My monitor
- adaptive:
- description:
- - Whether adaptive response time monitoring is enabled for this monitor.
- returned: queried
- type: bool
- sample: no
- adaptive_divergence_type:
- description:
- - Specifies whether the adaptive-divergence-value is C(relative) or
- C(absolute).
- returned: queried
- type: str
- sample: relative
- adaptive_divergence_value:
- description:
- - Specifies how far from mean latency each monitor probe is allowed
- to be.
- returned: queried
- type: int
- sample: 25
- adaptive_limit:
- description:
- - Specifies the hard limit, in milliseconds, which the probe is not
- allowed to exceed, regardless of the divergence value.
- returned: queried
- type: int
- sample: 200
- adaptive_sampling_timespan:
- description:
- - Specifies the size of the sliding window, in seconds, which
- records probe history.
- returned: queried
- type: int
- sample: 300
- destination:
- description:
- - Specifies the IP address and service port of the resource that is
- the destination of this monitor.
- returned: queried
- type: str
- sample: "*:*"
- interval:
- description:
- - Specifies, in seconds, the frequency at which the system issues
- the monitor check when either the resource is down or the status
- of the resource is unknown.
- returned: queried
- type: int
- sample: 5
- ip_dscp:
- description:
- - Specifies the differentiated services code point (DSCP).
- returned: queried
- type: int
- sample: 0
- manual_resume:
- description:
- - Specifies whether the system automatically changes the status of a
- resource to up at the next successful monitor check.
- returned: queried
- type: bool
- sample: yes
- receive_string:
- description:
- - Specifies the text string that the monitor looks for in the
- returned resource.
- returned: queried
- type: str
- sample: check string
- receive_disable_string:
- description:
- - Specifies a text string that the monitor looks for in the returned
- resource. If the text string is matched in the returned resource,
- the corresponding node or pool member is marked session disabled.
- returned: queried
- type: str
- sample: check disable string
- reverse:
- description:
- - Specifies whether the monitor operates in reverse mode. When the
- monitor is in reverse mode, a successful check marks the monitored
- object down instead of up.
- returned: queried
- type: bool
- sample: no
- send_string:
- description:
- - Specifies the text string that the monitor sends to the target
- object.
- returned: queried
- type: str
- sample: "GET /\\r\\n"
- ssl_profile:
- description:
- - Specifies the SSL profile to use for the HTTPS monitor.
- returned: queried
- type: str
- sample: /Common/serverssl
- time_until_up:
- description:
- - Specifies the amount of time, in seconds, after the first
- successful response before a node is marked up.
- returned: queried
- type: int
- sample: 0
- timeout:
- description:
- - Specifies the number of seconds the target has in which to respond
- to the monitor request.
- returned: queried
- type: int
- sample: 16
- transparent:
- description:
- - Specifies whether the monitor operates in transparent mode.
- returned: queried
- type: bool
- sample: no
- up_interval:
- description:
- - Specifies, in seconds, the frequency at which the system issues
- the monitor check when the resource is up.
- returned: queried
- type: int
- sample: 0
- username:
- description:
- - Specifies the username, if the monitored target requires
- authentication.
- returned: queried
- type: str
- sample: user1
- sample: hash/dictionary of values
-http_profiles:
- description: HTTP profile related information.
- returned: When C(http-profiles) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/http
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: http
- parent:
- description:
- - Profile from which this profile inherits settings.
- returned: queried
- type: str
- sample: http
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: My profile
- accept_xff:
- description:
- - Enables or disables trusting the client IP address, and statistics
- from the client IP address, based on the request's X-Forwarded-For
- (XFF) headers, if they exist.
- returned: queried
- type: bool
- sample: yes
- allow_truncated_redirects:
- description:
- - Specifies the pass-through behavior when a redirect lacking the
- trailing carriage-return and line feed pair at the end of the headers
- is parsed.
- - When C(no), will silently drop the invalid HTTP.
- returned: queried
- type: bool
- sample: no
- excess_client_headers:
- description:
- - Specifies the pass-through behavior when C(max_header_count) value is
- exceeded by the client.
- - When C(reject), rejects the connection.
- returned: queried
- type: str
- sample: reject
- excess_server_headers:
- description:
- - Specifies the pass-through behavior when C(max_header_count) value is
- exceeded by the server.
- - When C(reject), rejects the connection.
- returned: queried
- type: str
- sample: reject
- known_methods:
- description:
- - Optimizes the behavior of a known HTTP method in the list.
- - The default methods include the following HTTP/1.1 methods. CONNECT,
- DELETE, GET, HEAD, LOCK, OPTIONS, POST, PROPFIND, PUT, TRACE, UNLOCK.
- - If a known method is deleted from the C(known_methods) list, the
- BIG-IP system applies the C(unknown_method) setting to manage that traffic.
- returned: queried
- type: list
- sample: ['CONNECT', 'DELETE', ...]
- max_header_count:
- description:
- - Specifies the maximum number of headers the system supports.
- returned: queried
- type: int
- sample: 64
- max_header_size:
- description:
- - Specifies the maximum size in bytes the system allows for all HTTP
- request headers combined, including the request line.
- returned: queried
- type: int
- sample: 32768
- max_requests:
- description:
- - Specifies the number of requests that the system accepts on a per-connection
- basis.
- returned: queried
- type: int
- sample: 0
- oversize_client_headers:
- description:
- - Specifies the pass-through behavior when the C(max_header_size) value
- is exceeded by the client.
- returned: queried
- type: str
- sample: reject
- oversize_server_headers:
- description:
- - Specifies the pass-through behavior when the C(max_header_size) value
- is exceeded by the server.
- returned: queried
- type: str
- sample: reject
- pipeline_action:
- description:
- - Enables or disables HTTP/1.1 pipelining.
- returned: queried
- type: str
- sample: allow
- unknown_method:
- description:
- - Specifies the behavior (allow, reject, or pass through) when an unknown
- HTTP method is parsed.
- returned: queried
- type: str
- sample: allow
- default_connect_handling:
- description:
- - Specifies the behavior of the proxy service when handling outbound requests.
- returned: queried
- type: str
- sample: deny
- hsts_include_subdomains:
- description:
- - When C(yes), applies the HSTS policy to the HSTS host and its subdomains.
- returned: queried
- type: bool
- sample: yes
- hsts_enabled:
- description:
- - When C(yes), enables the HTTP Strict Transport Security settings.
- returned: queried
- type: bool
- sample: yes
- insert_x_forwarded_for:
- description:
- - When C(yes), specifies that the system inserts an X-Forwarded-For header in
- an HTTP request with the client IP address, to use with connection pooling.
- returned: queried
- type: bool
- sample: no
- lws_max_columns:
- description:
- - Specifies the maximum column width for any given line, when inserting an HTTP
- header in an HTTP request.
- returned: queried
- type: int
- sample: 80
- onconnect_transformations:
- description:
- - When C(yes), specifies, that the system performs HTTP header transformations
- for the purpose of keeping connections open.
- returned: queried
- type: bool
- sample: yes
- proxy_mode:
- description:
- - Specifies the proxy mode for this profile. Either reverse, explicit, or transparent.
- returned: queried
- type: str
- sample: reverse
- redirect_rewrite:
- description:
- - Specifies whether the system rewrites the URIs that are part of HTTP
- redirect (3XX) responses
- returned: queried
- type: str
- sample: none
- request_chunking:
- description:
- - Specifies how the system handles HTTP content that is chunked by a client.
- returned: queried
- type: str
- sample: preserve
- response_chunking:
- description:
- - Specifies how the system handles HTTP content that is chunked by a server.
- returned: queried
- type: str
- sample: selective
- server_agent_name:
- description:
- - Specifies the string used as the server name in traffic generated by LTM.
- returned: queried
- type: str
- sample: BigIP
- sflow_poll_interval:
- description:
- - The maximum interval in seconds between two pollings.
- returned: queried
- type: int
- sample: 0
- sflow_sampling_rate:
- description:
- - Specifies the ratio of packets observed to the samples generated.
- returned: queried
- type: int
- sample: 0
- via_request:
- description:
- - Specifies whether to Remove, Preserve, or Append Via headers included in
- a client request to an origin web server.
- returned: queried
- type: str
- sample: preserve
- via_response:
- description:
- - Specifies whether to Remove, Preserve, or Append Via headers included in
- an origin web server response to a client.
- returned: queried
- type: str
- sample: preserve
- sample: hash/dictionary of values
-iapp_services:
- description: iApp v1 service related information.
- returned: When C(iapp-services) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/service1
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: service1
- device_group:
- description:
- - The device group the iApp service is part of.
- returned: queried
- type: str
- sample: /Common/dg1
- inherited_device_group:
- description:
- - Whether the device group is inherited or not.
- returned: queried
- type: bool
- sample: yes
- inherited_traffic_group:
- description:
- - Whether the traffic group is inherited or not.
- returned: queried
- type: bool
- sample: yes
- strict_updates:
- description:
- - Whether strict updates are enabled or not.
- returned: queried
- type: bool
- sample: yes
- template_modified:
- description:
- - Whether template that the service is based on is modified from its
- default value, or not.
- returned: queried
- type: bool
- sample: yes
- traffic_group:
- description:
- - Traffic group the service is a part of.
- returned: queried
- type: str
- sample: /Common/tg
- tables:
- description:
- - List of the tabular data used to create the service.
- returned: queried
- type: complex
- sample: [{"name": "basic__snatpool_members"},...]
- variables:
- description:
- - List of the variable data used to create the service.
- returned: queried
- type: complex
- sample: [{"name": "afm__policy"},{"encrypted": "no"},{"value": "/#no_not_use#"},...]
- metadata:
- description:
- - List of the metadata data used to create the service..
- returned: queried
- type: complex
- sample: [{"name": "var1"},{"persist": "true"},...]
- lists:
- description:
- - List of the lists data used to create the service.
- returned: queried
- type: complex
- sample: [{"name": "irules__irules"},{"value": []},...]
- description:
- description:
- - Description of the service
- returned: queried
- type: str
- sample: My service
- sample: hash/dictionary of values
-icmp_monitors:
- description: ICMP monitor related information.
- returned: When C(icmp-monitors) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/icmp
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: icmp
- parent:
- description:
- - Profile from which this profile inherits settings.
- returned: queried
- type: str
- sample: icmp
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: My monitor
- adaptive:
- description:
- - Whether adaptive response time monitoring is enabled for this monitor.
- returned: queried
- type: bool
- sample: no
- adaptive_divergence_type:
- description:
- - Specifies whether the adaptive-divergence-value is C(relative) or
- C(absolute).
- returned: queried
- type: str
- sample: relative
- adaptive_divergence_value:
- description:
- - Specifies how far from mean latency each monitor probe is allowed
- to be.
- returned: queried
- type: int
- sample: 25
- adaptive_limit:
- description:
- - Specifies the hard limit, in milliseconds, which the probe is not
- allowed to exceed, regardless of the divergence value.
- returned: queried
- type: int
- sample: 200
- adaptive_sampling_timespan:
- description:
- - Specifies the size of the sliding window, in seconds, which
- records probe history.
- returned: queried
- type: int
- sample: 300
- destination:
- description:
- - Specifies the IP address and service port of the resource that is
- the destination of this monitor.
- returned: queried
- type: str
- sample: "*:*"
- interval:
- description:
- - Specifies, in seconds, the frequency at which the system issues
- the monitor check when either the resource is down or the status
- of the resource is unknown.
- returned: queried
- type: int
- sample: 5
- manual_resume:
- description:
- - Specifies whether the system automatically changes the status of a
- resource to up at the next successful monitor check.
- type: bool
- sample: yes
- time_until_up:
- description:
- - Specifies the amount of time, in seconds, after the first
- successful response before a node is marked up.
- returned: queried
- type: int
- sample: 0
- timeout:
- description:
- - Specifies the number of seconds the target has in which to respond
- to the monitor request.
- returned: queried
- type: int
- sample: 16
- transparent:
- description:
- - Specifies whether the monitor operates in transparent mode.
- returned: queried
- type: bool
- sample: no
- up_interval:
- description:
- - Specifies, in seconds, the frequency at which the system issues
- the monitor check when the resource is up.
- returned: queried
- type: int
- sample: 0
- sample: hash/dictionary of values
-interfaces:
- description: Interface related information.
- returned: When C(interfaces) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/interface1
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: interface1
- active_media_type:
- description:
- - Displays the current media setting for the interface.
- returned: queried
- type: str
- sample: 100TX-FD
- flow_control:
- description:
- - Specifies how the system controls the sending of PAUSE frames for
- flow control.
- returned: queried
- type: str
- sample: tx-rx
- description:
- description:
- - Description of the interface
- returned: queried
- type: str
- sample: My interface
- bundle:
- description:
- - The bundle capability on the port.
- returned: queried
- type: str
- sample: not-supported
- bundle_speed:
- description:
- - The bundle-speed on the port when bundle capability is
- enabled.
- returned: queried
- type: str
- sample: 100G
- enabled:
- description:
- - Whether the interface is enabled or not
- returned: queried
- type: bool
- sample: yes
- if_index:
- description:
- - The index assigned to this interface.
- returned: queried
- type: int
- sample: 32
- mac_address:
- description:
- - Displays the 6-byte ethernet address in non-case-sensitive
- hexadecimal colon notation.
- returned: queried
- type: str
- sample: "00:0b:09:88:00:9a"
- media_sfp:
- description:
- - The settings for an SFP (pluggable) interface.
- returned: queried
- type: str
- sample: auto
- lldp_admin:
- description:
- - Sets the sending or receiving of LLDP packets on that interface.
- Should be one of C(disable), C(txonly), C(rxonly) or C(txrx).
- returned: queried
- type: str
- sample: txonly
- mtu:
- description:
- - Displays the Maximum Transmission Unit (MTU) of the interface,
- which is the maximum number of bytes in a frame without IP
- fragmentation.
- returned: queried
- type: int
- sample: 1500
- prefer_port:
- description:
- - Indicates which side of a combo port the interface uses, if both
- sides of the port have the potential for external links.
- returned: queried
- type: str
- sample: sfp
- sflow_poll_interval:
- description:
- - Specifies the maximum interval in seconds between two
- pollings.
- returned: queried
- type: int
- sample: 0
- sflow_poll_interval_global:
- description:
- - Specifies whether the global interface poll-interval setting
- overrides the object-level poll-interval setting.
- returned: queried
- type: bool
- sample: yes
- stp_auto_edge_port:
- description:
- - STP edge port detection.
- returned: queried
- type: bool
- sample: yes
- stp_enabled:
- description:
- - Whether STP is enabled or not.
- returned: queried
- type: bool
- sample: no
- stp_link_type:
- description:
- - Specifies the STP link type for the interface.
- returned: queried
- type: str
- sample: auto
- sample: hash/dictionary of values
-irules:
- description: iRule related information.
- returned: When C(irules) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/irul1
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: irule1
- ignore_verification:
- description:
- - Whether the verification of the iRule should be ignored or not.
- returned: queried
- type: bool
- sample: no
- checksum:
- description:
- - Checksum of the iRule as calculated by BIG-IP.
- returned: queried
- type: str
- sample: d41d8cd98f00b204e9800998ecf8427e
- definition:
- description:
- - The actual definition of the iRule.
- returned: queried
- type: str
- sample: when HTTP_REQUEST ...
- signature:
- description:
- - The calculated signature of the iRule.
- returned: queried
- type: str
- sample: WsYy2M6xMqvosIKIEH/FSsvhtWMe6xKOA6i7f...
- sample: hash/dictionary of values
-ltm_pools:
- description: List of LTM (Local Traffic Manager) pools.
- returned: When C(ltm-pools) is specified in C(gather_subset).
- type: complex
- contains:
- active_member_count:
- description:
- - The number of active pool members in the pool.
- returned: queried
- type: int
- sample: 3
- all_avg_queue_entry_age:
- description:
- - Average queue entry age, for both the pool and its members.
- returned: queried
- type: int
- sample: 5
- all_max_queue_entry_age_ever:
- description:
- - Maximum queue entry age ever, for both the pool and its members.
- returned: queried
- type: int
- sample: 2
- all_max_queue_entry_age_recently:
- description:
- - Maximum queue entry age recently, for both the pool and its members.
- returned: queried
- type: int
- sample: 5
- all_num_connections_queued_now:
- description:
- - Number of connections queued now, for both the pool and its members.
- returned: queried
- type: int
- sample: 20
- all_num_connections_serviced:
- description:
- - Number of connections serviced, for both the pool and its members.
- returned: queried
- type: int
- sample: 15
- all_queue_head_entry_age:
- description:
- - Queue head entry age, for both the pool and its members.
- returned: queried
- type: int
- sample: 4
- available_member_count:
- description:
- - The number of available pool members in the pool.
- returned: queried
- type: int
- sample: 4
- availability_status:
- description:
- - The availability of the pool.
- returned: queried
- type: str
- sample: offline
- allow_nat:
- description:
- - Whether NATs are automatically enabled or disabled for any connections using this pool.
- returned: queried
- type: bool
- sample: yes
- allow_snat:
- description:
- - Whether SNATs are automatically enabled or disabled for any connections using this pool.
- returned: queried
- type: bool
- sample: yes
- client_ip_tos:
- description:
- - Whether the system sets a Type of Service (ToS) level within a packet sent to the client,
- based on the targeted pool.
- - Values can range from C(0) to C(255), or be set to C(pass-through) or C(mimic).
- returned: queried
- type: str
- sample: pass-through
- client_link_qos:
- description:
- - Whether the system sets a Quality of Service (QoS) level within a packet sent to the client,
- based on the targeted pool.
- - Values can range from C(0) to C(7), or be set to C(pass-through).
- returned: queried
- type: str
- sample: pass-through
- current_sessions:
- description:
- - Current sessions.
- returned: queried
- type: int
- sample: 2
- description:
- description:
- - Description of the pool.
- returned: queried
- type: str
- sample: my pool
- enabled_status:
- description:
- - The enabled-ness of the pool.
- returned: queried
- type: str
- sample: enabled
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/pool1
- ignore_persisted_weight:
- description:
- - Do not count the weight of persisted connections on pool members when making load balancing decisions.
- returned: queried
- type: bool
- sample: no
- lb_method:
- description:
- - Load balancing method used by the pool.
- returned: queried
- type: str
- sample: round-robin
- member_count:
- description:
- - Total number of members in the pool.
- returned: queried
- type: int
- sample: 50
- metadata:
- description:
- - Dictionary of arbitrary key/value pairs set on the pool.
- returned: queried
- type: complex
- sample: hash/dictionary of values
- minimum_active_members:
- description:
- - Whether the system load balances traffic according to the priority number assigned to the pool member.
- - This parameter is identical to C(priority_group_activation) and is just an alias for it.
- returned: queried
- type: int
- sample: 2
- minimum_up_members:
- description:
- - The minimum number of pool members that must be up.
- returned: queried
- type: int
- sample: 1
- minimum_up_members_action:
- description:
- - The action to take if the C(minimum_up_members_checking) is enabled and the number of active pool
- members falls below the number specified in C(minimum_up_members).
- returned: queried
- type: str
- sample: failover
- minimum_up_members_checking:
- description:
- - Enables or disables the C(minimum_up_members) feature.
- returned: queried
- type: bool
- sample: no
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: pool1
- pool_avg_queue_entry_age:
- description:
- - Average queue entry age, for the pool only.
- returned: queried
- type: int
- sample: 5
- pool_max_queue_entry_age_ever:
- description:
- - Maximum queue entry age ever, for the pool only.
- returned: queried
- type: int
- sample: 2
- pool_max_queue_entry_age_recently:
- description:
- - Maximum queue entry age recently, for the pool only.
- returned: queried
- type: int
- sample: 5
- pool_num_connections_queued_now:
- description:
- - Number of connections queued now, for the pool only.
- returned: queried
- type: int
- sample: 20
- pool_num_connections_serviced:
- description:
- - Number of connections serviced, for the pool only.
- returned: queried
- type: int
- sample: 15
- pool_queue_head_entry_age:
- description:
- - Queue head entry age, for the pool only.
- returned: queried
- type: int
- sample: 4
- priority_group_activation:
- description:
- - Whether the system load balances traffic according to the priority number assigned to the pool member.
- - This parameter is identical to C(minimum_active_members) and is just an alias for it.
- returned: queried
- type: int
- sample: 2
- queue_depth_limit:
- description:
- - The maximum number of connections that may simultaneously be queued to go to any member of this pool.
- returned: queried
- type: int
- sample: 3
- queue_on_connection_limit:
- description:
- - Enable or disable queuing connections when pool member or node connection limits are reached.
- returned: queried
- type: bool
- sample: yes
- queue_time_limit:
- description:
- - Specifies the maximum time, in milliseconds, a connection will remain enqueued.
- returned: queried
- type: int
- sample: 0
- real_session:
- description:
- - The actual REST API value for the C(session) attribute.
- - This is different from the C(state) return value, insofar as the return value
- can be considered a generalization of all available sessions, instead of the
- specific value of the session.
- returned: queried
- type: str
- sample: monitor-enabled
- real_state:
- description:
- - The actual REST API value for the C(state) attribute.
- - This is different from the C(state) return value, insofar as the return value
- can be considered a generalization of all available states, instead of the
- specific value of the state.
- returned: queried
- type: str
- sample: up
- reselect_tries:
- description:
- - The number of times the system tries to contact a pool member after a passive failure.
- returned: queried
- type: int
- sample: 0
- server_ip_tos:
- description:
- - The Type of Service (ToS) level to use when sending packets to a server.
- returned: queried
- type: str
- sample: pass-through
- server_link_qos:
- description:
- - The Quality of Service (QoS) level to use when sending packets to a server.
- returned: queried
- type: str
- sample: pass-through
- service_down_action:
- description:
- - The action to take if the service specified in the pool is marked down.
- returned: queried
- type: str
- sample: none
- server_side_bits_in:
- description:
- - Number of server-side ingress bits.
- returned: queried
- type: int
- sample: 1000
- server_side_bits_out:
- description:
- - Number of server-side egress bits.
- returned: queried
- type: int
- sample: 200
- server_side_current_connections:
- description:
- - Number of current connections server-side.
- returned: queried
- type: int
- sample: 300
- server_side_max_connections:
- description:
- - Maximum number of connections server-side.
- returned: queried
- type: int
- sample: 40
- server_side_pkts_in:
- description:
- - Number of server-side ingress packets.
- returned: queried
- type: int
- sample: 1098384
- server_side_pkts_out:
- description:
- - Number of server-side egress packets.
- returned: queried
- type: int
- sample: 3484734
- server_side_total_connections:
- description:
- - Total number of connections.
- returned: queried
- type: int
- sample: 24
- slow_ramp_time:
- description:
- - The ramp time for the pool.
- - This provides the ability to cause a pool member that has just been enabled,
- or marked up, to receive proportionally less traffic than other members in the pool.
- returned: queried
- type: int
- sample: 10
- status_reason:
- description:
- - If there is a problem with the status of the pool, that problem is reported here.
- returned: queried
- type: str
- sample: The children pool member(s) are down.
- members:
- description: List of LTM (Local Traffic Manager) pools.
- returned: when members exist in the pool.
- type: complex
- contains:
- address:
- description: IP address of the pool member.
- returned: queried
- type: str
- sample: 1.1.1.1
- connection_limit:
- description: The maximum number of concurrent connections allowed for a pool member.
- returned: queried
- type: int
- sample: 0
- description:
- description: The description of the pool member.
- returned: queried
- type: str
- sample: pool member 1
- dynamic_ratio:
- description:
- - A range of numbers that you want the system to use in conjunction with the ratio load balancing method.
- returned: queried
- type: int
- sample: 1
- ephemeral:
- description:
- - Whether the node backing the pool member is ephemeral or not.
- returned: queried
- type: bool
- sample: yes
- fqdn_autopopulate:
- description:
- - Whether the node should scale to the IP address set returned by DNS.
- returned: queried
- type: bool
- sample: yes
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- - Includes the port in the name
- returned: queried
- type: str
- sample: "/Common/member:80"
- inherit_profile:
- description:
- - Whether the pool member inherits the encapsulation profile from the parent pool.
- returned: queried
- type: bool
- sample: no
- logging:
- description:
- - Whether the monitor applied should log its actions.
- returned: queried
- type: bool
- sample: no
- monitors:
- description:
- - Monitors active on the pool member. Monitor names are in their "full_path" form.
- returned: queried
- type: list
- sample: ['/Common/http']
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: "member:80"
- partition:
- description:
- - Partition that the member exists on.
- returned: queried
- type: str
- sample: Common
- priority_group:
- description:
- - The priority group within the pool for this pool member.
- returned: queried
- type: int
- sample: 0
- encapsulation_profile:
- description:
- - The encapsulation profile to use for the pool member.
- returned: queried
- type: str
- sample: ip4ip4
- rate_limit:
- description:
- - The maximum number of connections per second allowed for a pool member.
- returned: queried
- type: bool
- sample: no
- ratio:
- description:
- - The weight of the pool for load balancing purposes.
- returned: queried
- type: int
- sample: 1
- session:
- description:
- - Enables or disables the pool member for new sessions.
- returned: queried
- type: str
- sample: monitor-enabled
- state:
- description:
- - Controls the state of the pool member, overriding any monitors.
- returned: queried
- type: str
- sample: down
- total_requests:
- description:
- - Total requests.
- returned: queried
- type: int
- sample: 8
- sample: hash/dictionary of values
-ltm_policies:
- description: List of LTM (Local Traffic Manager) policies.
- returned: When C(ltm-policies) is specified in C(gather_subset).
- type: complex
- contains:
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: policy1
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/policy1
- description:
- description:
- - Description of the policy.
- returned: queried
- type: str
- sample: My policy
- strategy:
- description:
- - The match strategy for the policy.
- returned: queried
- type: str
- sample: /Common/first-match
- requires:
- description:
- - Aspects of the system required by this policy.
- returned: queried
- type: list
- sample: ['http']
- controls:
- description:
- - Aspects of the system controlled by this policy.
- returned: queried
- type: list
- sample: ['forwarding']
- status:
- description:
- - Indicates published or draft policy status.
- returned: queried
- type: str
- sample: draft
- rules:
- description:
- - List of LTM (Local Traffic Manager) policy rules.
- returned: when rules are defined in the policy.
- type: complex
- contains:
- actions:
- description:
- - The actions the policy will take when a match is encountered.
- returned: when actions are defined in the rule.
- type: complex
- contains:
- http_reply:
- description:
- - Indicate if the action will affects a reply to a given HTTP request.
- returned: when defined in the action.
- type: bool
- sample: yes
- redirect:
- description:
- - This action will redirect a request.
- returned: when defined in the action.
- type: bool
- sample: no
- request:
- description:
- - This policy action is performed on connection requests.
- returned: when defined in the action.
- type: bool
- sample: no
- location:
- description:
- - This action will come from the given location.
- returned: when defined in the action.
- type: str
- sample: "tcl:https://[getfield [HTTP::host] \\\":\\\" 1][HTTP::uri]"
- sample: hash/dictionary of values
- conditions:
- description:
- - The conditions that a policy will match on.
- returned: when conditions are defined in the rule.
- type: complex
- contains:
- case_insensitive:
- description:
- - The value matched on is case insensitive.
- returned: when defined in the condition.
- type: bool
- sample: no
- case_sensitive:
- description:
- - The value matched on is case sensitive.
- returned: when defined in the condition.
- type: bool
- sample: yes
- contains_string:
- description:
- - The value matches if it contains a certain string.
- returned: when defined in the condition.
- type: bool
- sample: yes
- external:
- description:
- - The value matched on is from the external side of a connection.
- returned: when defined in the condition.
- type: bool
- sample: yes
- http_basic_auth:
- description:
- - This condition matches on basic HTTP authorization.
- returned: when defined in the condition.
- type: bool
- sample: no
- http_host:
- description:
- - This condition matches on an HTTP host.
- returned: when defined in the condition.
- type: bool
- sample: yes
- http_uri:
- description:
- - This condition matches on an HTTP URI.
- returned: when defined in the condition.
- type: bool
- sample: no
- request:
- description:
- - This policy will match on a request.
- returned: when defined in the condition.
- type: bool
- sample: yes
- username:
- description:
- - Matches on a username.
- returned: when defined in the condition.
- type: bool
- sample: yes
- all:
- description:
- - Matches all.
- returned: when defined in the condition.
- type: bool
- sample: yes
- values:
- description:
- - The specified values will be matched on.
- returned: when defined in the condition.
- type: list
- sample: ['foo.bar.com', 'baz.cool.com']
- sample: hash/dictionary of values
- sample: hash/dictionary of values
- sample: hash/dictionary of values
-nodes:
- description: Node related information.
- returned: When C(nodes) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/5.6.7.8
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: 5.6.7.8
- ratio:
- description:
- - Fixed size ratio used for node during C(Ratio) load balancing.
- returned: queried
- type: int
- sample: 10
- description:
- description:
- - Description of the node.
- returned: queried
- type: str
- sample: My node
- connection_limit:
- description:
- - Maximum number of connections that node can handle.
- returned: queried
- type: int
- sample: 100
- address:
- description:
- - IP address of the node.
- returned: queried
- type: str
- sample: 2.3.4.5
- dynamic_ratio:
- description:
- - Dynamic ratio number for the node used when doing C(Dynamic Ratio) load balancing.
- returned: queried
- type: int
- sample: 200
- rate_limit:
- description:
- - Maximum number of connections per second allowed for node.
- returned: queried
- type: int
- sample: 1000
- monitor_status:
- description:
- - Status of the node as reported by the monitor(s) associated with it.
- - This value is also used in determining node C(state).
- returned: queried
- type: str
- sample: down
- session_status:
- description:
- - This value is also used in determining node C(state).
- returned: queried
- type: str
- sample: enabled
- availability_status:
- description:
- - The availability of the node.
- returned: queried
- type: str
- sample: offline
- enabled_status:
- description:
- - The enabled-ness of the node.
- returned: queried
- type: str
- sample: enabled
- status_reason:
- description:
- - If there is a problem with the status of the node, that problem is reported here.
- returned: queried
- type: str
- sample: /Common/https_443 No successful responses received...
- monitor_rule:
- description:
- - A string representation of the full monitor rule.
- returned: queried
- type: str
- sample: /Common/https_443 and /Common/icmp
- monitors:
- description:
- - A list of the monitors identified in the C(monitor_rule).
- returned: queried
- type: list
- sample: ['/Common/https_443', '/Common/icmp']
- monitor_type:
- description:
- - The C(monitor_type) field related to the C(bigip_node) module, for this nodes
- monitors.
- returned: queried
- type: str
- sample: and_list
- sample: hash/dictionary of values
-oneconnect_profiles:
- description: OneConnect profile related information.
- returned: When C(oneconnect-profiles) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/oneconnect
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: oneconnect
- parent:
- description:
- - Profile from which this profile inherits settings.
- returned: queried
- type: str
- sample: oneconnect
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: My profile
- idle_timeout_override:
- description:
- - Specifies the number of seconds that a connection is idle before
- the connection flow is eligible for deletion.
- returned: queried
- type: int
- sample: 1000
- limit_type:
- description:
- - When C(none), simultaneous in-flight requests and responses over TCP
- connections to a pool member are counted toward the limit.
- - When C(idle), idle connections will be dropped as the TCP connection
- limit is reached.
- - When C(strict), the TCP connection limit is honored with no
- exceptions. This means that idle connections will prevent new TCP
- connections from being made until they expire, even if they could
- otherwise be reused.
- returned: queried
- type: str
- sample: idle
- max_age:
- description:
- - Specifies the maximum age, in number of seconds, of a connection
- in the connection reuse pool.
- returned: queried
- type: int
- sample: 100
- max_reuse:
- description:
- - Specifies the maximum number of times that a server connection can
- be reused.
- returned: queried
- type: int
- sample: 1000
- max_size:
- description:
- - Specifies the maximum number of connections that the system holds
- in the connection reuse pool.
- - If the pool is already full, then the server connection closes after
- the response is completed.
- returned: queried
- type: int
- sample: 1000
- share_pools:
- description:
- - Indicates that connections may be shared not only within a virtual
- server, but also among similar virtual servers.
- returned: queried
- type: bool
- sample: yes
- source_mask:
- description:
- - Specifies a source IP mask.
- - If no mask is provided, the value C(any6) is used.
- returned: queried
- type: str
- sample: 255.255.255.0
- sample: hash/dictionary of values
-partitions:
- description: Partition related information.
- returned: When C(partitions) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: Common
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: Common
- description:
- description:
- - Description of the partition.
- returned: queried
- type: str
- sample: Tenant 1
- default_route_domain:
- description:
- - ID of the route domain that is associated with the IP addresses that reside
- in the partition.
- returned: queried
- type: int
- sample: 0
- sample: hash/dictionary of values
-provision_info:
- description: Module provisioning related information.
- returned: When C(provision-info) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: asm
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: asm
- cpu_ratio:
- description:
- - Ratio of CPU allocated to this module.
- - Only relevant if C(level) was specified as C(custom). Otherwise, this value
- will be reported as C(0).
- returned: queried
- type: int
- sample: 0
- disk_ratio:
- description:
- - Ratio of disk allocated to this module.
- - Only relevant if C(level) was specified as C(custom). Otherwise, this value
- will be reported as C(0).
- returned: queried
- type: int
- sample: 0
- memory_ratio:
- description:
- - Ratio of memory allocated to this module.
- - Only relevant if C(level) was specified as C(custom). Otherwise, this value
- will be reported as C(0).
- returned: queried
- type: int
- sample: 0
- level:
- description:
- - Provisioned level of the module on BIG-IP.
- - Valid return values can include C(none), C(minimum), C(nominal), C(dedicated)
- and C(custom).
- returned: queried
- type: int
- sample: 0
- sample: hash/dictionary of values
-self_ips:
- description: Self-IP related information.
- returned: When C(self-ips) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/self1
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: self1
- description:
- description:
- - Description of the Self-IP.
- returned: queried
- type: str
- sample: My self-ip
- netmask:
- description:
- - Netmask portion of the IP address. In dotted notation.
- returned: queried
- type: str
- sample: 255.255.255.0
- netmask_cidr:
- description:
- - Netmask portion of the IP address. In CIDR notation.
- returned: queried
- type: int
- sample: 24
- floating:
- description:
- - Whether the Self-IP is a floating address or not.
- returned: queried
- type: bool
- sample: yes
- traffic_group:
- description:
- - Traffic group the Self-IP is associated with.
- returned: queried
- type: str
- sample: /Common/traffic-group-local-only
- service_policy:
- description:
- - Service policy assigned to the Self-IP.
- returned: queried
- type: str
- sample: /Common/service1
- vlan:
- description:
- - VLAN associated with the Self-IP.
- returned: queried
- type: str
- sample: /Common/vlan1
- allow_access_list:
- description:
- - List of protocols and optionally their ports that are allowed to access the
- Self-IP. Also known as port-lockdown in the web interface.
- - Items in the list are in the format of "protocol:port". Some items may not
- have a port associated with them and in those cases the port is C(0).
- returned: queried
- type: list
- sample: ['tcp:80', 'egp:0']
- traffic_group_inherited:
- description:
- - Whether or not the traffic group is inherited.
- returned: queried
- type: bool
- sample: no
- sample: hash/dictionary of values
-server_ssl_profiles:
- description: Server SSL related information.
- returned: When C(server-ssl-profiles) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: serverssl
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: serverssl
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: My profile
- parent:
- description:
- - Profile from which this profile inherits settings.
- returned: queried
- type: str
- sample: serverssl
- alert_timeout:
- description:
- - Maximum time period in seconds to keep the SSL
- session active after alert message is sent, or indefinite.
- returned: queried
- type: str
- sample: 100
- allow_expired_crl:
- description:
- - Use the specified CRL file even if it has expired.
- returned: queried
- type: bool
- sample: yes
- authentication_frequency:
- description:
- - Specifies the frequency of authentication.
- returned: queried
- type: str
- sample: once
- authenticate_depth:
- description:
- - The client certificate chain maximum traversal depth
- returned: queried
- type: int
- sample: 9
- authenticate_name:
- description:
- - Common Name (CN) that is embedded in a server certificate.
- - The system authenticates a server based on the specified CN.
- returned: queried
- type: str
- sample: foo
- bypass_on_client_cert_fail:
- description:
- - Enables or disables SSL forward proxy bypass on failing to get
- client certificate that server asks for.
- returned: queried
- type: bool
- sample: yes
- bypass_on_handshake_alert:
- description:
- - Enables or disables SSL forward proxy bypass on receiving
- handshake_failure, protocol_version or unsupported_extension alert
- message during the serverside SSL handshake.
- returned: queried
- type: bool
- sample: no
- c3d_ca_cert:
- description:
- - Name of the certificate file that is used as the
- certification authority certificate when SSL client certificate
- constrained delegation is enabled.
- returned: queried
- type: str
- sample: /Common/cacert.crt
- c3d_ca_key:
- description:
- - Name of the key file that is used as the
- certification authority key when SSL client certificate
- constrained delegation is enabled.
- returned: queried
- type: str
- sample: /Common/default.key
- c3d_cert_extension_includes:
- description:
- - Extensions of the client certificates to be included
- in the generated certificates using SSL client certificate
- constrained delegation.
- returned: queried
- type: list
- sample: [ "basic-constraints", "extended-key-usage", ... ]
- c3d_cert_lifespan:
- description:
- - Lifespan of the certificate generated using the SSL
- client certificate constrained delegation.
- returned: queried
- type: int
- sample: 24
- ca_file:
- description:
- - Certificate authority file name.
- returned: queried
- type: str
- sample: default.crt
- cache_size:
- description:
- - The SSL session cache size.
- returned: queried
- type: int
- sample: 262144
- cache_timeout:
- description:
- - The SSL session cache timeout value, which is the usable
- lifetime seconds of negotiated SSL session IDs.
- returned: queried
- type: int
- sample: 86400
- cert:
- description:
- - The name of the certificate installed on the traffic
- management system for the purpose of terminating or initiating an
- SSL connection.
- returned: queried
- type: str
- sample: /Common/default.crt
- chain:
- description:
- - Specifies or builds a certificate chain file that a client can use
- to authenticate the profile.
- returned: queried
- type: str
- sample: /Common/default.crt
- cipher_group:
- description:
- - Specifies a cipher group.
- returned: queried
- type: str
- ciphers:
- description:
- - Specifies a cipher name.
- returned: queried
- type: str
- sample: DEFAULT
- crl_file:
- description:
- - Specifies the certificate revocation list file name.
- returned: queried
- type: str
- expire_cert_response_control:
- description:
- - Specifies the BIGIP action when the server certificate has
- expired.
- returned: queried
- type: str
- sample: drop
- handshake_timeout:
- description:
- - Specifies the handshake timeout in seconds.
- returned: queried
- type: str
- sample: 10
- key:
- description:
- - Specifies the key file name. Specifies the name of the key
- installed on the traffic management system for the purpose of
- terminating or initiating an SSL connection.
- returned: queried
- type: str
- sample: /Common/default.key
- max_active_handshakes:
- description:
- - Specifies the maximum number allowed SSL active handshakes.
- returned: queried
- type: str
- sample: 100
- mod_ssl_methods:
- description:
- - Enables or disables ModSSL methods.
- returned: queried
- type: bool
- sample: yes
- mode:
- description:
- - Enables or disables SSL processing.
- returned: queried
- type: bool
- sample: no
- ocsp:
- description:
- - Specifies the name of ocsp profile for purpose of validating
- status of server certificate.
- returned: queried
- type: str
- options:
- description:
- - Enables options, including some industry-related workarounds.
- returned: queried
- type: list
- sample: [ "netscape-reuse-cipher-change-bug", "dont-insert-empty-fragments" ]
- peer_cert_mode:
- description:
- - Specifies the peer certificate mode.
- returned: queried
- type: str
- sample: ignore
- proxy_ssl:
- description:
- - Allows further modification of application traffic within
- an SSL tunnel while still allowing the server to perform necessary
- authorization, authentication, auditing steps.
- returned: queried
- type: bool
- sample: yes
- proxy_ssl_passthrough:
- description:
- - Allows Proxy SSL to passthrough the traffic when ciphersuite negotiated
- between the client and server is not supported.
- returned: queried
- type: bool
- sample: yes
- renegotiate_period:
- description:
- - Number of seconds from the initial connect time
- after which the system renegotiates an SSL session.
- returned: queried
- type: str
- sample: indefinite
- renegotiate_size:
- description:
- - Specifies a throughput size, in megabytes, of SSL renegotiation.
- returned: queried
- type: str
- sample: indefinite
- renegotiation:
- description:
- - Whether renegotiations are enabled.
- returned: queried
- type: bool
- sample: yes
- retain_certificate:
- description:
- - APM module requires storing certificate in SSL session. When C(no),
- certificate will not be stored in SSL session.
- returned: queried
- type: bool
- sample: no
- generic_alert:
- description:
- - Enables or disables generic-alert.
- returned: queried
- type: bool
- sample: yes
- secure_renegotiation:
- description:
- - Specifies the secure renegotiation mode.
- returned: queried
- type: str
- sample: require
- server_name:
- description:
- - Server name to be included in SNI (server name
- indication) extension during SSL handshake in ClientHello.
- returned: queried
- type: str
- session_mirroring:
- description:
- - Enables or disables the mirroring of sessions to high availability
- peer.
- returned: queried
- type: bool
- sample: yes
- session_ticket:
- description:
- - Enables or disables session-ticket.
- returned: queried
- type: bool
- sample: no
- sni_default:
- description:
- - When C(yes), this profile is the default SSL profile when the server
- name in a client connection does not match any configured server
- names, or a client connection does not specify any server name at
- all.
- returned: queried
- type: bool
- sample: yes
- sni_require:
- description:
- - When C(yes), connections to a server that does not support SNI
- extension will be rejected.
- returned: queried
- type: bool
- sample: no
- ssl_c3d:
- description:
- - Enables or disables SSL Client certificate constrained delegation.
- returned: queried
- type: bool
- sample: yes
- ssl_forward_proxy_enabled:
- description:
- - Enables or disables ssl-forward-proxy feature.
- returned: queried
- type: bool
- sample: no
- ssl_sign_hash:
- description:
- - Specifies SSL sign hash algorithm which is used to sign and verify
- SSL Server Key Exchange and Certificate Verify messages for the
- specified SSL profiles.
- returned: queried
- type: str
- sample: sha1
- ssl_forward_proxy_bypass:
- description:
- - Enables or disables ssl-forward-proxy-bypass feature.
- returned: queried
- type: bool
- sample: yes
- strict_resume:
- description:
- - Enables or disables the resumption of SSL sessions after an
- unclean shutdown.
- returned: queried
- type: bool
- sample: no
- unclean_shutdown:
- description:
- - Specifies, when C(yes), that the SSL profile performs unclean
- shutdowns of all SSL connections, which means that underlying TCP
- connections are closed without exchanging the required SSL
- shutdown alerts.
- returned: queried
- type: bool
- sample: yes
- untrusted_cert_response_control:
- description:
- - Specifies the BIGIP action when the server certificate has
- untrusted CA.
- returned: queried
- type: str
- sample: drop
- sample: hash/dictionary of values
-software_hotfixes:
- description: List of software hotfixes.
- returned: When C(software-hotfixes) is specified in C(gather_subset).
- type: complex
- contains:
- name:
- description:
- - Name of the image.
- returned: queried
- type: str
- sample: Hotfix-BIGIP-13.0.0.3.0.1679-HF3.iso
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: Hotfix-BIGIP-13.0.0.3.0.1679-HF3.iso
- build:
- description:
- - Build number of the image.
- - This is usually a sub-string of the C(name).
- returned: queried
- type: str
- sample: 3.0.1679
- checksum:
- description:
- - MD5 checksum of the image.
- - Note that this is the checksum that is stored inside the ISO. It is not
- the actual checksum of the ISO.
- returned: queried
- type: str
- sample: df1ec715d2089d0fa54c0c4284656a98
- product:
- description:
- - Product contained in the ISO.
- returned: queried
- type: str
- sample: BIG-IP
- id:
- description:
- - ID component of the image.
- - This is usually a sub-string of the C(name).
- returned: queried
- type: str
- sample: HF3
- title:
- description:
- - Human friendly name of the image.
- returned: queried
- type: str
- sample: Hotfix Version 3.0.1679
- verified:
- description:
- - Whether or not the system has verified this image.
- returned: queried
- type: bool
- sample: yes
- version:
- description:
- - Version of software contained in the image.
- - This is a sub-string of the C(name).
- returned: queried
- type: str
- sample: 13.0.0
- sample: hash/dictionary of values
-software_images:
- description: List of software images.
- returned: When C(software-images) is specified in C(gather_subset).
- type: complex
- contains:
- name:
- description:
- - Name of the image.
- returned: queried
- type: str
- sample: BIGIP-13.1.0.7-0.0.1.iso
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: BIGIP-13.1.0.7-0.0.1.iso
- build:
- description:
- - Build number of the image.
- - This is usually a sub-string of the C(name).
- returned: queried
- type: str
- sample: 0.0.1
- build_date:
- description:
- - Date of the build.
- returned: queried
- type: str
- sample: "2018-05-05T15:26:30"
- checksum:
- description:
- - MD5 checksum of the image.
- - Note that this is the checksum that is stored inside the ISO. It is not
- the actual checksum of the ISO.
- returned: queried
- type: str
- sample: df1ec715d2089d0fa54c0c4284656a98
- file_size:
- description:
- - Size, in megabytes, of the image.
- returned: queried
- type: int
- sample: 1938
- last_modified:
- description:
- - Last modified date of the ISO.
- returned: queried
- type: str
- sample: "2018-05-05T15:26:30"
- product:
- description:
- - Product contained in the ISO.
- returned: queried
- type: str
- sample: BIG-IP
- verified:
- description:
- - Whether or not the system has verified this image.
- returned: queried
- type: bool
- sample: yes
- version:
- description:
- - Version of software contained in the image.
- - This is a sub-string of the C(name).
- returned: queried
- type: str
- sample: 13.1.0.7
- sample: hash/dictionary of values
-software_volumes:
- description: List of software volumes.
- returned: When C(software-volumes) is specified in C(gather_subset).
- type: complex
- contains:
- active:
- description:
- - Whether the volume is currently active or not.
- - An active volume contains the currently running version of software.
- returned: queried
- type: bool
- sample: yes
- base_build:
- description:
- - Base build version of the software installed in the volume.
- - When a hotfix is installed, this refers to the base version of software
- that the hotfix requires.
- returned: queried
- type: str
- sample: 0.0.6
- build:
- description:
- - Build version of the software installed in the volume.
- returned: queried
- type: str
- sample: 0.0.6
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: HD1.1
- default_boot_location:
- description:
- - Whether this volume is the default boot location or not.
- returned: queried
- type: bool
- sample: yes
- name:
- description:
- - Relative name of the resource in BIG-IP.
- - This usually matches the C(full_name).
- returned: queried
- type: str
- sample: HD1.1
- product:
- description:
- - The F5 product installed in this slot.
- - This should always be BIG-IP.
- returned: queried
- type: str
- sample: BIG-IP
- status:
- description:
- - Status of the software installed, or being installed, in the volume.
- - When C(complete), indicates that the software has completed installing.
- returned: queried
- type: str
- sample: complete
- version:
- description:
- - Version of software installed in the volume, excluding the C(build) number.
- returned: queried
- type: str
- sample: 13.1.0.4
- sample: hash/dictionary of values
-ssl_certs:
- description: SSL certificate related information.
- returned: When C(ssl-certs) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/cert1
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: cert1
- key_type:
- description:
- - Specifies the type of cryptographic key associated with this certificate.
- returned: queried
- type: str
- sample: rsa-private
- key_size:
- description:
- - Specifies the size (in bytes) of the file associated with this file object.
- returned: queried
- type: int
- sample: 2048
- system_path:
- description:
- - Path on the BIG-IP where the cert can be found.
- returned: queried
- type: str
- sample: /config/ssl/ssl.crt/f5-irule.crt
- sha1_checksum:
- description:
- - SHA1 checksum of the certificate.
- returned: queried
- type: str
- sample: 1306e84e1e6a2da53816cefe1f684b80d6be1e3e
- subject:
- description:
- - Specifies X509 information of the certificate's subject.
- returned: queried
- type: str
- sample: "emailAddress=support@f5.com,CN=..."
- last_update_time:
- description:
- - Specifies the last time at which the file-object was
- updated/modified.
- returned: queried
- type: str
- sample: "2018-05-15T21:11:15Z"
- issuer:
- description:
- - Specifies X509 information of the certificate's issuer.
- returned: queried
- type: str
- sample: "emailAddress=support@f5.com,...CN=support.f5.com,"
- is_bundle:
- description:
- - Specifies whether the certificate file is a bundle (that is,
- whether it contains more than one certificate).
- returned: queried
- type: bool
- sample: no
- fingerprint:
- description:
- - Displays the SHA-256 fingerprint of the certificate.
- returned: queried
- type: str
- sample: "SHA256/88:A3:05:...:59:01:EA:5D:B0"
- expiration_date:
- description:
- - Specifies a string representation of the expiration date of the
- certificate.
- returned: queried
- type: str
- sample: "Aug 13 21:21:29 2031 GMT"
- expiration_timestamp:
- description:
- - Specifies the date at which this certificate expires. Stored as a
- POSIX time.
- returned: queried
- type: int
- sample: 1944422489
- create_time:
- description:
- - Specifies the time at which the file-object was created.
- returned: queried
- type: str
- sample: "2018-05-15T21:11:15Z"
- sample: hash/dictionary of values
-ssl_keys:
- description: SSL certificate related information.
- returned: When C(ssl-certs) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/key1
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: key1
- key_type:
- description:
- - Specifies the cryptographic type of the key in question. That is,
- which algorithm this key is compatible with.
- returned: queried
- type: str
- sample: rsa-private
- key_size:
- description:
- - Specifies the size of the cryptographic key associated with this
- file object, in bits.
- returned: queried
- type: int
- sample: 2048
- security_type:
- description:
- - Specifies the type of security used to handle or store the key.
- returned: queried
- type: str
- sample: normal
- system_path:
- description:
- - The path on the filesystem where the key is stored.
- returned: queried
- type: str
- sample: /config/ssl/ssl.key/default.key
- sha1_checksum:
- description:
- - The SHA1 checksum of the key.
- returned: queried
- type: str
- sample: 1fcf7de3dd8e834d613099d8e10b2060cd9ecc9f
- sample: hash/dictionary of values
-system_db:
- description: System DB related information.
- returned: When C(system-db) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: vendor.wwwurl
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: vendor.wwwurl
- default:
- description:
- - Default value of the key.
- returned: queried
- type: str
- sample: www.f5.com
- scf_config:
- description:
- - Whether the database key would be found in an SCF config or not.
- returned: queried
- type: str
- sample: false
- value:
- description:
- - The value of the key
- returned: queried
- type: str
- sample: www.f5.com
- value_range:
- description:
- - The accepted range of values for the key
- returned: queried
- type: str
- sample: string
- sample: hash/dictionary of values
-system_info:
- description: Traffic group related information.
- returned: When C(traffic-groups) is specified in C(gather_subset).
- type: complex
- contains:
- base_mac_address:
- description:
- - Media Access Control address (MAC address) of the device.
- returned: queried
- type: str
- sample: "fa:16:3e:c3:42:6f"
- marketing_name:
- description:
- - Marketing name of the device platform.
- returned: queried
- type: str
- sample: BIG-IP Virtual Edition
- time:
- description:
- - Mapping of the current time information to specific time-named keys.
- returned: queried
- type: complex
- contains:
- day:
- description:
- - The current day of the month, in numeric form.
- returned: queried
- type: int
- sample: 7
- hour:
- description:
- - The current hour of the day in 24-hour form.
- returned: queried
- type: int
- sample: 18
- minute:
- description:
- - The current minute of the hour.
- returned: queried
- type: int
- sample: 16
- month:
- description:
- - The current month, in numeric form.
- returned: queried
- type: int
- sample: 6
- second:
- description:
- - The current second of the minute.
- returned: queried
- type: int
- sample: 51
- year:
- description:
- - The current year in 4-digit form.
- returned: queried
- type: int
- sample: 2018
- hardware_information:
- description:
- - Information related to the hardware (drives and CPUs) of the system.
- type: complex
- returned: queried
- contains:
- model:
- description:
- - The model of the hardware.
- returned: queried
- type: str
- sample: Virtual Disk
- name:
- description:
- - The name of the hardware.
- returned: queried
- type: str
- sample: HD1
- type:
- description:
- - The type of hardware.
- returned: queried
- type: str
- sample: physical-disk
- versions:
- description:
- - Hardware specific properties.
- returned: queried
- type: complex
- contains:
- name:
- description:
- - Name of the property.
- returned: queried
- type: str
- sample: Size
- version:
- description:
- - Value of the property.
- returned: queried
- type: str
- sample: 154.00G
- package_edition:
- description:
- - Displays the software edition.
- returned: queried
- type: str
- sample: Point Release 7
- package_version:
- description:
- - A string combining the C(product_build) and C(product_build_date).
- returned: queried
- type: str
- sample: "Build 0.0.1 - Tue May 15 15:26:30 PDT 2018"
- product_code:
- description:
- - Code identifying the product.
- returned: queried
- type: str
- sample: BIG-IP
- product_build:
- description:
- - Build version of the release version.
- returned: queried
- type: str
- sample: 0.0.1
- product_version:
- description:
- - Major product version of the running software.
- returned: queried
- type: str
- sample: 13.1.0.7
- product_built:
- description:
- - Unix timestamp of when the product was built.
- returned: queried
- type: int
- sample: 180515152630
- product_build_date:
- description:
- - Human readable build date.
- returned: queried
- type: str
- sample: "Tue May 15 15:26:30 PDT 2018"
- product_changelist:
- description:
- - Changelist that product branches from.
- returned: queried
- type: int
- sample: 2557198
- product_jobid:
- description:
- - ID of the job that built the product version.
- returned: queried
- type: int
- sample: 1012030
- chassis_serial:
- description:
- - Serial of the chassis.
- returned: queried
- type: str
- sample: 11111111-2222-3333-444444444444
- host_board_part_revision:
- description:
- - Revision of the host board.
- returned: queried
- type: str
- host_board_serial:
- description:
- - Serial of the host board.
- returned: queried
- type: str
- platform:
- description:
- - Platform identifier.
- returned: queried
- type: str
- sample: Z100
- switch_board_part_revision:
- description:
- - Switch board revision.
- returned: queried
- type: str
- switch_board_serial:
- description:
- - Serial of the switch board.
- returned: queried
- type: str
- uptime:
- description:
- - Time, in seconds, since the system booted.
- returned: queried
- type: int
- sample: 603202
- sample: hash/dictionary of values
-tcp_monitors:
- description: TCP monitor related information.
- returned: When C(tcp-monitors) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/tcp
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: tcp
- parent:
- description:
- - Profile from which this profile inherits settings.
- returned: queried
- type: str
- sample: tcp
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: My monitor
- adaptive:
- description:
- - Whether adaptive response time monitoring is enabled for this monitor.
- returned: queried
- type: bool
- sample: no
- adaptive_divergence_type:
- description:
- - Specifies whether the adaptive-divergence-value is C(relative) or
- C(absolute).
- returned: queried
- type: str
- sample: relative
- adaptive_divergence_value:
- description:
- - Specifies how far from mean latency each monitor probe is allowed
- to be.
- returned: queried
- type: int
- sample: 25
- adaptive_limit:
- description:
- - Specifies the hard limit, in milliseconds, which the probe is not
- allowed to exceed, regardless of the divergence value.
- returned: queried
- type: int
- sample: 200
- adaptive_sampling_timespan:
- description:
- - Specifies the size of the sliding window, in seconds, which
- records probe history.
- returned: queried
- type: int
- sample: 300
- destination:
- description:
- - Specifies the IP address and service port of the resource that is
- the destination of this monitor.
- returned: queried
- type: str
- sample: "*:*"
- interval:
- description:
- - Specifies, in seconds, the frequency at which the system issues
- the monitor check when either the resource is down or the status
- of the resource is unknown.
- returned: queried
- type: int
- sample: 5
- ip_dscp:
- description:
- - Specifies the differentiated services code point (DSCP).
- returned: queried
- type: int
- sample: 0
- manual_resume:
- description:
- - Specifies whether the system automatically changes the status of a
- resource to up at the next successful monitor check.
- returned: queried
- type: bool
- sample: yes
- reverse:
- description:
- - Specifies whether the monitor operates in reverse mode. When the
- monitor is in reverse mode, a successful check marks the monitored
- object down instead of up.
- returned: queried
- type: bool
- sample: no
- time_until_up:
- description:
- - Specifies the amount of time, in seconds, after the first
- successful response before a node is marked up.
- returned: queried
- type: int
- sample: 0
- timeout:
- description:
- - Specifies the number of seconds the target has in which to respond
- to the monitor request.
- returned: queried
- type: int
- sample: 16
- transparent:
- description:
- - Specifies whether the monitor operates in transparent mode.
- returned: queried
- type: bool
- sample: no
- up_interval:
- description:
- - Specifies, in seconds, the frequency at which the system issues
- the monitor check when the resource is up.
- returned: queried
- type: int
- sample: 0
- sample: hash/dictionary of values
-tcp_half_open_monitors:
- description: TCP Half-open monitor related information.
- returned: When C(tcp-half-open-monitors) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/tcp
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: tcp
- parent:
- description:
- - Profile from which this profile inherits settings.
- returned: queried
- type: str
- sample: tcp
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: My monitor
- destination:
- description:
- - Specifies the IP address and service port of the resource that is
- the destination of this monitor.
- returned: queried
- type: str
- sample: "*:*"
- interval:
- description:
- - Specifies, in seconds, the frequency at which the system issues
- the monitor check when either the resource is down or the status
- of the resource is unknown.
- returned: queried
- type: int
- sample: 5
- manual_resume:
- description:
- - Specifies whether the system automatically changes the status of a
- resource to up at the next successful monitor check.
- returned: queried
- type: bool
- sample: yes
- time_until_up:
- description:
- - Specifies the amount of time, in seconds, after the first
- successful response before a node is marked up.
- returned: queried
- type: int
- sample: 0
- timeout:
- description:
- - Specifies the number of seconds the target has in which to respond
- to the monitor request.
- returned: queried
- type: int
- sample: 16
- transparent:
- description:
- - Specifies whether the monitor operates in transparent mode.
- returned: queried
- type: bool
- sample: no
- up_interval:
- description:
- - Specifies, in seconds, the frequency at which the system issues
- the monitor check when the resource is up.
- returned: queried
- type: int
- sample: 0
- sample: hash/dictionary of values
-tcp_profiles:
- description: TCP profile related information.
- returned: When C(tcp-profiles) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: tcp
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: /Common/tcp
- parent:
- description:
- - Profile from which this profile inherits settings.
- returned: queried
- type: str
- sample: tcp
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: My profile
- abc:
- description:
- - Appropriate Byte Counting (RFC 3465)
- - When C(yes), increases the congestion window by basing the increase
- amount on the number of previously unacknowledged bytes that each ACK covers.
- returned: queried
- type: bool
- sample: yes
- ack_on_push:
- description:
- - Specifies, when C(yes), significantly improved performance to Microsoft
- Windows and MacOS peers who are writing out on a very small send buffer.
- returned: queried
- type: bool
- sample: no
- auto_proxy_buffer:
- description:
- - Specifies, C(yes), that the system uses the network measurements to set
- the optimal proxy buffer size.
- returned: queried
- type: bool
- sample: yes
- auto_receive_window:
- description:
- - Specifies, when C(yes), that the system uses the network measurements to
- set the optimal receive window size.
- returned: queried
- type: bool
- sample: no
- auto_send_buffer:
- description:
- - Specifies, when C(yes), that the system uses the network measurements to
- set the optimal send buffer size.
- returned: queried
- type: bool
- sample: yes
- close_wait:
- description:
- - Specifies the length of time that a TCP connection remains in the LAST-ACK
- state before quitting.
- - In addition to a numeric value, the value of this fact may also be one of
- C(immediate) or C(indefinite).
- - When C(immediate), specifies that the TCP connection closes immediately
- after entering the LAST-ACK state.
- - When C(indefinite), specifies that TCP connections in the LAST-ACK state
- do not close until they meet the maximum retransmissions timeout.
- returned: queried
- type: str
- sample: indefinite
- congestion_metrics_cache:
- description:
- - Specifies, when C(yes), that the system uses a cache for storing congestion
- metrics.
- - Subsequently, because these metrics are already known and cached, the initial
- slow-start ramp for previously-encountered peers improves.
- returned: queried
- type: bool
- sample: yes
- congestion_metrics_cache_timeout:
- description:
- - Specifies the number of seconds for which entries in the congestion metrics
- cache are valid.
- returned: queried
- type: int
- sample: 0
- congestion_control:
- description:
- - Specifies the algorithm to use to share network resources among competing
- users to reduce congestion.
- - Return values may include, C(high-speed), C(cdg), C(chd), C(none), C(cubic),
- C(illinois), C(new-reno), C(reno), C(scalable), C(vegas), C(westwood), and
- C(woodside).
- returned: queried
- type: str
- sample: high-speed
- deferred_accept:
- description:
- - Specifies, when C(yes), that the system defers allocation of the connection
- chain context until the system has received the payload from the client.
- - Enabling this setting is useful in dealing with 3-way handshake denial-of-service
- attacks.
- returned: queried
- type: bool
- sample: yes
- delay_window_control:
- description:
- - Specifies that the system uses an estimate of queuing delay as a measure of
- congestion to control, in addition to the normal loss-based control, the amount
- of data sent.
- returned: queried
- type: bool
- sample: yes
- delayed_acks:
- description:
- - Specifies, when checked (enabled), that the system can send fewer than one ACK
- (acknowledgment) segment per data segment received.
- returned: queried
- type: bool
- sample: yes
- dsack:
- description:
- - D-SACK (RFC 2883)
- - Specifies, when C(yes), the use of the selective ACK (SACK) option to acknowledge
- duplicate segments.
- returned: queried
- type: bool
- sample: yes
- early_retransmit:
- description:
- - Specifies, when C(yes), that the system uses early retransmit (as specified in
- RFC 5827) to reduce the recovery time for connections that are receive- buffer
- or user-data limited.
- returned: queried
- type: bool
- sample: yes
- explicit_congestion_notification:
- description:
- - Specifies, when C(yes), that the system uses the TCP flags CWR (congestion window
- reduction) and ECE (ECN-Echo) to notify its peer of congestion and congestion
- counter-measures.
- returned: queried
- type: bool
- sample: yes
- enhanced_loss_recovery:
- description:
- - Specifies whether the system uses enhanced loss recovery to recover from random
- packet losses more effectively.
- returned: queried
- type: bool
- sample: yes
- fast_open:
- description:
- - Specifies, when C(yes), that the system supports TCP Fast Open, which reduces
- latency by allowing a client to include the first packet of data with the SYN
- returned: queried
- type: bool
- sample: yes
- fast_open_cookie_expiration:
- description:
- - Specifies the number of seconds that a Fast Open Cookie delivered to a client
- is valid for SYN packets from that client.
- returned: queried
- type: int
- sample: 1000
- fin_wait_1:
- description:
- - Specifies the length of time that a TCP connection is in the FIN-WAIT-1 or
- CLOSING state before quitting.
- returned: queried
- type: str
- sample: indefinite
- fin_wait_2:
- description:
- - Specifies the length of time that a TCP connection is in the FIN-WAIT-2 state
- before quitting.
- returned: queried
- type: str
- sample: 100
- idle_timeout:
- description:
- - Specifies the length of time that a connection is idle (has no traffic) before
- the connection is eligible for deletion.
- returned: queried
- type: str
- sample: 300
- initial_congestion_window_size:
- description:
- - Specifies the initial congestion window size for connections to this destination.
- returned: queried
- type: int
- sample: 3
- initial_receive_window_size:
- description:
- - Specifies the initial receive window size for connections to this destination.
- returned: queried
- type: int
- sample: 5
- dont_fragment_flag:
- description:
- - Specifies the Don't Fragment (DF) bit setting in the IP Header of the outgoing
- TCP packet.
- returned: queried
- type: str
- sample: pmtu
- ip_tos:
- description:
- - Specifies the L3 Type of Service (ToS) level that the system inserts in TCP
- packets destined for clients.
- returned: queried
- type: str
- sample: mimic
- time_to_live:
- description:
- - Specifies the outgoing TCP packet's IP Header TTL mode.
- returned: queried
- type: str
- sample: proxy
- time_to_live_v4:
- description:
- - Specifies the outgoing packet's IP Header TTL value for IPv4 traffic.
- returned: queried
- type: int
- sample: 255
- time_to_live_v6:
- description:
- - Specifies the outgoing packet's IP Header TTL value for IPv6 traffic.
- returned: queried
- type: int
- sample: 64
- keep_alive_interval:
- description:
- - Specifies how frequently the system sends data over an idle TCP
- connection, to determine whether the connection is still valid.
- returned: queried
- type: str
- sample: 50
- limited_transmit_recovery:
- description:
- - Specifies, when C(yes), that the system uses limited transmit recovery
- revisions for fast retransmits (as specified in RFC 3042) to reduce
- the recovery time for connections on a lossy network.
- returned: queried
- type: bool
- sample: yes
- link_qos:
- description:
- - Specifies the L2 Quality of Service (QoS) level that the system inserts
- in TCP packets destined for clients.
- returned: queried
- type: str
- sample: 200
- max_segment_retrans:
- description:
- - Specifies the maximum number of times that the system resends data segments.
- returned: queried
- type: int
- sample: 8
- max_syn_retrans:
- description:
- - Specifies the maximum number of times that the system resends a SYN
- packet when it does not receive a corresponding SYN-ACK.
- returned: queried
- type: int
- sample: 3
- max_segment_size:
- description:
- - Specifies the largest amount of data that the system can receive in a
- single TCP segment, not including the TCP and IP headers.
- returned: queried
- type: int
- sample: 1460
- md5_signature:
- description:
- - Specifies, when C(yes), to use RFC2385 TCP-MD5 signatures to protect
- TCP traffic against intermediate tampering.
- returned: queried
- type: bool
- sample: yes
- minimum_rto:
- description:
- - Specifies the minimum length of time the system waits for
- acknowledgements of data sent before resending the data.
- returned: queried
- type: int
- sample: 1000
- multipath_tcp:
- description:
- - Specifies, when C(yes), that the system accepts Multipath TCP (MPTCP)
- connections, which allow multiple client-side flows to connect to a
- single server-side flow.
- returned: queried
- type: bool
- sample: yes
- mptcp_checksum:
- description:
- - Specifies, when C(yes), that the system calculates the checksum for
- MPTCP connections.
- returned: queried
- type: bool
- sample: no
- mptcp_checksum_verify:
- description:
- - Specifies, when C(yes), that the system verifies the checksum for
- MPTCP connections.
- returned: queried
- type: bool
- sample: no
- mptcp_fallback:
- description:
- - Specifies an action on fallback, that is, when MPTCP transitions
- to regular TCP, because something prevents MPTCP from working correctly.
- returned: queried
- type: str
- sample: reset
- mptcp_fast_join:
- description:
- - Specifies, when C(yes), a FAST join, allowing data to be sent on the
- MP_JOIN_SYN, which can allow a server response to occur in parallel
- with the JOIN.
- returned: queried
- type: bool
- sample: no
- mptcp_idle_timeout:
- description:
- - Specifies the number of seconds that an MPTCP connection is idle
- before the connection is eligible for deletion.
- returned: queried
- type: int
- sample: 300
- mptcp_join_max:
- description:
- - Specifies the highest number of MPTCP connections that can join to
- a given connection.
- returned: queried
- type: int
- sample: 5
- mptcp_make_after_break:
- description:
- - Specifies that make-after-break functionality is supported, allowing
- for long-lived MPTCP sessions.
- returned: queried
- type: bool
- sample: no
- mptcp_no_join_dss_ack:
- description:
- - Specifies, when checked (enabled), that no DSS option is sent on the
- JOIN ACK.
- returned: queried
- type: bool
- sample: no
- mptcp_rto_max:
- description:
- - Specifies the number of RTOs (retransmission timeouts) before declaring
- the subflow dead.
- returned: queried
- type: int
- sample: 5
- mptcp_retransmit_min:
- description:
- - Specifies the minimum value (in msec) of the retransmission timer for
- these MPTCP flows.
- returned: queried
- type: int
- sample: 1000
- mptcp_subflow_max:
- description:
- - Specifies the maximum number of MPTCP subflows for a single flow.
- returned: queried
- type: int
- sample: 6
- mptcp_timeout:
- description:
- - Specifies, in seconds, the timeout value to discard long-lived sessions
- that do not have an active flow.
- returned: queried
- type: int
- sample: 3600
- nagle_algorithm:
- description:
- - Specifies whether the system applies Nagle's algorithm to reduce the
- number of short segments on the network.
- returned: queried
- type: bool
- sample: no
- pkt_loss_ignore_burst:
- description:
- - Specifies the probability of performing congestion control when
- multiple packets are lost, even if the Packet Loss Ignore Rate was
- not exceeded.
- returned: queried
- type: int
- sample: 0
- pkt_loss_ignore_rate:
- description:
- - Specifies the threshold of packets lost per million at which the
- system performs congestion control.
- returned: queried
- type: int
- sample: 0
- proxy_buffer_high:
- description:
- - Specifies the proxy buffer level, in bytes, at which the receive window
- is closed.
- returned: queried
- type: int
- sample: 49152
- proxy_buffer_low:
- description:
- - Specifies the proxy buffer level, in bytes, at which the receive window
- is opened.
- returned: queried
- type: int
- sample: 32768
- proxy_max_segment:
- description:
- - Specifies, when C(yes), that the system attempts to advertise the same
- maximum segment size (MSS) to the server-side connection as that of the
- client-side connection.
- returned: queried
- type: bool
- sample: yes
- proxy_options:
- description:
- - Specifies, when C(yes), that the system advertises an option (such as
- time stamps) to the server only when the option is negotiated with the
- client.
- returned: queried
- type: bool
- sample: no
- push_flag:
- description:
- - Specifies how the BIG-IP system receives ACKs.
- returned: queried
- type: str
- sample: default
- rate_pace:
- description:
- - Specifies, when C(yes), that the system paces the egress packets to
- avoid dropping packets, allowing for optimum goodput.
- returned: queried
- type: bool
- sample: yes
- rate_pace_max_rate:
- description:
- - Specifies the maximum rate in bytes per second to which the system
- paces TCP data transmission.
- returned: queried
- type: int
- sample: 0
- receive_window:
- description:
- - Specifies the maximum advertised RECEIVE window size.
- returned: queried
- type: int
- sample: 65535
- reset_on_timeout:
- description:
- - Specifies, when C(yes), that the system sends a reset packet (RST)
- in addition to deleting the connection, when a connection exceeds
- the idle timeout value.
- returned: queried
- type: bool
- sample: yes
- retransmit_threshold:
- description:
- - Specifies the number of duplicate ACKs (retransmit threshold) to start
- fast recovery.
- returned: queried
- type: int
- sample: 3
- selective_acks:
- description:
- - Specifies, when C(yes), that the system processes data using
- selective ACKs (SACKs) whenever possible, to improve system performance.
- returned: queried
- type: bool
- sample: yes
- selective_nack:
- description:
- - Specifies, when C(yes), that the system processes data using a selective
- negative acknowledgment (SNACK) whenever possible, to improve system
- performance.
- returned: queried
- type: bool
- sample: yes
- send_buffer:
- description:
- - Specifies the SEND window size.
- returned: queried
- type: int
- sample: 65535
- slow_start:
- description:
- - Specifies, when C(yes), that the system uses Slow-Start Congestion
- Avoidance as described in RFC3390 in order to ramp up traffic without
- causing excessive congestion on the link.
- returned: queried
- type: bool
- sample: yes
- syn_cookie_enable:
- description:
- - Specifies the default (if no DoS profile is associated) number of
- embryonic connections that are allowed on any virtual server,
- before SYN Cookie challenges are enabled for that virtual server.
- returned: queried
- type: bool
- sample: yes
- syn_cookie_white_list:
- description:
- - Specifies whether or not to use a SYN Cookie WhiteList when doing
- software SYN Cookies.
- returned: queried
- type: bool
- sample: no
- syn_retrans_to_base:
- description:
- - Specifies the initial RTO (Retransmission TimeOut) base multiplier
- for SYN retransmissions.
- returned: queried
- type: int
- sample: 3000
- tail_loss_probe:
- description:
- - Specifies, when C(yes), that the system uses Tail Loss Probe to
- reduce the number of retransmission timeouts.
- returned: queried
- type: bool
- sample: yes
- time_wait_recycle:
- description:
- - Specifies, when C(yes), that connections in a TIME-WAIT state are
- reused when the system receives a SYN packet, indicating a request
- for a new connection.
- returned: queried
- type: bool
- sample: yes
- time_wait:
- description:
- - Specifies the length of time that a TCP connection remains in the
- TIME-WAIT state before entering the CLOSED state.
- returned: queried
- type: str
- sample: 2000
- timestamps:
- description:
- - Specifies, when C(yes), that the system uses the timestamps extension
- for TCP (as specified in RFC 1323) to enhance high-speed network performance.
- returned: queried
- type: bool
- sample: yes
- verified_accept:
- description:
- - Specifies, when C(yes), that the system can actually communicate with
- the server before establishing a client connection.
- returned: queried
- type: bool
- sample: yes
- zero_window_timeout:
- description:
- - Specifies the timeout in milliseconds for terminating a connection
- with an effective zero length TCP transmit window.
- returned: queried
- type: str
- sample: 2000
- sample: hash/dictionary of values
-traffic_groups:
- description: Traffic group related information.
- returned: When C(traffic-groups) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/tg1
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: tg1
- description:
- description:
- - Description of the traffic group.
- returned: queried
- type: str
- sample: My traffic group
- auto_failback_enabled:
- description:
- - Specifies whether the traffic group fails back to the default
- device.
- returned: queried
- type: bool
- sample: yes
- auto_failback_time:
- description:
- - Specifies the time required to fail back.
- returned: queried
- type: int
- sample: 60
- ha_load_factor:
- description:
- - Specifies a number for this traffic group that represents the load
- this traffic group presents to the system relative to other
- traffic groups.
- returned: queried
- type: int
- sample: 1
- ha_order:
- description:
- - This list of devices specifies the order in which the devices will
- become active for the traffic group when a failure occurs.
- returned: queried
- type: list
- sample: ['/Common/device1', '/Common/device2']
- is_floating:
- description:
- - Indicates whether the traffic group can fail over to other devices
- in the device group.
- returned: queried
- type: bool
- sample: no
- mac_masquerade_address:
- description:
- - Specifies a MAC address for the traffic group.
- returned: queried
- type: str
- sample: "00:98:76:54:32:10"
- sample: hash/dictionary of values
-trunks:
- description: Trunk related information.
- returned: When C(trunks) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/trunk1
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: trunk1
- description:
- description:
- - Description of the Trunk.
- returned: queried
- type: str
- sample: My trunk
- media_speed:
- description:
- - Speed of the media attached to the trunk.
- returned: queried
- type: int
- sample: 10000
- lacp_mode:
- description:
- - The operation mode for LACP.
- returned: queried
- type: str
- sample: passive
- lacp_enabled:
- description:
- - Whether LACP is enabled or not.
- returned: queried
- type: bool
- sample: yes
- stp_enabled:
- description:
- - Whether Spanning Tree Protocol (STP) is enabled or not.
- returned: queried
- type: bool
- sample: yes
- operational_member_count:
- description:
- - Number of working members associated with the trunk.
- returned: queried
- type: int
- sample: 1
- media_status:
- description:
- - Whether the media that is part of the trunk is up or not.
- returned: queried
- type: bool
- sample: yes
- link_selection_policy:
- description:
- - The LACP policy that the trunk uses to determine which member link can handle
- new traffic.
- returned: queried
- type: str
- sample: maximum-bandwidth
- lacp_timeout:
- description:
- - The rate at which the system sends the LACP control packets.
- returned: queried
- type: int
- sample: 10
- interfaces:
- description:
- - The list of interfaces that are part of the trunk.
- returned: queried
- type: list
- sample: ['1.2', '1.3']
- distribution_hash:
- description:
- - The basis for the has that the system uses as the frame distribution algorithm.
- - The system uses this hash to determine which interface to use for forwarding
- traffic.
- returned: queried
- type: str
- sample: src-dst-ipport
- configured_member_count:
- description:
- - The number of configured members that are associated with the trunk.
- returned: queried
- type: int
- sample: 1
- sample: hash/dictionary of values
-udp_profiles:
- description: UDP profile related information.
- returned: When C(udp-profiles) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: udp
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: /Common/udp
- parent:
- description:
- - Profile from which this profile inherits settings.
- returned: queried
- type: str
- sample: udp
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: My profile
- allow_no_payload:
- description:
- - Allow the passage of datagrams that contain header information, but no essential data.
- returned: queried
- type: bool
- sample: yes
- buffer_max_bytes:
- description:
- - Ingress buffer byte limit. Maximum allowed value is 16777215.
- returned: queried
- type: int
- sample: 655350
- buffer_max_packets:
- description:
- - Ingress buffer packet limit. Maximum allowed value is 255.
- returned: queried
- type: int
- sample: 0
- datagram_load_balancing:
- description:
- - Load balance UDP datagram by datagram
- returned: queried
- type: bool
- sample: yes
- idle_timeout:
- description:
- - Number of seconds that a connection is idle before
- the connection is eligible for deletion.
- - In addition to a number, may be one of the values C(indefinite), or
- C(immediate).
- returned: queried
- type: bool
- sample: 200
- ip_df_mode:
- description:
- - Describes the Don't Fragment (DF) bit setting in the outgoing UDP
- packet.
- - May be one of C(pmtu), C(preserve), C(set), or C(clear).
- - When C(pmtu), sets the outgoing UDP packet DF big based on the ip
- pmtu setting.
- - When C(preserve), preserves the incoming UDP packet Don't Fragment bit.
- - When C(set), sets the outgoing UDP packet DF bit.
- - When C(clear), clears the outgoing UDP packet DF bit.
- returned: queried
- type: str
- sample: pmtu
- ip_tos_to_client:
- description:
- - The Type of Service level that the traffic management
- system assigns to UDP packets when sending them to clients.
- - May be numeric, or the values C(pass-through) or C(mimic).
- returned: queried
- type: str
- sample: mimic
- ip_ttl_mode:
- description:
- - The outgoing UDP packet's TTL mode.
- - Valid modes are C(proxy), C(preserve), C(decrement), and C(set).
- - When C(proxy), set the IP TTL of ipv4 to the default value of 255 and
- ipv6 to the default value of 64.
- - When C(preserve), set the IP TTL to the original packet TTL value.
- - When C(decrement), set the IP TTL to the original packet TTL value minus 1.
- - When C(set), set the IP TTL with the specified values in C(ip_ttl_v4) and
- C(ip_ttl_v6) values in the same profile.
- returned: queried
- type: str
- sample: proxy
- ip_ttl_v4:
- description:
- - IPv4 TTL.
- returned: queried
- type: int
- sample: 10
- ip_ttl_v6:
- description:
- - IPv6 TTL.
- returned: queried
- type: int
- sample: 100
- link_qos_to_client:
- description:
- - The Quality of Service level that the system assigns to
- UDP packets when sending them to clients.
- - May be either numeric, or the value C(pass-through).
- returned: queried
- type: str
- sample: pass-through
- no_checksum:
- description:
- - Whether the checksum processing is enabled or disabled.
- - Note that if the datagram is IPv6, the system always performs
- checksum processing.
- returned: queried
- type: bool
- sample: yes
- proxy_mss:
- description:
- - When C(yes), specifies that the system advertises the same mss
- to the server as was negotiated with the client.
- returned: queried
- type: bool
- sample: yes
- sample: hash/dictionary of values
-users:
- description: Details of the users on the system.
- returned: When C(users) is specified in C(gather_subset).
- type: complex
- contains:
- description:
- description:
- - Description of the resource.
- returned: queried
- type: str
- sample: Admin user
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: admin
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: admin
- partition_access:
- description:
- - Partition that user has access to, including user role.
- returned: queried
- type: complex
- contains:
- name:
- description:
- - Name of partition
- returned: queried
- type: str
- sample: all-partitions
- role:
- description:
- - Role allowed to user on partition.
- returned: queried
- type: str
- sample: auditor
- shell:
- description:
- - The shell assigned to the user account.
- returned: queried
- type: str
- sample: tmsh
-vcmp_guests:
- description: vCMP related information.
- returned: When C(vcmp-guests) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: guest1
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: guest1
- allowed_slots:
- description:
- - List of slots that the guest is allowed to be assigned to.
- returned: queried
- type: list
- sample: [0, 1, 3]
- assigned_slots:
- description:
- - Slots that the guest is assigned to.
- returned: queried
- type: list
- sample: [0]
- boot_priority:
- description:
- - Specifies boot priority of the guest. Lower number means earlier to boot.
- returned: queried
- type: int
- sample: 65535
- cores_per_slot:
- description:
- - Number of cores that the system allocates to the guest.
- returned: queried
- type: int
- sample: 2
- hostname:
- description:
- - FQDN assigned to the guest.
- returned: queried
- type: str
- sample: guest1.localdomain
- hotfix_image:
- description:
- - hotfix image to install onto any of this guest's newly created virtual disks.
- returned: queried
- type: str
- sample: Hotfix-BIGIP-12.1.3.4-0.0.2-hf1.iso
- initial_image:
- description:
- - Software image to install onto any of this guest's newly created virtual disks.
- returned: queried
- type: str
- sample: BIGIP-12.1.3.4-0.0.2.iso
- mgmt_route:
- description:
- - Management gateway IP address for the guest.
- returned: queried
- type: str
- sample: 2.2.2.1
- mgmt_address:
- description:
- - Management IP address configuration for the guest.
- returned: queried
- type: str
- sample: 2.3.2.3
- mgmt_network:
- description:
- - Accessibility of this vCMP guest's management network.
- returned: queried
- type: str
- sample: bridged
- vlans:
- description:
- - List of VLANs on which the guest is either enabled or disabled.
- returned: queried
- type: list
- sample: ['/Common/vlan1', '/Common/vlan2']
- min_number_of_slots:
- description:
- - Specifies the minimum number of slots that the guest must be assigned to.
- returned: queried
- type: int
- sample: 2
- number_of_slots:
- description:
- - Specifies the number of slots the guest should be assigned to.
- - This number is always greater than, or equal to, C(min_number_of_slots).
- returned: queried
- type: int
- sample: 2
- ssl_mode:
- description:
- - The SSL hardware allocation mode for the guest.
- returned: queried
- type: str
- sample: shared
- state:
- description:
- - Specifies the state of the guest.
- - May be one of C(configured), C(provisioned), or C(deployed).
- - Each state implies the actions of all states before it.
- returned: queried
- type: str
- sample: provisioned
- virtual_disk:
- description:
- - The filename of the virtual disk to use for this guest.
- returned: queried
- type: str
- sample: guest1.img
- sample: hash/dictionary of values
-virtual_addresses:
- description: Virtual address related information.
- returned: When C(virtual-addresses) is specified in C(gather_subset).
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/2.3.4.5
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: 2.3.4.5
- address:
- description:
- - The virtual IP address.
- returned: queried
- type: str
- sample: 2.3.4.5
- arp_enabled:
- description:
- - Whether or not ARP is enabled for the specified virtual address.
- returned: queried
- type: bool
- sample: yes
- auto_delete_enabled:
- description:
- - Indicates if the virtual address will be deleted automatically on
- deletion of the last associated virtual server or not.
- returned: queried
- type: bool
- sample: no
- connection_limit:
- description:
- - Concurrent connection limit for one or more virtual
- servers.
- returned: queried
- type: int
- sample: 0
- description:
- description:
- - The description of the virtual address.
- returned: queried
- type: str
- sample: My virtual address
- enabled:
- description:
- - Whether the virtual address is enabled or not.
- returned: queried
- type: bool
- sample: yes
- icmp_echo:
- description:
- - Whether the virtual address should reply to ICMP echo requests.
- returned: queried
- type: bool
- sample: yes
- floating:
- description:
- - Property derived from traffic-group. A floating virtual
- address is a virtual address for a VLAN that serves as a shared
- address by all devices of a BIG-IP traffic-group.
- returned: queried
- type: bool
- sample: yes
- netmask:
- description:
- - Netmask of the virtual address.
- returned: queried
- type: str
- sample: 255.255.255.255
- route_advertisement:
- description:
- - Specifies the route advertisement setting for the virtual address.
- returned: queried
- type: bool
- sample: no
- traffic_group:
- description:
- - Traffic group on which the virtual address is active.
- returned: queried
- type: str
- sample: /Common/traffic-group-1
- spanning:
- description:
- - Whether or not spanning is enabled for the specified virtual address.
- returned: queried
- type: bool
- sample: no
- inherited_traffic_group:
- description:
- - Indicates if the traffic-group is inherited from the parent folder.
- returned: queried
- type: bool
- sample: no
- sample: hash/dictionary of values
-virtual_servers:
- description: Virtual address related information.
- returned: When C(virtual-addresses) is specified in C(gather_subset).
- type: complex
- contains:
- availability_status:
- description:
- - The availability of the virtual server.
- returned: queried
- type: str
- sample: offline
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/2.3.4.5
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: 2.3.4.5
- auto_lasthop:
- description:
- - When enabled, allows the system to send return traffic to the MAC address
- that transmitted the request, even if the routing table points to a different
- network or interface.
- returned: queried
- type: str
- sample: default
- bw_controller_policy:
- description:
- - The bandwidth controller for the system to use to enforce a throughput policy
- for incoming network traffic.
- returned: queried
- type: str
- sample: /Common/bw1
- client_side_bits_in:
- description:
- - Number of client-side ingress bits.
- returned: queried
- type: int
- sample: 1000
- client_side_bits_out:
- description:
- - Number of client-side egress bits.
- returned: queried
- type: int
- sample: 200
- client_side_current_connections:
- description:
- - Number of current connections client-side.
- returned: queried
- type: int
- sample: 300
- client_side_evicted_connections:
- description:
- - Number of evicted connections client-side.
- returned: queried
- type: int
- sample: 100
- client_side_max_connections:
- description:
- - Maximum number of connections client-side.
- returned: queried
- type: int
- sample: 40
- client_side_pkts_in:
- description:
- - Number of client-side ingress packets.
- returned: queried
- type: int
- sample: 1098384
- client_side_pkts_out:
- description:
- - Number of client-side egress packets.
- returned: queried
- type: int
- sample: 3484734
- client_side_slow_killed:
- description:
- - Number of slow connections killed, client-side.
- returned: queried
- type: int
- sample: 234
- client_side_total_connections:
- description:
- - Total number of connections.
- returned: queried
- type: int
- sample: 24
- cmp_enabled:
- description:
- - Whether or not clustered multi-processor (CMP) acceleration is enabled.
- returned: queried
- type: bool
- sample: yes
- cmp_mode:
- description:
- - The clustered-multiprocessing mode.
- returned: queried
- type: str
- sample: all-cpus
- connection_limit:
- description:
- - Maximum number of concurrent connections you want to allow for the virtual server.
- returned: queried
- type: int
- sample: 100
- description:
- description:
- - The description of the virtual server.
- returned: queried
- type: str
- sample: My virtual
- enabled:
- description:
- - Whether or not the virtual is enabled.
- returned: queried
- type: bool
- sample: yes
- ephemeral_bits_in:
- description:
- - Number of ephemeral ingress bits.
- returned: queried
- type: int
- sample: 1000
- ephemeral_bits_out:
- description:
- - Number of ephemeral egress bits.
- returned: queried
- type: int
- sample: 200
- ephemeral_current_connections:
- description:
- - Number of ephemeral current connections.
- returned: queried
- type: int
- sample: 300
- ephemeral_evicted_connections:
- description:
- - Number of ephemeral evicted connections.
- returned: queried
- type: int
- sample: 100
- ephemeral_max_connections:
- description:
- - Maximum number of ephemeral connections.
- returned: queried
- type: int
- sample: 40
- ephemeral_pkts_in:
- description:
- - Number of ephemeral ingress packets.
- returned: queried
- type: int
- sample: 1098384
- ephemeral_pkts_out:
- description:
- - Number of ephemeral egress packets.
- returned: queried
- type: int
- sample: 3484734
- ephemeral_slow_killed:
- description:
- - Number of ephemeral slow connections killed.
- returned: queried
- type: int
- sample: 234
- ephemeral_total_connections:
- description:
- - Total number of ephemeral connections.
- returned: queried
- type: int
- sample: 24
- total_software_accepted_syn_cookies:
- description:
- - SYN Cookies Total Software Accepted.
- returned: queried
- type: int
- sample: 0
- total_hardware_accepted_syn_cookies:
- description:
- - SYN Cookies Total Hardware Accepted.
- returned: queried
- type: int
- sample: 0
- total_hardware_syn_cookies:
- description:
- - SYN Cookies Total Hardware
- returned: queried
- type: int
- sample: 0
- hardware_syn_cookie_instances:
- description:
- - Hardware SYN Cookie Instances
- returned: queried
- type: int
- sample: 0
- total_software_rejected_syn_cookies:
- description:
- - Total Software Rejected
- returned: queried
- type: int
- sample: 0
- software_syn_cookie_instances:
- description:
- - Software SYN Cookie Instances
- returned: queried
- type: int
- sample: 0
- current_syn_cache:
- description:
- - Current SYN Cache
- returned: queried
- type: int
- sample: 0
- max_conn_duration:
- description:
- - Max Conn Duration/msec
- returned: queried
- type: int
- sample: 0
- mean_conn_duration:
- description:
- - Mean Conn Duration/msec
- returned: queried
- type: int
- sample: 0
- min_conn_duration:
- description:
- - Min Conn Duration/msec
- returned: queried
- type: int
- sample: 0
- cpu_usage_ratio_last_5_min:
- description:
- - CPU Usage Ratio (%) Last 5 Minutes
- returned: queried
- type: int
- sample: 0
- cpu_usage_ratio_last_5_sec:
- description:
- - CPU Usage Ratio (%) Last 5 Seconds
- returned: queried
- type: int
- sample: 0
- cpu_usage_ratio_last_1_min:
- description:
- - CPU Usage Ratio (%) Last 1 Minute
- returned: queried
- type: int
- sample: 0
- syn_cache_overflow:
- description:
- - SYN Cache Overflow
- returned: queried
- type: int
- sample: 0
- total_software_syn_cookies:
- description:
- - Total Software
- returned: queried
- type: int
- sample: 0
- syn_cookies_status:
- description:
- - SYN Cookies Status
- returned: queried
- type: str
- sample: not-activated
- fallback_persistence_profile:
- description:
- - Fallback persistence profile for the virtual server to use
- when the default persistence profile is not available.
- returned: queried
- type: str
- sample: /Common/fallback1
- persistence_profile:
- description:
- - The persistence profile you want the system to use as the default
- for this virtual server.
- returned: queried
- type: str
- sample: /Common/persist1
- translate_port:
- description:
- - Enables or disables port translation.
- returned: queried
- type: bool
- sample: yes
- translate_address:
- description:
- - Enables or disables address translation for the virtual server.
- returned: queried
- type: bool
- sample: yes
- vlans:
- description:
- - List of VLANs on which the virtual server is either enabled or disabled.
- returned: queried
- type: list
- sample: ['/Common/vlan1', '/Common/vlan2']
- destination:
- description:
- - Name of the virtual address and service on which the virtual server
- listens for connections.
- returned: queried
- type: str
- sample: /Common/2.2.3.3%1:76
- last_hop_pool:
- description:
- - Name of the last hop pool that you want the virtual
- server to use to direct reply traffic to the last hop router.
- returned: queried
- type: str
- sample: /Common/pool1
- nat64_enabled:
- description:
- - Whether or not NAT64 is enabled.
- returned: queried
- type: bool
- sample: yes
- source_port_behavior:
- description:
- - Specifies whether the system preserves the source port of the connection.
- returned: queried
- type: str
- sample: preserve
- ip_intelligence_policy:
- description:
- - IP Intelligence policy assigned to the virtual
- returned: queried
- type: str
- sample: /Common/ip1
- protocol:
- description:
- - IP protocol for which you want the virtual server to direct traffic.
- returned: queried
- type: str
- sample: tcp
- default_pool:
- description:
- - Pool name that you want the virtual server to use as the default pool.
- returned: queried
- type: str
- sample: /Common/pool1
- rate_limit_mode:
- description:
- - Indicates whether the rate limit is applied per virtual object,
- per source address, per destination address, or some combination
- thereof.
- returned: queried
- type: str
- sample: object
- rate_limit_source_mask:
- description:
- - Specifies a mask, in bits, to be applied to the source address as
- part of the rate limiting.
- returned: queried
- type: int
- sample: 0
- rate_limit:
- description:
- - Maximum number of connections per second allowed for a virtual server.
- returned: queried
- type: int
- sample: 34
- snat_type:
- description:
- - Specifies the type of source address translation associated
- with the specified virtual server.
- returned: queried
- type: str
- sample: none
- snat_pool:
- description:
- - Specifies the name of a LSN or SNAT pool used by the specified virtual server.
- returned: queried
- type: str
- sample: /Common/pool1
- status_reason:
- description:
- - If there is a problem with the status of the virtual, that problem is reported here.
- returned: queried
- type: str
- sample: The children pool member(s) either don't have service checking...
- gtm_score:
- description:
- - Specifies a score that is associated with the virtual server.
- returned: queried
- type: int
- sample: 0
- rate_class:
- description:
- - Name of an existing rate class that you want the
- virtual server to use to enforce a throughput policy for incoming
- network traffic.
- returned: queried
- type: str
- rate_limit_destination_mask:
- description:
- - Specifies a mask, in bits, to be applied to the destination
- address as part of the rate limiting.
- returned: queried
- type: int
- sample: 32
- source_address:
- description:
- - Specifies an IP address or network from which the virtual server
- will accept traffic.
- returned: queried
- type: str
- sample: 0.0.0./0
- authentication_profile:
- description:
- - Specifies a list of authentication profile names, separated by
- spaces, that the virtual server uses to manage authentication.
- returned: queried
- type: list
- sample: ['/Common/ssl_drldp']
- connection_mirror_enabled:
- description:
- - Whether or not connection mirroring is enabled.
- returned: queried
- type: bool
- sample: yes
- irules:
- description:
- - List of iRules that customize the virtual server to direct and manage traffic.
- returned: queried
- type: list
- sample: ['/Common/rule1', /Common/rule2']
- security_log_profiles:
- description:
- - Specifies the log profile applied to the virtual server.
- returned: queried
- type: list
- sample: ['/Common/global-network', '/Common/local-dos']
- type:
- description:
- - Virtual server type.
- returned: queried
- type: str
- sample: standard
- destination_address:
- description:
- - Address portion of the C(destination).
- returned: queried
- type: str
- sample: 2.3.3.2
- destination_port:
- description:
- - Port potion of the C(destination).
- returned: queried
- type: int
- sample: 80
- profiles:
- description:
- - List of the profiles attached to the virtual.
- type: complex
- contains:
- context:
- description:
- - Which side of the connection the profile affects; either C(all),
- C(client-side) or C(server-side).
- returned: queried
- type: str
- sample: client-side
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: /Common/tcp
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: tcp
- total_requests:
- description:
- - Total requests.
- returned: queried
- type: int
- sample: 8
- sample: hash/dictionary of values
-vlans:
- description: List of VLAN information.
- returned: When C(vlans) is specified in C(gather_subset).
- type: complex
- contains:
- auto_lasthop:
- description:
- - Allows the system to send return traffic to the MAC address that transmitted the
- request, even if the routing table points to a different network or interface.
- returned: queried
- type: str
- sample: enabled
- cmp_hash_algorithm:
- description:
- - Specifies how the traffic on the VLAN will be disaggregated.
- returned: queried
- type: str
- sample: default
- description:
- description:
- - Description of the VLAN.
- returned: queried
- type: str
- sample: My vlan
- failsafe_action:
- description:
- - Action for the system to take when the fail-safe mechanism is triggered.
- returned: queried
- type: str
- sample: reboot
- failsafe_enabled:
- description:
- - Whether failsafe is enabled or not.
- returned: queried
- type: bool
- sample: yes
- failsafe_timeout:
- description:
- - Number of seconds that an active unit can run without detecting network traffic
- on this VLAN before it starts a failover.
- returned: queried
- type: int
- sample: 90
- if_index:
- description:
- - Index assigned to this VLAN. It is a unique identifier assigned for all objects
- displayed in the SNMP IF-MIB.
- returned: queried
- type: int
- sample: 176
- learning_mode:
- description:
- - Whether switch ports placed in the VLAN are configured for switch learning,
- forwarding only, or dropped.
- returned: queried
- type: str
- sample: enable-forward
- interfaces:
- description:
- - List of tagged or untagged interfaces and trunks that you want to configure for the VLAN.
- returned: queried
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: queried
- type: str
- sample: 1.3
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: queried
- type: str
- sample: 1.3
- tagged:
- description:
- - Whether the interface is tagged or not.
- returned: queried
- type: bool
- sample: no
- mtu:
- description:
- - Specific maximum transition unit (MTU) for the VLAN.
- returned: queried
- type: int
- sample: 1500
- sflow_poll_interval:
- description:
- - Maximum interval in seconds between two pollings.
- returned: queried
- type: int
- sample: 0
- sflow_poll_interval_global:
- description:
- - Whether the global VLAN poll-interval setting, overrides the object-level
- poll-interval setting.
- returned: queried
- type: bool
- sample: no
- sflow_sampling_rate:
- description:
- - Ratio of packets observed to the samples generated.
- returned: queried
- type: int
- sample: 0
- sflow_sampling_rate_global:
- description:
- - Whether the global VLAN sampling-rate setting, overrides the object-level
- sampling-rate setting.
- returned: queried
- type: bool
- sample: yes
- source_check_enabled:
- description:
- - Specifies that only connections that have a return route in the routing table are accepted.
- returned: queried
- type: bool
- sample: yes
- true_mac_address:
- description:
- - Media access control (MAC) address for the lowest-numbered interface assigned to this VLAN.
- returned: queried
- type: str
- sample: "fa:16:3e:10:da:ff"
- tag:
- description:
- - Tag number for the VLAN.
- returned: queried
- type: int
- sample: 30
- sample: hash/dictionary of values
-'''
-
-import datetime
-import math
-import re
-import time
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_netmask
-from ansible.module_utils.parsing.convert_bool import BOOLEANS_TRUE
-from ansible.module_utils.six import iteritems
-from ansible.module_utils.six import string_types
-from collections import namedtuple
-from distutils.version import LooseVersion
-
-try:
- from library.module_utils.network.f5.bigip import F5RestClient
- from library.module_utils.network.f5.common import F5ModuleError
- from library.module_utils.network.f5.common import AnsibleF5Parameters
- from library.module_utils.network.f5.common import f5_argument_spec
- from library.module_utils.network.f5.common import fq_name
- from library.module_utils.network.f5.common import flatten_boolean
- from library.module_utils.network.f5.common import transform_name
- from library.module_utils.network.f5.ipaddress import is_valid_ip
- from library.module_utils.network.f5.icontrol import modules_provisioned
- from library.module_utils.network.f5.icontrol import tmos_version
- from library.module_utils.network.f5.urls import parseStats
-except ImportError:
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.bigip import F5RestClient
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import F5ModuleError
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import AnsibleF5Parameters
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import f5_argument_spec
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import fq_name
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import flatten_boolean
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import transform_name
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.ipaddress import is_valid_ip
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.icontrol import modules_provisioned
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.icontrol import tmos_version
- from ansible_collections.community.general.plugins.module_utils.network.f5.urls import parseStats
-
-
-class BaseManager(object):
- def __init__(self, *args, **kwargs):
- self.module = kwargs.get('module', None)
- self.client = kwargs.get('client', None)
- self.kwargs = kwargs
-
- # A list of modules currently provisioned on the device.
- #
- # This list is used by different fact managers to check to see
- # if they should even attempt to gather information. If the module is
- # not provisioned, then it is likely that the REST API will not
- # return valid data.
- #
- # For example, ASM (at the time of this writing 13.x/14.x) will
- # raise an exception if you attempt to query its APIs if it is
- # not provisioned. An example error message is shown below.
- #
- # {
- # "code": 400,
- # "message": "java.net.ConnectException: Connection refused (Connection refused)",
- # "referer": "172.18.43.40",
- # "restOperationId": 18164160,
- # "kind": ":resterrorresponse"
- # }
- #
- # This list is provided to the specific fact manager by the
- # master ModuleManager of this module.
- self.provisioned_modules = []
-
- def exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- return results
-
-
-class Parameters(AnsibleF5Parameters):
- @property
- def gather_subset(self):
- if isinstance(self._values['gather_subset'], string_types):
- self._values['gather_subset'] = [self._values['gather_subset']]
- elif not isinstance(self._values['gather_subset'], list):
- raise F5ModuleError(
- "The specified gather_subset must be a list."
- )
- tmp = list(set(self._values['gather_subset']))
- tmp.sort()
- self._values['gather_subset'] = tmp
-
- return self._values['gather_subset']
-
-
-class BaseParameters(Parameters):
- @property
- def enabled(self):
- return flatten_boolean(self._values['enabled'])
-
- @property
- def disabled(self):
- return flatten_boolean(self._values['disabled'])
-
- def _remove_internal_keywords(self, resource):
- resource.pop('kind', None)
- resource.pop('generation', None)
- resource.pop('selfLink', None)
- resource.pop('isSubcollection', None)
- resource.pop('fullPath', None)
-
- def to_return(self):
- result = {}
- for returnable in self.returnables:
- result[returnable] = getattr(self, returnable)
- result = self._filter_params(result)
- return result
-
-
-class AsmPolicyStatsParameters(BaseParameters):
- api_map = {
-
- }
-
- returnables = [
- 'policies',
- 'policies_active',
- 'policies_attached',
- 'policies_inactive',
- 'policies_unattached',
- ]
-
- @property
- def policies(self):
- if self._values['policies'] is None or len(self._values['policies']) == 0:
- return None
- return len(self._values['policies'])
-
- @property
- def policies_active(self):
- if self._values['policies'] is None or len(self._values['policies']) == 0:
- return None
- return len([x for x in self._values['policies'] if x['active'] is True])
-
- @property
- def policies_inactive(self):
- if self._values['policies'] is None or len(self._values['policies']) == 0:
- return None
- return len([x for x in self._values['policies'] if x['active'] is not True])
-
- @property
- def policies_attached(self):
- if self._values['policies'] is None or len(self._values['policies']) == 0:
- return None
- return len([x for x in self._values['policies'] if x['active'] is True and len(x['virtualServers']) > 0])
-
- @property
- def policies_unattached(self):
- if self._values['policies'] is None or len(self._values['policies']) == 0:
- return None
- return len([x for x in self._values['policies'] if x['active'] is True and len(x['virtualServers']) == 0])
-
-
-class AsmPolicyStatsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(AsmPolicyStatsFactManager, self).__init__(**kwargs)
- self.want = AsmPolicyStatsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(asm_policy_stats=facts)
- return result
-
- def _exec_module(self):
- if 'asm' not in self.provisioned_modules:
- return []
- facts = self.read_facts()
- results = facts.to_return()
- return results
-
- def read_facts(self):
- collection = self.read_collection_from_device()
- params = AsmPolicyStatsParameters(params=collection)
- return params
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/asm/policies".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- return dict(
- policies=response['items']
- )
-
-
-class AsmPolicyFactParameters(BaseParameters):
- api_map = {
- 'hasParent': 'has_parent',
- 'protocolIndependent': 'protocol_independent',
- 'virtualServers': 'virtual_servers',
- 'allowedResponseCodes': 'allowed_response_codes',
- 'learningMode': 'learning_mode',
- 'enforcementMode': 'enforcement_mode',
- 'customXffHeaders': 'custom_xff_headers',
- 'caseInsensitive': 'case_insensitive',
- 'stagingSettings': 'staging_settings',
- 'applicationLanguage': 'application_language',
- 'trustXff': 'trust_xff',
- 'geolocation-enforcement': 'geolocation_enforcement',
- 'disallowedLocations': 'disallowed_locations',
- 'signature-settings': 'signature_settings',
- 'header-settings': 'header_settings',
- 'cookie-settings': 'cookie_settings',
- 'policy-builder': 'policy_builder',
- 'disallowed-geolocations': 'disallowed_geolocations',
- 'whitelist-ips': 'whitelist_ips',
- 'fullPath': 'full_path',
- 'csrf-protection': 'csrf_protection',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'policy_id',
- 'active',
- 'protocol_independent',
- 'has_parent',
- 'type',
- 'virtual_servers',
- 'allowed_response_codes',
- 'description',
- 'learning_mode',
- 'enforcement_mode',
- 'custom_xff_headers',
- 'case_insensitive',
- 'signature_staging',
- 'place_signatures_in_staging',
- 'enforcement_readiness_period',
- 'path_parameter_handling',
- 'trigger_asm_irule_event',
- 'inspect_http_uploads',
- 'mask_credit_card_numbers_in_request',
- 'maximum_http_header_length',
- 'use_dynamic_session_id_in_url',
- 'maximum_cookie_header_length',
- 'application_language',
- 'trust_xff',
- 'disallowed_geolocations',
- 'csrf_urls',
- 'csrf_protection_enabled',
- 'csrf_protection_ssl_only',
- 'csrf_protection_expiration_time_in_seconds',
- ]
-
- def _morph_keys(self, key_map, item):
- for k, v in iteritems(key_map):
- item[v] = item.pop(k, None)
- result = self._filter_params(item)
- return result
-
- @property
- def active(self):
- return flatten_boolean(self._values['active'])
-
- @property
- def case_insensitive(self):
- return flatten_boolean(self._values['case_insensitive'])
-
- @property
- def has_parent(self):
- return flatten_boolean(self._values['has_parent'])
-
- @property
- def policy_id(self):
- if self._values['id'] is None:
- return None
- return self._values['id']
-
- @property
- def signature_staging(self):
- if 'staging_settings' in self._values:
- if self._values['staging_settings'] is None:
- return None
- if 'signatureStaging' in self._values['staging_settings']:
- return flatten_boolean(self._values['staging_settings']['signatureStaging'])
- if 'signature_settings' in self._values:
- if self._values['signature_settings'] is None:
- return None
- if 'signatureStaging' in self._values['signature_settings']:
- return flatten_boolean(self._values['signature_settings']['signatureStaging'])
-
- @property
- def place_signatures_in_staging(self):
- if 'staging_settings' in self._values:
- if self._values['staging_settings'] is None:
- return None
- if 'placeSignaturesInStaging' in self._values['staging_settings']:
- return flatten_boolean(self._values['staging_settings']['placeSignaturesInStaging'])
- if 'signature_settings' in self._values:
- if self._values['signature_settings'] is None:
- return None
- if 'signatureStaging' in self._values['signature_settings']:
- return flatten_boolean(self._values['signature_settings']['placeSignaturesInStaging'])
-
- @property
- def enforcement_readiness_period(self):
- if 'staging_settings' in self._values:
- if self._values['staging_settings'] is None:
- return None
- if 'enforcementReadinessPeriod' in self._values['staging_settings']:
- return self._values['staging_settings']['enforcementReadinessPeriod']
- if 'general' in self._values:
- if self._values['general'] is None:
- return None
- if 'signatureStaging' in self._values['general']:
- return self._values['general']['enforcementReadinessPeriod']
-
- @property
- def path_parameter_handling(self):
- if 'attributes' in self._values:
- if self._values['attributes'] is None:
- return None
- if 'pathParameterHandling' in self._values['attributes']:
- return self._values['attributes']['pathParameterHandling']
- if 'general' in self._values:
- if self._values['general'] is None:
- return None
- if 'pathParameterHandling' in self._values['general']:
- return self._values['general']['pathParameterHandling']
-
- @property
- def trigger_asm_irule_event(self):
- if 'attributes' in self._values:
- if self._values['attributes'] is None:
- return None
- if 'triggerAsmIruleEvent' in self._values['attributes']:
- return self._values['attributes']['triggerAsmIruleEvent']
- if 'general' in self._values:
- if self._values['general'] is None:
- return None
- if 'triggerAsmIruleEvent' in self._values['general']:
- return self._values['general']['triggerAsmIruleEvent']
-
- @property
- def inspect_http_uploads(self):
- if 'attributes' in self._values:
- if self._values['attributes'] is None:
- return None
- if 'inspectHttpUploads' in self._values['attributes']:
- return flatten_boolean(self._values['attributes']['inspectHttpUploads'])
- if 'antivirus' in self._values:
- if self._values['antivirus'] is None:
- return None
- if 'inspectHttpUploads' in self._values['antivirus']:
- return flatten_boolean(self._values['antivirus']['inspectHttpUploads'])
-
- @property
- def mask_credit_card_numbers_in_request(self):
- if 'attributes' in self._values:
- if self._values['attributes'] is None:
- return None
- if 'maskCreditCardNumbersInRequest' in self._values['attributes']:
- return flatten_boolean(self._values['attributes']['maskCreditCardNumbersInRequest'])
- if 'general' in self._values:
- if self._values['general'] is None:
- return None
- if 'maskCreditCardNumbersInRequest' in self._values['general']:
- return flatten_boolean(self._values['general']['maskCreditCardNumbersInRequest'])
-
- @property
- def maximum_http_header_length(self):
- if 'attributes' in self._values:
- if self._values['attributes'] is None:
- return None
- if 'maximumHttpHeaderLength' in self._values['attributes']:
- if self._values['attributes']['maximumHttpHeaderLength'] == 'any':
- return 'any'
- return int(self._values['attributes']['maximumHttpHeaderLength'])
-
- if 'header_settings' in self._values:
- if self._values['header_settings'] is None:
- return None
- if 'maximumHttpHeaderLength' in self._values['header_settings']:
- if self._values['header_settings']['maximumHttpHeaderLength'] == 'any':
- return 'any'
- return int(self._values['header_settings']['maximumHttpHeaderLength'])
-
- @property
- def use_dynamic_session_id_in_url(self):
- if 'attributes' in self._values:
- if self._values['attributes'] is None:
- return None
- if 'useDynamicSessionIdInUrl' in self._values['attributes']:
- return flatten_boolean(self._values['attributes']['useDynamicSessionIdInUrl'])
- if 'general' in self._values:
- if self._values['general'] is None:
- return None
- if 'useDynamicSessionIdInUrl' in self._values['general']:
- return flatten_boolean(self._values['general']['useDynamicSessionIdInUrl'])
-
- @property
- def maximum_cookie_header_length(self):
- if 'attributes' in self._values:
- if self._values['attributes'] is None:
- return None
- if 'maximumCookieHeaderLength' in self._values['attributes']:
- if self._values['attributes']['maximumCookieHeaderLength'] == 'any':
- return 'any'
- return int(self._values['attributes']['maximumCookieHeaderLength'])
- if 'cookie_settings' in self._values:
- if self._values['cookie_settings'] is None:
- return None
- if 'maximumCookieHeaderLength' in self._values['cookie_settings']:
- if self._values['cookie_settings']['maximumCookieHeaderLength'] == 'any':
- return 'any'
- return int(self._values['cookie_settings']['maximumCookieHeaderLength'])
-
- @property
- def trust_xff(self):
- if 'trust_xff' in self._values:
- if self._values['trust_xff'] is None:
- return None
- return flatten_boolean(self._values['trust_xff'])
- if 'general' in self._values:
- if self._values['general'] is None:
- return None
- if 'trustXff' in self._values['general']:
- return flatten_boolean(self._values['general']['trustXff'])
-
- @property
- def custom_xff_headers(self):
- if 'custom_xff_headers' in self._values:
- if self._values['custom_xff_headers'] is None:
- return None
- return self._values['custom_xff_headers']
- if 'general' in self._values:
- if self._values['general'] is None:
- return None
- if 'customXffHeaders' in self._values['general']:
- return self._values['general']['customXffHeaders']
-
- @property
- def allowed_response_codes(self):
- if 'allowed_response_codes' in self._values:
- if self._values['allowed_response_codes'] is None:
- return None
- return self._values['allowed_response_codes']
- if 'general' in self._values:
- if self._values['general'] is None:
- return None
- if 'allowedResponseCodes' in self._values['general']:
- return self._values['general']['allowedResponseCodes']
-
- @property
- def learning_mode(self):
- if 'policy_builder' in self._values:
- if self._values['policy_builder'] is None:
- return None
- if 'learningMode' in self._values['policy_builder']:
- return self._values['policy_builder']['learningMode']
-
- @property
- def disallowed_locations(self):
- if 'geolocation_enforcement' in self._values:
- if self._values['geolocation_enforcement'] is None:
- return None
- return self._values['geolocation_enforcement']['disallowedLocations']
-
- @property
- def disallowed_geolocations(self):
- if 'disallowed_geolocations' in self._values:
- if self._values['disallowed_geolocations'] is None:
- return None
- return self._values['disallowed_geolocations']
-
- @property
- def csrf_protection_enabled(self):
- if 'csrf_protection' in self._values:
- return flatten_boolean(self._values['csrf_protection']['enabled'])
-
- @property
- def csrf_protection_ssl_only(self):
- if 'csrf_protection' in self._values:
- if 'sslOnly' in self._values['csrf_protection']:
- return flatten_boolean(self._values['csrf_protection']['sslOnly'])
-
- @property
- def csrf_protection_expiration_time_in_seconds(self):
- if 'csrf_protection' in self._values:
- if 'expirationTimeInSeconds' in self._values['csrf_protection']:
- if self._values['csrf_protection']['expirationTimeInSeconds'] is None:
- return None
- if self._values['csrf_protection']['expirationTimeInSeconds'] == 'disabled':
- return 'disabled'
- return int(self._values['csrf_protection']['expirationTimeInSeconds'])
-
- def format_csrf_collection(self, items):
- result = list()
- key_map = {
- 'requiredParameters': 'csrf_url_required_parameters',
- 'url': 'csrf_url',
- 'method': 'csrf_url_method',
- 'enforcementAction': 'csrf_url_enforcement_action',
- 'id': 'csrf_url_id',
- 'wildcardOrder': 'csrf_url_wildcard_order',
- 'parametersList': 'csrf_url_parameters_list'
- }
- for item in items:
- self._remove_internal_keywords(item)
- item.pop('lastUpdateMicros')
- output = self._morph_keys(key_map, item)
- result.append(output)
- return result
-
- @property
- def csrf_urls(self):
- if 'csrfUrls' in self._values:
- if self._values['csrfUrls'] is None:
- return None
- return self._values['csrfUrls']
- if 'csrf-urls' in self._values:
- if self._values['csrf-urls'] is None:
- return None
- return self.format_csrf_collection(self._values['csrf-urls'])
-
- @property
- def protocol_independent(self):
- return flatten_boolean(self._values['protocol_independent'])
-
-
-# TODO include: web-scraping,ip-intelligence,session-tracking,
-# TODO login-enforcement,data-guard,redirection-protection,vulnerability-assessment, parentPolicyReference
-
-
-class AsmPolicyFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(AsmPolicyFactManager, self).__init__(**kwargs)
- self.want = AsmPolicyFactParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(asm_policies=facts)
- return result
-
- def _exec_module(self):
- if 'asm' not in self.provisioned_modules:
- return []
- manager = self.get_manager()
- return manager._exec_module()
-
- def get_manager(self):
- if self.version_is_less_than_13():
- return AsmPolicyFactManagerV12(**self.kwargs)
- else:
- return AsmPolicyFactManagerV13(**self.kwargs)
-
- def version_is_less_than_13(self):
- version = tmos_version(self.client)
- if LooseVersion(version) < LooseVersion('13.0.0'):
- return True
- else:
- return False
-
- def read_facts(self):
- results = []
- collection = self.increment_read()
- for resource in collection:
- params = AsmPolicyFactParameters(params=resource)
- results.append(params)
- return results
-
- def increment_read(self):
- n = 0
- result = []
- while True:
- items = self.read_collection_from_device(skip=n)
- if not items:
- break
- result.extend(items)
- n = n + 10
- return result
-
-
-class AsmPolicyFactManagerV12(AsmPolicyFactManager):
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_collection_from_device(self, skip=0):
- uri = "https://{0}:{1}/mgmt/tm/asm/policies".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
-
- to_expand = 'policy-builder,geolocation-enforcement,csrf-protection'
- query = '?$top=10&$skip={0}&$expand={1}'.format(skip, to_expand)
-
- resp = self.client.api.get(uri + query)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- if 'items' not in response:
- return None
- return response['items']
-
-
-class AsmPolicyFactManagerV13(AsmPolicyFactManager):
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_collection_from_device(self, skip=0):
- uri = "https://{0}:{1}/mgmt/tm/asm/policies".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- to_expand = 'general,signature-settings,header-settings,cookie-settings,antivirus,' \
- 'policy-builder,csrf-protection,csrf-urls'
- query = '?$top=10&$skip={0}&$expand={1}'.format(skip, to_expand)
- resp = self.client.api.get(uri + query)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- if 'items' not in response:
- return None
-
- return response['items']
-
-
-class AsmServerTechnologyFactParameters(BaseParameters):
- api_map = {
- 'serverTechnologyName': 'server_technology_name',
- 'serverTechnologyReferences': 'server_technology_references',
- }
-
- returnables = [
- 'id',
- 'server_technology_name',
- 'server_technology_references',
- ]
-
-
-class AsmServerTechnologyFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(AsmServerTechnologyFactManager, self).__init__(**kwargs)
- self.want = AsmServerTechnologyFactParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(asm_server_technologies=facts)
- return result
-
- def _exec_module(self):
- results = []
- if 'asm' not in self.provisioned_modules:
- return results
- if self.version_is_less_than_13():
- return results
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['server_technology_name'])
- return results
-
- def version_is_less_than_13(self):
- version = tmos_version(self.client)
- if LooseVersion(version) < LooseVersion('13.0.0'):
- return True
- else:
- return False
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = AsmServerTechnologyFactParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/asm/server-technologies".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class AsmSignatureSetsFactParameters(BaseParameters):
- api_map = {
- 'isUserDefined': 'is_user_defined',
- 'assignToPolicyByDefault': 'assign_to_policy_by_default',
- 'defaultAlarm': 'default_alarm',
- 'defaultBlock': 'default_block',
- 'defaultLearn': 'default_learn',
- }
-
- returnables = [
- 'name',
- 'id',
- 'type',
- 'category',
- 'is_user_defined',
- 'assign_to_policy_by_default',
- 'default_alarm',
- 'default_block',
- 'default_learn',
- ]
-
- @property
- def is_user_defined(self):
- return flatten_boolean(self._values['is_user_defined'])
-
- @property
- def assign_to_policy_by_default(self):
- return flatten_boolean(self._values['assign_to_policy_by_default'])
-
- @property
- def default_alarm(self):
- return flatten_boolean(self._values['default_alarm'])
-
- @property
- def default_block(self):
- return flatten_boolean(self._values['default_block'])
-
- @property
- def default_learn(self):
- return flatten_boolean(self._values['default_learn'])
-
-# TODO: add the following: filter, systems, signatureReferences
-
-
-class AsmSignatureSetsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(AsmSignatureSetsFactManager, self).__init__(**kwargs)
- self.want = AsmSignatureSetsFactParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(asm_signature_sets=facts)
- return result
-
- def _exec_module(self):
- results = []
- if 'asm' not in self.provisioned_modules:
- return results
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['name'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.increment_read()
- for resource in collection:
- params = AsmSignatureSetsFactParameters(params=resource)
- results.append(params)
- return results
-
- def increment_read(self):
- n = 0
- result = []
- while True:
- items = self.read_collection_from_device(skip=n)
- if not items:
- break
- result.extend(items)
- n = n + 5
- return result
-
- def read_collection_from_device(self, skip=0):
- uri = "https://{0}:{1}/mgmt/tm/asm/signature-sets".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- query = '?$top=5&$skip={0}'.format(skip)
- resp = self.client.api.get(uri + query)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- if 'items' not in response:
- return None
-
- return response['items']
-
-
-class ClientSslProfilesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'alertTimeout': 'alert_timeout',
- 'allowNonSsl': 'allow_non_ssl',
- 'authenticateDepth': 'authenticate_depth',
- 'authenticate': 'authenticate_frequency',
- 'caFile': 'ca_file',
- 'cacheSize': 'cache_size',
- 'cacheTimeout': 'cache_timeout',
- 'cert': 'certificate_file',
- 'chain': 'chain_file',
- 'crlFile': 'crl_file',
- 'defaultsFrom': 'parent',
- 'modSslMethods': 'modssl_methods',
- 'peerCertMode': 'peer_certification_mode',
- 'sniRequire': 'sni_require',
- 'strictResume': 'strict_resume',
- 'mode': 'profile_mode_enabled',
- 'renegotiateMaxRecordDelay': 'renegotiation_maximum_record_delay',
- 'renegotiatePeriod': 'renegotiation_period',
- 'serverName': 'server_name',
- 'sessionTicket': 'session_ticket',
- 'sniDefault': 'sni_default',
- 'uncleanShutdown': 'unclean_shutdown',
- 'retainCertificate': 'retain_certificate',
- 'secureRenegotiation': 'secure_renegotiation_mode',
- 'handshakeTimeout': 'handshake_timeout',
- 'certExtensionIncludes': 'forward_proxy_certificate_extension_include',
- 'certLifespan': 'forward_proxy_certificate_lifespan',
- 'certLookupByIpaddrPort': 'forward_proxy_lookup_by_ipaddr_port',
- 'sslForwardProxy': 'forward_proxy_enabled',
- 'proxyCaPassphrase': 'forward_proxy_ca_passphrase',
- 'proxyCaCert': 'forward_proxy_ca_certificate_file',
- 'proxyCaKey': 'forward_proxy_ca_key_file'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'alert_timeout',
- 'allow_non_ssl',
- 'authenticate_depth',
- 'authenticate_frequency',
- 'ca_file',
- 'cache_size',
- 'cache_timeout',
- 'certificate_file',
- 'chain_file',
- 'ciphers',
- 'crl_file',
- 'parent',
- 'description',
- 'modssl_methods',
- 'peer_certification_mode',
- 'sni_require',
- 'sni_default',
- 'strict_resume',
- 'profile_mode_enabled',
- 'renegotiation_maximum_record_delay',
- 'renegotiation_period',
- 'renegotiation',
- 'server_name',
- 'session_ticket',
- 'unclean_shutdown',
- 'retain_certificate',
- 'secure_renegotiation_mode',
- 'handshake_timeout',
- 'forward_proxy_certificate_extension_include',
- 'forward_proxy_certificate_lifespan',
- 'forward_proxy_lookup_by_ipaddr_port',
- 'forward_proxy_enabled',
- 'forward_proxy_ca_passphrase',
- 'forward_proxy_ca_certificate_file',
- 'forward_proxy_ca_key_file'
- ]
-
- @property
- def alert_timeout(self):
- if self._values['alert_timeout'] is None:
- return None
- if self._values['alert_timeout'] == 'indefinite':
- return 0
- return int(self._values['alert_timeout'])
-
- @property
- def renegotiation_maximum_record_delay(self):
- if self._values['renegotiation_maximum_record_delay'] is None:
- return None
- if self._values['renegotiation_maximum_record_delay'] == 'indefinite':
- return 0
- return int(self._values['renegotiation_maximum_record_delay'])
-
- @property
- def renegotiation_period(self):
- if self._values['renegotiation_period'] is None:
- return None
- if self._values['renegotiation_period'] == 'indefinite':
- return 0
- return int(self._values['renegotiation_period'])
-
- @property
- def handshake_timeout(self):
- if self._values['handshake_timeout'] is None:
- return None
- if self._values['handshake_timeout'] == 'indefinite':
- return 0
- return int(self._values['handshake_timeout'])
-
- @property
- def allow_non_ssl(self):
- if self._values['allow_non_ssl'] is None:
- return None
- if self._values['allow_non_ssl'] == 'disabled':
- return 'no'
- return 'yes'
-
- @property
- def forward_proxy_enabled(self):
- if self._values['forward_proxy_enabled'] is None:
- return None
- if self._values['forward_proxy_enabled'] == 'disabled':
- return 'no'
- return 'yes'
-
- @property
- def renegotiation(self):
- if self._values['renegotiation'] is None:
- return None
- if self._values['renegotiation'] == 'disabled':
- return 'no'
- return 'yes'
-
- @property
- def forward_proxy_lookup_by_ipaddr_port(self):
- if self._values['forward_proxy_lookup_by_ipaddr_port'] is None:
- return None
- if self._values['forward_proxy_lookup_by_ipaddr_port'] == 'disabled':
- return 'no'
- return 'yes'
-
- @property
- def unclean_shutdown(self):
- if self._values['unclean_shutdown'] is None:
- return None
- if self._values['unclean_shutdown'] == 'disabled':
- return 'no'
- return 'yes'
-
- @property
- def session_ticket(self):
- if self._values['session_ticket'] is None:
- return None
- if self._values['session_ticket'] == 'disabled':
- return 'no'
- return 'yes'
-
- @property
- def retain_certificate(self):
- if self._values['retain_certificate'] is None:
- return None
- if self._values['retain_certificate'] == 'true':
- return 'yes'
- return 'no'
-
- @property
- def server_name(self):
- if self._values['server_name'] in [None, 'none']:
- return None
- return self._values['server_name']
-
- @property
- def forward_proxy_ca_certificate_file(self):
- if self._values['forward_proxy_ca_certificate_file'] in [None, 'none']:
- return None
- return self._values['forward_proxy_ca_certificate_file']
-
- @property
- def forward_proxy_ca_key_file(self):
- if self._values['forward_proxy_ca_key_file'] in [None, 'none']:
- return None
- return self._values['forward_proxy_ca_key_file']
-
- @property
- def authenticate_frequency(self):
- if self._values['authenticate_frequency'] is None:
- return None
- return self._values['authenticate_frequency']
-
- @property
- def ca_file(self):
- if self._values['ca_file'] in [None, 'none']:
- return None
- return self._values['ca_file']
-
- @property
- def certificate_file(self):
- if self._values['certificate_file'] in [None, 'none']:
- return None
- return self._values['certificate_file']
-
- @property
- def chain_file(self):
- if self._values['chain_file'] in [None, 'none']:
- return None
- return self._values['chain_file']
-
- @property
- def crl_file(self):
- if self._values['crl_file'] in [None, 'none']:
- return None
- return self._values['crl_file']
-
- @property
- def ciphers(self):
- if self._values['ciphers'] in [None, 'none']:
- return None
- return self._values['ciphers'].split(' ')
-
- @property
- def modssl_methods(self):
- if self._values['modssl_methods'] is None:
- return None
- if self._values['modssl_methods'] == 'disabled':
- return 'no'
- return 'yes'
-
- @property
- def strict_resume(self):
- if self._values['strict_resume'] is None:
- return None
- if self._values['strict_resume'] == 'disabled':
- return 'no'
- return 'yes'
-
- @property
- def profile_mode_enabled(self):
- if self._values['profile_mode_enabled'] is None:
- return None
- if self._values['profile_mode_enabled'] == 'disabled':
- return 'no'
- return 'yes'
-
- @property
- def sni_require(self):
- if self._values['sni_require'] is None:
- return None
- if self._values['sni_require'] == 'false':
- return 'no'
- return 'yes'
-
- @property
- def sni_default(self):
- if self._values['sni_default'] is None:
- return None
- if self._values['sni_default'] == 'false':
- return 'no'
- return 'yes'
-
-
-class ClientSslProfilesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(ClientSslProfilesFactManager, self).__init__(**kwargs)
- self.want = ClientSslProfilesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(client_ssl_profiles=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = ClientSslProfilesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/profile/client-ssl".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class DeviceGroupsParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'autoSync': 'autosync_enabled',
- 'asmSync': 'asm_sync_enabled',
- 'devicesReference': 'devices',
- 'fullLoadOnSync': 'full_load_on_sync',
- 'incrementalConfigSyncSizeMax': 'incremental_config_sync_size_maximum',
- 'networkFailover': 'network_failover_enabled'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'autosync_enabled',
- 'description',
- 'devices',
- 'full_load_on_sync',
- 'incremental_config_sync_size_maximum',
- 'network_failover_enabled',
- 'type',
- 'asm_sync_enabled'
- ]
-
- @property
- def network_failover_enabled(self):
- if self._values['network_failover_enabled'] is None:
- return None
- if self._values['network_failover_enabled'] == 'enabled':
- return 'yes'
- return 'no'
-
- @property
- def asm_sync_enabled(self):
- if self._values['asm_sync_enabled'] is None:
- return None
- if self._values['asm_sync_enabled'] == 'disabled':
- return 'no'
- return 'yes'
-
- @property
- def autosync_enabled(self):
- if self._values['autosync_enabled'] is None:
- return None
- if self._values['autosync_enabled'] == 'disabled':
- return 'no'
- return 'yes'
-
- @property
- def full_load_on_sync(self):
- if self._values['full_load_on_sync'] is None:
- return None
- if self._values['full_load_on_sync'] == 'true':
- return 'yes'
- return 'no'
-
- @property
- def devices(self):
- if self._values['devices'] is None or 'items' not in self._values['devices']:
- return None
- result = [x['fullPath'] for x in self._values['devices']['items']]
- result.sort()
- return result
-
-
-class DeviceGroupsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(DeviceGroupsFactManager, self).__init__(**kwargs)
- self.want = DeviceGroupsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(device_groups=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = DeviceGroupsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/cm/device-group/?expandSubcollections=true".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class DevicesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'activeModules': 'active_modules',
- 'baseMac': 'base_mac_address',
- 'chassisId': 'chassis_id',
- 'chassisType': 'chassis_type',
- 'configsyncIp': 'configsync_address',
- 'failoverState': 'failover_state',
- 'managementIp': 'management_address',
- 'marketingName': 'marketing_name',
- 'multicastIp': 'multicast_address',
- 'optionalModules': 'optional_modules',
- 'platformId': 'platform_id',
- 'mirrorIp': 'primary_mirror_address',
- 'mirrorSecondaryIp': 'secondary_mirror_address',
- 'version': 'software_version',
- 'timeLimitedModules': 'timelimited_modules',
- 'timeZone': 'timezone',
- 'unicastAddress': 'unicast_addresses',
- 'selfDevice': 'self'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'active_modules',
- 'base_mac_address',
- 'build',
- 'chassis_id',
- 'chassis_type',
- 'comment',
- 'configsync_address',
- 'contact',
- 'description',
- 'edition',
- 'failover_state',
- 'hostname',
- 'location',
- 'management_address',
- 'marketing_name',
- 'multicast_address',
- 'optional_modules',
- 'platform_id',
- 'primary_mirror_address',
- 'product',
- 'secondary_mirror_address',
- 'self',
- 'software_version',
- 'timelimited_modules',
- 'timezone',
- 'unicast_addresses',
- ]
-
- @property
- def active_modules(self):
- if self._values['active_modules'] is None:
- return None
- result = []
- for x in self._values['active_modules']:
- parts = x.split('|')
- result += parts[2:]
- return list(set(result))
-
- @property
- def self(self):
- result = flatten_boolean(self._values['self'])
- return result
-
- @property
- def configsync_address(self):
- if self._values['configsync_address'] in [None, 'none']:
- return None
- return self._values['configsync_address']
-
- @property
- def primary_mirror_address(self):
- if self._values['primary_mirror_address'] in [None, 'any6']:
- return None
- return self._values['primary_mirror_address']
-
- @property
- def secondary_mirror_address(self):
- if self._values['secondary_mirror_address'] in [None, 'any6']:
- return None
- return self._values['secondary_mirror_address']
-
- @property
- def unicast_addresses(self):
- if self._values['unicast_addresses'] is None:
- return None
- result = []
-
- for addr in self._values['unicast_addresses']:
- tmp = {}
- for key in ['effectiveIp', 'effectivePort', 'ip', 'port']:
- if key in addr:
- renamed_key = self.convert(key)
- tmp[renamed_key] = addr.get(key, None)
- if tmp:
- result.append(tmp)
- if result:
- return result
-
- def convert(self, name):
- s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
- return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
-
-
-class DevicesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(DevicesFactManager, self).__init__(**kwargs)
- self.want = DevicesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(devices=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = DevicesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/cm/device".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class ExternalMonitorsParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'defaultsFrom': 'parent',
- 'adaptiveDivergenceType': 'adaptive_divergence_type',
- 'adaptiveDivergenceValue': 'adaptive_divergence_value',
- 'adaptiveLimit': 'adaptive_limit',
- 'adaptiveSamplingTimespan': 'adaptive_sampling_timespan',
- 'manualResume': 'manual_resume',
- 'timeUntilUp': 'time_until_up',
- 'upInterval': 'up_interval',
- 'run': 'external_program',
- 'apiRawValues': 'variables',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'parent',
- 'description',
- 'args',
- 'destination',
- 'external_program',
- 'interval',
- 'manual_resume',
- 'time_until_up',
- 'timeout',
- 'up_interval',
- 'variables',
- ]
-
- @property
- def description(self):
- if self._values['description'] in [None, 'none']:
- return None
- return self._values['description']
-
- @property
- def manual_resume(self):
- return flatten_boolean(self._values['manual_resume'])
-
- @property
- def variables(self):
- if self._values['variables'] is None:
- return None
- result = {}
- for k, v in iteritems(self._values['variables']):
- k = k.replace('userDefined ', '').strip()
- result[k] = v
- return result
-
-
-class ExternalMonitorsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(ExternalMonitorsFactManager, self).__init__(**kwargs)
- self.want = ExternalMonitorsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(external_monitors=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = ExternalMonitorsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/external".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class FastHttpProfilesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'clientCloseTimeout': 'client_close_timeout',
- 'connpoolIdleTimeoutOverride': 'oneconnect_idle_timeout_override',
- 'connpoolMaxReuse': 'oneconnect_maximum_reuse',
- 'connpoolMaxSize': 'oneconnect_maximum_pool_size',
- 'connpoolMinSize': 'oneconnect_minimum_pool_size',
- 'connpoolReplenish': 'oneconnect_replenish',
- 'connpoolStep': 'oneconnect_ramp_up_increment',
- 'defaultsFrom': 'parent',
- 'forceHttp_10Response': 'force_http_1_0_response',
- 'headerInsert': 'request_header_insert',
- 'http_11CloseWorkarounds': 'http_1_1_close_workarounds',
- 'idleTimeout': 'idle_timeout',
- 'insertXforwardedFor': 'insert_x_forwarded_for',
- 'maxHeaderSize': 'maximum_header_size',
- 'maxRequests': 'maximum_requests',
- 'mssOverride': 'maximum_segment_size_override',
- 'receiveWindowSize': 'receive_window_size',
- 'resetOnTimeout': 'reset_on_timeout',
- 'serverCloseTimeout': 'server_close_timeout',
- 'serverSack': 'server_sack',
- 'serverTimestamp': 'server_timestamp',
- 'uncleanShutdown': 'unclean_shutdown'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'client_close_timeout',
- 'oneconnect_idle_timeout_override',
- 'oneconnect_maximum_reuse',
- 'oneconnect_maximum_pool_size',
- 'oneconnect_minimum_pool_size',
- 'oneconnect_replenish',
- 'oneconnect_ramp_up_increment',
- 'parent',
- 'description',
- 'force_http_1_0_response',
- 'request_header_insert',
- 'http_1_1_close_workarounds',
- 'idle_timeout',
- 'insert_x_forwarded_for',
- 'maximum_header_size',
- 'maximum_requests',
- 'maximum_segment_size_override',
- 'receive_window_size',
- 'reset_on_timeout',
- 'server_close_timeout',
- 'server_sack',
- 'server_timestamp',
- 'unclean_shutdown'
- ]
-
- @property
- def request_header_insert(self):
- if self._values['request_header_insert'] in [None, 'none']:
- return None
- return self._values['request_header_insert']
-
- @property
- def server_timestamp(self):
- return flatten_boolean(self._values['server_timestamp'])
-
- @property
- def server_sack(self):
- return flatten_boolean(self._values['server_sack'])
-
- @property
- def reset_on_timeout(self):
- return flatten_boolean(self._values['reset_on_timeout'])
-
- @property
- def insert_x_forwarded_for(self):
- return flatten_boolean(self._values['insert_x_forwarded_for'])
-
- @property
- def http_1_1_close_workarounds(self):
- return flatten_boolean(self._values['http_1_1_close_workarounds'])
-
- @property
- def force_http_1_0_response(self):
- return flatten_boolean(self._values['force_http_1_0_response'])
-
- @property
- def oneconnect_replenish(self):
- return flatten_boolean(self._values['oneconnect_replenish'])
-
- @property
- def idle_timeout(self):
- if self._values['idle_timeout'] is None:
- return None
- elif self._values['idle_timeout'] == 'immediate':
- return 0
- elif self._values['idle_timeout'] == 'indefinite':
- return 4294967295
- return int(self._values['idle_timeout'])
-
-
-class FastHttpProfilesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(FastHttpProfilesFactManager, self).__init__(**kwargs)
- self.want = FastHttpProfilesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(fasthttp_profiles=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = FastHttpProfilesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/profile/fasthttp".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class FastL4ProfilesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'clientTimeout': 'client_timeout',
- 'defaultsFrom': 'parent',
- 'explicitFlowMigration': 'explicit_flow_migration',
- 'hardwareSynCookie': 'hardware_syn_cookie',
- 'idleTimeout': 'idle_timeout',
- 'ipDfMode': 'dont_fragment_flag',
- 'ipTosToClient': 'ip_tos_to_client',
- 'ipTosToServer': 'ip_tos_to_server',
- 'ipTtlMode': 'ttl_mode',
- 'ipTtlV4': 'ttl_v4',
- 'ipTtlV6': 'ttl_v6',
- 'keepAliveInterval': 'keep_alive_interval',
- 'lateBinding': 'late_binding',
- 'linkQosToClient': 'link_qos_to_client',
- 'linkQosToServer': 'link_qos_to_server',
- 'looseClose': 'loose_close',
- 'looseInitialization': 'loose_init',
- 'mssOverride': 'mss_override',
- 'priorityToClient': 'priority_to_client',
- 'priorityToServer': 'priority_to_server',
- 'pvaAcceleration': 'pva_acceleration',
- 'pvaDynamicClientPackets': 'pva_dynamic_client_packets',
- 'pvaDynamicServerPackets': 'pva_dynamic_server_packets',
- 'pvaFlowAging': 'pva_flow_aging',
- 'pvaFlowEvict': 'pva_flow_evict',
- 'pvaOffloadDynamic': 'pva_offload_dynamic',
- 'pvaOffloadState': 'pva_offload_state',
- 'reassembleFragments': 'reassemble_fragments',
- 'receiveWindowSize': 'receive_window',
- 'resetOnTimeout': 'reset_on_timeout',
- 'rttFromClient': 'rtt_from_client',
- 'rttFromServer': 'rtt_from_server',
- 'serverSack': 'server_sack',
- 'serverTimestamp': 'server_timestamp',
- 'softwareSynCookie': 'software_syn_cookie',
- 'synCookieEnable': 'syn_cookie_enabled',
- 'synCookieMss': 'syn_cookie_mss',
- 'synCookieWhitelist': 'syn_cookie_whitelist',
- 'tcpCloseTimeout': 'tcp_close_timeout',
- 'tcpGenerateIsn': 'generate_init_seq_number',
- 'tcpHandshakeTimeout': 'tcp_handshake_timeout',
- 'tcpStripSack': 'strip_sack',
- 'tcpTimeWaitTimeout': 'tcp_time_wait_timeout',
- 'tcpTimestampMode': 'tcp_timestamp_mode',
- 'tcpWscaleMode': 'tcp_window_scale_mode',
- 'timeoutRecovery': 'timeout_recovery',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'client_timeout',
- 'parent',
- 'description',
- 'explicit_flow_migration',
- 'hardware_syn_cookie',
- 'idle_timeout',
- 'dont_fragment_flag',
- 'ip_tos_to_client',
- 'ip_tos_to_server',
- 'ttl_mode',
- 'ttl_v4',
- 'ttl_v6',
- 'keep_alive_interval',
- 'late_binding',
- 'link_qos_to_client',
- 'link_qos_to_server',
- 'loose_close',
- 'loose_init',
- 'mss_override', # Maximum Segment Size Override
- 'priority_to_client',
- 'priority_to_server',
- 'pva_acceleration',
- 'pva_dynamic_client_packets',
- 'pva_dynamic_server_packets',
- 'pva_flow_aging',
- 'pva_flow_evict',
- 'pva_offload_dynamic',
- 'pva_offload_state',
- 'reassemble_fragments',
- 'receive_window',
- 'reset_on_timeout',
- 'rtt_from_client',
- 'rtt_from_server',
- 'server_sack',
- 'server_timestamp',
- 'software_syn_cookie',
- 'syn_cookie_enabled',
- 'syn_cookie_mss',
- 'syn_cookie_whitelist',
- 'tcp_close_timeout',
- 'generate_init_seq_number',
- 'tcp_handshake_timeout',
- 'strip_sack',
- 'tcp_time_wait_timeout',
- 'tcp_timestamp_mode',
- 'tcp_window_scale_mode',
- 'timeout_recovery',
- ]
-
- @property
- def description(self):
- if self._values['description'] in [None, 'none']:
- return None
- return self._values['description']
-
- @property
- def strip_sack(self):
- return flatten_boolean(self._values['strip_sack'])
-
- @property
- def generate_init_seq_number(self):
- return flatten_boolean(self._values['generate_init_seq_number'])
-
- @property
- def syn_cookie_whitelist(self):
- return flatten_boolean(self._values['syn_cookie_whitelist'])
-
- @property
- def syn_cookie_enabled(self):
- return flatten_boolean(self._values['syn_cookie_enabled'])
-
- @property
- def software_syn_cookie(self):
- return flatten_boolean(self._values['software_syn_cookie'])
-
- @property
- def server_timestamp(self):
- return flatten_boolean(self._values['server_timestamp'])
-
- @property
- def server_sack(self):
- return flatten_boolean(self._values['server_sack'])
-
- @property
- def rtt_from_server(self):
- return flatten_boolean(self._values['rtt_from_server'])
-
- @property
- def rtt_from_client(self):
- return flatten_boolean(self._values['rtt_from_client'])
-
- @property
- def reset_on_timeout(self):
- return flatten_boolean(self._values['reset_on_timeout'])
-
- @property
- def explicit_flow_migration(self):
- return flatten_boolean(self._values['explicit_flow_migration'])
-
- @property
- def reassemble_fragments(self):
- return flatten_boolean(self._values['reassemble_fragments'])
-
- @property
- def pva_flow_aging(self):
- return flatten_boolean(self._values['pva_flow_aging'])
-
- @property
- def pva_flow_evict(self):
- return flatten_boolean(self._values['pva_flow_evict'])
-
- @property
- def pva_offload_dynamic(self):
- return flatten_boolean(self._values['pva_offload_dynamic'])
-
- @property
- def hardware_syn_cookie(self):
- return flatten_boolean(self._values['hardware_syn_cookie'])
-
- @property
- def loose_close(self):
- return flatten_boolean(self._values['loose_close'])
-
- @property
- def loose_init(self):
- return flatten_boolean(self._values['loose_init'])
-
- @property
- def late_binding(self):
- return flatten_boolean(self._values['late_binding'])
-
- @property
- def tcp_handshake_timeout(self):
- if self._values['tcp_handshake_timeout'] is None:
- return None
- elif self._values['tcp_handshake_timeout'] == 'immediate':
- return 0
- elif self._values['tcp_handshake_timeout'] == 'indefinite':
- return 4294967295
- return int(self._values['tcp_handshake_timeout'])
-
- @property
- def idle_timeout(self):
- if self._values['idle_timeout'] is None:
- return None
- elif self._values['idle_timeout'] == 'immediate':
- return 0
- elif self._values['idle_timeout'] == 'indefinite':
- return 4294967295
- return int(self._values['idle_timeout'])
-
- @property
- def tcp_close_timeout(self):
- if self._values['tcp_close_timeout'] is None:
- return None
- elif self._values['tcp_close_timeout'] == 'immediate':
- return 0
- elif self._values['tcp_close_timeout'] == 'indefinite':
- return 4294967295
- return int(self._values['tcp_close_timeout'])
-
- @property
- def keep_alive_interval(self):
- if self._values['keep_alive_interval'] is None:
- return None
- elif self._values['keep_alive_interval'] == 'disabled':
- return 0
- return int(self._values['keep_alive_interval'])
-
- @property
- def ip_tos_to_client(self):
- if self._values['ip_tos_to_client'] is None:
- return None
- try:
- return int(self._values['ip_tos_to_client'])
- except ValueError:
- return self._values['ip_tos_to_client']
-
- @property
- def ip_tos_to_server(self):
- if self._values['ip_tos_to_server'] is None:
- return None
- try:
- return int(self._values['ip_tos_to_server'])
- except ValueError:
- return self._values['ip_tos_to_server']
-
- @property
- def link_qos_to_client(self):
- if self._values['link_qos_to_client'] is None:
- return None
- try:
- return int(self._values['link_qos_to_client'])
- except ValueError:
- return self._values['link_qos_to_client']
-
- @property
- def link_qos_to_server(self):
- if self._values['link_qos_to_server'] is None:
- return None
- try:
- return int(self._values['link_qos_to_server'])
- except ValueError:
- return self._values['link_qos_to_server']
-
- @property
- def priority_to_client(self):
- if self._values['priority_to_client'] is None:
- return None
- try:
- return int(self._values['priority_to_client'])
- except ValueError:
- return self._values['priority_to_client']
-
- @property
- def priority_to_server(self):
- if self._values['priority_to_server'] is None:
- return None
- try:
- return int(self._values['priority_to_server'])
- except ValueError:
- return self._values['priority_to_server']
-
-
-class FastL4ProfilesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(FastL4ProfilesFactManager, self).__init__(**kwargs)
- self.want = FastL4ProfilesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(fastl4_profiles=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = FastL4ProfilesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/profile/fastl4".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class GatewayIcmpMonitorsParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'defaultsFrom': 'parent',
- 'adaptiveDivergenceType': 'adaptive_divergence_type',
- 'adaptiveDivergenceValue': 'adaptive_divergence_value',
- 'adaptiveLimit': 'adaptive_limit',
- 'adaptiveSamplingTimespan': 'adaptive_sampling_timespan',
- 'manualResume': 'manual_resume',
- 'timeUntilUp': 'time_until_up',
- 'upInterval': 'up_interval',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'parent',
- 'description',
- 'adaptive',
- 'adaptive_divergence_type',
- 'adaptive_divergence_value',
- 'adaptive_limit',
- 'adaptive_sampling_timespan',
- 'destination',
- 'interval',
- 'manual_resume',
- 'time_until_up',
- 'timeout',
- 'transparent',
- 'up_interval',
- ]
-
- @property
- def description(self):
- if self._values['description'] in [None, 'none']:
- return None
- return self._values['description']
-
- @property
- def transparent(self):
- return flatten_boolean(self._values['transparent'])
-
- @property
- def manual_resume(self):
- return flatten_boolean(self._values['manual_resume'])
-
- @property
- def adaptive(self):
- return flatten_boolean(self._values['adaptive'])
-
-
-class GatewayIcmpMonitorsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(GatewayIcmpMonitorsFactManager, self).__init__(**kwargs)
- self.want = GatewayIcmpMonitorsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(gateway_icmp_monitors=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = GatewayIcmpMonitorsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/gateway-icmp".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class GtmXPoolsParameters(BaseParameters):
- api_map = {
- 'alternateMode': 'alternate_mode',
- 'dynamicRatio': 'dynamic_ratio',
- 'fallbackMode': 'fallback_mode',
- 'fullPath': 'full_path',
- 'loadBalancingMode': 'load_balancing_mode',
- 'manualResume': 'manual_resume',
- 'maxAnswersReturned': 'max_answers_returned',
- 'qosHitRatio': 'qos_hit_ratio',
- 'qosHops': 'qos_hops',
- 'qosKilobytesSecond': 'qos_kilobytes_second',
- 'qosLcs': 'qos_lcs',
- 'qosPacketRate': 'qos_packet_rate',
- 'qosRtt': 'qos_rtt',
- 'qosTopology': 'qos_topology',
- 'qosVsCapacity': 'qos_vs_capacity',
- 'qosVsScore': 'qos_vs_score',
- 'verifyMemberAvailability': 'verify_member_availability',
- 'membersReference': 'members'
- }
-
- returnables = [
- 'alternate_mode',
- 'dynamic_ratio',
- 'enabled',
- 'disabled',
- 'fallback_mode',
- 'full_path',
- 'load_balancing_mode',
- 'manual_resume',
- 'max_answers_returned',
- 'members',
- 'name',
- 'partition',
- 'qos_hit_ratio',
- 'qos_hops',
- 'qos_kilobytes_second',
- 'qos_lcs',
- 'qos_packet_rate',
- 'qos_rtt',
- 'qos_topology',
- 'qos_vs_capacity',
- 'qos_vs_score',
- 'ttl',
- 'verify_member_availability',
- ]
-
- @property
- def verify_member_availability(self):
- return flatten_boolean(self._values['verify_member_availability'])
-
- @property
- def dynamic_ratio(self):
- return flatten_boolean(self._values['dynamic_ratio'])
-
- @property
- def max_answers_returned(self):
- if self._values['max_answers_returned'] is None:
- return None
- return int(self._values['max_answers_returned'])
-
- @property
- def members(self):
- result = []
- if self._values['members'] is None or 'items' not in self._values['members']:
- return result
- for item in self._values['members']['items']:
- self._remove_internal_keywords(item)
- if 'disabled' in item:
- item['disabled'] = flatten_boolean(item['disabled'])
- item['enabled'] = flatten_boolean(not item['disabled'])
- if 'enabled' in item:
- item['enabled'] = flatten_boolean(item['enabled'])
- item['disabled'] = flatten_boolean(not item['enabled'])
- if 'fullPath' in item:
- item['full_path'] = item.pop('fullPath')
- if 'memberOrder' in item:
- item['member_order'] = int(item.pop('memberOrder'))
- # Cast some attributes to integer
- for x in ['order', 'preference', 'ratio', 'service']:
- if x in item:
- item[x] = int(item[x])
- result.append(item)
- return result
-
- @property
- def qos_hit_ratio(self):
- if self._values['qos_hit_ratio'] is None:
- return None
- return int(self._values['qos_hit_ratio'])
-
- @property
- def qos_hops(self):
- if self._values['qos_hops'] is None:
- return None
- return int(self._values['qos_hops'])
-
- @property
- def qos_kilobytes_second(self):
- if self._values['qos_kilobytes_second'] is None:
- return None
- return int(self._values['qos_kilobytes_second'])
-
- @property
- def qos_lcs(self):
- if self._values['qos_lcs'] is None:
- return None
- return int(self._values['qos_lcs'])
-
- @property
- def qos_packet_rate(self):
- if self._values['qos_packet_rate'] is None:
- return None
- return int(self._values['qos_packet_rate'])
-
- @property
- def qos_rtt(self):
- if self._values['qos_rtt'] is None:
- return None
- return int(self._values['qos_rtt'])
-
- @property
- def qos_topology(self):
- if self._values['qos_topology'] is None:
- return None
- return int(self._values['qos_topology'])
-
- @property
- def qos_vs_capacity(self):
- if self._values['qos_vs_capacity'] is None:
- return None
- return int(self._values['qos_vs_capacity'])
-
- @property
- def qos_vs_score(self):
- if self._values['qos_vs_score'] is None:
- return None
- return int(self._values['qos_vs_score'])
-
- @property
- def availability_state(self):
- if self._values['stats'] is None:
- return None
- try:
- result = self._values['stats']['status']['availabilityState']
- return result['description']
- except AttributeError:
- return None
-
- @property
- def enabled_state(self):
- if self._values['stats'] is None:
- return None
- try:
- result = self._values['stats']['status']['enabledState']
- return result['description']
- except AttributeError:
- return None
-
- @property
- def availability_status(self):
- # This fact is a combination of the availability_state and enabled_state
- #
- # The purpose of the fact is to give a higher-level view of the availability
- # of the pool, that can be used in playbooks. If you need further detail,
- # consider using the following facts together.
- #
- # - availability_state
- # - enabled_state
- #
- if self.enabled_state == 'enabled':
- if self.availability_state == 'offline':
- return 'red'
- elif self.availability_state == 'available':
- return 'green'
- elif self.availability_state == 'unknown':
- return 'blue'
- else:
- return 'none'
- else:
- # disabled
- return 'black'
-
- @property
- def manual_resume(self):
- return flatten_boolean(self._values['manual_resume'])
-
-
-class GtmAPoolsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(GtmAPoolsFactManager, self).__init__(**kwargs)
- self.want = GtmXPoolsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(gtm_a_pools=facts)
- return result
-
- def _exec_module(self):
- if 'gtm' not in self.provisioned_modules:
- return []
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = GtmXPoolsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/gtm/pool/a".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- query = "?expandSubcollections=true"
- resp = self.client.api.get(uri + query)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class GtmAaaaPoolsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(GtmAaaaPoolsFactManager, self).__init__(**kwargs)
- self.want = GtmXPoolsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(gtm_aaaa_pools=facts)
- return result
-
- def _exec_module(self):
- if 'gtm' not in self.provisioned_modules:
- return []
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = GtmXPoolsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/gtm/pool/aaaa".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- query = "?expandSubcollections=true"
- resp = self.client.api.get(uri + query)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class GtmCnamePoolsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(GtmCnamePoolsFactManager, self).__init__(**kwargs)
- self.want = GtmXPoolsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(gtm_cname_pools=facts)
- return result
-
- def _exec_module(self):
- if 'gtm' not in self.provisioned_modules:
- return []
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = GtmXPoolsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/gtm/pool/cname".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- query = "?expandSubcollections=true"
- resp = self.client.api.get(uri + query)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class GtmMxPoolsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(GtmMxPoolsFactManager, self).__init__(**kwargs)
- self.want = GtmXPoolsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(gtm_mx_pools=facts)
- return result
-
- def _exec_module(self):
- if 'gtm' not in self.provisioned_modules:
- return []
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = GtmXPoolsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/gtm/pool/mx".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- query = "?expandSubcollections=true"
- resp = self.client.api.get(uri + query)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class GtmNaptrPoolsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(GtmNaptrPoolsFactManager, self).__init__(**kwargs)
- self.want = GtmXPoolsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(gtm_naptr_pools=facts)
- return result
-
- def _exec_module(self):
- if 'gtm' not in self.provisioned_modules:
- return []
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = GtmXPoolsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/gtm/pool/naptr".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- query = "?expandSubcollections=true"
- resp = self.client.api.get(uri + query)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class GtmSrvPoolsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(GtmSrvPoolsFactManager, self).__init__(**kwargs)
- self.want = GtmXPoolsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(gtm_srv_pools=facts)
- return result
-
- def _exec_module(self):
- if 'gtm' not in self.provisioned_modules:
- return []
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = GtmXPoolsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/gtm/pool/srv".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- query = "?expandSubcollections=true"
- resp = self.client.api.get(uri + query)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class GtmServersParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'exposeRouteDomains': 'expose_route_domains',
- 'iqAllowPath': 'iq_allow_path',
- 'iqAllowServiceCheck': 'iq_allow_service_check',
- 'iqAllowSnmp': 'iq_allow_snmp',
- 'limitCpuUsage': 'limit_cpu_usage',
- 'limitCpuUsageStatus': 'limit_cpu_usage_status',
- 'limitMaxBps': 'limit_max_bps',
- 'limitMaxBpsStatus': 'limit_max_bps_status',
- 'limitMaxConnections': 'limit_max_connections',
- 'limitMaxConnectionsStatus': 'limit_max_connections_status',
- 'limitMaxPps': 'limit_max_pps',
- 'limitMaxPpsStatus': 'limit_max_pps_status',
- 'limitMemAvail': 'limit_mem_available',
- 'limitMemAvailStatus': 'limit_mem_available_status',
- 'linkDiscovery': 'link_discovery',
- 'proberFallback': 'prober_fallback',
- 'proberPreference': 'prober_preference',
- 'virtualServerDiscovery': 'virtual_server_discovery',
- 'devicesReference': 'devices',
- 'virtualServersReference': 'virtual_servers',
- 'monitor': 'monitors',
- }
-
- returnables = [
- 'datacenter',
- 'enabled',
- 'disabled',
- 'expose_route_domains',
- 'iq_allow_path',
- 'full_path',
- 'iq_allow_service_check',
- 'iq_allow_snmp',
- 'limit_cpu_usage',
- 'limit_cpu_usage_status',
- 'limit_max_bps',
- 'limit_max_bps_status',
- 'limit_max_connections',
- 'limit_max_connections_status',
- 'limit_max_pps',
- 'limit_max_pps_status',
- 'limit_mem_available',
- 'limit_mem_available_status',
- 'link_discovery',
- 'monitors',
- 'monitor_type',
- 'name',
- 'product',
- 'prober_fallback',
- 'prober_preference',
- 'virtual_server_discovery',
- 'addresses',
- 'devices',
- 'virtual_servers',
- ]
-
- @property
- def monitors(self):
- if self._values['monitors'] is None:
- return []
- try:
- result = re.findall(r'/\w+/[^\s}]+', self._values['monitors'])
- return result
- except Exception:
- return [self._values['monitors']]
-
- @property
- def monitor_type(self):
- if self._values['monitors'] is None:
- return None
- pattern = r'min\s+\d+\s+of'
- matches = re.search(pattern, self._values['monitors'])
- if matches:
- return 'm_of_n'
- else:
- return 'and_list'
-
- @property
- def limit_mem_available_status(self):
- return flatten_boolean(self._values['limit_mem_available_status'])
-
- @property
- def limit_max_pps_status(self):
- return flatten_boolean(self._values['limit_max_pps_status'])
-
- @property
- def limit_max_connections_status(self):
- return flatten_boolean(self._values['limit_max_connections_status'])
-
- @property
- def limit_max_bps_status(self):
- return flatten_boolean(self._values['limit_max_bps_status'])
-
- @property
- def limit_cpu_usage_status(self):
- return flatten_boolean(self._values['limit_cpu_usage_status'])
-
- @property
- def iq_allow_service_check(self):
- return flatten_boolean(self._values['iq_allow_service_check'])
-
- @property
- def iq_allow_snmp(self):
- return flatten_boolean(self._values['iq_allow_snmp'])
-
- @property
- def expose_route_domains(self):
- return flatten_boolean(self._values['expose_route_domains'])
-
- @property
- def iq_allow_path(self):
- return flatten_boolean(self._values['iq_allow_path'])
-
- @property
- def product(self):
- if self._values['product'] is None:
- return None
- if self._values['product'] in ['single-bigip', 'redundant-bigip']:
- return 'bigip'
- return self._values['product']
-
- @property
- def devices(self):
- result = []
- if self._values['devices'] is None or 'items' not in self._values['devices']:
- return result
- for item in self._values['devices']['items']:
- self._remove_internal_keywords(item)
- if 'fullPath' in item:
- item['full_path'] = item.pop('fullPath')
- result.append(item)
- return result
-
- @property
- def virtual_servers(self):
- result = []
- if self._values['virtual_servers'] is None or 'items' not in self._values['virtual_servers']:
- return result
- for item in self._values['virtual_servers']['items']:
- self._remove_internal_keywords(item)
- if 'disabled' in item:
- if item['disabled'] in BOOLEANS_TRUE:
- item['disabled'] = flatten_boolean(item['disabled'])
- item['enabled'] = flatten_boolean(not item['disabled'])
- if 'enabled' in item:
- if item['enabled'] in BOOLEANS_TRUE:
- item['enabled'] = flatten_boolean(item['enabled'])
- item['disabled'] = flatten_boolean(not item['enabled'])
- if 'fullPath' in item:
- item['full_path'] = item.pop('fullPath')
- if 'limitMaxBps' in item:
- item['limit_max_bps'] = int(item.pop('limitMaxBps'))
- if 'limitMaxBpsStatus' in item:
- item['limit_max_bps_status'] = item.pop('limitMaxBpsStatus')
- if 'limitMaxConnections' in item:
- item['limit_max_connections'] = int(item.pop('limitMaxConnections'))
- if 'limitMaxConnectionsStatus' in item:
- item['limit_max_connections_status'] = item.pop('limitMaxConnectionsStatus')
- if 'limitMaxPps' in item:
- item['limit_max_pps'] = int(item.pop('limitMaxPps'))
- if 'limitMaxPpsStatus' in item:
- item['limit_max_pps_status'] = item.pop('limitMaxPpsStatus')
- if 'translationAddress' in item:
- item['translation_address'] = item.pop('translationAddress')
- if 'translationPort' in item:
- item['translation_port'] = int(item.pop('translationPort'))
- result.append(item)
- return result
-
- @property
- def limit_cpu_usage(self):
- if self._values['limit_cpu_usage'] is None:
- return None
- return int(self._values['limit_cpu_usage'])
-
- @property
- def limit_max_bps(self):
- if self._values['limit_max_bps'] is None:
- return None
- return int(self._values['limit_max_bps'])
-
- @property
- def limit_max_connections(self):
- if self._values['limit_max_connections'] is None:
- return None
- return int(self._values['limit_max_connections'])
-
- @property
- def limit_max_pps(self):
- if self._values['limit_max_pps'] is None:
- return None
- return int(self._values['limit_max_pps'])
-
- @property
- def limit_mem_available(self):
- if self._values['limit_mem_available'] is None:
- return None
- return int(self._values['limit_mem_available'])
-
-
-class GtmServersFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(GtmServersFactManager, self).__init__(**kwargs)
- self.want = GtmServersParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(gtm_servers=facts)
- return result
-
- def _exec_module(self):
- if 'gtm' not in self.provisioned_modules:
- return []
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = GtmServersParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/gtm/server".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class GtmXWideIpsParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'failureRcode': 'failure_rcode',
- 'failureRcodeResponse': 'failure_rcode_response',
- 'failureRcodeTtl': 'failure_rcode_ttl',
- 'lastResortPool': 'last_resort_pool',
- 'minimalResponse': 'minimal_response',
- 'persistCidrIpv4': 'persist_cidr_ipv4',
- 'persistCidrIpv6': 'persist_cidr_ipv6',
- 'poolLbMode': 'pool_lb_mode',
- 'ttlPersistence': 'ttl_persistence'
- }
-
- returnables = [
- 'full_path',
- 'description',
- 'enabled',
- 'disabled',
- 'failure_rcode',
- 'failure_rcode_response',
- 'failure_rcode_ttl',
- 'last_resort_pool',
- 'minimal_response',
- 'name',
- 'persist_cidr_ipv4',
- 'persist_cidr_ipv6',
- 'pool_lb_mode',
- 'ttl_persistence',
- 'pools',
- ]
-
- @property
- def pools(self):
- result = []
- if self._values['pools'] is None:
- return []
- for pool in self._values['pools']:
- del pool['nameReference']
- for x in ['order', 'ratio']:
- if x in pool:
- pool[x] = int(pool[x])
- result.append(pool)
- return result
-
- @property
- def failure_rcode_response(self):
- return flatten_boolean(self._values['failure_rcode_response'])
-
- @property
- def failure_rcode_ttl(self):
- if self._values['failure_rcode_ttl'] is None:
- return None
- return int(self._values['failure_rcode_ttl'])
-
- @property
- def persist_cidr_ipv4(self):
- if self._values['persist_cidr_ipv4'] is None:
- return None
- return int(self._values['persist_cidr_ipv4'])
-
- @property
- def persist_cidr_ipv6(self):
- if self._values['persist_cidr_ipv6'] is None:
- return None
- return int(self._values['persist_cidr_ipv6'])
-
- @property
- def ttl_persistence(self):
- if self._values['ttl_persistence'] is None:
- return None
- return int(self._values['ttl_persistence'])
-
-
-class GtmAWideIpsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(GtmAWideIpsFactManager, self).__init__(**kwargs)
- self.want = GtmXWideIpsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(gtm_a_wide_ips=facts)
- return result
-
- def _exec_module(self):
- if 'gtm' not in self.provisioned_modules:
- return []
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = GtmXWideIpsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/gtm/wideip/a".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class GtmAaaaWideIpsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(GtmAaaaWideIpsFactManager, self).__init__(**kwargs)
- self.want = GtmXWideIpsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(gtm_aaaa_wide_ips=facts)
- return result
-
- def _exec_module(self):
- if 'gtm' not in self.provisioned_modules:
- return []
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = GtmXWideIpsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/gtm/wideip/aaaa".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class GtmCnameWideIpsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(GtmCnameWideIpsFactManager, self).__init__(**kwargs)
- self.want = GtmXWideIpsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(gtm_cname_wide_ips=facts)
- return result
-
- def _exec_module(self):
- if 'gtm' not in self.provisioned_modules:
- return []
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = GtmXWideIpsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/gtm/wideip/cname".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class GtmMxWideIpsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(GtmMxWideIpsFactManager, self).__init__(**kwargs)
- self.want = GtmXWideIpsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(gtm_mx_wide_ips=facts)
- return result
-
- def _exec_module(self):
- if 'gtm' not in self.provisioned_modules:
- return []
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = GtmXWideIpsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/gtm/wideip/mx".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class GtmNaptrWideIpsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(GtmNaptrWideIpsFactManager, self).__init__(**kwargs)
- self.want = GtmXWideIpsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(gtm_naptr_wide_ips=facts)
- return result
-
- def _exec_module(self):
- results = []
- if 'gtm' not in self.provisioned_modules:
- return []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = GtmXWideIpsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/gtm/wideip/naptr".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class GtmSrvWideIpsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(GtmSrvWideIpsFactManager, self).__init__(**kwargs)
- self.want = GtmXWideIpsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(gtm_srv_wide_ips=facts)
- return result
-
- def _exec_module(self):
- if 'gtm' not in self.provisioned_modules:
- return []
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = GtmXWideIpsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/gtm/wideip/srv".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class HttpMonitorsParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'defaultsFrom': 'parent',
- 'adaptiveDivergenceType': 'adaptive_divergence_type',
- 'adaptiveDivergenceValue': 'adaptive_divergence_value',
- 'adaptiveLimit': 'adaptive_limit',
- 'adaptiveSamplingTimespan': 'adaptive_sampling_timespan',
- 'ipDscp': 'ip_dscp',
- 'manualResume': 'manual_resume',
- 'recv': 'receive_string',
- 'recvDisable': 'receive_disable_string',
- 'send': 'send_string',
- 'timeUntilUp': 'time_until_up',
- 'upInterval': 'up_interval',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'parent',
- 'description',
- 'adaptive',
- 'adaptive_divergence_type',
- 'adaptive_divergence_value',
- 'adaptive_limit',
- 'adaptive_sampling_timespan',
- 'destination',
- 'interval',
- 'ip_dscp',
- 'manual_resume',
- 'receive_string',
- 'receive_disable_string',
- 'reverse',
- 'send_string',
- 'time_until_up',
- 'timeout',
- 'transparent',
- 'up_interval',
- 'username',
- ]
-
- @property
- def description(self):
- if self._values['description'] in [None, 'none']:
- return None
- return self._values['description']
-
- @property
- def transparent(self):
- return flatten_boolean(self._values['transparent'])
-
- @property
- def reverse(self):
- return flatten_boolean(self._values['reverse'])
-
- @property
- def manual_resume(self):
- return flatten_boolean(self._values['manual_resume'])
-
- @property
- def adaptive(self):
- return flatten_boolean(self._values['adaptive'])
-
-
-class HttpMonitorsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(HttpMonitorsFactManager, self).__init__(**kwargs)
- self.want = HttpMonitorsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(http_monitors=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = HttpMonitorsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/http".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = response['items']
- return result
-
-
-class HttpsMonitorsParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'defaultsFrom': 'parent',
- 'adaptiveDivergenceType': 'adaptive_divergence_type',
- 'adaptiveDivergenceValue': 'adaptive_divergence_value',
- 'adaptiveLimit': 'adaptive_limit',
- 'adaptiveSamplingTimespan': 'adaptive_sampling_timespan',
- 'ipDscp': 'ip_dscp',
- 'manualResume': 'manual_resume',
- 'recv': 'receive_string',
- 'recvDisable': 'receive_disable_string',
- 'send': 'send_string',
- 'sslProfile': 'ssl_profile',
- 'timeUntilUp': 'time_until_up',
- 'upInterval': 'up_interval',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'parent',
- 'description',
- 'adaptive',
- 'adaptive_divergence_type',
- 'adaptive_divergence_value',
- 'adaptive_limit',
- 'adaptive_sampling_timespan',
- 'destination',
- 'interval',
- 'ip_dscp',
- 'manual_resume',
- 'receive_string',
- 'receive_disable_string',
- 'reverse',
- 'send_string',
- 'ssl_profile',
- 'time_until_up',
- 'timeout',
- 'transparent',
- 'up_interval',
- 'username',
- ]
-
- @property
- def description(self):
- if self._values['description'] in [None, 'none']:
- return None
- return self._values['description']
-
- @property
- def transparent(self):
- return flatten_boolean(self._values['transparent'])
-
- @property
- def reverse(self):
- return flatten_boolean(self._values['reverse'])
-
- @property
- def manual_resume(self):
- return flatten_boolean(self._values['manual_resume'])
-
- @property
- def adaptive(self):
- return flatten_boolean(self._values['adaptive'])
-
-
-class HttpsMonitorsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(HttpsMonitorsFactManager, self).__init__(**kwargs)
- self.want = HttpsMonitorsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(https_monitors=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = HttpsMonitorsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/https".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = response['items']
- return result
-
-
-class HttpProfilesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'defaultsFrom': 'parent',
- 'acceptXff': 'accept_xff',
- 'explicitProxy': 'explicit_proxy',
- 'insertXforwardedFor': 'insert_x_forwarded_for',
- 'lwsWidth': 'lws_max_columns',
- 'oneconnectTransformations': 'onconnect_transformations',
- 'proxyType': 'proxy_mode',
- 'redirectRewrite': 'redirect_rewrite',
- 'requestChunking': 'request_chunking',
- 'responseChunking': 'response_chunking',
- 'serverAgentName': 'server_agent_name',
- 'viaRequest': 'via_request',
- 'viaResponse': 'via_response',
- 'pipeline': 'pipeline_action',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'parent',
- 'description',
- 'accept_xff',
- 'allow_truncated_redirects',
- 'excess_client_headers',
- 'excess_server_headers',
- 'known_methods',
- 'max_header_count',
- 'max_header_size',
- 'max_requests',
- 'oversize_client_headers',
- 'oversize_server_headers',
- 'pipeline_action',
- 'unknown_method',
- 'default_connect_handling',
- 'hsts_include_subdomains',
- 'hsts_enabled',
- 'insert_x_forwarded_for',
- 'lws_max_columns',
- 'onconnect_transformations',
- 'proxy_mode',
- 'redirect_rewrite',
- 'request_chunking',
- 'response_chunking',
- 'server_agent_name',
- 'sflow_poll_interval',
- 'sflow_sampling_rate',
- 'via_request',
- 'via_response',
- ]
-
- @property
- def description(self):
- if self._values['description'] in [None, 'none']:
- return None
- return self._values['description']
-
- @property
- def accept_xff(self):
- return flatten_boolean(self._values['accept_xff'])
-
- @property
- def excess_client_headers(self):
- if self._values['enforcement'] is None:
- return None
- if self._values['enforcement']['excessClientHeaders'] is None:
- return None
- return self._values['enforcement']['excessClientHeaders']
-
- @property
- def excess_server_headers(self):
- if self._values['enforcement'] is None:
- return None
- if self._values['enforcement']['excessServerHeaders'] is None:
- return None
- return self._values['enforcement']['excessServerHeaders']
-
- @property
- def known_methods(self):
- if self._values['enforcement'] is None:
- return None
- if self._values['enforcement']['knownMethods'] is None:
- return None
- return self._values['enforcement']['knownMethods']
-
- @property
- def max_header_count(self):
- if self._values['enforcement'] is None:
- return None
- if self._values['enforcement']['maxHeaderCount'] is None:
- return None
- return self._values['enforcement']['maxHeaderCount']
-
- @property
- def max_header_size(self):
- if self._values['enforcement'] is None:
- return None
- if self._values['enforcement']['maxHeaderSize'] is None:
- return None
- return self._values['enforcement']['maxHeaderSize']
-
- @property
- def max_requests(self):
- if self._values['enforcement'] is None:
- return None
- if self._values['enforcement']['maxRequests'] is None:
- return None
- return self._values['enforcement']['maxRequests']
-
- @property
- def oversize_client_headers(self):
- if self._values['enforcement'] is None:
- return None
- if self._values['enforcement']['oversizeClientHeaders'] is None:
- return None
- return self._values['enforcement']['oversizeClientHeaders']
-
- @property
- def oversize_server_headers(self):
- if self._values['enforcement'] is None:
- return None
- if self._values['enforcement']['oversizeServerHeaders'] is None:
- return None
- return self._values['enforcement']['oversizeServerHeaders']
-
- @property
- def allow_truncated_redirects(self):
- if self._values['enforcement'] is None:
- return None
- if self._values['enforcement']['truncatedRedirects'] is None:
- return None
- return flatten_boolean(self._values['enforcement']['truncatedRedirects'])
-
- @property
- def unknown_method(self):
- if self._values['enforcement'] is None:
- return None
- if self._values['enforcement']['unknownMethod'] is None:
- return None
- return self._values['enforcement']['unknownMethod']
-
- @property
- def default_connect_handling(self):
- if self._values['explicit_proxy'] is None:
- return None
- if self._values['explicit_proxy']['defaultConnectHandling'] is None:
- return None
- return self._values['explicit_proxy']['defaultConnectHandling']
-
- @property
- def hsts_include_subdomains(self):
- if self._values['hsts'] is None:
- return None
- if self._values['hsts']['includeSubdomains'] is None:
- return None
- return flatten_boolean(self._values['hsts']['includeSubdomains'])
-
- @property
- def hsts_enabled(self):
- if self._values['hsts'] is None:
- return None
- if self._values['hsts']['mode'] is None:
- return None
- return flatten_boolean(self._values['hsts']['mode'])
-
- @property
- def hsts_max_age(self):
- if self._values['hsts'] is None:
- return None
- if self._values['hsts']['mode'] is None:
- return None
- return self._values['hsts']['maximumAge']
-
- @property
- def insert_x_forwarded_for(self):
- if self._values['insert_x_forwarded_for'] is None:
- return None
- return flatten_boolean(self._values['insert_x_forwarded_for'])
-
- @property
- def onconnect_transformations(self):
- if self._values['onconnect_transformations'] is None:
- return None
- return flatten_boolean(self._values['onconnect_transformations'])
-
- @property
- def sflow_poll_interval(self):
- if self._values['sflow'] is None:
- return None
- if self._values['sflow']['pollInterval'] is None:
- return None
- return self._values['sflow']['pollInterval']
-
- @property
- def sflow_sampling_rate(self):
- if self._values['sflow'] is None:
- return None
- if self._values['sflow']['samplingRate'] is None:
- return None
- return self._values['sflow']['samplingRate']
-
-
-class HttpProfilesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(HttpProfilesFactManager, self).__init__(**kwargs)
- self.want = HttpProfilesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(http_profiles=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = HttpProfilesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/profile/http".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class IappServicesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'deviceGroup': 'device_group',
- 'inheritedDevicegroup': 'inherited_device_group',
- 'inheritedTrafficGroup': 'inherited_traffic_group',
- 'strictUpdates': 'strict_updates',
- 'templateModified': 'template_modified',
- 'trafficGroup': 'traffic_group',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'device_group',
- 'inherited_device_group',
- 'inherited_traffic_group',
- 'strict_updates',
- 'template_modified',
- 'traffic_group',
- 'tables',
- 'variables',
- 'metadata',
- 'lists',
- 'description',
- ]
-
- @property
- def description(self):
- if self._values['description'] in [None, 'none']:
- return None
- return self._values['description']
-
- @property
- def inherited_device_group(self):
- return flatten_boolean(self._values['inherited_device_group'])
-
- @property
- def inherited_traffic_group(self):
- return flatten_boolean(self._values['inherited_traffic_group'])
-
- @property
- def strict_updates(self):
- return flatten_boolean(self._values['strict_updates'])
-
- @property
- def template_modified(self):
- return flatten_boolean(self._values['template_modified'])
-
-
-class IappServicesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(IappServicesFactManager, self).__init__(**kwargs)
- self.want = IappServicesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(iapp_services=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = IappServicesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/sys/application/service".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class IapplxPackagesParameters(BaseParameters):
- api_map = {
- 'packageName': 'package_name',
- }
-
- returnables = [
- 'name',
- 'version',
- 'release',
- 'arch',
- 'package_name',
- 'tags',
- ]
-
-
-class IapplxPackagesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(IapplxPackagesFactManager, self).__init__(**kwargs)
- self.want = IapplxPackagesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(iapplx_packages=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['name'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = IapplxPackagesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- params = dict(operation='QUERY')
- uri = "https://{0}:{1}/mgmt/shared/iapp/package-management-tasks".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.post(uri, json=params)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- status = self.wait_for_task(response['id'])
- if status == 'FINISHED':
- uri = "https://{0}:{1}/mgmt/shared/iapp/package-management-tasks/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- response['id']
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- else:
- raise F5ModuleError(
- "An error occurred querying iAppLX packages."
- )
- result = response['queryResponse']
- return result
-
- def wait_for_task(self, task_id):
- uri = "https://{0}:{1}/mgmt/shared/iapp/package-management-tasks/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- task_id
- )
- for x in range(0, 60):
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if response['status'] in ['FINISHED', 'FAILED']:
- return response['status']
- time.sleep(1)
- return response['status']
-
-
-class IcmpMonitorsParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'defaultsFrom': 'parent',
- 'adaptiveDivergenceType': 'adaptive_divergence_type',
- 'adaptiveDivergenceValue': 'adaptive_divergence_value',
- 'adaptiveLimit': 'adaptive_limit',
- 'adaptiveSamplingTimespan': 'adaptive_sampling_timespan',
- 'manualResume': 'manual_resume',
- 'timeUntilUp': 'time_until_up',
- 'upInterval': 'up_interval',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'parent',
- 'description',
- 'adaptive',
- 'adaptive_divergence_type',
- 'adaptive_divergence_value',
- 'adaptive_limit',
- 'adaptive_sampling_timespan',
- 'destination',
- 'interval',
- 'manual_resume',
- 'time_until_up',
- 'timeout',
- 'transparent',
- 'up_interval',
- ]
-
- @property
- def description(self):
- if self._values['description'] in [None, 'none']:
- return None
- return self._values['description']
-
- @property
- def transparent(self):
- return flatten_boolean(self._values['transparent'])
-
- @property
- def manual_resume(self):
- return flatten_boolean(self._values['manual_resume'])
-
- @property
- def adaptive(self):
- return flatten_boolean(self._values['adaptive'])
-
-
-class IcmpMonitorsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(IcmpMonitorsFactManager, self).__init__(**kwargs)
- self.want = IcmpMonitorsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(icmp_monitors=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = IcmpMonitorsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/icmp".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class InterfacesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'mediaActive': 'active_media_type',
- 'flowControl': 'flow_control',
- 'bundleSpeed': 'bundle_speed',
- 'ifIndex': 'if_index',
- 'macAddress': 'mac_address',
- 'mediaSfp': 'media_sfp',
- 'lldpAdmin': 'lldp_admin',
- 'preferPort': 'prefer_port',
- 'stpAutoEdgePort': 'stp_auto_edge_port',
- 'stp': 'stp_enabled',
- 'stpLinkType': 'stp_link_type'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'active_media_type',
- 'flow_control',
- 'description',
- 'bundle',
- 'bundle_speed',
- 'enabled',
- 'if_index',
- 'mac_address',
- 'media_sfp',
- 'lldp_admin',
- 'mtu',
- 'prefer_port',
- 'sflow_poll_interval',
- 'sflow_poll_interval_global',
- 'stp_auto_edge_port',
- 'stp_enabled',
- 'stp_link_type'
- ]
-
- @property
- def stp_auto_edge_port(self):
- return flatten_boolean(self._values['stp_auto_edge_port'])
-
- @property
- def stp_enabled(self):
- return flatten_boolean(self._values['stp_enabled'])
-
- @property
- def sflow_poll_interval_global(self):
- if self._values['sflow'] is None:
- return None
- if 'pollIntervalGlobal' in self._values['sflow']:
- return self._values['sflow']['pollIntervalGlobal']
-
- @property
- def sflow_poll_interval(self):
- if self._values['sflow'] is None:
- return None
- if 'pollInterval' in self._values['sflow']:
- return self._values['sflow']['pollInterval']
-
- @property
- def mac_address(self):
- if self._values['mac_address'] in [None, 'none']:
- return None
- return self._values['mac_address']
-
- @property
- def enabled(self):
- return flatten_boolean(self._values['enabled'])
-
-
-class InterfacesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(InterfacesFactManager, self).__init__(**kwargs)
- self.want = InterfacesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(interfaces=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = InterfacesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/net/interface".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class InternalDataGroupsParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'type',
- 'records'
- ]
-
-
-class InternalDataGroupsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(InternalDataGroupsFactManager, self).__init__(**kwargs)
- self.want = InternalDataGroupsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(internal_data_groups=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = InternalDataGroupsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/data-group/internal".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class IrulesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'ignoreVerification': 'ignore_verification',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'ignore_verification',
- 'checksum',
- 'definition',
- 'signature'
- ]
-
- @property
- def checksum(self):
- if self._values['apiAnonymous'] is None:
- return None
- pattern = r'definition-checksum\s(?P\w+)'
- matches = re.search(pattern, self._values['apiAnonymous'])
- if matches:
- return matches.group('checksum')
-
- @property
- def definition(self):
- if self._values['apiAnonymous'] is None:
- return None
- pattern = r'(definition-(checksum|signature)\s[\w=\/+]+)'
- result = re.sub(pattern, '', self._values['apiAnonymous']).strip()
- if result:
- return result
-
- @property
- def signature(self):
- if self._values['apiAnonymous'] is None:
- return None
- pattern = r'definition-signature\s(?P[\w=\/+]+)'
- matches = re.search(pattern, self._values['apiAnonymous'])
- if matches:
- return matches.group('signature')
-
- @property
- def ignore_verification(self):
- if self._values['ignore_verification'] is None:
- return 'no'
- return 'yes'
-
-
-class IrulesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(IrulesFactManager, self).__init__(**kwargs)
- self.want = IrulesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(irules=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = IrulesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/rule".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class LtmPoolsParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'allowNat': 'allow_nat',
- 'allowSnat': 'allow_snat',
- 'ignorePersistedWeight': 'ignore_persisted_weight',
- 'ipTosToClient': 'client_ip_tos',
- 'ipTosToServer': 'server_ip_tos',
- 'linkQosToClient': 'client_link_qos',
- 'linkQosToServer': 'server_link_qos',
- 'loadBalancingMode': 'lb_method',
- 'minActiveMembers': 'minimum_active_members',
- 'minUpMembers': 'minimum_up_members',
- 'minUpMembersAction': 'minimum_up_members_action',
- 'minUpMembersChecking': 'minimum_up_members_checking',
- 'queueDepthLimit': 'queue_depth_limit',
- 'queueOnConnectionLimit': 'queue_on_connection_limit',
- 'queueTimeLimit': 'queue_time_limit',
- 'reselectTries': 'reselect_tries',
- 'serviceDownAction': 'service_down_action',
- 'slowRampTime': 'slow_ramp_time',
- 'monitor': 'monitors',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'allow_nat',
- 'allow_snat',
- 'description',
- 'ignore_persisted_weight',
- 'client_ip_tos',
- 'server_ip_tos',
- 'client_link_qos',
- 'server_link_qos',
- 'lb_method',
- 'minimum_active_members',
- 'minimum_up_members',
- 'minimum_up_members_action',
- 'minimum_up_members_checking',
- 'monitors',
- 'queue_depth_limit',
- 'queue_on_connection_limit',
- 'queue_time_limit',
- 'reselect_tries',
- 'service_down_action',
- 'slow_ramp_time',
- 'priority_group_activation',
- 'members',
- 'metadata',
- 'active_member_count',
- 'available_member_count',
- 'availability_status',
- 'enabled_status',
- 'status_reason',
- 'all_max_queue_entry_age_ever',
- 'all_avg_queue_entry_age',
- 'all_queue_head_entry_age',
- 'all_max_queue_entry_age_recently',
- 'all_num_connections_queued_now',
- 'all_num_connections_serviced',
- 'pool_max_queue_entry_age_ever',
- 'pool_avg_queue_entry_age',
- 'pool_queue_head_entry_age',
- 'pool_max_queue_entry_age_recently',
- 'pool_num_connections_queued_now',
- 'pool_num_connections_serviced',
- 'current_sessions',
- 'member_count',
- 'total_requests',
- 'server_side_bits_in',
- 'server_side_bits_out',
- 'server_side_current_connections',
- 'server_side_max_connections',
- 'server_side_pkts_in',
- 'server_side_pkts_out',
- 'server_side_total_connections',
- ]
-
- @property
- def active_member_count(self):
- if 'availableMemberCnt' in self._values['stats']:
- return int(self._values['stats']['activeMemberCnt'])
- return None
-
- @property
- def available_member_count(self):
- if 'availableMemberCnt' in self._values['stats']:
- return int(self._values['stats']['availableMemberCnt'])
- return None
-
- @property
- def all_max_queue_entry_age_ever(self):
- return self._values['stats']['connqAll']['ageEdm']
-
- @property
- def all_avg_queue_entry_age(self):
- return self._values['stats']['connqAll']['ageEma']
-
- @property
- def all_queue_head_entry_age(self):
- return self._values['stats']['connqAll']['ageHead']
-
- @property
- def all_max_queue_entry_age_recently(self):
- return self._values['stats']['connqAll']['ageMax']
-
- @property
- def all_num_connections_queued_now(self):
- return self._values['stats']['connqAll']['depth']
-
- @property
- def all_num_connections_serviced(self):
- return self._values['stats']['connqAll']['serviced']
-
- @property
- def availability_status(self):
- return self._values['stats']['status']['availabilityState']
-
- @property
- def enabled_status(self):
- return self._values['stats']['status']['enabledState']
-
- @property
- def status_reason(self):
- return self._values['stats']['status']['statusReason']
-
- @property
- def pool_max_queue_entry_age_ever(self):
- return self._values['stats']['connq']['ageEdm']
-
- @property
- def pool_avg_queue_entry_age(self):
- return self._values['stats']['connq']['ageEma']
-
- @property
- def pool_queue_head_entry_age(self):
- return self._values['stats']['connq']['ageHead']
-
- @property
- def pool_max_queue_entry_age_recently(self):
- return self._values['stats']['connq']['ageMax']
-
- @property
- def pool_num_connections_queued_now(self):
- return self._values['stats']['connq']['depth']
-
- @property
- def pool_num_connections_serviced(self):
- return self._values['stats']['connq']['serviced']
-
- @property
- def current_sessions(self):
- return self._values['stats']['curSessions']
-
- @property
- def member_count(self):
- if 'memberCnt' in self._values['stats']:
- return self._values['stats']['memberCnt']
- return None
-
- @property
- def total_requests(self):
- return self._values['stats']['totRequests']
-
- @property
- def server_side_bits_in(self):
- return self._values['stats']['serverside']['bitsIn']
-
- @property
- def server_side_bits_out(self):
- return self._values['stats']['serverside']['bitsOut']
-
- @property
- def server_side_current_connections(self):
- return self._values['stats']['serverside']['curConns']
-
- @property
- def server_side_max_connections(self):
- return self._values['stats']['serverside']['maxConns']
-
- @property
- def server_side_pkts_in(self):
- return self._values['stats']['serverside']['pktsIn']
-
- @property
- def server_side_pkts_out(self):
- return self._values['stats']['serverside']['pktsOut']
-
- @property
- def server_side_total_connections(self):
- return self._values['stats']['serverside']['totConns']
-
- @property
- def ignore_persisted_weight(self):
- return flatten_boolean(self._values['ignore_persisted_weight'])
-
- @property
- def minimum_up_members_checking(self):
- return flatten_boolean(self._values['minimum_up_members_checking'])
-
- @property
- def queue_on_connection_limit(self):
- return flatten_boolean(self._values['queue_on_connection_limit'])
-
- @property
- def priority_group_activation(self):
- """Returns the TMUI value for "Priority Group Activation"
-
- This value is identified as ``minActiveMembers`` in the REST API, so this
- is just a convenience key for users of Ansible (where the ``bigip_virtual_server``
- parameter is called ``priority_group_activation``.
-
- Returns:
- int: Priority number assigned to the pool members.
- """
- return self._values['minimum_active_members']
-
- @property
- def metadata(self):
- """Returns metadata associated with a pool
-
- An arbitrary amount of metadata may be associated with a pool. You typically
- see this used in situations where the user wants to annotate a resource, maybe
- in cases where an automation system is responsible for creating the resource.
-
- The metadata in the API is always stored as a list of dictionaries. We change
- this to be a simple dictionary before it is returned to the user.
-
- Returns:
- dict: A dictionary of key/value pairs where the key is the metadata name
- and the value is the metadata value.
- """
- if self._values['metadata'] is None:
- return None
- result = dict([(k['name'], k['value']) for k in self._values['metadata']])
- return result
-
- @property
- def members(self):
- if not self._values['members']:
- return None
- result = []
- for member in self._values['members']:
- member['connection_limit'] = member.pop('connectionLimit', None)
- member['dynamic_ratio'] = member.pop('dynamicRatio', None)
- member['full_path'] = member.pop('fullPath', None)
- member['inherit_profile'] = member.pop('inheritProfile', None)
- member['priority_group'] = member.pop('priorityGroup', None)
- member['rate_limit'] = member.pop('rateLimit', None)
-
- if 'fqdn' in member and 'autopopulate' in member['fqdn']:
- if member['fqdn']['autopopulate'] == 'enabled':
- member['fqdn_autopopulate'] = 'yes'
- elif member['fqdn']['autopopulate'] == 'disabled':
- member['fqdn_autopopulate'] = 'no'
- del member['fqdn']
-
- for key in ['ephemeral', 'inherit_profile', 'logging', 'rate_limit']:
- tmp = flatten_boolean(member[key])
- member[key] = tmp
-
- if 'profiles' in member:
- # Even though the ``profiles`` is a list, there is only ever 1
- member['encapsulation_profile'] = [x['name'] for x in member['profiles']][0]
- del member['profiles']
-
- if 'monitor' in member:
- monitors = member.pop('monitor')
- if monitors is not None:
- try:
- member['monitors'] = re.findall(r'/[\w-]+/[^\s}]+', monitors)
- except Exception:
- member['monitors'] = [monitors.strip()]
-
- session = member.pop('session')
- state = member.pop('state')
-
- member['real_session'] = session
- member['real_state'] = state
-
- if state in ['user-up', 'unchecked', 'fqdn-up-no-addr', 'fqdn-up'] and session in ['user-enabled']:
- member['state'] = 'present'
- elif state in ['user-down'] and session in ['user-disabled']:
- member['state'] = 'forced_offline'
- elif state in ['up', 'checking'] and session in ['monitor-enabled']:
- member['state'] = 'present'
- elif state in ['down'] and session in ['monitor-enabled']:
- member['state'] = 'offline'
- else:
- member['state'] = 'disabled'
- self._remove_internal_keywords(member)
- member = dict([(k, v) for k, v in iteritems(member) if v is not None])
- result.append(member)
- return result
-
- @property
- def monitors(self):
- if self._values['monitors'] is None:
- return None
- try:
- result = re.findall(r'/[\w-]+/[^\s}]+', self._values['monitors'])
- return result
- except Exception:
- return [self._values['monitors'].strip()]
-
-
-class LtmPoolsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(LtmPoolsFactManager, self).__init__(**kwargs)
- self.want = LtmPoolsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(ltm_pools=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- attrs = resource
- members = self.read_member_from_device(attrs['fullPath'])
- attrs['members'] = members
- attrs['stats'] = self.read_stats_from_device(attrs['fullPath'])
- params = LtmPoolsParameters(params=attrs)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- """Read the LTM pools collection from the device
-
- Note that sub-collection expansion does not work with LTM pools. Therefore,
- one needs to query the ``members`` endpoint separately and add that to the
- list of ``attrs`` before the full set of attributes is sent to the ``Parameters``
- class.
-
- Returns:
- list: List of ``Pool`` objects
- """
- uri = "https://{0}:{1}/mgmt/tm/ltm/pool".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
- def read_member_from_device(self, full_path):
- uri = "https://{0}:{1}/mgmt/tm/ltm/pool/{2}/members".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(name=full_path)
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
- def read_stats_from_device(self, full_path):
- uri = "https://{0}:{1}/mgmt/tm/ltm/pool/{2}/stats".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(name=full_path)
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = parseStats(response)
- try:
- return result['stats']
- except KeyError:
- return {}
-
-
-class LtmPolicyParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'rulesReference': 'rules',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'status',
- 'description',
- 'strategy',
- 'rules',
- 'requires',
- 'controls',
- ]
-
- def _handle_conditions(self, conditions):
- result = []
- if conditions is None or 'items' not in conditions:
- return result
- for condition in conditions['items']:
- tmp = dict()
- tmp['case_insensitive'] = flatten_boolean(condition.pop('caseInsensitive', None))
- tmp['case_sensitive'] = flatten_boolean(condition.pop('caseSensitive', None))
- tmp['contains_string'] = flatten_boolean(condition.pop('contains', None))
- tmp['external'] = flatten_boolean(condition.pop('external', None))
- tmp['http_basic_auth'] = flatten_boolean(condition.pop('httpBasicAuth', None))
- tmp['http_host'] = flatten_boolean(condition.pop('httpHost', None))
- tmp['http_uri'] = flatten_boolean(condition.pop('httpUri', None))
- tmp['request'] = flatten_boolean(condition.pop('request', None))
- tmp['username'] = flatten_boolean(condition.pop('username', None))
- tmp['external'] = flatten_boolean(condition.pop('external', None))
- tmp['values'] = condition.pop('values', None)
- tmp['all'] = flatten_boolean(condition.pop('all', None))
- result.append(self._filter_params(tmp))
- return result
-
- def _handle_actions(self, actions):
- result = []
- if actions is None or 'items' not in actions:
- return result
- for action in actions['items']:
- tmp = dict()
- tmp['httpReply'] = flatten_boolean(action.pop('http_reply', None))
- tmp['redirect'] = flatten_boolean(action.pop('redirect', None))
- tmp['request'] = flatten_boolean(action.pop('request', None))
- tmp['location'] = action.pop('location', None)
- result.append(self._filter_params(tmp))
- return result
-
- @property
- def rules(self):
- result = []
- if self._values['rules'] is None or 'items' not in self._values['rules']:
- return result
- for item in self._values['rules']['items']:
- self._remove_internal_keywords(item)
- item['conditions'] = self._handle_conditions(item.pop('conditionsReference', None))
- item['actions'] = self._handle_actions(item.pop('actionsReference', None))
- result.append(item)
- return result
-
-
-class LtmPolicyFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(LtmPolicyFactManager, self).__init__(**kwargs)
- self.want = LtmPolicyParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(ltm_policies=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = LtmPolicyParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/policy/".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- query = "?expandSubcollections=true"
- resp = self.client.api.get(uri + query)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class NodesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'connectionLimit': 'connection_limit',
- 'dynamicRatio': 'dynamic_ratio',
- 'rateLimit': 'rate_limit',
- 'monitor': 'monitors'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'ratio',
- 'description',
- 'connection_limit',
- 'address',
- 'dynamic_ratio',
- 'rate_limit',
- 'monitor_status',
- 'session_status',
- 'availability_status',
- 'enabled_status',
- 'status_reason',
- 'monitor_rule',
- 'monitors',
- 'monitor_type'
- ]
-
- @property
- def monitors(self):
- if self._values['monitors'] is None:
- return []
- try:
- result = re.findall(r'/\w+/[^\s}]+', self._values['monitors'])
- return result
- except Exception:
- return [self._values['monitors']]
-
- @property
- def monitor_type(self):
- if self._values['monitors'] is None:
- return None
- pattern = r'min\s+\d+\s+of'
- matches = re.search(pattern, self._values['monitors'])
- if matches:
- return 'm_of_n'
- else:
- return 'and_list'
-
- @property
- def rate_limit(self):
- if self._values['rate_limit'] is None:
- return None
- elif self._values['rate_limit'] == 'disabled':
- return 0
- else:
- return int(self._values['rate_limit'])
-
- @property
- def monitor_status(self):
- return self._values['stats']['monitorStatus']
-
- @property
- def session_status(self):
- return self._values['stats']['sessionStatus']
-
- @property
- def availability_status(self):
- return self._values['stats']['status']['availabilityState']
-
- @property
- def enabled_status(self):
- return self._values['stats']['status']['enabledState']
-
- @property
- def status_reason(self):
- return self._values['stats']['status']['statusReason']
-
- @property
- def monitor_rule(self):
- return self._values['stats']['monitorRule']
-
-
-class NodesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(NodesFactManager, self).__init__(**kwargs)
- self.want = NodesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(nodes=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- attrs = resource
- attrs['stats'] = self.read_stats_from_device(attrs['fullPath'])
- params = NodesParameters(params=attrs)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/node".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
- def read_stats_from_device(self, full_path):
- uri = "https://{0}:{1}/mgmt/tm/ltm/node/{2}/stats".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(name=full_path)
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = parseStats(response)
- try:
- return result['stats']
- except KeyError:
- return {}
-
-
-class OneConnectProfilesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'clientTimeout': 'client_timeout',
- 'defaultsFrom': 'parent',
- 'idleTimeoutOverride': 'idle_timeout_override',
- 'limitType': 'limit_type',
- 'maxAge': 'max_age',
- 'maxReuse': 'max_reuse',
- 'maxSize': 'max_size',
- 'sharePools': 'share_pools',
- 'sourceMask': 'source_mask',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'parent',
- 'description',
- 'idle_timeout_override',
- 'limit_type',
- 'max_age',
- 'max_reuse',
- 'max_size',
- 'share_pools',
- 'source_mask',
- ]
-
- @property
- def description(self):
- if self._values['description'] in [None, 'none']:
- return None
- return self._values['description']
-
- @property
- def idle_timeout_override(self):
- if self._values['idle_timeout_override'] is None:
- return None
- elif self._values['idle_timeout_override'] == 'disabled':
- return 0
- elif self._values['idle_timeout_override'] == 'indefinite':
- return 4294967295
- return int(self._values['idle_timeout_override'])
-
- @property
- def share_pools(self):
- return flatten_boolean(self._values['share_pools'])
-
-
-class OneConnectProfilesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(OneConnectProfilesFactManager, self).__init__(**kwargs)
- self.want = OneConnectProfilesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(oneconnect_profiles=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = OneConnectProfilesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/profile/one-connect".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class PartitionParameters(BaseParameters):
- api_map = {
- 'defaultRouteDomain': 'default_route_domain',
- 'fullPath': 'full_path',
- }
-
- returnables = [
- 'name',
- 'full_path',
- 'description',
- 'default_route_domain'
- ]
-
-
-class PartitionFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(PartitionFactManager, self).__init__(**kwargs)
- self.want = PartitionParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(partitions=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = PartitionParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/auth/partition".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class ProvisionInfoParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'cpuRatio': 'cpu_ratio',
- 'diskRatio': 'disk_ratio',
- 'memoryRatio': 'memory_ratio',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'cpu_ratio',
- 'disk_ratio',
- 'memory_ratio',
- 'level'
- ]
-
-
-class ProvisionInfoFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(ProvisionInfoFactManager, self).__init__(**kwargs)
- self.want = ProvisionInfoParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(provision_info=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = ProvisionInfoParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/sys/provision".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class RouteDomainParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'bwcPolicy': 'bandwidth_controller_policy',
- 'connectionLimit': 'connection_limit',
- 'flowEvictionPolicy': 'flow_eviction_policy',
- 'servicePolicy': 'service_policy',
- 'routingProtocol': 'routing_protocol'
- }
-
- returnables = [
- 'name',
- 'id',
- 'full_path',
- 'parent',
- 'bandwidth_controller_policy',
- 'connection_limit',
- 'description',
- 'flow_eviction_policy',
- 'service_policy',
- 'strict',
- 'routing_protocol',
- 'vlans'
- ]
-
- @property
- def strict(self):
- return flatten_boolean(self._values['strict'])
-
- @property
- def connection_limit(self):
- if self._values['connection_limit'] is None:
- return None
- return int(self._values['connection_limit'])
-
-
-class RouteDomainFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(RouteDomainFactManager, self).__init__(**kwargs)
- self.want = RouteDomainParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(route_domains=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = RouteDomainParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/net/route-domain".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class SelfIpsParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'trafficGroup': 'traffic_group',
- 'servicePolicy': 'service_policy',
- 'allowService': 'allow_access_list',
- 'inheritedTrafficGroup': 'traffic_group_inherited'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'address',
- 'description',
- 'netmask',
- 'netmask_cidr',
- 'floating',
- 'traffic_group',
- 'service_policy',
- 'vlan',
- 'allow_access_list',
- 'traffic_group_inherited'
- ]
-
- @property
- def address(self):
- parts = self._values['address'].split('/')
- return parts[0]
-
- @property
- def netmask(self):
- parts = self._values['address'].split('/')
- return to_netmask(parts[1])
-
- @property
- def netmask_cidr(self):
- parts = self._values['address'].split('/')
- return int(parts[1])
-
- @property
- def traffic_group_inherited(self):
- if self._values['traffic_group_inherited'] is None:
- return None
- elif self._values['traffic_group_inherited'] in [False, 'false']:
- # BIG-IP appears to store this as a string. This is a bug, so we handle both
- # cases here.
- return 'no'
- else:
- return 'yes'
-
- @property
- def floating(self):
- if self._values['floating'] is None:
- return None
- elif self._values['floating'] == 'disabled':
- return 'no'
- else:
- return 'yes'
-
-
-class SelfIpsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(SelfIpsFactManager, self).__init__(**kwargs)
- self.want = SelfIpsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(self_ips=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = SelfIpsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/net/self".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class ServerSslProfilesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'alertTimeout': 'alert_timeout',
- 'allowExpiredCrl': 'allow_expired_crl',
- 'authenticate': 'authentication_frequency',
- 'authenticateDepth': 'authenticate_depth',
- 'authenticateName': 'authenticate_name',
- 'bypassOnClientCertFail': 'bypass_on_client_cert_fail',
- 'bypassOnHandshakeAlert': 'bypass_on_handshake_alert',
- 'c3dCaCert': 'c3d_ca_cert',
- 'c3dCaKey': 'c3d_ca_key',
- 'c3dCertExtensionIncludes': 'c3d_cert_extension_includes',
- 'c3dCertLifespan': 'c3d_cert_lifespan',
- 'caFile': 'ca_file',
- 'cacheSize': 'cache_size',
- 'cacheTimeout': 'cache_timeout',
- 'cipherGroup': 'cipher_group',
- 'crlFile': 'crl_file',
- 'expireCertResponseControl': 'expire_cert_response_control',
- 'genericAlert': 'generic_alert',
- 'handshakeTimeout': 'handshake_timeout',
- 'maxActiveHandshakes': 'max_active_handshakes',
- 'modSslMethods': 'mod_ssl_methods',
- 'tmOptions': 'options',
- 'peerCertMode': 'peer_cert_mode',
- 'proxySsl': 'proxy_ssl',
- 'proxySslPassthrough': 'proxy_ssl_passthrough',
- 'renegotiatePeriod': 'renegotiate_period',
- 'renegotiateSize': 'renegotiate_size',
- 'retainCertificate': 'retain_certificate',
- 'secureRenegotiation': 'secure_renegotiation',
- 'serverName': 'server_name',
- 'sessionMirroring': 'session_mirroring',
- 'sessionTicket': 'session_ticket',
- 'sniDefault': 'sni_default',
- 'sniRequire': 'sni_require',
- 'sslC3d': 'ssl_c3d',
- 'sslForwardProxy': 'ssl_forward_proxy_enabled',
- 'sslForwardProxyBypass': 'ssl_forward_proxy_bypass',
- 'sslSignHash': 'ssl_sign_hash',
- 'strictResume': 'strict_resume',
- 'uncleanShutdown': 'unclean_shutdown',
- 'untrustedCertResponseControl': 'untrusted_cert_response_control'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'parent',
- 'description',
- 'unclean_shutdown',
- 'strict_resume',
- 'ssl_forward_proxy_enabled',
- 'ssl_forward_proxy_bypass',
- 'sni_default',
- 'sni_require',
- 'ssl_c3d',
- 'session_mirroring',
- 'session_ticket',
- 'mod_ssl_methods',
- 'allow_expired_crl',
- 'retain_certificate',
- 'mode',
- 'bypass_on_client_cert_fail',
- 'bypass_on_handshake_alert',
- 'generic_alert',
- 'renegotiation',
- 'proxy_ssl',
- 'proxy_ssl_passthrough',
- 'peer_cert_mode',
- 'untrusted_cert_response_control',
- 'ssl_sign_hash',
- 'server_name',
- 'secure_renegotiation',
- 'renegotiate_size',
- 'renegotiate_period',
- 'options',
- 'ocsp',
- 'max_active_handshakes',
- 'key',
- 'handshake_timeout',
- 'expire_cert_response_control',
- 'cert',
- 'chain',
- 'authentication_frequency',
- 'ciphers',
- 'cipher_group',
- 'crl_file',
- 'cache_timeout',
- 'cache_size',
- 'ca_file',
- 'c3d_cert_lifespan',
- 'alert_timeout',
- 'c3d_ca_key',
- 'authenticate_depth',
- 'authenticate_name',
- 'c3d_ca_cert',
- 'c3d_cert_extension_includes',
- ]
-
- @property
- def c3d_cert_extension_includes(self):
- if self._values['c3d_cert_extension_includes'] is None:
- return None
- if len(self._values['c3d_cert_extension_includes']) == 0:
- return None
- self._values['c3d_cert_extension_includes'].sort()
- return self._values['c3d_cert_extension_includes']
-
- @property
- def options(self):
- if self._values['options'] is None:
- return None
- if len(self._values['options']) == 0:
- return None
- self._values['options'].sort()
- return self._values['options']
-
- @property
- def c3d_ca_cert(self):
- if self._values['c3d_ca_cert'] in [None, 'none']:
- return None
- return self._values['c3d_ca_cert']
-
- @property
- def ocsp(self):
- if self._values['ocsp'] in [None, 'none']:
- return None
- return self._values['ocsp']
-
- @property
- def server_name(self):
- if self._values['server_name'] in [None, 'none']:
- return None
- return self._values['server_name']
-
- @property
- def cipher_group(self):
- if self._values['cipher_group'] in [None, 'none']:
- return None
- return self._values['cipher_group']
-
- @property
- def authenticate_name(self):
- if self._values['authenticate_name'] in [None, 'none']:
- return None
- return self._values['authenticate_name']
-
- @property
- def c3d_ca_key(self):
- if self._values['c3d_ca_key'] in [None, 'none']:
- return None
- return self._values['c3d_ca_key']
-
- @property
- def ca_file(self):
- if self._values['ca_file'] in [None, 'none']:
- return None
- return self._values['ca_file']
-
- @property
- def crl_file(self):
- if self._values['crl_file'] in [None, 'none']:
- return None
- return self._values['crl_file']
-
- @property
- def authentication_frequency(self):
- if self._values['authentication_frequency'] in [None, 'none']:
- return None
- return self._values['authentication_frequency']
-
- @property
- def description(self):
- if self._values['description'] in [None, 'none']:
- return None
- return self._values['description']
-
- @property
- def proxy_ssl_passthrough(self):
- return flatten_boolean(self._values['proxy_ssl_passthrough'])
-
- @property
- def proxy_ssl(self):
- return flatten_boolean(self._values['proxy_ssl'])
-
- @property
- def generic_alert(self):
- return flatten_boolean(self._values['generic_alert'])
-
- @property
- def renegotiation(self):
- return flatten_boolean(self._values['renegotiation'])
-
- @property
- def bypass_on_handshake_alert(self):
- return flatten_boolean(self._values['bypass_on_handshake_alert'])
-
- @property
- def bypass_on_client_cert_fail(self):
- return flatten_boolean(self._values['bypass_on_client_cert_fail'])
-
- @property
- def mode(self):
- return flatten_boolean(self._values['mode'])
-
- @property
- def retain_certificate(self):
- return flatten_boolean(self._values['retain_certificate'])
-
- @property
- def allow_expired_crl(self):
- return flatten_boolean(self._values['allow_expired_crl'])
-
- @property
- def mod_ssl_methods(self):
- return flatten_boolean(self._values['mod_ssl_methods'])
-
- @property
- def session_ticket(self):
- return flatten_boolean(self._values['session_ticket'])
-
- @property
- def session_mirroring(self):
- return flatten_boolean(self._values['session_mirroring'])
-
- @property
- def unclean_shutdown(self):
- return flatten_boolean(self._values['unclean_shutdown'])
-
- @property
- def strict_resume(self):
- return flatten_boolean(self._values['strict_resume'])
-
- @property
- def ssl_forward_proxy_enabled(self):
- return flatten_boolean(self._values['ssl_forward_proxy_enabled'])
-
- @property
- def ssl_forward_proxy_bypass(self):
- return flatten_boolean(self._values['ssl_forward_proxy_bypass'])
-
- @property
- def sni_default(self):
- return flatten_boolean(self._values['sni_default'])
-
- @property
- def sni_require(self):
- return flatten_boolean(self._values['sni_require'])
-
- @property
- def ssl_c3d(self):
- return flatten_boolean(self._values['ssl_c3d'])
-
-
-class ServerSslProfilesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(ServerSslProfilesFactManager, self).__init__(**kwargs)
- self.want = ServerSslProfilesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(server_ssl_profiles=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = ServerSslProfilesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/profile/server-ssl".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class SoftwareVolumesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'basebuild': 'base_build',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'active',
- 'base_build',
- 'build',
- 'product',
- 'status',
- 'version',
- 'install_volume',
- 'default_boot_location'
- ]
-
- @property
- def install_volume(self):
- if self._values['media'] is None:
- return None
- return self._values['media'].get('name', None)
-
- @property
- def default_boot_location(self):
- if self._values['media'] is None:
- return None
- return flatten_boolean(self._values['media'].get('defaultBootLocation', None))
-
- @property
- def active(self):
- if self._values['active'] is True:
- return 'yes'
- return 'no'
-
-
-class SoftwareVolumesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(SoftwareVolumesFactManager, self).__init__(**kwargs)
- self.want = SoftwareVolumesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(software_volumes=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = SoftwareVolumesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/sys/software/volume".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class SoftwareHotfixesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- }
-
- returnables = [
- 'name',
- 'full_path',
- 'build',
- 'checksum',
- 'id',
- 'product',
- 'title',
- 'verified',
- 'version',
- ]
-
-
-class SoftwareHotfixesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(SoftwareHotfixesFactManager, self).__init__(**kwargs)
- self.want = SoftwareHotfixesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(software_hotfixes=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = SoftwareHotfixesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/sys/software/hotfix".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class SoftwareImagesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'buildDate': 'build_date',
- 'fileSize': 'file_size',
- 'lastModified': 'last_modified',
- }
-
- returnables = [
- 'name',
- 'full_path',
- 'build',
- 'build_date',
- 'checksum',
- 'file_size',
- 'last_modified',
- 'product',
- 'verified',
- 'version',
- ]
-
- @property
- def file_size(self):
- if self._values['file_size'] is None:
- return None
- matches = re.match(r'\d+', self._values['file_size'])
- if matches:
- return int(matches.group(0))
-
- @property
- def build_date(self):
- """Normalizes the build_date string
-
- The ISOs usually ship with a broken format
-
- ex: Tue May 15 15 26 30 PDT 2018
-
- This will re-format that time so that it looks like ISO 8601 without
- microseconds
-
- ex: 2018-05-15T15:26:30
-
- :return:
- """
- if self._values['build_date'] is None:
- return None
-
- d = self._values['build_date'].split(' ')
-
- # This removes the timezone portion from the string. This is done
- # because Python has awfule tz parsing and strptime doesnt work with
- # all timezones in %Z; it only uses the timezones found in time.tzname
- d.pop(6)
-
- result = datetime.datetime.strptime(' '.join(d), '%a %b %d %H %M %S %Y').isoformat()
- return result
-
- @property
- def last_modified(self):
- """Normalizes the last_modified string
-
- The strings that the system reports look like the following
-
- ex: Tue May 15 15:26:30 2018
-
- This property normalizes this value to be isoformat
-
- ex: 2018-05-15T15:26:30
-
- :return:
- """
- if self._values['last_modified'] is None:
- return None
- result = datetime.datetime.strptime(self._values['last_modified'], '%a %b %d %H:%M:%S %Y').isoformat()
- return result
-
-
-class SoftwareImagesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(SoftwareImagesFactManager, self).__init__(**kwargs)
- self.want = SoftwareImagesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(software_images=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = SoftwareImagesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/sys/software/image".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class SslCertificatesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'keyType': 'key_type',
- 'certificateKeySize': 'key_size',
- 'systemPath': 'system_path',
- 'checksum': 'sha1_checksum',
- 'lastUpdateTime': 'last_update_time',
- 'isBundle': 'is_bundle',
- 'expirationString': 'expiration_date',
- 'expirationDate': 'expiration_timestamp',
- 'createTime': 'create_time'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'key_type',
- 'key_size',
- 'system_path',
- 'sha1_checksum',
- 'subject',
- 'last_update_time',
- 'issuer',
- 'is_bundle',
- 'fingerprint',
- 'expiration_date',
- 'expiration_timestamp',
- 'create_time',
- ]
-
- @property
- def sha1_checksum(self):
- if self._values['sha1_checksum'] is None:
- return None
- parts = self._values['sha1_checksum'].split(':')
- return parts[2]
-
- @property
- def is_bundle(self):
- if self._values['sha1_checksum'] is None:
- return None
- if self._values['is_bundle'] in BOOLEANS_TRUE:
- return 'yes'
- return 'no'
-
-
-class SslCertificatesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(SslCertificatesFactManager, self).__init__(**kwargs)
- self.want = SslCertificatesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(ssl_certs=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = SslCertificatesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/sys/file/ssl-cert".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class SslKeysParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'keyType': 'key_type',
- 'keySize': 'key_size',
- 'securityType': 'security_type',
- 'systemPath': 'system_path',
- 'checksum': 'sha1_checksum'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'key_type',
- 'key_size',
- 'security_type',
- 'system_path',
- 'sha1_checksum'
- ]
-
- @property
- def sha1_checksum(self):
- if self._values['sha1_checksum'] is None:
- return None
- parts = self._values['sha1_checksum'].split(':')
- return parts[2]
-
-
-class SslKeysFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(SslKeysFactManager, self).__init__(**kwargs)
- self.want = SslKeysParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(ssl_keys=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = SslKeysParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/sys/file/ssl-key".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class SystemDbParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'defaultValue': 'default',
- 'scfConfig': 'scf_config',
- 'valueRange': 'value_range'
- }
-
- returnables = [
- 'name',
- 'full_path',
- 'default',
- 'scf_config',
- 'value',
- 'value_range'
- ]
-
-
-class SystemDbFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(SystemDbFactManager, self).__init__(**kwargs)
- self.want = SystemInfoParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(system_db=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = SystemDbParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/sys/db".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class SystemInfoParameters(BaseParameters):
- api_map = {
-
- }
-
- returnables = [
- 'base_mac_address',
- 'marketing_name',
- 'time',
- 'hardware_information',
- 'product_information',
- 'package_edition',
- 'package_version',
- 'product_code',
- 'product_build',
- 'product_built',
- 'product_build_date',
- 'product_changelist',
- 'product_jobid',
- 'product_version',
- 'uptime',
- 'chassis_serial',
- 'host_board_part_revision',
- 'host_board_serial',
- 'platform',
- 'switch_board_part_revision',
- 'switch_board_serial'
- ]
-
- @property
- def chassis_serial(self):
- if self._values['system-info'] is None:
- return None
- if 'bigipChassisSerialNum' not in self._values['system-info'][0]:
- return None
- return self._values['system-info'][0]['bigipChassisSerialNum']
-
- @property
- def switch_board_serial(self):
- if self._values['system-info'] is None:
- return None
- if 'switchBoardSerialNum' not in self._values['system-info'][0]:
- return None
- if self._values['system-info'][0]['switchBoardSerialNum'].strip() == '':
- return None
- return self._values['system-info'][0]['switchBoardSerialNum']
-
- @property
- def switch_board_part_revision(self):
- if self._values['system-info'] is None:
- return None
- if 'switchBoardPartRevNum' not in self._values['system-info'][0]:
- return None
- if self._values['system-info'][0]['switchBoardPartRevNum'].strip() == '':
- return None
- return self._values['system-info'][0]['switchBoardPartRevNum']
-
- @property
- def platform(self):
- if self._values['system-info'] is None:
- return None
- return self._values['system-info'][0]['platform']
-
- @property
- def host_board_serial(self):
- if self._values['system-info'] is None:
- return None
- if 'hostBoardSerialNum' not in self._values['system-info'][0]:
- return None
- if self._values['system-info'][0]['hostBoardSerialNum'].strip() == '':
- return None
- return self._values['system-info'][0]['hostBoardSerialNum']
-
- @property
- def host_board_part_revision(self):
- if self._values['system-info'] is None:
- return None
- if 'hostBoardPartRevNum' not in self._values['system-info'][0]:
- return None
- if self._values['system-info'][0]['hostBoardPartRevNum'].strip() == '':
- return None
- return self._values['system-info'][0]['hostBoardPartRevNum']
-
- @property
- def package_edition(self):
- return self._values['Edition']
-
- @property
- def package_version(self):
- return 'Build {0} - {1}'.format(self._values['Build'], self._values['Date'])
-
- @property
- def product_build(self):
- return self._values['Build']
-
- @property
- def product_build_date(self):
- return self._values['Date']
-
- @property
- def product_built(self):
- if 'Built' in self._values['version_info']:
- return int(self._values['version_info']['Built'])
-
- @property
- def product_changelist(self):
- if 'Changelist' in self._values['version_info']:
- return int(self._values['version_info']['Changelist'])
-
- @property
- def product_jobid(self):
- if 'JobID' in self._values['version_info']:
- return int(self._values['version_info']['JobID'])
-
- @property
- def product_code(self):
- return self._values['Product']
-
- @property
- def product_version(self):
- return self._values['Version']
-
- @property
- def hardware_information(self):
- if self._values['hardware-version'] is None:
- return None
- self._transform_name_attribute(self._values['hardware-version'])
- result = [v for k, v in iteritems(self._values['hardware-version'])]
- return result
-
- def _transform_name_attribute(self, entry):
- if isinstance(entry, dict):
- for k, v in iteritems(entry):
- if k == 'tmName':
- entry['name'] = entry.pop('tmName')
- self._transform_name_attribute(v)
- elif isinstance(entry, list):
- for k in entry:
- if k == 'tmName':
- entry['name'] = entry.pop('tmName')
- self._transform_name_attribute(k)
- else:
- return
-
- @property
- def time(self):
- if self._values['fullDate'] is None:
- return None
- date = datetime.datetime.strptime(self._values['fullDate'], "%Y-%m-%dT%H:%M:%SZ")
- result = dict(
- day=date.day,
- hour=date.hour,
- minute=date.minute,
- month=date.month,
- second=date.second,
- year=date.year
- )
- return result
-
- @property
- def marketing_name(self):
- if self._values['platform'] is None:
- return None
- return self._values['platform'][0]['marketingName']
-
- @property
- def base_mac_address(self):
- if self._values['platform'] is None:
- return None
- return self._values['platform'][0]['baseMac']
-
-
-class SystemInfoFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(SystemInfoFactManager, self).__init__(**kwargs)
- self.want = SystemInfoParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(system_info=facts)
- return result
-
- def _exec_module(self):
- facts = self.read_facts()
- results = facts.to_return()
- return results
-
- def read_facts(self):
- collection = self.read_collection_from_device()
- params = SystemInfoParameters(params=collection)
- return params
-
- def read_collection_from_device(self):
- result = dict()
- tmp = self.read_hardware_info_from_device()
- if tmp:
- result.update(tmp)
-
- tmp = self.read_clock_info_from_device()
- if tmp:
- result.update(tmp)
-
- tmp = self.read_version_info_from_device()
- if tmp:
- result.update(tmp)
-
- tmp = self.read_uptime_info_from_device()
- if tmp:
- result.update(tmp)
-
- tmp = self.read_version_file_info_from_device()
- if tmp:
- result.update(tmp)
-
- return result
-
- def read_version_file_info_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/util/bash".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- args = dict(
- command='run',
- utilCmdArgs='-c "cat /VERSION"'
- )
- resp = self.client.api.post(uri, json=args)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- try:
- pattern = r'^(?P(Product|Build|Sequence|BaseBuild|Edition|Date|Built|Changelist|JobID))\:(?P.*)'
- result = response['commandResult'].strip()
- except KeyError:
- return None
-
- if 'No such file or directory' in result:
- return None
-
- lines = response['commandResult'].split("\n")
- result = dict()
- for line in lines:
- if not line:
- continue
- matches = re.match(pattern, line)
- if matches:
- result[matches.group('key')] = matches.group('value').strip()
-
- if result:
- return dict(
- version_info=result
- )
-
- def read_uptime_info_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/util/bash".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- args = dict(
- command='run',
- utilCmdArgs='-c "cat /proc/uptime"'
- )
- resp = self.client.api.post(uri, json=args)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- try:
- parts = response['commandResult'].strip().split(' ')
- return dict(
- uptime=math.floor(float(parts[0]))
- )
- except KeyError:
- pass
-
- def read_hardware_info_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/sys/hardware".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = parseStats(response)
- return result
-
- def read_clock_info_from_device(self):
- """Parses clock info from the REST API
-
- The clock stat returned from the REST API (at the time of 13.1.0.7)
- is similar to the following.
-
- {
- "kind": "tm:sys:clock:clockstats",
- "selfLink": "https://localhost/mgmt/tm/sys/clock?ver=13.1.0.4",
- "entries": {
- "https://localhost/mgmt/tm/sys/clock/0": {
- "nestedStats": {
- "entries": {
- "fullDate": {
- "description": "2018-06-05T13:38:33Z"
- }
- }
- }
- }
- }
- }
-
- Parsing this data using the ``parseStats`` method, yields a list of
- the clock stats in a format resembling that below.
-
- [{'fullDate': '2018-06-05T13:41:05Z'}]
-
- Therefore, this method cherry-picks the first entry from this list
- and returns it. There can be no other items in this list.
-
- Returns:
- A dict mapping keys to the corresponding clock stats. For
- example:
-
- {'fullDate': '2018-06-05T13:41:05Z'}
-
- There should never not be a clock stat, unless by chance it
- is removed from the API in the future, or changed to a different
- API endpoint.
-
- Raises:
- F5ModuleError: A non-successful HTTP code was returned or a JSON
- response was not found.
- """
- uri = "https://{0}:{1}/mgmt/tm/sys/clock".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = parseStats(response)
- return result[0]
-
- def read_version_info_from_device(self):
- """Parses version info from the REST API
-
- The version stat returned from the REST API (at the time of 13.1.0.7)
- is similar to the following.
-
- {
- "kind": "tm:sys:version:versionstats",
- "selfLink": "https://localhost/mgmt/tm/sys/version?ver=13.1.0.4",
- "entries": {
- "https://localhost/mgmt/tm/sys/version/0": {
- "nestedStats": {
- "entries": {
- "Build": {
- "description": "0.0.6"
- },
- "Date": {
- "description": "Tue Mar 13 20:10:42 PDT 2018"
- },
- "Edition": {
- "description": "Point Release 4"
- },
- "Product": {
- "description": "BIG-IP"
- },
- "Title": {
- "description": "Main Package"
- },
- "Version": {
- "description": "13.1.0.4"
- }
- }
- }
- }
- }
- }
-
- Parsing this data using the ``parseStats`` method, yields a list of
- the clock stats in a format resembling that below.
-
- [{'Build': '0.0.6', 'Date': 'Tue Mar 13 20:10:42 PDT 2018',
- 'Edition': 'Point Release 4', 'Product': 'BIG-IP', 'Title': 'Main Package',
- 'Version': '13.1.0.4'}]
-
- Therefore, this method cherry-picks the first entry from this list
- and returns it. There can be no other items in this list.
-
- Returns:
- A dict mapping keys to the corresponding clock stats. For
- example:
-
- {'Build': '0.0.6', 'Date': 'Tue Mar 13 20:10:42 PDT 2018',
- 'Edition': 'Point Release 4', 'Product': 'BIG-IP', 'Title': 'Main Package',
- 'Version': '13.1.0.4'}
-
- There should never not be a version stat, unless by chance it
- is removed from the API in the future, or changed to a different
- API endpoint.
-
- Raises:
- F5ModuleError: A non-successful HTTP code was returned or a JSON
- response was not found.
- """
- uri = "https://{0}:{1}/mgmt/tm/sys/version".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = parseStats(response)
- return result[0]
-
-
-class TcpMonitorsParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'defaultsFrom': 'parent',
- 'adaptiveDivergenceType': 'adaptive_divergence_type',
- 'adaptiveDivergenceValue': 'adaptive_divergence_value',
- 'adaptiveLimit': 'adaptive_limit',
- 'adaptiveSamplingTimespan': 'adaptive_sampling_timespan',
- 'ipDscp': 'ip_dscp',
- 'manualResume': 'manual_resume',
- 'timeUntilUp': 'time_until_up',
- 'upInterval': 'up_interval',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'parent',
- 'description',
- 'adaptive',
- 'adaptive_divergence_type',
- 'adaptive_divergence_value',
- 'adaptive_limit',
- 'adaptive_sampling_timespan',
- 'destination',
- 'interval',
- 'ip_dscp',
- 'manual_resume',
- 'reverse',
- 'time_until_up',
- 'timeout',
- 'transparent',
- 'up_interval',
- ]
-
- @property
- def description(self):
- if self._values['description'] in [None, 'none']:
- return None
- return self._values['description']
-
- @property
- def transparent(self):
- return flatten_boolean(self._values['transparent'])
-
- @property
- def manual_resume(self):
- return flatten_boolean(self._values['manual_resume'])
-
- @property
- def adaptive(self):
- return flatten_boolean(self._values['adaptive'])
-
- @property
- def reverse(self):
- return flatten_boolean(self._values['reverse'])
-
-
-class TcpMonitorsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(TcpMonitorsFactManager, self).__init__(**kwargs)
- self.want = TcpMonitorsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(tcp_monitors=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = TcpMonitorsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class TcpHalfOpenMonitorsParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'defaultsFrom': 'parent',
- 'manualResume': 'manual_resume',
- 'timeUntilUp': 'time_until_up',
- 'upInterval': 'up_interval',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'parent',
- 'description',
- 'destination',
- 'interval',
- 'manual_resume',
- 'time_until_up',
- 'timeout',
- 'transparent',
- 'up_interval',
- ]
-
- @property
- def description(self):
- if self._values['description'] in [None, 'none']:
- return None
- return self._values['description']
-
- @property
- def transparent(self):
- return flatten_boolean(self._values['transparent'])
-
- @property
- def manual_resume(self):
- return flatten_boolean(self._values['manual_resume'])
-
-
-class TcpHalfOpenMonitorsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(TcpHalfOpenMonitorsFactManager, self).__init__(**kwargs)
- self.want = TcpHalfOpenMonitorsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(tcp_half_open_monitors=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = TcpHalfOpenMonitorsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp-half-open".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class TcpProfilesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'defaultsFrom': 'parent',
- 'ackOnPush': 'ack_on_push',
- 'autoProxyBufferSize': 'auto_proxy_buffer',
- 'autoReceiveWindowSize': 'auto_receive_window',
- 'autoSendBufferSize': 'auto_send_buffer',
- 'closeWaitTimeout': 'close_wait',
- 'cmetricsCache': 'congestion_metrics_cache',
- 'cmetricsCacheTimeout': 'congestion_metrics_cache_timeout',
- 'congestionControl': 'congestion_control',
- 'deferredAccept': 'deferred_accept',
- 'delayWindowControl': 'delay_window_control',
- 'delayedAcks': 'delayed_acks',
- 'earlyRetransmit': 'early_retransmit',
- 'ecn': 'explicit_congestion_notification',
- 'enhancedLossRecovery': 'enhanced_loss_recovery',
- 'fastOpen': 'fast_open',
- 'fastOpenCookieExpiration': 'fast_open_cookie_expiration',
- 'finWaitTimeout': 'fin_wait_1',
- 'finWait_2Timeout': 'fin_wait_2',
- 'idleTimeout': 'idle_timeout',
- 'initCwnd': 'initial_congestion_window_size',
- 'initRwnd': 'initial_receive_window_size',
- 'ipDfMode': 'dont_fragment_flag',
- 'ipTosToClient': 'ip_tos',
- 'ipTtlMode': 'time_to_live',
- 'ipTtlV4': 'time_to_live_v4',
- 'ipTtlV6': 'time_to_live_v6',
- 'keepAliveInterval': 'keep_alive_interval',
- 'limitedTransmit': 'limited_transmit_recovery',
- 'linkQosToClient': 'link_qos',
- 'maxRetrans': 'max_segment_retrans',
- 'synMaxRetrans': 'max_syn_retrans',
- 'rexmtThresh': 'retransmit_threshold',
- 'maxSegmentSize': 'max_segment_size',
- 'md5Signature': 'md5_signature',
- 'minimumRto': 'minimum_rto',
- 'mptcp': 'multipath_tcp',
- 'mptcpCsum': 'mptcp_checksum',
- 'mptcpCsumVerify': 'mptcp_checksum_verify',
- 'mptcpFallback': 'mptcp_fallback',
- 'mptcpFastjoin': 'mptcp_fast_join',
- 'mptcpIdleTimeout': 'mptcp_idle_timeout',
- 'mptcpJoinMax': 'mptcp_join_max',
- 'mptcpMakeafterbreak': 'mptcp_make_after_break',
- 'mptcpNojoindssack': 'mptcp_no_join_dss_ack',
- 'mptcpRtomax': 'mptcp_rto_max',
- 'mptcpRxmitmin': 'mptcp_retransmit_min',
- 'mptcpSubflowmax': 'mptcp_subflow_max',
- 'mptcpTimeout': 'mptcp_timeout',
- 'nagle': 'nagle_algorithm',
- 'pktLossIgnoreBurst': 'pkt_loss_ignore_burst',
- 'pktLossIgnoreRate': 'pkt_loss_ignore_rate',
- 'proxyBufferHigh': 'proxy_buffer_high',
- 'proxyBufferLow': 'proxy_buffer_low',
- 'proxyMss': 'proxy_max_segment',
- 'proxyOptions': 'proxy_options',
- 'pushFlag': 'push_flag',
- 'ratePace': 'rate_pace',
- 'ratePaceMaxRate': 'rate_pace_max_rate',
- 'receiveWindowSize': 'receive_window',
- 'resetOnTimeout': 'reset_on_timeout',
- 'selectiveAcks': 'selective_acks',
- 'selectiveNack': 'selective_nack',
- 'sendBufferSize': 'send_buffer',
- 'slowStart': 'slow_start',
- 'synCookieEnable': 'syn_cookie_enable',
- 'synCookieWhitelist': 'syn_cookie_white_list',
- 'synRtoBase': 'syn_retrans_to_base',
- 'tailLossProbe': 'tail_loss_probe',
- 'timeWaitRecycle': 'time_wait_recycle',
- 'timeWaitTimeout': 'time_wait',
- 'verifiedAccept': 'verified_accept',
- 'zeroWindowTimeout': 'zero_window_timeout',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'parent',
- 'description',
- 'abc',
- 'ack_on_push',
- 'auto_proxy_buffer',
- 'auto_receive_window',
- 'auto_send_buffer',
- 'close_wait',
- 'congestion_metrics_cache',
- 'congestion_metrics_cache_timeout',
- 'congestion_control',
- 'deferred_accept',
- 'delay_window_control',
- 'delayed_acks',
- 'dsack',
- 'early_retransmit',
- 'explicit_congestion_notification',
- 'enhanced_loss_recovery',
- 'fast_open',
- 'fast_open_cookie_expiration',
- 'fin_wait_1',
- 'fin_wait_2',
- 'idle_timeout',
- 'initial_congestion_window_size',
- 'initial_receive_window_size',
- 'dont_fragment_flag',
- 'ip_tos',
- 'time_to_live',
- 'time_to_live_v4',
- 'time_to_live_v6',
- 'keep_alive_interval',
- 'limited_transmit_recovery',
- 'link_qos',
- 'max_segment_retrans',
- 'max_syn_retrans',
- 'max_segment_size',
- 'md5_signature',
- 'minimum_rto',
- 'multipath_tcp',
- 'mptcp_checksum',
- 'mptcp_checksum_verify',
- 'mptcp_fallback',
- 'mptcp_fast_join',
- 'mptcp_idle_timeout',
- 'mptcp_join_max',
- 'mptcp_make_after_break',
- 'mptcp_no_join_dss_ack',
- 'mptcp_rto_max',
- 'mptcp_retransmit_min',
- 'mptcp_subflow_max',
- 'mptcp_timeout',
- 'nagle_algorithm',
- 'pkt_loss_ignore_burst',
- 'pkt_loss_ignore_rate',
- 'proxy_buffer_high',
- 'proxy_buffer_low',
- 'proxy_max_segment',
- 'proxy_options',
- 'push_flag',
- 'rate_pace',
- 'rate_pace_max_rate',
- 'receive_window',
- 'reset_on_timeout',
- 'retransmit_threshold',
- 'selective_acks',
- 'selective_nack',
- 'send_buffer',
- 'slow_start',
- 'syn_cookie_enable',
- 'syn_cookie_white_list',
- 'syn_retrans_to_base',
- 'tail_loss_probe',
- 'time_wait_recycle',
- 'time_wait',
- 'timestamps',
- 'verified_accept',
- 'zero_window_timeout',
- ]
-
- @property
- def description(self):
- if self._values['description'] in [None, 'none']:
- return None
- return self._values['description']
-
- @property
- def time_wait(self):
- if self._values['time_wait'] is None:
- return None
- if self._values['time_wait'] == 0:
- return "immediate"
- if self._values['time_wait'] == 4294967295:
- return 'indefinite'
- return self._values['time_wait']
-
- @property
- def close_wait(self):
- if self._values['close_wait'] is None:
- return None
- if self._values['close_wait'] == 0:
- return "immediate"
- if self._values['close_wait'] == 4294967295:
- return 'indefinite'
- return self._values['close_wait']
-
- @property
- def fin_wait_1(self):
- if self._values['fin_wait_1'] is None:
- return None
- if self._values['fin_wait_1'] == 0:
- return "immediate"
- if self._values['fin_wait_1'] == 4294967295:
- return 'indefinite'
- return self._values['fin_wait_1']
-
- @property
- def fin_wait_2(self):
- if self._values['fin_wait_2'] is None:
- return None
- if self._values['fin_wait_2'] == 0:
- return "immediate"
- if self._values['fin_wait_2'] == 4294967295:
- return 'indefinite'
- return self._values['fin_wait_2']
-
- @property
- def zero_window_timeout(self):
- if self._values['zero_window_timeout'] is None:
- return None
- if self._values['zero_window_timeout'] == 4294967295:
- return 'indefinite'
- return self._values['zero_window_timeout']
-
- @property
- def idle_timeout(self):
- if self._values['idle_timeout'] is None:
- return None
- if self._values['idle_timeout'] == 4294967295:
- return 'indefinite'
- return self._values['idle_timeout']
-
- @property
- def keep_alive_interval(self):
- if self._values['keep_alive_interval'] is None:
- return None
- if self._values['keep_alive_interval'] == 4294967295:
- return 'indefinite'
- return self._values['keep_alive_interval']
-
- @property
- def verified_accept(self):
- return flatten_boolean(self._values['verified_accept'])
-
- @property
- def timestamps(self):
- return flatten_boolean(self._values['timestamps'])
-
- @property
- def time_wait_recycle(self):
- return flatten_boolean(self._values['time_wait_recycle'])
-
- @property
- def tail_loss_probe(self):
- return flatten_boolean(self._values['tail_loss_probe'])
-
- @property
- def syn_cookie_white_list(self):
- return flatten_boolean(self._values['syn_cookie_white_list'])
-
- @property
- def syn_cookie_enable(self):
- return flatten_boolean(self._values['syn_cookie_enable'])
-
- @property
- def slow_start(self):
- return flatten_boolean(self._values['slow_start'])
-
- @property
- def selective_nack(self):
- return flatten_boolean(self._values['selective_nack'])
-
- @property
- def selective_acks(self):
- return flatten_boolean(self._values['selective_acks'])
-
- @property
- def reset_on_timeout(self):
- return flatten_boolean(self._values['reset_on_timeout'])
-
- @property
- def rate_pace(self):
- return flatten_boolean(self._values['rate_pace'])
-
- @property
- def proxy_options(self):
- return flatten_boolean(self._values['proxy_options'])
-
- @property
- def proxy_max_segment(self):
- return flatten_boolean(self._values['proxy_max_segment'])
-
- @property
- def nagle_algorithm(self):
- return flatten_boolean(self._values['nagle_algorithm'])
-
- @property
- def mptcp_no_join_dss_ack(self):
- return flatten_boolean(self._values['mptcp_no_join_dss_ack'])
-
- @property
- def mptcp_make_after_break(self):
- return flatten_boolean(self._values['mptcp_make_after_break'])
-
- @property
- def mptcp_fast_join(self):
- return flatten_boolean(self._values['mptcp_fast_join'])
-
- @property
- def mptcp_checksum_verify(self):
- return flatten_boolean(self._values['mptcp_checksum_verify'])
-
- @property
- def mptcp_checksum(self):
- return flatten_boolean(self._values['mptcp_checksum'])
-
- @property
- def multipath_tcp(self):
- return flatten_boolean(self._values['multipath_tcp'])
-
- @property
- def md5_signature(self):
- return flatten_boolean(self._values['md5_signature'])
-
- @property
- def limited_transmit_recovery(self):
- return flatten_boolean(self._values['limited_transmit_recovery'])
-
- @property
- def fast_open(self):
- return flatten_boolean(self._values['fast_open'])
-
- @property
- def enhanced_loss_recovery(self):
- return flatten_boolean(self._values['enhanced_loss_recovery'])
-
- @property
- def explicit_congestion_notification(self):
- return flatten_boolean(self._values['explicit_congestion_notification'])
-
- @property
- def early_retransmit(self):
- return flatten_boolean(self._values['early_retransmit'])
-
- @property
- def dsack(self):
- return flatten_boolean(self._values['dsack'])
-
- @property
- def delayed_acks(self):
- return flatten_boolean(self._values['delayed_acks'])
-
- @property
- def delay_window_control(self):
- return flatten_boolean(self._values['delay_window_control'])
-
- @property
- def deferred_accept(self):
- return flatten_boolean(self._values['deferred_accept'])
-
- @property
- def congestion_metrics_cache(self):
- return flatten_boolean(self._values['congestion_metrics_cache'])
-
- @property
- def auto_send_buffer(self):
- return flatten_boolean(self._values['auto_send_buffer'])
-
- @property
- def auto_receive_window(self):
- return flatten_boolean(self._values['auto_receive_window'])
-
- @property
- def auto_proxy_buffer(self):
- return flatten_boolean(self._values['auto_proxy_buffer'])
-
- @property
- def abc(self):
- return flatten_boolean(self._values['abc'])
-
- @property
- def ack_on_push(self):
- return flatten_boolean(self._values['ack_on_push'])
-
-
-class TcpProfilesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(TcpProfilesFactManager, self).__init__(**kwargs)
- self.want = TcpProfilesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(tcp_profiles=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = TcpProfilesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/profile/tcp".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class TrafficGroupsParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'autoFailbackEnabled': 'auto_failback_enabled',
- 'autoFailbackTime': 'auto_failback_time',
- 'haLoadFactor': 'ha_load_factor',
- 'haOrder': 'ha_order',
- 'isFloating': 'is_floating',
- 'mac': 'mac_masquerade_address'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'description',
- 'auto_failback_enabled',
- 'auto_failback_time',
- 'ha_load_factor',
- 'ha_order',
- 'is_floating',
- 'mac_masquerade_address'
- ]
-
- @property
- def auto_failback_time(self):
- if self._values['auto_failback_time'] is None:
- return None
- return int(self._values['auto_failback_time'])
-
- @property
- def auto_failback_enabled(self):
- if self._values['auto_failback_enabled'] is None:
- return None
- elif self._values['auto_failback_enabled'] == 'false':
- # Yes, the REST API stores this as a string
- return 'no'
- return 'yes'
-
- @property
- def is_floating(self):
- if self._values['is_floating'] is None:
- return None
- elif self._values['is_floating'] == 'true':
- # Yes, the REST API stores this as a string
- return 'yes'
- return 'no'
-
- @property
- def mac_masquerade_address(self):
- if self._values['mac_masquerade_address'] in [None, 'none']:
- return None
- return self._values['mac_masquerade_address']
-
-
-class TrafficGroupsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(TrafficGroupsFactManager, self).__init__(**kwargs)
- self.want = TrafficGroupsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(traffic_groups=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- attrs = resource
- attrs['stats'] = self.read_stats_from_device(attrs['fullPath'])
- params = TrafficGroupsParameters(params=attrs)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/cm/traffic-group".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
- def read_stats_from_device(self, full_path):
- uri = "https://{0}:{1}/mgmt/tm/cm/traffic-group/{2}/stats".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(name=full_path)
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = parseStats(response)
- try:
- return result['stats']
- except KeyError:
- return {}
-
-
-class TrunksParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'media': 'media_speed',
- 'lacpMode': 'lacp_mode',
- 'lacp': 'lacp_state',
- 'lacpTimeout': 'lacp_timeout',
- 'stp': 'stp_enabled',
- 'workingMbrCount': 'operational_member_count',
- 'linkSelectPolicy': 'link_selection_policy',
- 'distributionHash': 'distribution_hash',
- 'cfgMbrCount': 'configured_member_count'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'description',
- 'media_speed',
- 'lacp_mode', # 'active' or 'passive'
- 'lacp_enabled',
- 'stp_enabled',
- 'operational_member_count',
- 'media_status',
- 'link_selection_policy',
- 'lacp_timeout',
- 'interfaces',
- 'distribution_hash',
- 'configured_member_count'
- ]
-
- @property
- def lacp_enabled(self):
- if self._values['lacp_enabled'] is None:
- return None
- elif self._values['lacp_enabled'] == 'disabled':
- return 'no'
- return 'yes'
-
- @property
- def stp_enabled(self):
- if self._values['stp_enabled'] is None:
- return None
- elif self._values['stp_enabled'] == 'disabled':
- return 'no'
- return 'yes'
-
- @property
- def media_status(self):
- return self._values['stats']['status']
-
-
-class TrunksFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(TrunksFactManager, self).__init__(**kwargs)
- self.want = TrunksParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(trunks=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- attrs = resource
- attrs['stats'] = self.read_stats_from_device(attrs['fullPath'])
- params = TrunksParameters(params=attrs)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/net/trunk".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
- def read_stats_from_device(self, full_path):
- uri = "https://{0}:{1}/mgmt/tm/net/trunk/{2}/stats".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(name=full_path)
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = parseStats(response)
- try:
- return result['stats']
- except KeyError:
- return {}
-
-
-class UsersParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'partitionAccess': 'partition_access',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'description',
- 'partition_access',
- 'shell',
- ]
-
- @property
- def partition_access(self):
- result = []
- if self._values['partition_access'] is None:
- return []
- for partition in self._values['partition_access']:
- del partition['nameReference']
- result.append(partition)
- return result
-
- @property
- def shell(self):
- if self._values['shell'] in [None, 'none']:
- return None
- return self._values['shell']
-
-
-class UsersFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(UsersFactManager, self).__init__(**kwargs)
- self.want = UsersParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(users=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- attrs = resource
- params = UsersParameters(params=attrs)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/auth/user".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class UdpProfilesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'allowNoPayload': 'allow_no_payload',
- 'bufferMaxBytes': 'buffer_max_bytes',
- 'bufferMaxPackets': 'buffer_max_packets',
- 'datagramLoadBalancing': 'datagram_load_balancing',
- 'defaultsFrom': 'parent',
- 'idleTimeout': 'idle_timeout',
- 'ipDfMode': 'ip_df_mode',
- 'ipTosToClient': 'ip_tos_to_client',
- 'ipTtlMode': 'ip_ttl_mode',
- 'ipTtlV4': 'ip_ttl_v4',
- 'ipTtlV6': 'ip_ttl_v6',
- 'linkQosToClient': 'link_qos_to_client',
- 'noChecksum': 'no_checksum',
- 'proxyMss': 'proxy_mss',
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'parent',
- 'description',
- 'allow_no_payload',
- 'buffer_max_bytes',
- 'buffer_max_packets',
- 'datagram_load_balancing',
- 'idle_timeout',
- 'ip_df_mode',
- 'ip_tos_to_client',
- 'ip_ttl_mode',
- 'ip_ttl_v4',
- 'ip_ttl_v6',
- 'link_qos_to_client',
- 'no_checksum',
- 'proxy_mss',
- ]
-
- @property
- def description(self):
- if self._values['description'] in [None, 'none']:
- return None
- return self._values['description']
-
- @property
- def allow_no_payload(self):
- return flatten_boolean(self._values['allow_no_payload'])
-
- @property
- def datagram_load_balancing(self):
- return flatten_boolean(self._values['datagram_load_balancing'])
-
- @property
- def proxy_mss(self):
- return flatten_boolean(self._values['proxy_mss'])
-
- @property
- def no_checksum(self):
- return flatten_boolean(self._values['no_checksum'])
-
-
-class UdpProfilesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(UdpProfilesFactManager, self).__init__(**kwargs)
- self.want = UdpProfilesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(udp_profiles=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = UdpProfilesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/profile/udp".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class VcmpGuestsParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'allowedSlots': 'allowed_slots',
- 'assignedSlots': 'assigned_slots',
- 'bootPriority': 'boot_priority',
- 'coresPerSlot': 'cores_per_slot',
- 'initialImage': 'initial_image',
- 'initialHotfix': 'hotfix_image',
- 'managementGw': 'mgmt_route',
- 'managementIp': 'mgmt_address',
- 'managementNetwork': 'mgmt_network',
- 'minSlots': 'min_number_of_slots',
- 'slots': 'number_of_slots',
- 'sslMode': 'ssl_mode',
- 'virtualDisk': 'virtual_disk'
- }
-
- returnables = [
- 'name',
- 'full_path',
- 'allowed_slots',
- 'assigned_slots',
- 'boot_priority',
- 'cores_per_slot',
- 'hostname',
- 'hotfix_image',
- 'initial_image',
- 'mgmt_route',
- 'mgmt_address',
- 'mgmt_network',
- 'vlans',
- 'min_number_of_slots',
- 'number_of_slots',
- 'ssl_mode',
- 'state',
- 'virtual_disk',
- ]
-
-
-class VcmpGuestsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(VcmpGuestsFactManager, self).__init__(**kwargs)
- self.want = VcmpGuestsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(vcmp_guests=facts)
- return result
-
- def _exec_module(self):
- if 'vcmp' not in self.provisioned_modules:
- return []
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = VcmpGuestsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/vcmp/guest".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class VirtualAddressesParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'arp': 'arp_enabled',
- 'autoDelete': 'auto_delete_enabled',
- 'connectionLimit': 'connection_limit',
- 'icmpEcho': 'icmp_echo',
- 'mask': 'netmask',
- 'routeAdvertisement': 'route_advertisement',
- 'trafficGroup': 'traffic_group',
- 'inheritedTrafficGroup': 'inherited_traffic_group'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'address',
- 'arp_enabled',
- 'auto_delete_enabled',
- 'connection_limit',
- 'description',
- 'enabled',
- 'icmp_echo',
- 'floating',
- 'netmask',
- 'route_advertisement',
- 'traffic_group',
- 'spanning',
- 'inherited_traffic_group'
- ]
-
- @property
- def spanning(self):
- return flatten_boolean(self._values['spanning'])
-
- @property
- def arp_enabled(self):
- return flatten_boolean(self._values['arp_enabled'])
-
- @property
- def route_advertisement(self):
- return flatten_boolean(self._values['route_advertisement'])
-
- @property
- def auto_delete_enabled(self):
- return flatten_boolean(self._values['auto_delete_enabled'])
-
- @property
- def inherited_traffic_group(self):
- return flatten_boolean(self._values['inherited_traffic_group'])
-
- @property
- def icmp_echo(self):
- return flatten_boolean(self._values['icmp_echo'])
-
- @property
- def floating(self):
- return flatten_boolean(self._values['floating'])
-
- @property
- def enabled(self):
- return flatten_boolean(self._values['enabled'])
-
-
-class VirtualAddressesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(VirtualAddressesFactManager, self).__init__(**kwargs)
- self.want = VirtualAddressesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(virtual_addresses=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = VirtualAddressesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/virtual-address".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class VirtualServersParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'autoLasthop': 'auto_lasthop',
- 'bwcPolicy': 'bw_controller_policy',
- 'cmpEnabled': 'cmp_enabled',
- 'connectionLimit': 'connection_limit',
- 'fallbackPersistence': 'fallback_persistence_profile',
- 'persist': 'persistence_profile',
- 'translatePort': 'translate_port',
- 'translateAddress': 'translate_address',
- 'lastHopPool': 'last_hop_pool',
- 'nat64': 'nat64_enabled',
- 'sourcePort': 'source_port_behavior',
- 'ipIntelligencePolicy': 'ip_intelligence_policy',
- 'ipProtocol': 'protocol',
- 'pool': 'default_pool',
- 'rateLimitMode': 'rate_limit_mode',
- 'rateLimitSrcMask': 'rate_limit_source_mask',
- 'rateLimitDstMask': 'rate_limit_destination_mask',
- 'rateLimit': 'rate_limit',
- 'sourceAddressTranslation': 'snat_type',
- 'gtmScore': 'gtm_score',
- 'rateClass': 'rate_class',
- 'source': 'source_address',
- 'auth': 'authentication_profile',
- 'mirror': 'connection_mirror_enabled',
- 'rules': 'irules',
- 'securityLogProfiles': 'security_log_profiles',
- 'profilesReference': 'profiles'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'auto_lasthop',
- 'bw_controller_policy',
- 'cmp_enabled',
- 'connection_limit',
- 'description',
- 'enabled',
- 'fallback_persistence_profile',
- 'persistence_profile',
- 'translate_port',
- 'translate_address',
- 'vlans',
- 'destination',
- 'last_hop_pool',
- 'nat64_enabled',
- 'source_port_behavior',
- 'ip_intelligence_policy',
- 'protocol',
- 'default_pool',
- 'rate_limit_mode',
- 'rate_limit_source_mask',
- 'rate_limit',
- 'snat_type',
- 'snat_pool',
- 'gtm_score',
- 'rate_class',
- 'rate_limit_destination_mask',
- 'source_address',
- 'authentication_profile',
- 'connection_mirror_enabled',
- 'irules',
- 'security_log_profiles',
- 'type',
- 'profiles',
- 'destination_address',
- 'destination_port',
- 'availability_status',
- 'status_reason',
- 'total_requests',
- 'client_side_bits_in',
- 'client_side_bits_out',
- 'client_side_current_connections',
- 'client_side_evicted_connections',
- 'client_side_max_connections',
- 'client_side_pkts_in',
- 'client_side_pkts_out',
- 'client_side_slow_killed',
- 'client_side_total_connections',
- 'cmp_mode',
- 'ephemeral_bits_in',
- 'ephemeral_bits_out',
- 'ephemeral_current_connections',
- 'ephemeral_evicted_connections',
- 'ephemeral_max_connections',
- 'ephemeral_pkts_in',
- 'ephemeral_pkts_out',
- 'ephemeral_slow_killed',
- 'ephemeral_total_connections',
- 'total_software_accepted_syn_cookies',
- 'total_hardware_accepted_syn_cookies',
- 'total_hardware_syn_cookies',
- 'hardware_syn_cookie_instances',
- 'total_software_rejected_syn_cookies',
- 'software_syn_cookie_instances',
- 'current_syn_cache',
- 'syn_cache_overflow',
- 'total_software_syn_cookies',
- 'syn_cookies_status',
- 'max_conn_duration',
- 'mean_conn_duration',
- 'min_conn_duration',
- 'cpu_usage_ratio_last_5_min',
- 'cpu_usage_ratio_last_5_sec',
- 'cpu_usage_ratio_last_1_min',
- ]
-
- @property
- def max_conn_duration(self):
- return self._values['stats']['csMaxConnDur']
-
- @property
- def mean_conn_duration(self):
- return self._values['stats']['csMeanConnDur']
-
- @property
- def min_conn_duration(self):
- return self._values['stats']['csMinConnDur']
-
- @property
- def cpu_usage_ratio_last_5_min(self):
- return self._values['stats']['fiveMinAvgUsageRatio']
-
- @property
- def cpu_usage_ratio_last_5_sec(self):
- return self._values['stats']['fiveSecAvgUsageRatio']
-
- @property
- def cpu_usage_ratio_last_1_min(self):
- return self._values['stats']['oneMinAvgUsageRatio']
-
- @property
- def cmp_mode(self):
- return self._values['stats']['cmpEnableMode']
-
- @property
- def availability_status(self):
- return self._values['stats']['status']['availabilityState']
-
- @property
- def status_reason(self):
- return self._values['stats']['status']['statusReason']
-
- @property
- def total_requests(self):
- return self._values['stats']['totRequests']
-
- @property
- def ephemeral_bits_in(self):
- return self._values['stats']['ephemeral']['bitsIn']
-
- @property
- def ephemeral_bits_out(self):
- return self._values['stats']['ephemeral']['bitsOut']
-
- @property
- def ephemeral_current_connections(self):
- return self._values['stats']['ephemeral']['curConns']
-
- @property
- def ephemeral_evicted_connections(self):
- return self._values['stats']['ephemeral']['evictedConns']
-
- @property
- def ephemeral_max_connections(self):
- return self._values['stats']['ephemeral']['maxConns']
-
- @property
- def ephemeral_pkts_in(self):
- return self._values['stats']['ephemeral']['pktsIn']
-
- @property
- def ephemeral_pkts_out(self):
- return self._values['stats']['ephemeral']['pktsOut']
-
- @property
- def ephemeral_slow_killed(self):
- return self._values['stats']['ephemeral']['slowKilled']
-
- @property
- def ephemeral_total_connections(self):
- return self._values['stats']['ephemeral']['totConns']
-
- @property
- def client_side_bits_in(self):
- return self._values['stats']['clientside']['bitsIn']
-
- @property
- def client_side_bits_out(self):
- return self._values['stats']['clientside']['bitsOut']
-
- @property
- def client_side_current_connections(self):
- return self._values['stats']['clientside']['curConns']
-
- @property
- def client_side_evicted_connections(self):
- return self._values['stats']['clientside']['evictedConns']
-
- @property
- def client_side_max_connections(self):
- return self._values['stats']['clientside']['maxConns']
-
- @property
- def client_side_pkts_in(self):
- return self._values['stats']['clientside']['pktsIn']
-
- @property
- def client_side_pkts_out(self):
- return self._values['stats']['clientside']['pktsOut']
-
- @property
- def client_side_slow_killed(self):
- return self._values['stats']['clientside']['slowKilled']
-
- @property
- def client_side_total_connections(self):
- return self._values['stats']['clientside']['totConns']
-
- @property
- def total_software_accepted_syn_cookies(self):
- return self._values['stats']['syncookie']['accepts']
-
- @property
- def total_hardware_accepted_syn_cookies(self):
- return self._values['stats']['syncookie']['hwAccepts']
-
- @property
- def total_hardware_syn_cookies(self):
- return self._values['stats']['syncookie']['hwSyncookies']
-
- @property
- def hardware_syn_cookie_instances(self):
- return self._values['stats']['syncookie']['hwsyncookieInstance']
-
- @property
- def total_software_rejected_syn_cookies(self):
- return self._values['stats']['syncookie']['rejects']
-
- @property
- def software_syn_cookie_instances(self):
- return self._values['stats']['syncookie']['swsyncookieInstance']
-
- @property
- def current_syn_cache(self):
- return self._values['stats']['syncookie']['syncacheCurr']
-
- @property
- def syn_cache_overflow(self):
- return self._values['stats']['syncookie']['syncacheOver']
-
- @property
- def total_software_syn_cookies(self):
- return self._values['stats']['syncookie']['syncookies']
-
- @property
- def syn_cookies_status(self):
- return self._values['stats']['syncookieStatus']
-
- @property
- def destination_address(self):
- if self._values['destination'] is None:
- return None
- tup = self.destination_tuple
- return tup.ip
-
- @property
- def destination_port(self):
- if self._values['destination'] is None:
- return None
- tup = self.destination_tuple
- return tup.port
-
- @property
- def type(self):
- """Attempt to determine the current server type
-
- This check is very unscientific. It turns out that this information is not
- exactly available anywhere on a BIG-IP. Instead, we rely on a semi-reliable
- means for determining what the type of the virtual server is. Hopefully it
- always works.
-
- There are a handful of attributes that can be used to determine a specific
- type. There are some types though that can only be determined by looking at
- the profiles that are assigned to them. We follow that method for those
- complicated types; message-routing, fasthttp, and fastl4.
-
- Because type determination is an expensive operation, we cache the result
- from the operation.
-
- Returns:
- string: The server type.
- """
- if self._values['l2Forward'] is True:
- result = 'forwarding-l2'
- elif self._values['ipForward'] is True:
- result = 'forwarding-ip'
- elif self._values['stateless'] is True:
- result = 'stateless'
- elif self._values['reject'] is True:
- result = 'reject'
- elif self._values['dhcpRelay'] is True:
- result = 'dhcp'
- elif self._values['internal'] is True:
- result = 'internal'
- elif self.has_fasthttp_profiles:
- result = 'performance-http'
- elif self.has_fastl4_profiles:
- result = 'performance-l4'
- elif self.has_message_routing_profiles:
- result = 'message-routing'
- else:
- result = 'standard'
- return result
-
- @property
- def profiles(self):
- """Returns a list of profiles from the API
-
- The profiles are formatted so that they are usable in this module and
- are able to be compared by the Difference engine.
-
- Returns:
- list (:obj:`list` of :obj:`dict`): List of profiles.
-
- Each dictionary in the list contains the following three (3) keys.
-
- * name
- * context
- * fullPath
-
- Raises:
- F5ModuleError: If the specified context is a value other that
- ``all``, ``server-side``, or ``client-side``.
- """
- if 'items' not in self._values['profiles']:
- return None
- result = []
- for item in self._values['profiles']['items']:
- context = item['context']
- if context == 'serverside':
- context = 'server-side'
- elif context == 'clientside':
- context = 'client-side'
- name = item['name']
- if context in ['all', 'server-side', 'client-side']:
- result.append(dict(name=name, context=context, full_path=item['fullPath']))
- else:
- raise F5ModuleError(
- "Unknown profile context found: '{0}'".format(context)
- )
- return result
-
- @property
- def has_message_routing_profiles(self):
- if self.profiles is None:
- return None
- current = self._read_current_message_routing_profiles_from_device()
- result = [x['name'] for x in self.profiles if x['name'] in current]
- if len(result) > 0:
- return True
- return False
-
- @property
- def has_fastl4_profiles(self):
- if self.profiles is None:
- return None
- current = self._read_current_fastl4_profiles_from_device()
- result = [x['name'] for x in self.profiles if x['name'] in current]
- if len(result) > 0:
- return True
- return False
-
- @property
- def has_fasthttp_profiles(self):
- """Check if ``fasthttp`` profile is in API profiles
-
- This method is used to determine the server type when doing comparisons
- in the Difference class.
-
- Returns:
- bool: True if server has ``fasthttp`` profiles. False otherwise.
- """
- if self.profiles is None:
- return None
- current = self._read_current_fasthttp_profiles_from_device()
- result = [x['name'] for x in self.profiles if x['name'] in current]
- if len(result) > 0:
- return True
- return False
-
- def _read_current_message_routing_profiles_from_device(self):
- result = []
- result += self._read_diameter_profiles_from_device()
- result += self._read_sip_profiles_from_device()
- return result
-
- def _read_diameter_profiles_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/profile/diameter/".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = [x['name'] for x in response['items']]
- return result
-
- def _read_sip_profiles_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/profile/sip/".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = [x['name'] for x in response['items']]
- return result
-
- def _read_current_fastl4_profiles_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/profile/fastl4/".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = [x['name'] for x in response['items']]
- return result
-
- def _read_current_fasthttp_profiles_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/profile/fasthttp/".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = [x['name'] for x in response['items']]
- return result
-
- @property
- def security_log_profiles(self):
- if self._values['security_log_profiles'] is None:
- return None
- result = list(set([x.strip('"') for x in self._values['security_log_profiles']]))
- result.sort()
- return result
-
- @property
- def snat_type(self):
- if self._values['snat_type'] is None:
- return None
- if 'type' in self._values['snat_type']:
- if self._values['snat_type']['type'] == 'automap':
- return 'automap'
- elif self._values['snat_type']['type'] == 'none':
- return 'none'
- elif self._values['snat_type']['type'] == 'pool':
- return 'snat'
-
- @property
- def connection_mirror_enabled(self):
- if self._values['connection_mirror_enabled'] is None:
- return None
- elif self._values['connection_mirror_enabled'] == 'enabled':
- return 'yes'
- return 'no'
-
- @property
- def rate_limit(self):
- if self._values['rate_limit'] is None:
- return None
- elif self._values['rate_limit'] == 'disabled':
- return -1
- return int(self._values['rate_limit'])
-
- @property
- def nat64_enabled(self):
- if self._values['nat64_enabled'] is None:
- return None
- elif self._values['nat64_enabled'] == 'enabled':
- return 'yes'
- return 'no'
-
- @property
- def enabled(self):
- if self._values['enabled'] is None:
- return 'no'
- elif self._values['enabled'] is True:
- return 'yes'
- return 'no'
-
- @property
- def translate_port(self):
- if self._values['translate_port'] is None:
- return None
- elif self._values['translate_port'] == 'enabled':
- return 'yes'
- return 'no'
-
- @property
- def translate_address(self):
- if self._values['translate_address'] is None:
- return None
- elif self._values['translate_address'] == 'enabled':
- return 'yes'
- return 'no'
-
- @property
- def persistence_profile(self):
- """Return persistence profile in a consumable form
-
- I don't know why the persistence profile is stored this way, but below is the
- general format of it.
-
- "persist": [
- {
- "name": "msrdp",
- "partition": "Common",
- "tmDefault": "yes",
- "nameReference": {
- "link": "https://localhost/mgmt/tm/ltm/persistence/msrdp/~Common~msrdp?ver=13.1.0.4"
- }
- }
- ],
-
- As you can see, this is quite different from something like the fallback
- persistence profile which is just simply
-
- /Common/fallback1
-
- This method makes the persistence profile look like the fallback profile.
-
- Returns:
- string: The persistence profile configured on the virtual.
- """
- if self._values['persistence_profile'] is None:
- return None
- profile = self._values['persistence_profile'][0]
- result = fq_name(profile['partition'], profile['name'])
- return result
-
- @property
- def destination_tuple(self):
- Destination = namedtuple('Destination', ['ip', 'port', 'route_domain'])
-
- # Remove the partition
- if self._values['destination'] is None:
- result = Destination(ip=None, port=None, route_domain=None)
- return result
- destination = re.sub(r'^/[a-zA-Z0-9_.-]+/', '', self._values['destination'])
-
- if is_valid_ip(destination):
- result = Destination(
- ip=destination,
- port=None,
- route_domain=None
- )
- return result
-
- # Covers the following examples
- #
- # /Common/2700:bc00:1f10:101::6%2.80
- # 2700:bc00:1f10:101::6%2.80
- # 1.1.1.1%2:80
- # /Common/1.1.1.1%2:80
- # /Common/2700:bc00:1f10:101::6%2.any
- #
- pattern = r'(?P[^%]+)%(?P[0-9]+)[:.](?P[0-9]+|any)'
- matches = re.search(pattern, destination)
- if matches:
- try:
- port = int(matches.group('port'))
- except ValueError:
- # Can be a port of "any". This only happens with IPv6
- port = matches.group('port')
- if port == 'any':
- port = 0
- ip = matches.group('ip')
- if not is_valid_ip(ip):
- raise F5ModuleError(
- "The provided destination is not a valid IP address"
- )
- result = Destination(
- ip=matches.group('ip'),
- port=port,
- route_domain=int(matches.group('route_domain'))
- )
- return result
-
- pattern = r'(?P[^%]+)%(?P[0-9]+)'
- matches = re.search(pattern, destination)
- if matches:
- ip = matches.group('ip')
- if not is_valid_ip(ip):
- raise F5ModuleError(
- "The provided destination is not a valid IP address"
- )
- result = Destination(
- ip=matches.group('ip'),
- port=None,
- route_domain=int(matches.group('route_domain'))
- )
- return result
-
- parts = destination.split('.')
- if len(parts) == 4:
- # IPv4
- ip, port = destination.split(':')
- if not is_valid_ip(ip):
- raise F5ModuleError(
- "The provided destination is not a valid IP address"
- )
- result = Destination(
- ip=ip,
- port=int(port),
- route_domain=None
- )
- return result
- elif len(parts) == 2:
- # IPv6
- ip, port = destination.split('.')
- try:
- port = int(port)
- except ValueError:
- # Can be a port of "any". This only happens with IPv6
- if port == 'any':
- port = 0
- if not is_valid_ip(ip):
- raise F5ModuleError(
- "The provided destination is not a valid IP address"
- )
- result = Destination(
- ip=ip,
- port=port,
- route_domain=None
- )
- return result
- else:
- result = Destination(ip=None, port=None, route_domain=None)
- return result
-
-
-class VirtualServersFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(VirtualServersFactManager, self).__init__(**kwargs)
- self.want = VirtualServersParameters(client=self.client, params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(virtual_servers=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- attrs = resource
- attrs['stats'] = self.read_stats_from_device(attrs['fullPath'])
- params = VirtualServersParameters(params=attrs)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/ltm/virtual?expandSubcollections=true".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
- def read_stats_from_device(self, full_path):
- uri = "https://{0}:{1}/mgmt/tm/ltm/virtual/{2}/stats".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(name=full_path)
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = parseStats(response)
- try:
- return result['stats']
- except KeyError:
- return {}
-
-
-class VlansParameters(BaseParameters):
- api_map = {
- 'autoLasthop': 'auto_lasthop',
- 'cmpHash': 'cmp_hash_algorithm',
- 'failsafeAction': 'failsafe_action',
- 'failsafe': 'failsafe_enabled',
- 'failsafeTimeout': 'failsafe_timeout',
- 'ifIndex': 'if_index',
- 'learning': 'learning_mode',
- 'interfacesReference': 'interfaces',
- 'sourceChecking': 'source_check_enabled',
- 'fullPath': 'full_path'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'auto_lasthop',
- 'cmp_hash_algorithm',
- 'description',
- 'failsafe_action',
- 'failsafe_enabled',
- 'failsafe_timeout',
- 'if_index',
- 'learning_mode',
- 'interfaces',
- 'mtu',
- 'sflow_poll_interval',
- 'sflow_poll_interval_global',
- 'sflow_sampling_rate',
- 'sflow_sampling_rate_global',
- 'source_check_enabled',
- 'true_mac_address',
- 'tag',
- ]
-
- @property
- def interfaces(self):
- if self._values['interfaces'] is None:
- return None
- if 'items' not in self._values['interfaces']:
- return None
- result = []
- for item in self._values['interfaces']['items']:
- tmp = dict(
- name=item['name'],
- full_path=item['fullPath']
- )
- if 'tagged' in item:
- tmp['tagged'] = 'yes'
- else:
- tmp['tagged'] = 'no'
- result.append(tmp)
- return result
-
- @property
- def sflow_poll_interval(self):
- return int(self._values['sflow']['pollInterval'])
-
- @property
- def sflow_poll_interval_global(self):
- return flatten_boolean(self._values['sflow']['pollIntervalGlobal'])
-
- @property
- def sflow_sampling_rate(self):
- return int(self._values['sflow']['samplingRate'])
-
- @property
- def sflow_sampling_rate_global(self):
- return flatten_boolean(self._values['sflow']['samplingRateGlobal'])
-
- @property
- def source_check_state(self):
- return flatten_boolean(self._values['source_check_state'])
-
- @property
- def true_mac_address(self):
- # Who made this field a "description"!?
- return self._values['stats']['macTrue']
-
- @property
- def tag(self):
- # We can't agree on field names...SMH
- return self._values['stats']['id']
-
- @property
- def failsafe_enabled(self):
- return flatten_boolean(self._values['failsafe_enabled'])
-
-
-class VlansFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(VlansFactManager, self).__init__(**kwargs)
- self.want = VlansParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(vlans=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- attrs = resource
- attrs['stats'] = self.read_stats_from_device(attrs['fullPath'])
- params = VlansParameters(params=attrs)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/net/vlan?expandSubcollections=true".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
- def read_stats_from_device(self, full_path):
- uri = "https://{0}:{1}/mgmt/tm/net/vlan/{2}/stats".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(name=full_path)
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = parseStats(response)
- try:
- return result['stats']
- except KeyError:
- return {}
-
-
-class ModuleManager(object):
- def __init__(self, *args, **kwargs):
- self.module = kwargs.get('module', None)
- self.client = kwargs.get('client', None)
- self.kwargs = kwargs
- self.want = Parameters(params=self.module.params)
- self.managers = {
- 'asm-policy-stats': AsmPolicyStatsFactManager,
- 'asm-policies': AsmPolicyFactManager,
- 'asm-server-technologies': AsmServerTechnologyFactManager,
- 'asm-signature-sets': AsmSignatureSetsFactManager,
- 'client-ssl-profiles': ClientSslProfilesFactManager,
- 'devices': DevicesFactManager,
- 'device-groups': DeviceGroupsFactManager,
- 'external-monitors': ExternalMonitorsFactManager,
- 'fasthttp-profiles': FastHttpProfilesFactManager,
- 'fastl4-profiles': FastL4ProfilesFactManager,
- 'gateway-icmp-monitors': GatewayIcmpMonitorsFactManager,
- 'gtm-a-pools': GtmAPoolsFactManager,
- 'gtm-servers': GtmServersFactManager,
- 'gtm-a-wide-ips': GtmAWideIpsFactManager,
- 'gtm-aaaa-pools': GtmAaaaPoolsFactManager,
- 'gtm-aaaa-wide-ips': GtmAaaaWideIpsFactManager,
- 'gtm-cname-pools': GtmCnamePoolsFactManager,
- 'gtm-cname-wide-ips': GtmCnameWideIpsFactManager,
- 'gtm-mx-pools': GtmMxPoolsFactManager,
- 'gtm-mx-wide-ips': GtmMxWideIpsFactManager,
- 'gtm-naptr-pools': GtmNaptrPoolsFactManager,
- 'gtm-naptr-wide-ips': GtmNaptrWideIpsFactManager,
- 'gtm-srv-pools': GtmSrvPoolsFactManager,
- 'gtm-srv-wide-ips': GtmSrvWideIpsFactManager,
- 'http-monitors': HttpMonitorsFactManager,
- 'https-monitors': HttpsMonitorsFactManager,
- 'http-profiles': HttpProfilesFactManager,
- 'iapp-services': IappServicesFactManager,
- 'iapplx-packages': IapplxPackagesFactManager,
- 'icmp-monitors': IcmpMonitorsFactManager,
- 'interfaces': InterfacesFactManager,
- 'internal-data-groups': InternalDataGroupsFactManager,
- 'irules': IrulesFactManager,
- 'ltm-pools': LtmPoolsFactManager,
- 'ltm-policies': LtmPolicyFactManager,
- 'nodes': NodesFactManager,
- 'oneconnect-profiles': OneConnectProfilesFactManager,
- 'partitions': PartitionFactManager,
- 'provision-info': ProvisionInfoFactManager,
- 'route-domains': RouteDomainFactManager,
- 'self-ips': SelfIpsFactManager,
- 'server-ssl-profiles': ServerSslProfilesFactManager,
- 'software-volumes': SoftwareVolumesFactManager,
- 'software-images': SoftwareImagesFactManager,
- 'software-hotfixes': SoftwareHotfixesFactManager,
- 'ssl-certs': SslCertificatesFactManager,
- 'ssl-keys': SslKeysFactManager,
- 'system-db': SystemDbFactManager,
- 'system-info': SystemInfoFactManager,
- 'tcp-monitors': TcpMonitorsFactManager,
- 'tcp-half-open-monitors': TcpHalfOpenMonitorsFactManager,
- 'tcp-profiles': TcpProfilesFactManager,
- 'traffic-groups': TrafficGroupsFactManager,
- 'trunks': TrunksFactManager,
- 'udp-profiles': UdpProfilesFactManager,
- 'users': UsersFactManager,
- 'vcmp-guests': VcmpGuestsFactManager,
- 'virtual-addresses': VirtualAddressesFactManager,
- 'virtual-servers': VirtualServersFactManager,
- 'vlans': VlansFactManager,
- }
-
- def exec_module(self):
- self.handle_all_keyword()
- self.handle_profiles_keyword()
- self.handle_monitors_keyword()
- self.handle_gtm_pools_keyword()
- self.handle_gtm_wide_ips_keyword()
- res = self.check_valid_gather_subset(self.want.gather_subset)
- if res:
- invalid = ','.join(res)
- raise F5ModuleError(
- "The specified 'gather_subset' options are invalid: {0}".format(invalid)
- )
- result = self.filter_excluded_facts()
-
- managers = []
- for name in result:
- manager = self.get_manager(name)
- if manager:
- managers.append(manager)
-
- if not managers:
- result = dict(
- queried=False
- )
- return result
-
- result = self.execute_managers(managers)
- if result:
- result['queried'] = True
- else:
- result['queried'] = False
- return result
-
- def filter_excluded_facts(self):
- # Remove the excluded entries from the list of possible facts
- exclude = [x[1:] for x in self.want.gather_subset if x[0] == '!']
- include = [x for x in self.want.gather_subset if x[0] != '!']
- result = [x for x in include if x not in exclude]
- return result
-
- def handle_all_keyword(self):
- if 'all' not in self.want.gather_subset:
- return
- managers = list(self.managers.keys()) + self.want.gather_subset
- managers.remove('all')
- self.want.update({'gather_subset': managers})
-
- def handle_profiles_keyword(self):
- if 'profiles' not in self.want.gather_subset:
- return
- managers = [x for x in self.managers.keys() if '-profiles' in x] + self.want.gather_subset
- managers.remove('profiles')
- self.want.update({'gather_subset': managers})
-
- def handle_monitors_keyword(self):
- if 'monitors' not in self.want.gather_subset:
- return
- managers = [x for x in self.managers.keys() if '-monitors' in x] + self.want.gather_subset
- managers.remove('monitors')
- self.want.update({'gather_subset': managers})
-
- def handle_gtm_pools_keyword(self):
- if 'gtm-pools' not in self.want.gather_subset:
- return
- keys = self.managers.keys()
- managers = [x for x in keys if x.startswith('gtm-') and x.endswith('-pools')]
- managers += self.want.gather_subset
- managers.remove('gtm-pools')
- self.want.update({'gather_subset': managers})
-
- def handle_gtm_wide_ips_keyword(self):
- if 'gtm-wide-ips' not in self.want.gather_subset:
- return
- keys = self.managers.keys()
- managers = [x for x in keys if x.startswith('gtm-') and x.endswith('-wide-ips')]
- managers += self.want.gather_subset
- managers.remove('gtm-wide-ips')
- self.want.update({'gather_subset': managers})
-
- def check_valid_gather_subset(self, includes):
- """Check that the specified subset is valid
-
- The ``gather_subset`` parameter is specified as a "raw" field which means that
- any Python type could technically be provided
-
- :param includes:
- :return:
- """
- keys = self.managers.keys()
- result = []
- for x in includes:
- if x not in keys:
- if x[0] == '!':
- if x[1:] not in keys:
- result.append(x)
- else:
- result.append(x)
- return result
-
- def execute_managers(self, managers):
- results = dict()
- client = F5RestClient(**self.module.params)
- prov = modules_provisioned(client)
- for manager in managers:
- manager.provisioned_modules = prov
- result = manager.exec_module()
- results.update(result)
- return results
-
- def get_manager(self, which):
- result = {}
- manager = self.managers.get(which, None)
- if not manager:
- return result
- kwargs = dict()
- kwargs.update(self.kwargs)
-
- kwargs['client'] = F5RestClient(**self.module.params)
- result = manager(**kwargs)
- return result
-
-
-class ArgumentSpec(object):
- def __init__(self):
- self.supports_check_mode = False
- argument_spec = dict(
- gather_subset=dict(
- type='list',
- required=True,
- aliases=['include'],
- choices=[
- # Meta choices
- 'all',
- 'monitors',
- 'profiles',
- 'gtm-pools',
- 'gtm-wide-ips',
-
- # Non-meta choices
- 'asm-policies',
- 'asm-policy-stats',
- 'asm-server-technologies',
- 'asm-signature-sets',
- 'client-ssl-profiles',
- 'devices',
- 'device-groups',
- 'external-monitors',
- 'fasthttp-profiles',
- 'fastl4-profiles',
- 'gateway-icmp-monitors',
- 'gtm-a-pools',
- 'gtm-servers',
- 'gtm-a-wide-ips',
- 'gtm-aaaa-pools',
- 'gtm-aaaa-wide-ips',
- 'gtm-cname-pools',
- 'gtm-cname-wide-ips',
- 'gtm-mx-pools',
- 'gtm-mx-wide-ips',
- 'gtm-naptr-pools',
- 'gtm-naptr-wide-ips',
- 'gtm-srv-pools',
- 'gtm-srv-wide-ips',
- 'http-profiles',
- 'http-monitors',
- 'https-monitors',
- 'iapp-services',
- 'iapplx-packages',
- 'icmp-monitors',
- 'interfaces',
- 'internal-data-groups',
- 'irules',
- 'ltm-pools',
- 'ltm-policies',
- 'nodes',
- 'oneconnect-profiles',
- 'partitions',
- 'provision-info',
- 'self-ips',
- 'server-ssl-profiles',
- 'software-volumes',
- 'software-images',
- 'software-hotfixes',
- 'ssl-certs',
- 'ssl-keys',
- 'system-db',
- 'system-info',
- 'tcp-monitors',
- 'tcp-half-open-monitors',
- 'tcp-profiles',
- 'traffic-groups',
- 'trunks',
- 'udp-profiles',
- 'users',
- 'vcmp-guests',
- 'virtual-addresses',
- 'virtual-servers',
- 'vlans',
-
- # Negations of meta choices
- '!all',
- "!monitors",
- '!profiles',
- '!gtm-pools',
- '!gtm-wide-ips',
-
- # Negations of non-meta-choices
- '!asm-policy-stats',
- '!asm-policies',
- '!asm-server-technologies',
- '!asm-signature-sets',
- '!client-ssl-profiles',
- '!devices',
- '!device-groups',
- '!external-monitors',
- '!fasthttp-profiles',
- '!fastl4-profiles',
- '!gateway-icmp-monitors',
- '!gtm-a-pools',
- '!gtm-servers',
- '!gtm-a-wide-ips',
- '!gtm-aaaa-pools',
- '!gtm-aaaa-wide-ips',
- '!gtm-cname-pools',
- '!gtm-cname-wide-ips',
- '!gtm-mx-pools',
- '!gtm-mx-wide-ips',
- '!gtm-naptr-pools',
- '!gtm-naptr-wide-ips',
- '!gtm-srv-pools',
- '!gtm-srv-wide-ips',
- '!http-profiles',
- '!http-monitors',
- '!https-monitors',
- '!iapp-services',
- '!iapplx-packages',
- '!icmp-monitors',
- '!interfaces',
- '!internal-data-groups',
- '!irules',
- '!ltm-pools',
- '!ltm-policies',
- '!nodes',
- '!oneconnect-profiles',
- '!partitions',
- '!provision-info',
- '!self-ips',
- '!server-ssl-profiles',
- '!software-volumes',
- '!software-images',
- '!software-hotfixes',
- '!ssl-certs',
- '!ssl-keys',
- '!system-db',
- '!system-info',
- '!tcp-monitors',
- '!tcp-half-open-monitors',
- '!tcp-profiles',
- '!traffic-groups',
- '!trunks',
- '!udp-profiles',
- '!users',
- '!vcmp-guests',
- '!virtual-addresses',
- '!virtual-servers',
- '!vlans',
- ]
- ),
- )
- self.argument_spec = {}
- self.argument_spec.update(f5_argument_spec)
- self.argument_spec.update(argument_spec)
-
-
-def main():
- spec = ArgumentSpec()
-
- module = AnsibleModule(
- argument_spec=spec.argument_spec,
- supports_check_mode=spec.supports_check_mode
- )
- if module._name == 'bigip_device_facts':
- module.deprecate("The 'bigip_device_facts' module has been renamed to 'bigip_device_info'", version='2.13')
-
- try:
- mm = ModuleManager(module=module)
- results = mm.exec_module()
- module.exit_json(**results)
- except F5ModuleError as ex:
- module.fail_json(msg=str(ex))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/f5/bigip_device_traffic_group.py b/plugins/modules/network/f5/bigip_device_traffic_group.py
deleted file mode 100644
index c5d459fb99..0000000000
--- a/plugins/modules/network/f5/bigip_device_traffic_group.py
+++ /dev/null
@@ -1,667 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, F5 Networks Inc.
-# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'certified'}
-
-DOCUMENTATION = r'''
----
-module: bigip_device_traffic_group
-short_description: Manages traffic groups on BIG-IP
-description:
- - Supports managing traffic groups and their attributes on a BIG-IP.
-options:
- name:
- description:
- - The name of the traffic group.
- type: str
- required: True
- mac_address:
- description:
- - Specifies the floating Media Access Control (MAC) address associated with the floating IP addresses
- defined for a traffic group.
- - Primarily, a MAC masquerade address minimizes ARP communications or dropped packets as a result of failover.
- - A MAC masquerade address ensures that any traffic destined for a specific traffic group reaches an available
- device after failover, which happens because along with the traffic group, the MAC masquerade address floats
- to the available device.
- - Without a MAC masquerade address, the sending host must learn the MAC address for a newly-active device,
- either by sending an ARP request or by relying on the gratuitous ARP from the newly-active device.
- - To unset the MAC address, specify an empty value (C("")) to this parameter.
- type: str
- ha_order:
- description:
- - Specifies order in which you would like to assign devices for failover.
- - If you configure this setting, you must configure the setting on every traffic group in the device group.
- - The values should be device names of the devices that belong to the failover group configured beforehand.
- - The order in which the devices are placed as arguments to this parameter, determines their HA order
- on the device, in other words changing the order of the same elements will cause a change on the unit.
- - To disable an HA order failover method , specify an empty string value (C("")) to this parameter.
- - Disabling HA order will revert the device back to using Load Aware method as it is the default,
- unless C(ha_group) setting is also configured.
- - Device names will be prepended by a partition by the module, so you can provide either the full path format
- name C(/Common/bigip1) or just the name string C(bigip1).
- type: list
- ha_group:
- description:
- - Specifies a configured C(HA group) to be associated with the traffic group.
- - Once you create an HA group on a device and associate the HA group with a traffic group,
- you must create an HA group and associate it with that same traffic group on every device in the device group.
- - To disable an HA group failover method , specify an empty string value (C("")) to this parameter.
- - Disabling HA group will revert the device back to using C(Load Aware) method as it is the default,
- unless C(ha_order) setting is also configured.
- - The C(auto_failback) and C(auto_failback_time) are not compatible with C(ha_group).
- type: str
- ha_load_factor:
- description:
- - The value of the load the traffic-group presents the system relative to other traffic groups.
- - This parameter only takes effect when C(Load Aware) failover method is in use.
- - The correct value range is C(1 - 1000) inclusive.
- type: int
- auto_failback:
- description:
- - Specifies whether the traffic group fails back to the initial device specified in C(ha_order).
- type: bool
- auto_failback_time:
- description:
- - Specifies the number of seconds the system delays before failing back to the initial device
- specified in C(ha_order).
- - The correct value range is C(0 - 300) inclusive.
- type: int
- partition:
- description:
- - Device partition to manage resources on.
- type: str
- default: Common
- state:
- description:
- - When C(present), ensures that the traffic group exists.
- - When C(absent), ensures the traffic group is removed.
- type: str
- choices:
- - present
- - absent
- default: present
-extends_documentation_fragment:
-- f5networks.f5_modules.f5
-
-author:
- - Tim Rupp (@caphrim007)
- - Wojciech Wypior (@wojtek0806)
-'''
-
-EXAMPLES = r'''
-- name: Create a traffic group
- bigip_device_traffic_group:
- name: foo1
- state: present
- provider:
- user: admin
- password: secret
- server: lb.mydomain.com
- delegate_to: localhost
-
-- name: Create a traffic group with ha_group failover
- bigip_device_traffic_group:
- name: foo2
- state: present
- ha_group: foo_HA_grp
- provider:
- user: admin
- password: secret
- server: lb.mydomain.com
- delegate_to: localhost
-
-- name: Create a traffic group with ha_order failover
- bigip_device_traffic_group:
- name: foo3
- state: present
- ha_order:
- - /Common/bigip1.lab.local
- - /Common/bigip2.lab.local
- auto_failback: yes
- auto_failback_time: 40
- provider:
- user: admin
- password: secret
- server: lb.mydomain.com
- delegate_to: localhost
-
-- name: Change traffic group ha_order to ha_group
- bigip_device_traffic_group:
- name: foo3
- state: present
- ha_group: foo_HA_grp
- ha_order: ""
- auto_failback: no
- provider:
- user: admin
- password: secret
- server: lb.mydomain.com
- delegate_to: localhost
-
-- name: Remove traffic group
- bigip_device_traffic_group:
- name: foo
- state: absent
- provider:
- user: admin
- password: secret
- server: lb.mydomain.com
- delegate_to: localhost
-'''
-
-RETURN = r'''
-mac_address:
- description: The MAC masquerade address
- returned: changed
- type: str
- sample: "02:01:d7:93:35:08"
-ha_group:
- description: The configured HA group associated with traffic group
- returned: changed
- type: str
- sample: foo_HA_grp
-ha_order:
- description: Specifies the order in which the devices will failover
- returned: changed
- type: list
- sample: ['/Common/bigip1', '/Common/bigip2']
-ha_load_factor:
- description: The value of the load the traffic-group presents the system relative to other traffic groups
- returned: changed
- type: int
- sample: 20
-auto_failback:
- description: Specifies whether the traffic group fails back to the initial device specified in ha_order
- returned: changed
- type: bool
- sample: yes
-auto_failback_time:
- description: Specifies the number of seconds the system delays before failing back
- returned: changed
- type: int
- sample: 60
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.basic import env_fallback
-
-try:
- from library.module_utils.network.f5.bigip import F5RestClient
- from library.module_utils.network.f5.common import F5ModuleError
- from library.module_utils.network.f5.common import AnsibleF5Parameters
- from library.module_utils.network.f5.common import f5_argument_spec
- from library.module_utils.network.f5.common import fq_name
- from library.module_utils.network.f5.common import transform_name
- from library.module_utils.network.f5.common import flatten_boolean
-except ImportError:
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.bigip import F5RestClient
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import F5ModuleError
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import AnsibleF5Parameters
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import f5_argument_spec
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import fq_name
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import transform_name
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import flatten_boolean
-
-
-class Parameters(AnsibleF5Parameters):
- api_map = {
- 'mac': 'mac_address',
- 'haGroup': 'ha_group',
- 'haOrder': 'ha_order',
- 'haLoadFactor': 'ha_load_factor',
- 'autoFailbackTime': 'auto_failback_time',
- 'autoFailbackEnabled': 'auto_failback',
- }
-
- api_attributes = [
- 'mac',
- 'haGroup',
- 'haOrder',
- 'haLoadFactor',
- 'autoFailbackTime',
- 'autoFailbackEnabled',
-
- ]
-
- returnables = [
- 'mac_address',
- 'ha_group',
- 'ha_order',
- 'ha_load_factor',
- 'auto_failback_time',
- 'auto_failback',
- ]
-
- updatables = [
- 'mac_address',
- 'ha_group',
- 'ha_order',
- 'ha_load_factor',
- 'auto_failback_time',
- 'auto_failback',
- ]
-
-
-class ApiParameters(Parameters):
- pass
-
-
-class ModuleParameters(Parameters):
- @property
- def mac_address(self):
- if self._values['mac_address'] is None:
- return None
- if self._values['mac_address'] == '':
- return 'none'
- return self._values['mac_address']
-
- @property
- def ha_group(self):
- if self._values['ha_group'] is None:
- return None
- if self._values['ha_group'] == '':
- return 'none'
- if self.auto_failback == 'true':
- raise F5ModuleError(
- "The auto_failback cannot be enabled when ha_group is specified."
- )
- return self._values['ha_group']
-
- @property
- def ha_load_factor(self):
- if self._values['ha_load_factor'] is None:
- return None
- value = self._values['ha_load_factor']
- if value < 1 or value > 1000:
- raise F5ModuleError(
- "Invalid ha_load_factor value, correct range is 1 - 1000, specified value: {0}.".format(value))
- return value
-
- @property
- def auto_failback_time(self):
- if self._values['auto_failback_time'] is None:
- return None
- value = self._values['auto_failback_time']
- if value < 0 or value > 300:
- raise F5ModuleError(
- "Invalid auto_failback_time value, correct range is 0 - 300, specified value: {0}.".format(value))
- return value
-
- @property
- def auto_failback(self):
- result = flatten_boolean(self._values['auto_failback'])
- if result == 'yes':
- return 'true'
- if result == 'no':
- return 'false'
- return None
-
- @property
- def ha_order(self):
- if self._values['ha_order'] is None:
- return None
- if len(self._values['ha_order']) == 1 and self._values['ha_order'][0] == '':
- if self.auto_failback == 'true':
- raise F5ModuleError(
- 'Cannot enable auto failback when HA order list is empty, at least one device must be specified.'
- )
- return 'none'
- result = [fq_name(self.partition, value) for value in self._values['ha_order']]
- return result
-
-
-class Changes(Parameters):
- def to_return(self):
- result = {}
- for returnable in self.returnables:
- result[returnable] = getattr(self, returnable)
- result = self._filter_params(result)
- return result
-
-
-class UsableChanges(Changes):
- pass
-
-
-class ReportableChanges(Changes):
-
- @property
- def mac_address(self):
- if self._values['mac_address'] is None:
- return None
- if self._values['mac_address'] == 'none':
- return ''
- return self._values['mac_address']
-
- @property
- def ha_group(self):
- if self._values['ha_group'] is None:
- return None
- if self._values['ha_group'] == 'none':
- return ''
- return self._values['ha_group']
-
- @property
- def auto_failback(self):
- result = self._values['auto_failback']
- if result == 'true':
- return 'yes'
- if result == 'false':
- return 'no'
- return None
-
- @property
- def ha_order(self):
- if self._values['ha_order'] is None:
- return None
- if self._values['ha_order'] == 'none':
- return ''
- return self._values['ha_order']
-
-
-class Difference(object):
- def __init__(self, want, have=None):
- self.want = want
- self.have = have
-
- def compare(self, param):
- try:
- result = getattr(self, param)
- return result
- except AttributeError:
- return self.__default(param)
-
- def __default(self, param):
- attr1 = getattr(self.want, param)
- try:
- attr2 = getattr(self.have, param)
- if attr1 != attr2:
- return attr1
- except AttributeError:
- return attr1
-
- @property
- def ha_group(self):
- if self.want.ha_group is None:
- return None
- if self.have.ha_group is None and self.want.ha_group == 'none':
- return None
- if self.want.ha_group != self.have.ha_group:
- if self.have.auto_failback == 'true' and self.want.auto_failback != 'false':
- raise F5ModuleError(
- "The auto_failback parameter on the device must disabled to use ha_group failover method."
- )
- return self.want.ha_group
-
- @property
- def ha_order(self):
- # Device order is literally derived from the order in the array,
- # hence lists with the same elements but in different order cannot be equal, so cmp_simple_list
- # function will not work here.
- if self.want.ha_order is None:
- return None
- if self.have.ha_order is None and self.want.ha_order == 'none':
- return None
- if self.want.ha_order != self.have.ha_order:
- return self.want.ha_order
-
- @property
- def partition(self):
- raise F5ModuleError(
- "Partition cannot be changed for a traffic group. Only /Common is allowed."
- )
-
-
-class ModuleManager(object):
- def __init__(self, *args, **kwargs):
- self.module = kwargs.get('module', None)
- self.client = F5RestClient(**self.module.params)
- self.have = None
- self.want = ModuleParameters(params=self.module.params)
- self.changes = UsableChanges()
-
- def _set_changed_options(self):
- changed = {}
- for key in Parameters.returnables:
- if getattr(self.want, key) is not None:
- changed[key] = getattr(self.want, key)
- if changed:
- self.changes = UsableChanges(params=changed)
-
- def _update_changed_options(self):
- diff = Difference(self.want, self.have)
- updatables = Parameters.updatables
- changed = dict()
- for k in updatables:
- change = diff.compare(k)
- if change is None:
- continue
- else:
- if isinstance(change, dict):
- changed.update(change)
- else:
- changed[k] = change
- if changed:
- self.changes = UsableChanges(params=changed)
- return True
- return False
-
- def _announce_deprecations(self, result):
- warnings = result.pop('__warnings', [])
- for warning in warnings:
- self.module.deprecate(
- msg=warning['msg'],
- version=warning['version']
- )
-
- def exec_module(self):
- changed = False
- result = dict()
- state = self.want.state
-
- if state == "present":
- changed = self.present()
- elif state == "absent":
- changed = self.absent()
-
- reportable = ReportableChanges(params=self.changes.to_return())
- changes = reportable.to_return()
- result.update(**changes)
- result.update(dict(changed=changed))
- self._announce_deprecations(result)
- return result
-
- def present(self):
- if self.exists():
- return self.update()
- else:
- return self.create()
-
- def absent(self):
- if self.exists():
- return self.remove()
- return False
-
- def should_update(self):
- result = self._update_changed_options()
- if result:
- return True
- return False
-
- def update(self):
- self.have = self.read_current_from_device()
- if not self.should_update():
- return False
- if self.module.check_mode:
- return True
- self.update_on_device()
- return True
-
- def remove(self):
- if self.module.check_mode:
- return True
- self.remove_from_device()
- if self.exists():
- raise F5ModuleError("Failed to delete the resource.")
- return True
-
- def create(self):
- self._set_changed_options()
- if self.want.partition.lower().strip('/') != 'common':
- raise F5ModuleError(
- "Traffic groups can only be created in the /Common partition"
- )
- if self.module.check_mode:
- return True
- self.create_on_device()
- return True
-
- def exists(self):
- uri = "https://{0}:{1}/mgmt/tm/cm/traffic-group/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(self.want.partition, self.want.name)
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError:
- return False
- if resp.status == 404 or 'code' in response and response['code'] == 404:
- return False
- return True
-
- def create_on_device(self):
- params = self.changes.api_params()
- params['name'] = self.want.name
- params['partition'] = self.want.partition
- uri = "https://{0}:{1}/mgmt/tm/cm/traffic-group/".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.post(uri, json=params)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] in [400, 403]:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- return response['selfLink']
-
- def update_on_device(self):
- params = self.changes.api_params()
- uri = "https://{0}:{1}/mgmt/tm/cm/traffic-group/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(self.want.partition, self.want.name)
- )
- resp = self.client.api.patch(uri, json=params)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- def read_current_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/cm/traffic-group/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(self.want.partition, self.want.name)
- )
-
- resp = self.client.api.get(uri)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- return ApiParameters(params=response)
-
- def remove_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/cm/traffic-group/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(self.want.partition, self.want.name)
- )
- response = self.client.api.delete(uri)
- if response.status == 200:
- return True
- raise F5ModuleError(response.content)
-
-
-class ArgumentSpec(object):
- def __init__(self):
- self.supports_check_mode = True
- argument_spec = dict(
- name=dict(required=True),
- mac_address=dict(),
- ha_order=dict(
- type='list'
- ),
- ha_group=dict(),
- ha_load_factor=dict(
- type='int'
- ),
- auto_failback=dict(
- type='bool',
- ),
- auto_failback_time=dict(
- type='int'
- ),
- state=dict(
- default='present',
- choices=['absent', 'present']
- ),
- partition=dict(
- default='Common',
- fallback=(env_fallback, ['F5_PARTITION'])
- ),
-
- )
- self.argument_spec = {}
- self.argument_spec.update(f5_argument_spec)
- self.argument_spec.update(argument_spec)
-
-
-def main():
- spec = ArgumentSpec()
-
- module = AnsibleModule(
- argument_spec=spec.argument_spec,
- supports_check_mode=spec.supports_check_mode,
- )
-
- try:
- mm = ModuleManager(module=module)
- results = mm.exec_module()
- module.exit_json(**results)
- except F5ModuleError as ex:
- module.fail_json(msg=str(ex))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/f5/bigip_facts.py b/plugins/modules/network/f5/bigip_facts.py
deleted file mode 100644
index 5dc9d498e9..0000000000
--- a/plugins/modules/network/f5/bigip_facts.py
+++ /dev/null
@@ -1,1803 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2017 F5 Networks Inc.
-# Copyright (c) 2013 Matt Hite
-# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['deprecated'],
- 'supported_by': 'certified'}
-
-DOCUMENTATION = r'''
----
-module: bigip_facts
-short_description: Collect facts from F5 BIG-IP devices
-description:
- - Collect facts from F5 BIG-IP devices via iControl SOAP API
-author:
- - Matt Hite (@mhite)
- - Tim Rupp (@caphrim007)
-notes:
- - Requires BIG-IP software version >= 11.4
- - F5 developed module 'bigsuds' required (see http://devcentral.f5.com)
- - Best run as a local_action in your playbook
- - Tested with manager and above account privilege level
- - C(provision) facts were added in 2.2
- - This module is deprecated. Use the C(bigip_device_info) module instead.
-deprecated:
- removed_in: '2.11'
- alternative: bigip_device_info
- why: >
- The bigip_facts module relies on SOAP to communicate with the BIG-IP,
- and has a large amount of code that does not conform to existing F5 standards.
- The M(bigip_device_info) module is easier to maintain and use.
-requirements:
- - bigsuds
-options:
- session:
- description:
- - BIG-IP session support; may be useful to avoid concurrency
- issues in certain circumstances.
- default: no
- type: bool
- include:
- description:
- - Fact category or list of categories to collect
- required: True
- choices:
- - address_class
- - certificate
- - client_ssl_profile
- - device
- - device_group
- - interface
- - key
- - node
- - pool
- - provision
- - rule
- - self_ip
- - software
- - system_info
- - traffic_group
- - trunk
- - virtual_address
- - virtual_server
- - vlan
- filter:
- description:
- - Shell-style glob matching string used to filter fact keys. Not
- applicable for software, provision, and system_info fact categories.
-extends_documentation_fragment:
-- f5networks.f5_modules.f5
-
-'''
-
-EXAMPLES = r'''
-- name: Collect BIG-IP facts
- bigip_facts:
- server: lb.mydomain.com
- user: admin
- password: secret
- include:
- - interface
- - vlan
- delegate_to: localhost
-'''
-
-import fnmatch
-import re
-import traceback
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.six import string_types
-from ansible.module_utils.six.moves import zip
-
-try:
- from library.module_utils.network.f5.legacy import bigip_api, bigsuds_found
- from library.module_utils.network.f5.common import f5_argument_spec
- from library.module_utils.network.f5.common import F5BaseClient
-except ImportError:
- from ansible_collections.community.general.plugins.module_utils.network.f5.legacy import bigip_api, bigsuds_found
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import f5_argument_spec
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import F5BaseClient
-
-try:
- from suds import MethodNotFound, WebFault
-except ImportError:
- pass # Handle via f5_utils.bigsuds_found
-
-
-class F5(object):
- """F5 iControl class.
-
- F5 BIG-IP iControl API class.
-
- Attributes:
- api: iControl API instance.
- """
-
- def __init__(self, host, user, password, session=False, validate_certs=True, port=443):
- self.api = bigip_api(host, user, password, validate_certs, port)
- if session:
- self.start_session()
-
- def start_session(self):
- self.api = self.api.with_session_id()
-
- def get_api(self):
- return self.api
-
- def set_recursive_query_state(self, state):
- self.api.System.Session.set_recursive_query_state(state)
-
- def get_recursive_query_state(self):
- return self.api.System.Session.get_recursive_query_state()
-
- def enable_recursive_query_state(self):
- self.set_recursive_query_state('STATE_ENABLED')
-
- def disable_recursive_query_state(self):
- self.set_recursive_query_state('STATE_DISABLED')
-
- def set_active_folder(self, folder):
- self.api.System.Session.set_active_folder(folder=folder)
-
- def get_active_folder(self):
- return self.api.System.Session.get_active_folder()
-
-
-class Interfaces(object):
- """Interfaces class.
-
- F5 BIG-IP interfaces class.
-
- Attributes:
- api: iControl API instance.
- interfaces: A list of BIG-IP interface names.
- """
-
- def __init__(self, api, regex=None):
- self.api = api
- self.interfaces = api.Networking.Interfaces.get_list()
- if regex:
- re_filter = re.compile(regex)
- self.interfaces = filter(re_filter.search, self.interfaces)
-
- def get_list(self):
- return self.interfaces
-
- def get_active_media(self):
- return self.api.Networking.Interfaces.get_active_media(self.interfaces)
-
- def get_actual_flow_control(self):
- return self.api.Networking.Interfaces.get_actual_flow_control(self.interfaces)
-
- def get_bundle_state(self):
- return self.api.Networking.Interfaces.get_bundle_state(self.interfaces)
-
- def get_description(self):
- return self.api.Networking.Interfaces.get_description(self.interfaces)
-
- def get_dual_media_state(self):
- return self.api.Networking.Interfaces.get_dual_media_state(self.interfaces)
-
- def get_enabled_state(self):
- return self.api.Networking.Interfaces.get_enabled_state(self.interfaces)
-
- def get_if_index(self):
- return self.api.Networking.Interfaces.get_if_index(self.interfaces)
-
- def get_learning_mode(self):
- return self.api.Networking.Interfaces.get_learning_mode(self.interfaces)
-
- def get_lldp_admin_status(self):
- return self.api.Networking.Interfaces.get_lldp_admin_status(self.interfaces)
-
- def get_lldp_tlvmap(self):
- return self.api.Networking.Interfaces.get_lldp_tlvmap(self.interfaces)
-
- def get_mac_address(self):
- return self.api.Networking.Interfaces.get_mac_address(self.interfaces)
-
- def get_media(self):
- return self.api.Networking.Interfaces.get_media(self.interfaces)
-
- def get_media_option(self):
- return self.api.Networking.Interfaces.get_media_option(self.interfaces)
-
- def get_media_option_sfp(self):
- return self.api.Networking.Interfaces.get_media_option_sfp(self.interfaces)
-
- def get_media_sfp(self):
- return self.api.Networking.Interfaces.get_media_sfp(self.interfaces)
-
- def get_media_speed(self):
- return self.api.Networking.Interfaces.get_media_speed(self.interfaces)
-
- def get_media_status(self):
- return self.api.Networking.Interfaces.get_media_status(self.interfaces)
-
- def get_mtu(self):
- return self.api.Networking.Interfaces.get_mtu(self.interfaces)
-
- def get_phy_master_slave_mode(self):
- return self.api.Networking.Interfaces.get_phy_master_slave_mode(self.interfaces)
-
- def get_prefer_sfp_state(self):
- return self.api.Networking.Interfaces.get_prefer_sfp_state(self.interfaces)
-
- def get_flow_control(self):
- return self.api.Networking.Interfaces.get_requested_flow_control(self.interfaces)
-
- def get_sflow_poll_interval(self):
- return self.api.Networking.Interfaces.get_sflow_poll_interval(self.interfaces)
-
- def get_sflow_poll_interval_global(self):
- return self.api.Networking.Interfaces.get_sflow_poll_interval_global(self.interfaces)
-
- def get_sfp_media_state(self):
- return self.api.Networking.Interfaces.get_sfp_media_state(self.interfaces)
-
- def get_stp_active_edge_port_state(self):
- return self.api.Networking.Interfaces.get_stp_active_edge_port_state(self.interfaces)
-
- def get_stp_enabled_state(self):
- return self.api.Networking.Interfaces.get_stp_enabled_state(self.interfaces)
-
- def get_stp_link_type(self):
- return self.api.Networking.Interfaces.get_stp_link_type(self.interfaces)
-
- def get_stp_protocol_detection_reset_state(self):
- return self.api.Networking.Interfaces.get_stp_protocol_detection_reset_state(self.interfaces)
-
-
-class SelfIPs(object):
- """Self IPs class.
-
- F5 BIG-IP Self IPs class.
-
- Attributes:
- api: iControl API instance.
- self_ips: List of self IPs.
- """
-
- def __init__(self, api, regex=None):
- self.api = api
- self.self_ips = api.Networking.SelfIPV2.get_list()
- if regex:
- re_filter = re.compile(regex)
- self.self_ips = filter(re_filter.search, self.self_ips)
-
- def get_list(self):
- return self.self_ips
-
- def get_address(self):
- return self.api.Networking.SelfIPV2.get_address(self.self_ips)
-
- def get_allow_access_list(self):
- return self.api.Networking.SelfIPV2.get_allow_access_list(self.self_ips)
-
- def get_description(self):
- return self.api.Networking.SelfIPV2.get_description(self.self_ips)
-
- def get_enforced_firewall_policy(self):
- return self.api.Networking.SelfIPV2.get_enforced_firewall_policy(self.self_ips)
-
- def get_floating_state(self):
- return self.api.Networking.SelfIPV2.get_floating_state(self.self_ips)
-
- def get_fw_rule(self):
- return self.api.Networking.SelfIPV2.get_fw_rule(self.self_ips)
-
- def get_netmask(self):
- return self.api.Networking.SelfIPV2.get_netmask(self.self_ips)
-
- def get_staged_firewall_policy(self):
- return self.api.Networking.SelfIPV2.get_staged_firewall_policy(self.self_ips)
-
- def get_traffic_group(self):
- return self.api.Networking.SelfIPV2.get_traffic_group(self.self_ips)
-
- def get_vlan(self):
- return self.api.Networking.SelfIPV2.get_vlan(self.self_ips)
-
- def get_is_traffic_group_inherited(self):
- return self.api.Networking.SelfIPV2.is_traffic_group_inherited(self.self_ips)
-
-
-class Trunks(object):
- """Trunks class.
-
- F5 BIG-IP trunks class.
-
- Attributes:
- api: iControl API instance.
- trunks: List of trunks.
- """
-
- def __init__(self, api, regex=None):
- self.api = api
- self.trunks = api.Networking.Trunk.get_list()
- if regex:
- re_filter = re.compile(regex)
- self.trunks = filter(re_filter.search, self.trunks)
-
- def get_list(self):
- return self.trunks
-
- def get_active_lacp_state(self):
- return self.api.Networking.Trunk.get_active_lacp_state(self.trunks)
-
- def get_configured_member_count(self):
- return self.api.Networking.Trunk.get_configured_member_count(self.trunks)
-
- def get_description(self):
- return self.api.Networking.Trunk.get_description(self.trunks)
-
- def get_distribution_hash_option(self):
- return self.api.Networking.Trunk.get_distribution_hash_option(self.trunks)
-
- def get_interface(self):
- return self.api.Networking.Trunk.get_interface(self.trunks)
-
- def get_lacp_enabled_state(self):
- return self.api.Networking.Trunk.get_lacp_enabled_state(self.trunks)
-
- def get_lacp_timeout_option(self):
- return self.api.Networking.Trunk.get_lacp_timeout_option(self.trunks)
-
- def get_link_selection_policy(self):
- return self.api.Networking.Trunk.get_link_selection_policy(self.trunks)
-
- def get_media_speed(self):
- return self.api.Networking.Trunk.get_media_speed(self.trunks)
-
- def get_media_status(self):
- return self.api.Networking.Trunk.get_media_status(self.trunks)
-
- def get_operational_member_count(self):
- return self.api.Networking.Trunk.get_operational_member_count(self.trunks)
-
- def get_stp_enabled_state(self):
- return self.api.Networking.Trunk.get_stp_enabled_state(self.trunks)
-
- def get_stp_protocol_detection_reset_state(self):
- return self.api.Networking.Trunk.get_stp_protocol_detection_reset_state(self.trunks)
-
-
-class Vlans(object):
- """Vlans class.
-
- F5 BIG-IP Vlans class.
-
- Attributes:
- api: iControl API instance.
- vlans: List of VLANs.
- """
-
- def __init__(self, api, regex=None):
- self.api = api
- self.vlans = api.Networking.VLAN.get_list()
- if regex:
- re_filter = re.compile(regex)
- self.vlans = filter(re_filter.search, self.vlans)
-
- def get_list(self):
- return self.vlans
-
- def get_auto_lasthop(self):
- return self.api.Networking.VLAN.get_auto_lasthop(self.vlans)
-
- def get_cmp_hash_algorithm(self):
- return self.api.Networking.VLAN.get_cmp_hash_algorithm(self.vlans)
-
- def get_description(self):
- return self.api.Networking.VLAN.get_description(self.vlans)
-
- def get_dynamic_forwarding(self):
- return self.api.Networking.VLAN.get_dynamic_forwarding(self.vlans)
-
- def get_failsafe_action(self):
- return self.api.Networking.VLAN.get_failsafe_action(self.vlans)
-
- def get_failsafe_state(self):
- return self.api.Networking.VLAN.get_failsafe_state(self.vlans)
-
- def get_failsafe_timeout(self):
- return self.api.Networking.VLAN.get_failsafe_timeout(self.vlans)
-
- def get_if_index(self):
- return self.api.Networking.VLAN.get_if_index(self.vlans)
-
- def get_learning_mode(self):
- return self.api.Networking.VLAN.get_learning_mode(self.vlans)
-
- def get_mac_masquerade_address(self):
- return self.api.Networking.VLAN.get_mac_masquerade_address(self.vlans)
-
- def get_member(self):
- return self.api.Networking.VLAN.get_member(self.vlans)
-
- def get_mtu(self):
- return self.api.Networking.VLAN.get_mtu(self.vlans)
-
- def get_sflow_poll_interval(self):
- return self.api.Networking.VLAN.get_sflow_poll_interval(self.vlans)
-
- def get_sflow_poll_interval_global(self):
- return self.api.Networking.VLAN.get_sflow_poll_interval_global(self.vlans)
-
- def get_sflow_sampling_rate(self):
- return self.api.Networking.VLAN.get_sflow_sampling_rate(self.vlans)
-
- def get_sflow_sampling_rate_global(self):
- return self.api.Networking.VLAN.get_sflow_sampling_rate_global(self.vlans)
-
- def get_source_check_state(self):
- return self.api.Networking.VLAN.get_source_check_state(self.vlans)
-
- def get_true_mac_address(self):
- return self.api.Networking.VLAN.get_true_mac_address(self.vlans)
-
- def get_vlan_id(self):
- return self.api.Networking.VLAN.get_vlan_id(self.vlans)
-
-
-class Software(object):
- """Software class.
-
- F5 BIG-IP software class.
-
- Attributes:
- api: iControl API instance.
- """
-
- def __init__(self, api):
- self.api = api
-
- def get_all_software_status(self):
- return self.api.System.SoftwareManagement.get_all_software_status()
-
-
-class VirtualServers(object):
- """Virtual servers class.
-
- F5 BIG-IP virtual servers class.
-
- Attributes:
- api: iControl API instance.
- virtual_servers: List of virtual servers.
- """
-
- def __init__(self, api, regex=None):
- self.api = api
- self.virtual_servers = api.LocalLB.VirtualServer.get_list()
- if regex:
- re_filter = re.compile(regex)
- self.virtual_servers = filter(re_filter.search, self.virtual_servers)
-
- def get_list(self):
- return self.virtual_servers
-
- def get_name(self):
- return [x[x.rfind('/') + 1:] for x in self.virtual_servers]
-
- def get_actual_hardware_acceleration(self):
- return self.api.LocalLB.VirtualServer.get_actual_hardware_acceleration(self.virtual_servers)
-
- def get_authentication_profile(self):
- return self.api.LocalLB.VirtualServer.get_authentication_profile(self.virtual_servers)
-
- def get_auto_lasthop(self):
- return self.api.LocalLB.VirtualServer.get_auto_lasthop(self.virtual_servers)
-
- def get_bw_controller_policy(self):
- return self.api.LocalLB.VirtualServer.get_bw_controller_policy(self.virtual_servers)
-
- def get_clone_pool(self):
- return self.api.LocalLB.VirtualServer.get_clone_pool(self.virtual_servers)
-
- def get_cmp_enable_mode(self):
- return self.api.LocalLB.VirtualServer.get_cmp_enable_mode(self.virtual_servers)
-
- def get_connection_limit(self):
- return self.api.LocalLB.VirtualServer.get_connection_limit(self.virtual_servers)
-
- def get_connection_mirror_state(self):
- return self.api.LocalLB.VirtualServer.get_connection_mirror_state(self.virtual_servers)
-
- def get_default_pool_name(self):
- return self.api.LocalLB.VirtualServer.get_default_pool_name(self.virtual_servers)
-
- def get_description(self):
- return self.api.LocalLB.VirtualServer.get_description(self.virtual_servers)
-
- def get_destination(self):
- return self.api.LocalLB.VirtualServer.get_destination_v2(self.virtual_servers)
-
- def get_enabled_state(self):
- return self.api.LocalLB.VirtualServer.get_enabled_state(self.virtual_servers)
-
- def get_enforced_firewall_policy(self):
- return self.api.LocalLB.VirtualServer.get_enforced_firewall_policy(self.virtual_servers)
-
- def get_fallback_persistence_profile(self):
- return self.api.LocalLB.VirtualServer.get_fallback_persistence_profile(self.virtual_servers)
-
- def get_fw_rule(self):
- return self.api.LocalLB.VirtualServer.get_fw_rule(self.virtual_servers)
-
- def get_gtm_score(self):
- return self.api.LocalLB.VirtualServer.get_gtm_score(self.virtual_servers)
-
- def get_last_hop_pool(self):
- return self.api.LocalLB.VirtualServer.get_last_hop_pool(self.virtual_servers)
-
- def get_nat64_state(self):
- return self.api.LocalLB.VirtualServer.get_nat64_state(self.virtual_servers)
-
- def get_object_status(self):
- return self.api.LocalLB.VirtualServer.get_object_status(self.virtual_servers)
-
- def get_persistence_profile(self):
- return self.api.LocalLB.VirtualServer.get_persistence_profile(self.virtual_servers)
-
- def get_profile(self):
- return self.api.LocalLB.VirtualServer.get_profile(self.virtual_servers)
-
- def get_protocol(self):
- return self.api.LocalLB.VirtualServer.get_protocol(self.virtual_servers)
-
- def get_rate_class(self):
- return self.api.LocalLB.VirtualServer.get_rate_class(self.virtual_servers)
-
- def get_rate_limit(self):
- return self.api.LocalLB.VirtualServer.get_rate_limit(self.virtual_servers)
-
- def get_rate_limit_destination_mask(self):
- return self.api.LocalLB.VirtualServer.get_rate_limit_destination_mask(self.virtual_servers)
-
- def get_rate_limit_mode(self):
- return self.api.LocalLB.VirtualServer.get_rate_limit_mode(self.virtual_servers)
-
- def get_rate_limit_source_mask(self):
- return self.api.LocalLB.VirtualServer.get_rate_limit_source_mask(self.virtual_servers)
-
- def get_related_rule(self):
- return self.api.LocalLB.VirtualServer.get_related_rule(self.virtual_servers)
-
- def get_rule(self):
- return self.api.LocalLB.VirtualServer.get_rule(self.virtual_servers)
-
- def get_security_log_profile(self):
- return self.api.LocalLB.VirtualServer.get_security_log_profile(self.virtual_servers)
-
- def get_snat_pool(self):
- return self.api.LocalLB.VirtualServer.get_snat_pool(self.virtual_servers)
-
- def get_snat_type(self):
- return self.api.LocalLB.VirtualServer.get_snat_type(self.virtual_servers)
-
- def get_source_address(self):
- return self.api.LocalLB.VirtualServer.get_source_address(self.virtual_servers)
-
- def get_source_address_translation_lsn_pool(self):
- return self.api.LocalLB.VirtualServer.get_source_address_translation_lsn_pool(self.virtual_servers)
-
- def get_source_address_translation_snat_pool(self):
- return self.api.LocalLB.VirtualServer.get_source_address_translation_snat_pool(self.virtual_servers)
-
- def get_source_address_translation_type(self):
- return self.api.LocalLB.VirtualServer.get_source_address_translation_type(self.virtual_servers)
-
- def get_source_port_behavior(self):
- return self.api.LocalLB.VirtualServer.get_source_port_behavior(self.virtual_servers)
-
- def get_staged_firewall_policy(self):
- return self.api.LocalLB.VirtualServer.get_staged_firewall_policy(self.virtual_servers)
-
- def get_translate_address_state(self):
- return self.api.LocalLB.VirtualServer.get_translate_address_state(self.virtual_servers)
-
- def get_translate_port_state(self):
- return self.api.LocalLB.VirtualServer.get_translate_port_state(self.virtual_servers)
-
- def get_type(self):
- return self.api.LocalLB.VirtualServer.get_type(self.virtual_servers)
-
- def get_vlan(self):
- return self.api.LocalLB.VirtualServer.get_vlan(self.virtual_servers)
-
- def get_wildmask(self):
- return self.api.LocalLB.VirtualServer.get_wildmask(self.virtual_servers)
-
-
-class Pools(object):
- """Pools class.
-
- F5 BIG-IP pools class.
-
- Attributes:
- api: iControl API instance.
- pool_names: List of pool names.
- """
-
- def __init__(self, api, regex=None):
- self.api = api
- self.pool_names = api.LocalLB.Pool.get_list()
- if regex:
- re_filter = re.compile(regex)
- self.pool_names = filter(re_filter.search, self.pool_names)
-
- def get_list(self):
- return self.pool_names
-
- def get_name(self):
- return [x[x.rfind('/') + 1:] for x in self.pool_names]
-
- def get_action_on_service_down(self):
- return self.api.LocalLB.Pool.get_action_on_service_down(self.pool_names)
-
- def get_active_member_count(self):
- return self.api.LocalLB.Pool.get_active_member_count(self.pool_names)
-
- def get_aggregate_dynamic_ratio(self):
- return self.api.LocalLB.Pool.get_aggregate_dynamic_ratio(self.pool_names)
-
- def get_allow_nat_state(self):
- return self.api.LocalLB.Pool.get_allow_nat_state(self.pool_names)
-
- def get_allow_snat_state(self):
- return self.api.LocalLB.Pool.get_allow_snat_state(self.pool_names)
-
- def get_client_ip_tos(self):
- return self.api.LocalLB.Pool.get_client_ip_tos(self.pool_names)
-
- def get_client_link_qos(self):
- return self.api.LocalLB.Pool.get_client_link_qos(self.pool_names)
-
- def get_description(self):
- return self.api.LocalLB.Pool.get_description(self.pool_names)
-
- def get_gateway_failsafe_device(self):
- return self.api.LocalLB.Pool.get_gateway_failsafe_device(self.pool_names)
-
- def get_ignore_persisted_weight_state(self):
- return self.api.LocalLB.Pool.get_ignore_persisted_weight_state(self.pool_names)
-
- def get_lb_method(self):
- result = []
- lb_choice = dict(
- LB_METHOD_DYNAMIC_RATIO_MEMBER='dynamic-ratio-member',
- LB_METHOD_DYNAMIC_RATIO='dynamic-ratio-node',
- LB_METHOD_FASTEST_APP_RESPONSE='fastest-app-response',
- LB_METHOD_FASTEST_NODE_ADDRESS='fastest-node',
- LB_METHOD_LEAST_CONNECTION_MEMBER='least-connections-member',
- LB_METHOD_LEAST_CONNECTION_NODE_ADDRESS='least-connections-node',
- LB_METHOD_LEAST_SESSIONS='least-sessions',
- LB_METHOD_OBSERVED_MEMBER='observed-member',
- LB_METHOD_OBSERVED_NODE_ADDRESS='observed-node',
- LB_METHOD_PREDICTIVE_MEMBER='predictive-member',
- LB_METHOD_PREDICTIVE_NODE_ADDRESS='predictive-node',
- LB_METHOD_RATIO_LEAST_CONNECTION_MEMBER='ratio-least-connections-member',
- LB_METHOD_RATIO_LEAST_CONNECTION_NODE_ADDRESS='ratio-least-connections-node',
- LB_METHOD_RATIO_MEMBER='ratio-member',
- LB_METHOD_RATIO_NODE_ADDRESS='ratio-node',
- LB_METHOD_RATIO_SESSION='ratio-session',
- LB_METHOD_ROUND_ROBIN='round-robin',
- LB_METHOD_WEIGHTED_LEAST_CONNECTION_MEMBER='weighted-least-connections-member',
- LB_METHOD_WEIGHTED_LEAST_CONNECTION_NODE_ADDRESS='weighted-least-connections-node'
- )
- methods = self.api.LocalLB.Pool.get_lb_method(self.pool_names)
- for method in methods:
- result.append(lb_choice.get(method, method))
- return result
-
- def get_member(self):
- return self.api.LocalLB.Pool.get_member_v2(self.pool_names)
-
- def get_minimum_active_member(self):
- return self.api.LocalLB.Pool.get_minimum_active_member(self.pool_names)
-
- def get_minimum_up_member(self):
- return self.api.LocalLB.Pool.get_minimum_up_member(self.pool_names)
-
- def get_minimum_up_member_action(self):
- return self.api.LocalLB.Pool.get_minimum_up_member_action(self.pool_names)
-
- def get_minimum_up_member_enabled_state(self):
- return self.api.LocalLB.Pool.get_minimum_up_member_enabled_state(self.pool_names)
-
- def get_monitor_association(self):
- return self.api.LocalLB.Pool.get_monitor_association(self.pool_names)
-
- def get_monitor_instance(self):
- return self.api.LocalLB.Pool.get_monitor_instance(self.pool_names)
-
- def get_object_status(self):
- return self.api.LocalLB.Pool.get_object_status(self.pool_names)
-
- def get_profile(self):
- return self.api.LocalLB.Pool.get_profile(self.pool_names)
-
- def get_queue_depth_limit(self):
- return self.api.LocalLB.Pool.get_queue_depth_limit(self.pool_names)
-
- def get_queue_on_connection_limit_state(self):
- return self.api.LocalLB.Pool.get_queue_on_connection_limit_state(self.pool_names)
-
- def get_queue_time_limit(self):
- return self.api.LocalLB.Pool.get_queue_time_limit(self.pool_names)
-
- def get_reselect_tries(self):
- return self.api.LocalLB.Pool.get_reselect_tries(self.pool_names)
-
- def get_server_ip_tos(self):
- return self.api.LocalLB.Pool.get_server_ip_tos(self.pool_names)
-
- def get_server_link_qos(self):
- return self.api.LocalLB.Pool.get_server_link_qos(self.pool_names)
-
- def get_simple_timeout(self):
- return self.api.LocalLB.Pool.get_simple_timeout(self.pool_names)
-
- def get_slow_ramp_time(self):
- return self.api.LocalLB.Pool.get_slow_ramp_time(self.pool_names)
-
-
-class Devices(object):
- """Devices class.
-
- F5 BIG-IP devices class.
-
- Attributes:
- api: iControl API instance.
- devices: List of devices.
- """
-
- def __init__(self, api, regex=None):
- self.api = api
- self.devices = api.Management.Device.get_list()
- if regex:
- re_filter = re.compile(regex)
- self.devices = filter(re_filter.search, self.devices)
-
- def get_list(self):
- return self.devices
-
- def get_active_modules(self):
- return self.api.Management.Device.get_active_modules(self.devices)
-
- def get_base_mac_address(self):
- return self.api.Management.Device.get_base_mac_address(self.devices)
-
- def get_blade_addresses(self):
- return self.api.Management.Device.get_blade_addresses(self.devices)
-
- def get_build(self):
- return self.api.Management.Device.get_build(self.devices)
-
- def get_chassis_id(self):
- return self.api.Management.Device.get_chassis_id(self.devices)
-
- def get_chassis_type(self):
- return self.api.Management.Device.get_chassis_type(self.devices)
-
- def get_comment(self):
- return self.api.Management.Device.get_comment(self.devices)
-
- def get_configsync_address(self):
- return self.api.Management.Device.get_configsync_address(self.devices)
-
- def get_contact(self):
- return self.api.Management.Device.get_contact(self.devices)
-
- def get_description(self):
- return self.api.Management.Device.get_description(self.devices)
-
- def get_edition(self):
- return self.api.Management.Device.get_edition(self.devices)
-
- def get_failover_state(self):
- return self.api.Management.Device.get_failover_state(self.devices)
-
- def get_local_device(self):
- return self.api.Management.Device.get_local_device()
-
- def get_hostname(self):
- return self.api.Management.Device.get_hostname(self.devices)
-
- def get_inactive_modules(self):
- return self.api.Management.Device.get_inactive_modules(self.devices)
-
- def get_location(self):
- return self.api.Management.Device.get_location(self.devices)
-
- def get_management_address(self):
- return self.api.Management.Device.get_management_address(self.devices)
-
- def get_marketing_name(self):
- return self.api.Management.Device.get_marketing_name(self.devices)
-
- def get_multicast_address(self):
- return self.api.Management.Device.get_multicast_address(self.devices)
-
- def get_optional_modules(self):
- return self.api.Management.Device.get_optional_modules(self.devices)
-
- def get_platform_id(self):
- return self.api.Management.Device.get_platform_id(self.devices)
-
- def get_primary_mirror_address(self):
- return self.api.Management.Device.get_primary_mirror_address(self.devices)
-
- def get_product(self):
- return self.api.Management.Device.get_product(self.devices)
-
- def get_secondary_mirror_address(self):
- return self.api.Management.Device.get_secondary_mirror_address(self.devices)
-
- def get_software_version(self):
- return self.api.Management.Device.get_software_version(self.devices)
-
- def get_timelimited_modules(self):
- return self.api.Management.Device.get_timelimited_modules(self.devices)
-
- def get_timezone(self):
- return self.api.Management.Device.get_timezone(self.devices)
-
- def get_unicast_addresses(self):
- return self.api.Management.Device.get_unicast_addresses(self.devices)
-
-
-class DeviceGroups(object):
- """Device groups class.
-
- F5 BIG-IP device groups class.
-
- Attributes:
- api: iControl API instance.
- device_groups: List of device groups.
- """
-
- def __init__(self, api, regex=None):
- self.api = api
- self.device_groups = api.Management.DeviceGroup.get_list()
- if regex:
- re_filter = re.compile(regex)
- self.device_groups = filter(re_filter.search, self.device_groups)
-
- def get_list(self):
- return self.device_groups
-
- def get_all_preferred_active(self):
- return self.api.Management.DeviceGroup.get_all_preferred_active(self.device_groups)
-
- def get_autosync_enabled_state(self):
- return self.api.Management.DeviceGroup.get_autosync_enabled_state(self.device_groups)
-
- def get_description(self):
- return self.api.Management.DeviceGroup.get_description(self.device_groups)
-
- def get_device(self):
- return self.api.Management.DeviceGroup.get_device(self.device_groups)
-
- def get_full_load_on_sync_state(self):
- return self.api.Management.DeviceGroup.get_full_load_on_sync_state(self.device_groups)
-
- def get_incremental_config_sync_size_maximum(self):
- return self.api.Management.DeviceGroup.get_incremental_config_sync_size_maximum(self.device_groups)
-
- def get_network_failover_enabled_state(self):
- return self.api.Management.DeviceGroup.get_network_failover_enabled_state(self.device_groups)
-
- def get_sync_status(self):
- return self.api.Management.DeviceGroup.get_sync_status(self.device_groups)
-
- def get_type(self):
- return self.api.Management.DeviceGroup.get_type(self.device_groups)
-
-
-class TrafficGroups(object):
- """Traffic groups class.
-
- F5 BIG-IP traffic groups class.
-
- Attributes:
- api: iControl API instance.
- traffic_groups: List of traffic groups.
- """
-
- def __init__(self, api, regex=None):
- self.api = api
- self.traffic_groups = api.Management.TrafficGroup.get_list()
- if regex:
- re_filter = re.compile(regex)
- self.traffic_groups = filter(re_filter.search, self.traffic_groups)
-
- def get_list(self):
- return self.traffic_groups
-
- def get_auto_failback_enabled_state(self):
- return self.api.Management.TrafficGroup.get_auto_failback_enabled_state(self.traffic_groups)
-
- def get_auto_failback_time(self):
- return self.api.Management.TrafficGroup.get_auto_failback_time(self.traffic_groups)
-
- def get_default_device(self):
- return self.api.Management.TrafficGroup.get_default_device(self.traffic_groups)
-
- def get_description(self):
- return self.api.Management.TrafficGroup.get_description(self.traffic_groups)
-
- def get_ha_load_factor(self):
- return self.api.Management.TrafficGroup.get_ha_load_factor(self.traffic_groups)
-
- def get_ha_order(self):
- return self.api.Management.TrafficGroup.get_ha_order(self.traffic_groups)
-
- def get_is_floating(self):
- return self.api.Management.TrafficGroup.get_is_floating(self.traffic_groups)
-
- def get_mac_masquerade_address(self):
- return self.api.Management.TrafficGroup.get_mac_masquerade_address(self.traffic_groups)
-
- def get_unit_id(self):
- return self.api.Management.TrafficGroup.get_unit_id(self.traffic_groups)
-
-
-class Rules(object):
- """Rules class.
-
- F5 BIG-IP iRules class.
-
- Attributes:
- api: iControl API instance.
- rules: List of iRules.
- """
-
- def __init__(self, api, regex=None):
- self.api = api
- self.rules = api.LocalLB.Rule.get_list()
- if regex:
- re_filter = re.compile(regex)
- self.traffic_groups = filter(re_filter.search, self.rules)
-
- def get_list(self):
- return self.rules
-
- def get_description(self):
- return self.api.LocalLB.Rule.get_description(rule_names=self.rules)
-
- def get_ignore_vertification(self):
- return self.api.LocalLB.Rule.get_ignore_vertification(rule_names=self.rules)
-
- def get_verification_status(self):
- return self.api.LocalLB.Rule.get_verification_status_v2(rule_names=self.rules)
-
- def get_definition(self):
- return [x['rule_definition'] for x in self.api.LocalLB.Rule.query_rule(rule_names=self.rules)]
-
-
-class Nodes(object):
- """Nodes class.
-
- F5 BIG-IP nodes class.
-
- Attributes:
- api: iControl API instance.
- nodes: List of nodes.
- """
-
- def __init__(self, api, regex=None):
- self.api = api
- self.nodes = api.LocalLB.NodeAddressV2.get_list()
- if regex:
- re_filter = re.compile(regex)
- self.nodes = filter(re_filter.search, self.nodes)
-
- def get_list(self):
- return self.nodes
-
- def get_address(self):
- return self.api.LocalLB.NodeAddressV2.get_address(nodes=self.nodes)
-
- def get_name(self):
- return [x[x.rfind('/') + 1:] for x in self.nodes]
-
- def get_connection_limit(self):
- return self.api.LocalLB.NodeAddressV2.get_connection_limit(nodes=self.nodes)
-
- def get_description(self):
- return self.api.LocalLB.NodeAddressV2.get_description(nodes=self.nodes)
-
- def get_dynamic_ratio(self):
- return self.api.LocalLB.NodeAddressV2.get_dynamic_ratio_v2(nodes=self.nodes)
-
- def get_monitor_instance(self):
- return self.api.LocalLB.NodeAddressV2.get_monitor_instance(nodes=self.nodes)
-
- def get_monitor_rule(self):
- return self.api.LocalLB.NodeAddressV2.get_monitor_rule(nodes=self.nodes)
-
- def get_monitor_status(self):
- return self.api.LocalLB.NodeAddressV2.get_monitor_status(nodes=self.nodes)
-
- def get_object_status(self):
- return self.api.LocalLB.NodeAddressV2.get_object_status(nodes=self.nodes)
-
- def get_rate_limit(self):
- return self.api.LocalLB.NodeAddressV2.get_rate_limit(nodes=self.nodes)
-
- def get_ratio(self):
- return self.api.LocalLB.NodeAddressV2.get_ratio(nodes=self.nodes)
-
- def get_session_status(self):
- return self.api.LocalLB.NodeAddressV2.get_session_status(nodes=self.nodes)
-
-
-class VirtualAddresses(object):
- """Virtual addresses class.
-
- F5 BIG-IP virtual addresses class.
-
- Attributes:
- api: iControl API instance.
- virtual_addresses: List of virtual addresses.
- """
-
- def __init__(self, api, regex=None):
- self.api = api
- self.virtual_addresses = api.LocalLB.VirtualAddressV2.get_list()
- if regex:
- re_filter = re.compile(regex)
- self.virtual_addresses = filter(re_filter.search, self.virtual_addresses)
-
- def get_list(self):
- return self.virtual_addresses
-
- def get_address(self):
- return self.api.LocalLB.VirtualAddressV2.get_address(self.virtual_addresses)
-
- def get_arp_state(self):
- return self.api.LocalLB.VirtualAddressV2.get_arp_state(self.virtual_addresses)
-
- def get_auto_delete_state(self):
- return self.api.LocalLB.VirtualAddressV2.get_auto_delete_state(self.virtual_addresses)
-
- def get_connection_limit(self):
- return self.api.LocalLB.VirtualAddressV2.get_connection_limit(self.virtual_addresses)
-
- def get_description(self):
- return self.api.LocalLB.VirtualAddressV2.get_description(self.virtual_addresses)
-
- def get_enabled_state(self):
- return self.api.LocalLB.VirtualAddressV2.get_enabled_state(self.virtual_addresses)
-
- def get_icmp_echo_state(self):
- return self.api.LocalLB.VirtualAddressV2.get_icmp_echo_state(self.virtual_addresses)
-
- def get_is_floating_state(self):
- return self.api.LocalLB.VirtualAddressV2.get_is_floating_state(self.virtual_addresses)
-
- def get_netmask(self):
- return self.api.LocalLB.VirtualAddressV2.get_netmask(self.virtual_addresses)
-
- def get_object_status(self):
- return self.api.LocalLB.VirtualAddressV2.get_object_status(self.virtual_addresses)
-
- def get_route_advertisement_state(self):
- return self.api.LocalLB.VirtualAddressV2.get_route_advertisement_state(self.virtual_addresses)
-
- def get_traffic_group(self):
- return self.api.LocalLB.VirtualAddressV2.get_traffic_group(self.virtual_addresses)
-
-
-class AddressClasses(object):
- """Address group/class class.
-
- F5 BIG-IP address group/class class.
-
- In TMUI these things are known as Address Data Groups. Examples that ship with the
- box include /Common/aol and /Common/private_net
-
- Attributes:
- api: iControl API instance.
- address_classes: List of address classes.
- """
-
- def __init__(self, api, regex=None):
- self.api = api
- self.address_classes = api.LocalLB.Class.get_address_class_list()
- if regex:
- re_filter = re.compile(regex)
- self.address_classes = filter(re_filter.search, self.address_classes)
-
- def get_list(self):
- return self.address_classes
-
- def get_address_class(self):
- key = self.api.LocalLB.Class.get_address_class(self.address_classes)
- value = self.api.LocalLB.Class.get_address_class_member_data_value(key)
-
- result = []
- for idx, v in enumerate(key):
- for idx2, member in enumerate(v['members']):
- dg_value = dict(
- value=value[idx][idx2]
- )
- dg_value.update(member)
- result.append(dg_value)
- return result
-
- def get_description(self):
- return self.api.LocalLB.Class.get_description(self.address_classes)
-
-
-class Certificates(object):
- """Certificates class.
-
- F5 BIG-IP certificates class.
-
- Attributes:
- api: iControl API instance.
- certificates: List of certificate identifiers.
- certificate_list: List of certificate information structures.
- """
-
- def __init__(self, api, regex=None, mode="MANAGEMENT_MODE_DEFAULT"):
- self.api = api
- self.certificate_list = api.Management.KeyCertificate.get_certificate_list(mode=mode)
- self.certificates = [x['certificate']['cert_info']['id'] for x in self.certificate_list]
- if regex:
- re_filter = re.compile(regex)
- self.certificates = filter(re_filter.search, self.certificates)
- self.certificate_list = [x for x in self.certificate_list if x['certificate']['cert_info']['id'] in self.certificates]
-
- def get_list(self):
- return self.certificates
-
- def get_certificate_list(self):
- return self.certificate_list
-
-
-class Keys(object):
- """Keys class.
-
- F5 BIG-IP keys class.
-
- Attributes:
- api: iControl API instance.
- keys: List of key identifiers.
- key_list: List of key information structures.
- """
-
- def __init__(self, api, regex=None, mode="MANAGEMENT_MODE_DEFAULT"):
- self.api = api
- self.key_list = api.Management.KeyCertificate.get_key_list(mode=mode)
- self.keys = [x['key_info']['id'] for x in self.key_list]
- if regex:
- re_filter = re.compile(regex)
- self.keys = filter(re_filter.search, self.keys)
- self.key_list = [x for x in self.key_list if x['key_info']['id'] in self.keys]
-
- def get_list(self):
- return self.keys
-
- def get_key_list(self):
- return self.key_list
-
-
-class ProfileClientSSL(object):
- """Client SSL profiles class.
-
- F5 BIG-IP client SSL profiles class.
-
- Attributes:
- api: iControl API instance.
- profiles: List of client SSL profiles.
- """
-
- def __init__(self, api, regex=None):
- self.api = api
- self.profiles = api.LocalLB.ProfileClientSSL.get_list()
- if regex:
- re_filter = re.compile(regex)
- self.profiles = filter(re_filter.search, self.profiles)
-
- def get_list(self):
- return self.profiles
-
- def get_alert_timeout(self):
- return self.api.LocalLB.ProfileClientSSL.get_alert_timeout(self.profiles)
-
- def get_allow_nonssl_state(self):
- return self.api.LocalLB.ProfileClientSSL.get_allow_nonssl_state(self.profiles)
-
- def get_authenticate_depth(self):
- return self.api.LocalLB.ProfileClientSSL.get_authenticate_depth(self.profiles)
-
- def get_authenticate_once_state(self):
- return self.api.LocalLB.ProfileClientSSL.get_authenticate_once_state(self.profiles)
-
- def get_ca_file(self):
- return self.api.LocalLB.ProfileClientSSL.get_ca_file_v2(self.profiles)
-
- def get_cache_size(self):
- return self.api.LocalLB.ProfileClientSSL.get_cache_size(self.profiles)
-
- def get_cache_timeout(self):
- return self.api.LocalLB.ProfileClientSSL.get_cache_timeout(self.profiles)
-
- def get_certificate_file(self):
- return self.api.LocalLB.ProfileClientSSL.get_certificate_file_v2(self.profiles)
-
- def get_chain_file(self):
- return self.api.LocalLB.ProfileClientSSL.get_chain_file_v2(self.profiles)
-
- def get_cipher_list(self):
- return self.api.LocalLB.ProfileClientSSL.get_cipher_list(self.profiles)
-
- def get_client_certificate_ca_file(self):
- return self.api.LocalLB.ProfileClientSSL.get_client_certificate_ca_file_v2(self.profiles)
-
- def get_crl_file(self):
- return self.api.LocalLB.ProfileClientSSL.get_crl_file_v2(self.profiles)
-
- def get_default_profile(self):
- return self.api.LocalLB.ProfileClientSSL.get_default_profile(self.profiles)
-
- def get_description(self):
- return self.api.LocalLB.ProfileClientSSL.get_description(self.profiles)
-
- def get_forward_proxy_ca_certificate_file(self):
- return self.api.LocalLB.ProfileClientSSL.get_forward_proxy_ca_certificate_file(self.profiles)
-
- def get_forward_proxy_ca_key_file(self):
- return self.api.LocalLB.ProfileClientSSL.get_forward_proxy_ca_key_file(self.profiles)
-
- def get_forward_proxy_ca_passphrase(self):
- return self.api.LocalLB.ProfileClientSSL.get_forward_proxy_ca_passphrase(self.profiles)
-
- def get_forward_proxy_certificate_extension_include(self):
- return self.api.LocalLB.ProfileClientSSL.get_forward_proxy_certificate_extension_include(self.profiles)
-
- def get_forward_proxy_certificate_lifespan(self):
- return self.api.LocalLB.ProfileClientSSL.get_forward_proxy_certificate_lifespan(self.profiles)
-
- def get_forward_proxy_enabled_state(self):
- return self.api.LocalLB.ProfileClientSSL.get_forward_proxy_enabled_state(self.profiles)
-
- def get_forward_proxy_lookup_by_ipaddr_port_state(self):
- return self.api.LocalLB.ProfileClientSSL.get_forward_proxy_lookup_by_ipaddr_port_state(self.profiles)
-
- def get_handshake_timeout(self):
- return self.api.LocalLB.ProfileClientSSL.get_handshake_timeout(self.profiles)
-
- def get_key_file(self):
- return self.api.LocalLB.ProfileClientSSL.get_key_file_v2(self.profiles)
-
- def get_modssl_emulation_state(self):
- return self.api.LocalLB.ProfileClientSSL.get_modssl_emulation_state(self.profiles)
-
- def get_passphrase(self):
- return self.api.LocalLB.ProfileClientSSL.get_passphrase(self.profiles)
-
- def get_peer_certification_mode(self):
- return self.api.LocalLB.ProfileClientSSL.get_peer_certification_mode(self.profiles)
-
- def get_profile_mode(self):
- return self.api.LocalLB.ProfileClientSSL.get_profile_mode(self.profiles)
-
- def get_renegotiation_maximum_record_delay(self):
- return self.api.LocalLB.ProfileClientSSL.get_renegotiation_maximum_record_delay(self.profiles)
-
- def get_renegotiation_period(self):
- return self.api.LocalLB.ProfileClientSSL.get_renegotiation_period(self.profiles)
-
- def get_renegotiation_state(self):
- return self.api.LocalLB.ProfileClientSSL.get_renegotiation_state(self.profiles)
-
- def get_renegotiation_throughput(self):
- return self.api.LocalLB.ProfileClientSSL.get_renegotiation_throughput(self.profiles)
-
- def get_retain_certificate_state(self):
- return self.api.LocalLB.ProfileClientSSL.get_retain_certificate_state(self.profiles)
-
- def get_secure_renegotiation_mode(self):
- return self.api.LocalLB.ProfileClientSSL.get_secure_renegotiation_mode(self.profiles)
-
- def get_server_name(self):
- return self.api.LocalLB.ProfileClientSSL.get_server_name(self.profiles)
-
- def get_session_ticket_state(self):
- return self.api.LocalLB.ProfileClientSSL.get_session_ticket_state(self.profiles)
-
- def get_sni_default_state(self):
- return self.api.LocalLB.ProfileClientSSL.get_sni_default_state(self.profiles)
-
- def get_sni_require_state(self):
- return self.api.LocalLB.ProfileClientSSL.get_sni_require_state(self.profiles)
-
- def get_ssl_option(self):
- return self.api.LocalLB.ProfileClientSSL.get_ssl_option(self.profiles)
-
- def get_strict_resume_state(self):
- return self.api.LocalLB.ProfileClientSSL.get_strict_resume_state(self.profiles)
-
- def get_unclean_shutdown_state(self):
- return self.api.LocalLB.ProfileClientSSL.get_unclean_shutdown_state(self.profiles)
-
- def get_is_base_profile(self):
- return self.api.LocalLB.ProfileClientSSL.is_base_profile(self.profiles)
-
- def get_is_system_profile(self):
- return self.api.LocalLB.ProfileClientSSL.is_system_profile(self.profiles)
-
-
-class SystemInfo(object):
- """System information class.
-
- F5 BIG-IP system information class.
-
- Attributes:
- api: iControl API instance.
- """
-
- def __init__(self, api):
- self.api = api
-
- def get_base_mac_address(self):
- return self.api.System.SystemInfo.get_base_mac_address()
-
- def get_blade_temperature(self):
- return self.api.System.SystemInfo.get_blade_temperature()
-
- def get_chassis_slot_information(self):
- return self.api.System.SystemInfo.get_chassis_slot_information()
-
- def get_globally_unique_identifier(self):
- return self.api.System.SystemInfo.get_globally_unique_identifier()
-
- def get_group_id(self):
- return self.api.System.SystemInfo.get_group_id()
-
- def get_hardware_information(self):
- return self.api.System.SystemInfo.get_hardware_information()
-
- def get_marketing_name(self):
- return self.api.System.SystemInfo.get_marketing_name()
-
- def get_product_information(self):
- return self.api.System.SystemInfo.get_product_information()
-
- def get_pva_version(self):
- return self.api.System.SystemInfo.get_pva_version()
-
- def get_system_id(self):
- return self.api.System.SystemInfo.get_system_id()
-
- def get_system_information(self):
- return self.api.System.SystemInfo.get_system_information()
-
- def get_time(self):
- return self.api.System.SystemInfo.get_time()
-
- def get_time_zone(self):
- return self.api.System.SystemInfo.get_time_zone()
-
- def get_uptime(self):
- return self.api.System.SystemInfo.get_uptime()
-
-
-class ProvisionInfo(object):
- """Provision information class.
-
- F5 BIG-IP provision information class.
-
- Attributes:
- api: iControl API instance.
- """
-
- def __init__(self, api):
- self.api = api
-
- def get_list(self):
- result = []
- list = self.api.Management.Provision.get_list()
- for item in list:
- item = item.lower().replace('tmos_module_', '')
- result.append(item)
- return result
-
- def get_provisioned_list(self):
- result = []
- list = self.api.Management.Provision.get_provisioned_list()
- for item in list:
- item = item.lower().replace('tmos_module_', '')
- result.append(item)
- return result
-
-
-def generate_dict(api_obj, fields):
- result_dict = {}
- lists = []
- supported_fields = []
- if api_obj.get_list():
- for field in fields:
- try:
- api_response = getattr(api_obj, "get_" + field)()
- except (MethodNotFound, WebFault):
- pass
- else:
- lists.append(api_response)
- supported_fields.append(field)
- for i, j in enumerate(api_obj.get_list()):
- temp = {}
- temp.update([(item[0], item[1][i]) for item in zip(supported_fields, lists)])
- result_dict[j] = temp
- return result_dict
-
-
-def generate_simple_dict(api_obj, fields):
- result_dict = {}
- for field in fields:
- try:
- api_response = getattr(api_obj, "get_" + field)()
- except (MethodNotFound, WebFault):
- pass
- else:
- result_dict[field] = api_response
- return result_dict
-
-
-def generate_interface_dict(f5, regex):
- interfaces = Interfaces(f5.get_api(), regex)
- fields = ['active_media', 'actual_flow_control', 'bundle_state',
- 'description', 'dual_media_state', 'enabled_state', 'if_index',
- 'learning_mode', 'lldp_admin_status', 'lldp_tlvmap',
- 'mac_address', 'media', 'media_option', 'media_option_sfp',
- 'media_sfp', 'media_speed', 'media_status', 'mtu',
- 'phy_master_slave_mode', 'prefer_sfp_state', 'flow_control',
- 'sflow_poll_interval', 'sflow_poll_interval_global',
- 'sfp_media_state', 'stp_active_edge_port_state',
- 'stp_enabled_state', 'stp_link_type',
- 'stp_protocol_detection_reset_state']
- return generate_dict(interfaces, fields)
-
-
-def generate_self_ip_dict(f5, regex):
- self_ips = SelfIPs(f5.get_api(), regex)
- fields = ['address', 'allow_access_list', 'description',
- 'enforced_firewall_policy', 'floating_state', 'fw_rule',
- 'netmask', 'staged_firewall_policy', 'traffic_group',
- 'vlan', 'is_traffic_group_inherited']
- return generate_dict(self_ips, fields)
-
-
-def generate_trunk_dict(f5, regex):
- trunks = Trunks(f5.get_api(), regex)
- fields = ['active_lacp_state', 'configured_member_count', 'description',
- 'distribution_hash_option', 'interface', 'lacp_enabled_state',
- 'lacp_timeout_option', 'link_selection_policy', 'media_speed',
- 'media_status', 'operational_member_count', 'stp_enabled_state',
- 'stp_protocol_detection_reset_state']
- return generate_dict(trunks, fields)
-
-
-def generate_vlan_dict(f5, regex):
- vlans = Vlans(f5.get_api(), regex)
- fields = ['auto_lasthop', 'cmp_hash_algorithm', 'description',
- 'dynamic_forwarding', 'failsafe_action', 'failsafe_state',
- 'failsafe_timeout', 'if_index', 'learning_mode',
- 'mac_masquerade_address', 'member', 'mtu',
- 'sflow_poll_interval', 'sflow_poll_interval_global',
- 'sflow_sampling_rate', 'sflow_sampling_rate_global',
- 'source_check_state', 'true_mac_address', 'vlan_id']
- return generate_dict(vlans, fields)
-
-
-def generate_vs_dict(f5, regex):
- virtual_servers = VirtualServers(f5.get_api(), regex)
- fields = ['actual_hardware_acceleration', 'authentication_profile',
- 'auto_lasthop', 'bw_controller_policy', 'clone_pool',
- 'cmp_enable_mode', 'connection_limit', 'connection_mirror_state',
- 'default_pool_name', 'description', 'destination',
- 'enabled_state', 'enforced_firewall_policy',
- 'fallback_persistence_profile', 'fw_rule', 'gtm_score',
- 'last_hop_pool', 'nat64_state', 'object_status',
- 'persistence_profile', 'profile', 'protocol',
- 'rate_class', 'rate_limit', 'rate_limit_destination_mask',
- 'rate_limit_mode', 'rate_limit_source_mask', 'related_rule',
- 'rule', 'security_log_profile', 'snat_pool', 'snat_type',
- 'source_address', 'source_address_translation_lsn_pool',
- 'source_address_translation_snat_pool',
- 'source_address_translation_type', 'source_port_behavior',
- 'staged_firewall_policy', 'translate_address_state',
- 'translate_port_state', 'type', 'vlan', 'wildmask',
- 'name']
- return generate_dict(virtual_servers, fields)
-
-
-def generate_pool_dict(f5, regex):
- pools = Pools(f5.get_api(), regex)
- fields = ['action_on_service_down', 'active_member_count',
- 'aggregate_dynamic_ratio', 'allow_nat_state',
- 'allow_snat_state', 'client_ip_tos', 'client_link_qos',
- 'description', 'gateway_failsafe_device',
- 'ignore_persisted_weight_state', 'lb_method', 'member',
- 'minimum_active_member', 'minimum_up_member',
- 'minimum_up_member_action', 'minimum_up_member_enabled_state',
- 'monitor_association', 'monitor_instance', 'object_status',
- 'profile', 'queue_depth_limit',
- 'queue_on_connection_limit_state', 'queue_time_limit',
- 'reselect_tries', 'server_ip_tos', 'server_link_qos',
- 'simple_timeout', 'slow_ramp_time', 'name']
- return generate_dict(pools, fields)
-
-
-def generate_device_dict(f5, regex):
- devices = Devices(f5.get_api(), regex)
- fields = ['active_modules', 'base_mac_address', 'blade_addresses',
- 'build', 'chassis_id', 'chassis_type', 'comment',
- 'configsync_address', 'contact', 'description', 'edition',
- 'failover_state', 'hostname', 'inactive_modules', 'location',
- 'management_address', 'marketing_name', 'multicast_address',
- 'optional_modules', 'platform_id', 'primary_mirror_address',
- 'product', 'secondary_mirror_address', 'software_version',
- 'timelimited_modules', 'timezone', 'unicast_addresses']
- return generate_dict(devices, fields)
-
-
-def generate_device_group_dict(f5, regex):
- device_groups = DeviceGroups(f5.get_api(), regex)
- fields = ['all_preferred_active', 'autosync_enabled_state', 'description',
- 'device', 'full_load_on_sync_state',
- 'incremental_config_sync_size_maximum',
- 'network_failover_enabled_state', 'sync_status', 'type']
- return generate_dict(device_groups, fields)
-
-
-def generate_traffic_group_dict(f5, regex):
- traffic_groups = TrafficGroups(f5.get_api(), regex)
- fields = ['auto_failback_enabled_state', 'auto_failback_time',
- 'default_device', 'description', 'ha_load_factor',
- 'ha_order', 'is_floating', 'mac_masquerade_address',
- 'unit_id']
- return generate_dict(traffic_groups, fields)
-
-
-def generate_rule_dict(f5, regex):
- rules = Rules(f5.get_api(), regex)
- fields = ['definition', 'description', 'ignore_vertification',
- 'verification_status']
- return generate_dict(rules, fields)
-
-
-def generate_node_dict(f5, regex):
- nodes = Nodes(f5.get_api(), regex)
- fields = ['name', 'address', 'connection_limit', 'description', 'dynamic_ratio',
- 'monitor_instance', 'monitor_rule', 'monitor_status',
- 'object_status', 'rate_limit', 'ratio', 'session_status']
- return generate_dict(nodes, fields)
-
-
-def generate_virtual_address_dict(f5, regex):
- virtual_addresses = VirtualAddresses(f5.get_api(), regex)
- fields = ['address', 'arp_state', 'auto_delete_state', 'connection_limit',
- 'description', 'enabled_state', 'icmp_echo_state',
- 'is_floating_state', 'netmask', 'object_status',
- 'route_advertisement_state', 'traffic_group']
- return generate_dict(virtual_addresses, fields)
-
-
-def generate_address_class_dict(f5, regex):
- address_classes = AddressClasses(f5.get_api(), regex)
- fields = ['address_class', 'description']
- return generate_dict(address_classes, fields)
-
-
-def generate_certificate_dict(f5, regex):
- certificates = Certificates(f5.get_api(), regex)
- return dict(zip(certificates.get_list(), certificates.get_certificate_list()))
-
-
-def generate_key_dict(f5, regex):
- keys = Keys(f5.get_api(), regex)
- return dict(zip(keys.get_list(), keys.get_key_list()))
-
-
-def generate_client_ssl_profile_dict(f5, regex):
- profiles = ProfileClientSSL(f5.get_api(), regex)
- fields = ['alert_timeout', 'allow_nonssl_state', 'authenticate_depth',
- 'authenticate_once_state', 'ca_file', 'cache_size',
- 'cache_timeout', 'certificate_file', 'chain_file',
- 'cipher_list', 'client_certificate_ca_file', 'crl_file',
- 'default_profile', 'description',
- 'forward_proxy_ca_certificate_file', 'forward_proxy_ca_key_file',
- 'forward_proxy_ca_passphrase',
- 'forward_proxy_certificate_extension_include',
- 'forward_proxy_certificate_lifespan',
- 'forward_proxy_enabled_state',
- 'forward_proxy_lookup_by_ipaddr_port_state', 'handshake_timeout',
- 'key_file', 'modssl_emulation_state', 'passphrase',
- 'peer_certification_mode', 'profile_mode',
- 'renegotiation_maximum_record_delay', 'renegotiation_period',
- 'renegotiation_state', 'renegotiation_throughput',
- 'retain_certificate_state', 'secure_renegotiation_mode',
- 'server_name', 'session_ticket_state', 'sni_default_state',
- 'sni_require_state', 'ssl_option', 'strict_resume_state',
- 'unclean_shutdown_state', 'is_base_profile', 'is_system_profile']
- return generate_dict(profiles, fields)
-
-
-def generate_system_info_dict(f5):
- system_info = SystemInfo(f5.get_api())
- fields = ['base_mac_address',
- 'blade_temperature', 'chassis_slot_information',
- 'globally_unique_identifier', 'group_id',
- 'hardware_information',
- 'marketing_name',
- 'product_information', 'pva_version', 'system_id',
- 'system_information', 'time',
- 'time_zone', 'uptime']
- return generate_simple_dict(system_info, fields)
-
-
-def generate_software_list(f5):
- software = Software(f5.get_api())
- software_list = software.get_all_software_status()
- return software_list
-
-
-def generate_provision_dict(f5):
- provisioned = ProvisionInfo(f5.get_api())
- fields = ['list', 'provisioned_list']
- return generate_simple_dict(provisioned, fields)
-
-
-class ArgumentSpec(object):
- def __init__(self):
- self.supports_check_mode = False
- argument_spec = dict(
- session=dict(type='bool', default='no'),
- include=dict(
- type='raw',
- required=True,
- choices=[
- 'address_class', 'certificate', 'client_ssl_profile', 'device',
- 'device_group', 'interface', 'key', 'node', 'pool', 'provision',
- 'rule', 'self_ip', 'software', 'system_info', 'traffic_group',
- 'trunk', 'virtual_address', 'virtual_server', 'vlan'
- ]
- ),
- filter=dict(type='str'),
- )
- self.argument_spec = {}
- self.argument_spec.update(f5_argument_spec)
- self.argument_spec.update(argument_spec)
-
-
-def main():
- spec = ArgumentSpec()
-
- module = AnsibleModule(
- argument_spec=spec.argument_spec
- )
- client = F5BaseClient(**module.params)
- provider = client.merge_provider_params()
-
- if not bigsuds_found:
- module.fail_json(msg="the python suds and bigsuds modules are required")
-
- server = provider['server']
- server_port = provider['server_port']
- user = provider['user']
- password = provider['password']
- validate_certs = provider['validate_certs']
-
- session = module.params['session']
- fact_filter = module.params['filter']
-
- if validate_certs:
- import ssl
- if not hasattr(ssl, 'SSLContext'):
- module.fail_json(
- msg='bigsuds does not support verifying certificates with python < 2.7.9. Either update python or set validate_certs=False on the task'
- )
-
- if fact_filter:
- regex = fnmatch.translate(fact_filter)
- else:
- regex = None
- if isinstance(module.params['include'], string_types):
- includes = module.params['include'].split(',')
- else:
- includes = module.params['include']
- include = [x.lower() for x in includes]
- valid_includes = ('address_class', 'certificate', 'client_ssl_profile',
- 'device', 'device_group', 'interface', 'key', 'node',
- 'pool', 'provision', 'rule', 'self_ip', 'software',
- 'system_info', 'traffic_group', 'trunk',
- 'virtual_address', 'virtual_server', 'vlan')
- include_test = (x in valid_includes for x in include)
- if not all(include_test):
- module.fail_json(msg="Value of include must be one or more of: %s, got: %s" % (",".join(valid_includes), ",".join(include)))
-
- try:
- facts = {}
-
- if len(include) > 0:
- f5 = F5(server, user, password, session, validate_certs, server_port)
- saved_active_folder = f5.get_active_folder()
- saved_recursive_query_state = f5.get_recursive_query_state()
- if saved_active_folder != "/":
- f5.set_active_folder("/")
- if saved_recursive_query_state != "STATE_ENABLED":
- f5.enable_recursive_query_state()
-
- if 'interface' in include:
- facts['interface'] = generate_interface_dict(f5, regex)
- if 'self_ip' in include:
- facts['self_ip'] = generate_self_ip_dict(f5, regex)
- if 'trunk' in include:
- facts['trunk'] = generate_trunk_dict(f5, regex)
- if 'vlan' in include:
- facts['vlan'] = generate_vlan_dict(f5, regex)
- if 'virtual_server' in include:
- facts['virtual_server'] = generate_vs_dict(f5, regex)
- if 'pool' in include:
- facts['pool'] = generate_pool_dict(f5, regex)
- if 'provision' in include:
- facts['provision'] = generate_provision_dict(f5)
- if 'device' in include:
- facts['device'] = generate_device_dict(f5, regex)
- if 'device_group' in include:
- facts['device_group'] = generate_device_group_dict(f5, regex)
- if 'traffic_group' in include:
- facts['traffic_group'] = generate_traffic_group_dict(f5, regex)
- if 'rule' in include:
- facts['rule'] = generate_rule_dict(f5, regex)
- if 'node' in include:
- facts['node'] = generate_node_dict(f5, regex)
- if 'virtual_address' in include:
- facts['virtual_address'] = generate_virtual_address_dict(f5, regex)
- if 'address_class' in include:
- facts['address_class'] = generate_address_class_dict(f5, regex)
- if 'software' in include:
- facts['software'] = generate_software_list(f5)
- if 'certificate' in include:
- facts['certificate'] = generate_certificate_dict(f5, regex)
- if 'key' in include:
- facts['key'] = generate_key_dict(f5, regex)
- if 'client_ssl_profile' in include:
- facts['client_ssl_profile'] = generate_client_ssl_profile_dict(f5, regex)
- if 'system_info' in include:
- facts['system_info'] = generate_system_info_dict(f5)
-
- # restore saved state
- if saved_active_folder and saved_active_folder != "/":
- f5.set_active_folder(saved_active_folder)
- if saved_recursive_query_state and \
- saved_recursive_query_state != "STATE_ENABLED":
- f5.set_recursive_query_state(saved_recursive_query_state)
-
- result = dict(
- ansible_facts=facts,
- )
- result.update(**facts)
-
- except Exception as e:
- module.fail_json(msg="received exception: %s\ntraceback: %s" % (e, traceback.format_exc()))
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/f5/bigip_firewall_address_list.py b/plugins/modules/network/f5/bigip_firewall_address_list.py
deleted file mode 100644
index 9b1216965a..0000000000
--- a/plugins/modules/network/f5/bigip_firewall_address_list.py
+++ /dev/null
@@ -1,979 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright: (c) 2017, F5 Networks Inc.
-# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'certified'}
-
-DOCUMENTATION = r'''
----
-module: bigip_firewall_address_list
-short_description: Manage address lists on BIG-IP AFM
-description:
- - Manages the AFM address lists on a BIG-IP. This module can be used to add
- and remove address list entries.
-options:
- name:
- description:
- - Specifies the name of the address list.
- type: str
- required: True
- partition:
- description:
- - Device partition to manage resources on.
- type: str
- default: Common
- description:
- description:
- - Description of the address list
- type: str
- geo_locations:
- description:
- - List of geolocations specified by their C(country) and C(region).
- suboptions:
- country:
- description:
- - The country name, or code, of the geolocation to use.
- - In addition to the country full names, you may also specify their abbreviated
- form, such as C(US) instead of C(United States).
- - Valid country codes can be found here https://countrycode.org/.
- type: str
- required: True
- choices:
- - Any valid 2 character ISO country code.
- - Any valid country name.
- region:
- description:
- - Region name of the country to use.
- type: str
- type: list
- addresses:
- description:
- - Individual addresses that you want to add to the list. These addresses differ
- from ranges, and lists of lists such as what can be used in C(address_ranges)
- and C(address_lists) respectively.
- - This list can also include networks that have CIDR notation.
- type: list
- address_ranges:
- description:
- - A list of address ranges where the range starts with a port number, is followed
- by a dash (-) and then a second number.
- - If the first address is greater than the second number, the numbers will be
- reversed so-as to be properly formatted. ie, C(2.2.2.2-1.1.1). would become
- C(1.1.1.1-2.2.2.2).
- type: list
- address_lists:
- description:
- - Simple list of existing address lists to add to this list. Address lists can be
- specified in either their fully qualified name (/Common/foo) or their short
- name (foo). If a short name is used, the C(partition) argument will automatically
- be prepended to the short name.
- type: list
- fqdns:
- description:
- - A list of fully qualified domain names (FQDNs).
- - An FQDN has at least one decimal point in it, separating the host from the domain.
- - To add FQDNs to a list requires that a global FQDN resolver be configured.
- At the moment, this must either be done via C(bigip_command), or, in the GUI
- of BIG-IP. If using C(bigip_command), this can be done with C(tmsh modify security
- firewall global-fqdn-policy FOO) where C(FOO) is a DNS resolver configured
- at C(tmsh create net dns-resolver FOO).
- type: list
- state:
- description:
- - When C(present), ensures that the address list and entries exists.
- - When C(absent), ensures the address list is removed.
- type: str
- choices:
- - present
- - absent
- default: present
-extends_documentation_fragment:
-- f5networks.f5_modules.f5
-
-author:
- - Tim Rupp (@caphrim007)
- - Wojciech Wypior (@wojtek0806)
-'''
-
-EXAMPLES = r'''
-- name: Create an address list
- bigip_firewall_address_list:
- name: foo
- addresses:
- - 3.3.3.3
- - 4.4.4.4
- - 5.5.5.5
- provider:
- password: secret
- server: lb.mydomain.com
- user: admin
- delegate_to: localhost
-'''
-
-RETURN = r'''
-description:
- description: The new description of the address list.
- returned: changed
- type: str
- sample: My address list
-addresses:
- description: The new list of addresses applied to the address list.
- returned: changed
- type: list
- sample: [1.1.1.1, 2.2.2.2]
-address_ranges:
- description: The new list of address ranges applied to the address list.
- returned: changed
- type: list
- sample: [1.1.1.1-2.2.2.2, 3.3.3.3-4.4.4.4]
-address_lists:
- description: The new list of address list names applied to the address list.
- returned: changed
- type: list
- sample: [/Common/list1, /Common/list2]
-fqdns:
- description: The new list of FQDN names applied to the address list.
- returned: changed
- type: list
- sample: [google.com, mit.edu]
-geo_locations:
- description: The new list of geo locations applied to the address list.
- returned: changed
- type: complex
- contains:
- country:
- description: Country of the geo location.
- returned: changed
- type: str
- sample: US
- region:
- description: Region of the geo location.
- returned: changed
- type: str
- sample: California
-'''
-
-import re
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.basic import env_fallback
-
-try:
- from library.module_utils.network.f5.bigip import F5RestClient
- from library.module_utils.network.f5.common import F5ModuleError
- from library.module_utils.network.f5.common import AnsibleF5Parameters
- from library.module_utils.network.f5.common import fq_name
- from library.module_utils.network.f5.common import f5_argument_spec
- from library.module_utils.network.f5.common import transform_name
- from library.module_utils.compat.ipaddress import ip_address
- from library.module_utils.compat.ipaddress import ip_interface
- from library.module_utils.network.f5.ipaddress import is_valid_ip
- from library.module_utils.network.f5.ipaddress import is_valid_ip_interface
-except ImportError:
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.bigip import F5RestClient
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import F5ModuleError
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import AnsibleF5Parameters
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import fq_name
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import f5_argument_spec
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import transform_name
- from ansible_collections.ansible.netcommon.plugins.module_utils.compat.ipaddress import ip_address
- from ansible_collections.ansible.netcommon.plugins.module_utils.compat.ipaddress import ip_interface
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.ipaddress import is_valid_ip
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.ipaddress import is_valid_ip_interface
-
-
-class Parameters(AnsibleF5Parameters):
- api_map = {
- 'addressLists': 'address_lists',
- 'geo': 'geo_locations',
- }
-
- api_attributes = [
- 'addressLists',
- 'addresses',
- 'description',
- 'fqdns',
- 'geo',
- ]
-
- returnables = [
- 'addresses',
- 'address_ranges',
- 'address_lists',
- 'description',
- 'fqdns',
- 'geo_locations',
- ]
-
- updatables = [
- 'addresses',
- 'address_ranges',
- 'address_lists',
- 'description',
- 'fqdns',
- 'geo_locations',
- ]
-
-
-class ApiParameters(Parameters):
- @property
- def address_ranges(self):
- if self._values['addresses'] is None:
- return None
- result = []
- for address_range in self._values['addresses']:
- if '-' not in address_range['name']:
- continue
- result.append(address_range['name'].strip())
- result = sorted(result)
- return result
-
- @property
- def address_lists(self):
- if self._values['address_lists'] is None:
- return None
- result = []
- for x in self._values['address_lists']:
- item = '/{0}/{1}'.format(x['partition'], x['name'])
- result.append(item)
- result = sorted(result)
- return result
-
- @property
- def addresses(self):
- if self._values['addresses'] is None:
- return None
- result = [x['name'] for x in self._values['addresses'] if '-' not in x['name']]
- result = sorted(result)
- return result
-
- @property
- def fqdns(self):
- if self._values['fqdns'] is None:
- return None
- result = [str(x['name']) for x in self._values['fqdns']]
- result = sorted(result)
- return result
-
- @property
- def geo_locations(self):
- if self._values['geo_locations'] is None:
- return None
- result = [str(x['name']) for x in self._values['geo_locations']]
- result = sorted(result)
- return result
-
-
-class ModuleParameters(Parameters):
- def __init__(self, params=None):
- super(ModuleParameters, self).__init__(params=params)
- self.country_iso_map = {
- 'Afghanistan': 'AF',
- 'Albania': 'AL',
- 'Algeria': 'DZ',
- 'American Samoa': 'AS',
- 'Andorra': 'AD',
- 'Angola': 'AO',
- 'Anguilla': 'AI',
- 'Antarctica': 'AQ',
- 'Antigua and Barbuda': 'AG',
- 'Argentina': 'AR',
- 'Armenia': 'AM',
- 'Aruba': 'AW',
- 'Australia': 'AU',
- 'Austria': 'AT',
- 'Azerbaijan': 'AZ',
- 'Bahamas': 'BS',
- 'Bahrain': 'BH',
- 'Bangladesh': 'BD',
- 'Barbados': 'BB',
- 'Belarus': 'BY',
- 'Belgium': 'BE',
- 'Belize': 'BZ',
- 'Benin': 'BJ',
- 'Bermuda': 'BM',
- 'Bhutan': 'BT',
- 'Bolivia': 'BO',
- 'Bosnia and Herzegovina': 'BA',
- 'Botswana': 'BW',
- 'Brazil': 'BR',
- 'Brunei': 'BN',
- 'Bulgaria': 'BG',
- 'Burkina Faso': 'BF',
- 'Burundi': 'BI',
- 'Cameroon': 'CM',
- 'Canada': 'CA',
- 'Cape Verde': 'CV',
- 'Central African Republic': 'CF',
- 'Chile': 'CL',
- 'China': 'CN',
- 'Christmas Island': 'CX',
- 'Cocos Islands': 'CC',
- 'Colombia': 'CO',
- 'Cook Islands': 'CK',
- 'Costa Rica': 'CR',
- 'Cuba': 'CU',
- 'Curacao': 'CW',
- 'Cyprus': 'CY',
- 'Czech Republic': 'CZ',
- 'Democratic Republic of the Congo': 'CD',
- 'Denmark': 'DK',
- 'Djibouti': 'DJ',
- 'Dominica': 'DM',
- 'Dominican Republic': 'DO',
- 'Ecuador': 'EC',
- 'Egypt': 'EG',
- 'Eritrea': 'ER',
- 'Estonia': 'EE',
- 'Ethiopia': 'ET',
- 'Falkland Islands': 'FK',
- 'Faroe Islands': 'FO',
- 'Fiji': 'FJ',
- 'Finland': 'FI',
- 'France': 'FR',
- 'French Polynesia': 'PF',
- 'Gabon': 'GA',
- 'Gambia': 'GM',
- 'Georgia': 'GE',
- 'Germany': 'DE',
- 'Ghana': 'GH',
- 'Gilbraltar': 'GI',
- 'Greece': 'GR',
- 'Greenland': 'GL',
- 'Grenada': 'GD',
- 'Guam': 'GU',
- 'Guatemala': 'GT',
- 'Guernsey': 'GG',
- 'Guinea': 'GN',
- 'Guinea-Bissau': 'GW',
- 'Guyana': 'GY',
- 'Haiti': 'HT',
- 'Honduras': 'HN',
- 'Hong Kong': 'HK',
- 'Hungary': 'HU',
- 'Iceland': 'IS',
- 'India': 'IN',
- 'Indonesia': 'ID',
- 'Iran': 'IR',
- 'Iraq': 'IQ',
- 'Ireland': 'IE',
- 'Isle of Man': 'IM',
- 'Israel': 'IL',
- 'Italy': 'IT',
- 'Ivory Coast': 'CI',
- 'Jamaica': 'JM',
- 'Japan': 'JP',
- 'Jersey': 'JE',
- 'Jordan': 'JO',
- 'Kazakhstan': 'KZ',
- 'Laos': 'LA',
- 'Latvia': 'LV',
- 'Lebanon': 'LB',
- 'Lesotho': 'LS',
- 'Liberia': 'LR',
- 'Libya': 'LY',
- 'Liechtenstein': 'LI',
- 'Lithuania': 'LT',
- 'Luxembourg': 'LU',
- 'Macau': 'MO',
- 'Macedonia': 'MK',
- 'Madagascar': 'MG',
- 'Malawi': 'MW',
- 'Malaysia': 'MY',
- 'Maldives': 'MV',
- 'Mali': 'ML',
- 'Malta': 'MT',
- 'Marshall Islands': 'MH',
- 'Mauritania': 'MR',
- 'Mauritius': 'MU',
- 'Mayotte': 'YT',
- 'Mexico': 'MX',
- 'Micronesia': 'FM',
- 'Moldova': 'MD',
- 'Monaco': 'MC',
- 'Mongolia': 'MN',
- 'Montenegro': 'ME',
- 'Montserrat': 'MS',
- 'Morocco': 'MA',
- 'Mozambique': 'MZ',
- 'Myanmar': 'MM',
- 'Namibia': 'NA',
- 'Nauru': 'NR',
- 'Nepal': 'NP',
- 'Netherlands': 'NL',
- 'Netherlands Antilles': 'AN',
- 'New Caledonia': 'NC',
- 'New Zealand': 'NZ',
- 'Nicaragua': 'NI',
- 'Niger': 'NE',
- 'Nigeria': 'NG',
- 'Niue': 'NU',
- 'North Korea': 'KP',
- 'Northern Mariana Islands': 'MP',
- 'Norway': 'NO',
- 'Oman': 'OM',
- 'Pakistan': 'PK',
- 'Palau': 'PW',
- 'Palestine': 'PS',
- 'Panama': 'PA',
- 'Papua New Guinea': 'PG',
- 'Paraguay': 'PY',
- 'Peru': 'PE',
- 'Philippines': 'PH',
- 'Pitcairn': 'PN',
- 'Poland': 'PL',
- 'Portugal': 'PT',
- 'Puerto Rico': 'PR',
- 'Qatar': 'QA',
- 'Republic of the Congo': 'CG',
- 'Reunion': 'RE',
- 'Romania': 'RO',
- 'Russia': 'RU',
- 'Rwanda': 'RW',
- 'Saint Barthelemy': 'BL',
- 'Saint Helena': 'SH',
- 'Saint Kitts and Nevis': 'KN',
- 'Saint Lucia': 'LC',
- 'Saint Martin': 'MF',
- 'Saint Pierre and Miquelon': 'PM',
- 'Saint Vincent and the Grenadines': 'VC',
- 'Samoa': 'WS',
- 'San Marino': 'SM',
- 'Sao Tome and Principe': 'ST',
- 'Saudi Arabia': 'SA',
- 'Senegal': 'SN',
- 'Serbia': 'RS',
- 'Seychelles': 'SC',
- 'Sierra Leone': 'SL',
- 'Singapore': 'SG',
- 'Sint Maarten': 'SX',
- 'Slovakia': 'SK',
- 'Slovenia': 'SI',
- 'Solomon Islands': 'SB',
- 'Somalia': 'SO',
- 'South Africa': 'ZA',
- 'South Korea': 'KR',
- 'South Sudan': 'SS',
- 'Spain': 'ES',
- 'Sri Lanka': 'LK',
- 'Sudan': 'SD',
- 'Suriname': 'SR',
- 'Svalbard and Jan Mayen': 'SJ',
- 'Swaziland': 'SZ',
- 'Sweden': 'SE',
- 'Switzerland': 'CH',
- 'Syria': 'SY',
- 'Taiwan': 'TW',
- 'Tajikstan': 'TJ',
- 'Tanzania': 'TZ',
- 'Thailand': 'TH',
- 'Togo': 'TG',
- 'Tokelau': 'TK',
- 'Tonga': 'TO',
- 'Trinidad and Tobago': 'TT',
- 'Tunisia': 'TN',
- 'Turkey': 'TR',
- 'Turkmenistan': 'TM',
- 'Turks and Caicos Islands': 'TC',
- 'Tuvalu': 'TV',
- 'U.S. Virgin Islands': 'VI',
- 'Uganda': 'UG',
- 'Ukraine': 'UA',
- 'United Arab Emirates': 'AE',
- 'United Kingdom': 'GB',
- 'United States': 'US',
- 'Uruguay': 'UY',
- 'Uzbekistan': 'UZ',
- 'Vanuatu': 'VU',
- 'Vatican': 'VA',
- 'Venezuela': 'VE',
- 'Vietnam': 'VN',
- 'Wallis and Futuna': 'WF',
- 'Western Sahara': 'EH',
- 'Yemen': 'YE',
- 'Zambia': 'ZM',
- 'Zimbabwe': 'ZW'
- }
- self.choices_iso_codes = self.country_iso_map.values()
-
- def is_valid_hostname(self, host):
- """Reasonable attempt at validating a hostname
-
- Compiled from various paragraphs outlined here
- https://tools.ietf.org/html/rfc3696#section-2
- https://tools.ietf.org/html/rfc1123
-
- Notably,
- * Host software MUST handle host names of up to 63 characters and
- SHOULD handle host names of up to 255 characters.
- * The "LDH rule", after the characters that it permits. (letters, digits, hyphen)
- * If the hyphen is used, it is not permitted to appear at
- either the beginning or end of a label
-
- :param host:
- :return:
- """
- if len(host) > 255:
- return False
- host = host.rstrip(".")
- allowed = re.compile(r'(?!-)[A-Z0-9-]{1,63}(? int(stop):
- stop, start = start, stop
- item = '{0}-{1}'.format(str(start), str(stop))
- result.append(item)
- result = sorted(result)
- return result
-
- @property
- def address_lists(self):
- if self._values['address_lists'] is None:
- return None
- result = []
- for x in self._values['address_lists']:
- item = fq_name(self.partition, x)
- result.append(item)
- result = sorted(result)
- return result
-
- @property
- def fqdns(self):
- if self._values['fqdns'] is None:
- return None
- result = []
- for x in self._values['fqdns']:
- if self.is_valid_hostname(x):
- result.append(x)
- else:
- raise F5ModuleError(
- "The hostname '{0}' looks invalid.".format(x)
- )
- result = sorted(result)
- return result
-
- @property
- def geo_locations(self):
- if self._values['geo_locations'] is None:
- return None
- result = []
- for x in self._values['geo_locations']:
- if x['region'] is not None and x['region'].strip() != '':
- tmp = '{0}:{1}'.format(x['country'], x['region'])
- else:
- tmp = x['country']
- result.append(tmp)
- result = sorted(result)
- return result
-
-
-class Changes(Parameters):
- def to_return(self):
- result = {}
- try:
- for returnable in self.returnables:
- result[returnable] = getattr(self, returnable)
- result = self._filter_params(result)
- except Exception:
- pass
- return result
-
-
-class ReportableChanges(Changes):
- @property
- def addresses(self):
- result = []
- for item in self._values['addresses']:
- if '-' in item['name']:
- continue
- result.append(item['name'])
- return result
-
- @property
- def address_ranges(self):
- result = []
- for item in self._values['addresses']:
- if '-' not in item['name']:
- continue
- start, stop = item['name'].split('-')
- start = start.strip()
- stop = stop.strip()
-
- start = ip_address(u'{0}'.format(start))
- stop = ip_address(u'{0}'.format(stop))
- if start.version != stop.version:
- raise F5ModuleError(
- "When specifying a range, IP addresses must be of the same type; IPv4 or IPv6."
- )
- if int(start) > int(stop):
- stop, start = start, stop
- item = '{0}-{1}'.format(str(start), str(stop))
- result.append(item)
- result = sorted(result)
- return result
-
- @property
- def address_lists(self):
- result = []
- for x in self._values['address_lists']:
- item = '/{0}/{1}'.format(x['partition'], x['name'])
- result.append(item)
- result = sorted(result)
- return result
-
-
-class UsableChanges(Changes):
- @property
- def addresses(self):
- if self._values['addresses'] is None and self._values['address_ranges'] is None:
- return None
- result = []
- if self._values['addresses']:
- result += [dict(name=str(x)) for x in self._values['addresses']]
- if self._values['address_ranges']:
- result += [dict(name=str(x)) for x in self._values['address_ranges']]
- return result
-
- @property
- def address_lists(self):
- if self._values['address_lists'] is None:
- return None
- result = []
- for x in self._values['address_lists']:
- partition, name = x.split('/')[1:]
- result.append(dict(
- name=name,
- partition=partition
- ))
- return result
-
-
-class Difference(object):
- def __init__(self, want, have=None):
- self.want = want
- self.have = have
-
- def compare(self, param):
- try:
- result = getattr(self, param)
- return result
- except AttributeError:
- return self.__default(param)
-
- def __default(self, param):
- attr1 = getattr(self.want, param)
- try:
- attr2 = getattr(self.have, param)
- if attr1 != attr2:
- return attr1
- except AttributeError:
- return attr1
-
- @property
- def addresses(self):
- if self.want.addresses is None:
- return None
- elif self.have.addresses is None:
- return self.want.addresses
- if sorted(self.want.addresses) != sorted(self.have.addresses):
- return self.want.addresses
-
- @property
- def address_lists(self):
- if self.want.address_lists is None:
- return None
- elif self.have.address_lists is None:
- return self.want.address_lists
- if sorted(self.want.address_lists) != sorted(self.have.address_lists):
- return self.want.address_lists
-
- @property
- def address_ranges(self):
- if self.want.address_ranges is None:
- return None
- elif self.have.address_ranges is None:
- return self.want.address_ranges
- if sorted(self.want.address_ranges) != sorted(self.have.address_ranges):
- return self.want.address_ranges
-
- @property
- def fqdns(self):
- if self.want.fqdns is None:
- return None
- elif self.have.fqdns is None:
- return self.want.fqdns
- if sorted(self.want.fqdns) != sorted(self.have.fqdns):
- return self.want.fqdns
-
-
-class ModuleManager(object):
- def __init__(self, *args, **kwargs):
- self.module = kwargs.get('module', None)
- self.client = F5RestClient(**self.module.params)
- self.want = ModuleParameters(params=self.module.params)
- self.have = ApiParameters()
- self.changes = UsableChanges()
-
- def _update_changed_options(self):
- diff = Difference(self.want, self.have)
- updatables = Parameters.updatables
- changed = dict()
- for k in updatables:
- change = diff.compare(k)
- if change is None:
- continue
- else:
- if isinstance(change, dict):
- changed.update(change)
- else:
- changed[k] = change
- if changed:
- self.changes = UsableChanges(params=changed)
- return True
- return False
-
- def should_update(self):
- result = self._update_changed_options()
- if result:
- return True
- return False
-
- def exec_module(self):
- changed = False
- result = dict()
- state = self.want.state
-
- if state == "present":
- changed = self.present()
- elif state == "absent":
- changed = self.absent()
-
- reportable = ReportableChanges(params=self.changes.to_return())
- changes = reportable.to_return()
- result.update(**changes)
- result.update(dict(changed=changed))
- self._announce_deprecations(result)
- return result
-
- def _announce_deprecations(self, result):
- warnings = result.pop('__warnings', [])
- for warning in warnings:
- self.module.deprecate(
- msg=warning['msg'],
- version=warning['version']
- )
-
- def present(self):
- if self.exists():
- return self.update()
- else:
- return self.create()
-
- def absent(self):
- if self.exists():
- return self.remove()
- return False
-
- def update(self):
- self.have = self.read_current_from_device()
- if not self.should_update():
- return False
- if self.module.check_mode:
- return True
- self.update_on_device()
- return True
-
- def remove(self):
- if self.module.check_mode:
- return True
- self.remove_from_device()
- if self.exists():
- raise F5ModuleError("Failed to delete the resource.")
- return True
-
- def create(self):
- self.have = ApiParameters()
- self._update_changed_options()
- if self.module.check_mode:
- return True
- self.create_on_device()
- return True
-
- def exists(self):
- uri = "https://{0}:{1}/mgmt/tm/security/firewall/address-list/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(self.want.partition, self.want.name)
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError:
- return False
- if resp.status == 404 or 'code' in response and response['code'] == 404:
- return False
- return True
-
- def create_on_device(self):
- params = self.changes.api_params()
- params['name'] = self.want.name
- params['partition'] = self.want.partition
- uri = "https://{0}:{1}/mgmt/tm/security/firewall/address-list/".format(
- self.client.provider['server'],
- self.client.provider['server_port']
- )
- resp = self.client.api.post(uri, json=params)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] in [400, 403]:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- def update_on_device(self):
- params = self.changes.api_params()
- uri = "https://{0}:{1}/mgmt/tm/security/firewall/address-list/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(self.want.partition, self.want.name)
- )
- resp = self.client.api.patch(uri, json=params)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- def remove_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/security/firewall/address-list/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(self.want.partition, self.want.name)
- )
- resp = self.client.api.delete(uri)
- if resp.status == 200:
- return True
- raise F5ModuleError(resp.content)
-
- def read_current_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/security/firewall/address-list/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(self.want.partition, self.want.name)
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- return ApiParameters(params=response)
-
-
-class ArgumentSpec(object):
- def __init__(self):
- self.supports_check_mode = True
- argument_spec = dict(
- description=dict(),
- name=dict(required=True),
- addresses=dict(type='list'),
- address_ranges=dict(type='list'),
- address_lists=dict(type='list'),
- geo_locations=dict(
- type='list',
- elements='dict',
- options=dict(
- country=dict(
- required=True,
- ),
- region=dict()
- )
- ),
- fqdns=dict(type='list'),
- partition=dict(
- default='Common',
- fallback=(env_fallback, ['F5_PARTITION'])
- ),
- state=dict(
- default='present',
- choices=['present', 'absent']
- )
- )
- self.argument_spec = {}
- self.argument_spec.update(f5_argument_spec)
- self.argument_spec.update(argument_spec)
-
-
-def main():
- spec = ArgumentSpec()
-
- module = AnsibleModule(
- argument_spec=spec.argument_spec,
- supports_check_mode=spec.supports_check_mode
- )
-
- try:
- mm = ModuleManager(module=module)
- results = mm.exec_module()
- module.exit_json(**results)
- except F5ModuleError as ex:
- module.fail_json(msg=str(ex))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/f5/bigip_firewall_port_list.py b/plugins/modules/network/f5/bigip_firewall_port_list.py
deleted file mode 100644
index 8f19495e65..0000000000
--- a/plugins/modules/network/f5/bigip_firewall_port_list.py
+++ /dev/null
@@ -1,646 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright: (c) 2017, F5 Networks Inc.
-# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'certified'}
-
-DOCUMENTATION = r'''
----
-module: bigip_firewall_port_list
-short_description: Manage port lists on BIG-IP AFM
-description:
- - Manages the AFM port lists on a BIG-IP. This module can be used to add
- and remove port list entries.
-options:
- name:
- description:
- - Specifies the name of the port list.
- type: str
- required: True
- partition:
- description:
- - Device partition to manage resources on.
- type: str
- default: Common
- description:
- description:
- - Description of the port list
- type: str
- ports:
- description:
- - Simple list of port values to add to the list
- type: list
- port_ranges:
- description:
- - A list of port ranges where the range starts with a port number, is followed
- by a dash (-) and then a second number.
- - If the first number is greater than the second number, the numbers will be
- reversed so-as to be properly formatted. ie, 90-78 would become 78-90.
- type: list
- port_lists:
- description:
- - Simple list of existing port lists to add to this list. Port lists can be
- specified in either their fully qualified name (/Common/foo) or their short
- name (foo). If a short name is used, the C(partition) argument will automatically
- be prepended to the short name.
- type: list
- state:
- description:
- - When C(present), ensures that the address list and entries exists.
- - When C(absent), ensures the address list is removed.
- type: str
- choices:
- - present
- - absent
- default: present
-extends_documentation_fragment:
-- f5networks.f5_modules.f5
-
-author:
- - Tim Rupp (@caphrim007)
- - Wojciech Wypior (@wojtek0806)
-'''
-
-EXAMPLES = r'''
-- name: Create a simple port list
- bigip_firewall_port_list:
- name: foo
- ports:
- - 80
- - 443
- state: present
- provider:
- password: secret
- server: lb.mydomain.com
- user: admin
- delegate_to: localhost
-
-- name: Override the above list of ports with a new list
- bigip_firewall_port_list:
- name: foo
- ports:
- - 3389
- - 8080
- - 25
- state: present
- provider:
- password: secret
- server: lb.mydomain.com
- user: admin
- delegate_to: localhost
-
-- name: Create port list with series of ranges
- bigip_firewall_port_list:
- name: foo
- port_ranges:
- - 25-30
- - 80-500
- - 50-78
- state: present
- provider:
- password: secret
- server: lb.mydomain.com
- user: admin
- delegate_to: localhost
-
-- name: Use multiple types of port arguments
- bigip_firewall_port_list:
- name: foo
- port_ranges:
- - 25-30
- - 80-500
- - 50-78
- ports:
- - 8080
- - 443
- state: present
- provider:
- password: secret
- server: lb.mydomain.com
- user: admin
- delegate_to: localhost
-
-- name: Remove port list
- bigip_firewall_port_list:
- name: foo
- state: absent
- provider:
- password: secret
- server: lb.mydomain.com
- user: admin
- delegate_to: localhost
-
-- name: Create port list from a file with one port per line
- bigip_firewall_port_list:
- name: lot-of-ports
- ports: "{{ lookup('file', 'my-large-port-list.txt').split('\n') }}"
- state: present
- provider:
- password: secret
- server: lb.mydomain.com
- user: admin
- delegate_to: localhost
-'''
-
-RETURN = r'''
-description:
- description: The new description of the port list.
- returned: changed
- type: str
- sample: My port list
-ports:
- description: The new list of ports applied to the port list.
- returned: changed
- type: list
- sample: [80, 443]
-port_ranges:
- description: The new list of port ranges applied to the port list.
- returned: changed
- type: list
- sample: [80-100, 200-8080]
-port_lists:
- description: The new list of port list names applied to the port list.
- returned: changed
- type: list
- sample: [/Common/list1, /Common/list2]
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.basic import env_fallback
-
-try:
- from library.module_utils.network.f5.bigip import F5RestClient
- from library.module_utils.network.f5.common import F5ModuleError
- from library.module_utils.network.f5.common import AnsibleF5Parameters
- from library.module_utils.network.f5.common import fq_name
- from library.module_utils.network.f5.common import f5_argument_spec
- from library.module_utils.network.f5.common import transform_name
- from library.module_utils.network.f5.icontrol import module_provisioned
-except ImportError:
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.bigip import F5RestClient
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import F5ModuleError
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import AnsibleF5Parameters
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import fq_name
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import f5_argument_spec
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import transform_name
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.icontrol import module_provisioned
-
-
-class Parameters(AnsibleF5Parameters):
- api_map = {
- 'portLists': 'port_lists',
- }
-
- api_attributes = [
- 'portLists', 'ports', 'description',
- ]
-
- returnables = [
- 'ports', 'port_ranges', 'port_lists', 'description',
- ]
-
- updatables = [
- 'description', 'ports', 'port_ranges', 'port_lists',
- ]
-
-
-class ApiParameters(Parameters):
- @property
- def port_ranges(self):
- if self._values['ports'] is None:
- return None
- result = []
- for port_range in self._values['ports']:
- if '-' not in port_range['name']:
- continue
- start, stop = port_range['name'].split('-')
- start = int(start.strip())
- stop = int(stop.strip())
- if start > stop:
- stop, start = start, stop
- item = '{0}-{1}'.format(start, stop)
- result.append(item)
- return result
-
- @property
- def port_lists(self):
- if self._values['port_lists'] is None:
- return None
- result = []
- for x in self._values['port_lists']:
- item = '/{0}/{1}'.format(x['partition'], x['name'])
- result.append(item)
- return result
-
- @property
- def ports(self):
- if self._values['ports'] is None:
- return None
- result = [int(x['name']) for x in self._values['ports'] if '-' not in x['name']]
- return result
-
-
-class ModuleParameters(Parameters):
- @property
- def ports(self):
- if self._values['ports'] is None:
- return None
- if any(x for x in self._values['ports'] if '-' in str(x)):
- raise F5ModuleError(
- "Ports must be whole numbers between 0 and 65,535"
- )
- if any(x for x in self._values['ports'] if 0 < int(x) > 65535):
- raise F5ModuleError(
- "Ports must be whole numbers between 0 and 65,535"
- )
- result = [int(x) for x in self._values['ports']]
- return result
-
- @property
- def port_ranges(self):
- if self._values['port_ranges'] is None:
- return None
- result = []
- for port_range in self._values['port_ranges']:
- if '-' not in port_range:
- continue
- start, stop = port_range.split('-')
- start = int(start.strip())
- stop = int(stop.strip())
- if start > stop:
- stop, start = start, stop
- if 0 < start > 65535 or 0 < stop > 65535:
- raise F5ModuleError(
- "Ports must be whole numbers between 0 and 65,535"
- )
- item = '{0}-{1}'.format(start, stop)
- result.append(item)
- return result
-
- @property
- def port_lists(self):
- if self._values['port_lists'] is None:
- return None
- result = []
- for x in self._values['port_lists']:
- item = fq_name(self.partition, x)
- result.append(item)
- return result
-
-
-class Changes(Parameters):
- def to_return(self):
- result = {}
- try:
- for returnable in self.returnables:
- result[returnable] = getattr(self, returnable)
- result = self._filter_params(result)
- except Exception:
- pass
- return result
-
-
-class ReportableChanges(Changes):
- @property
- def ports(self):
- result = []
- for item in self._values['ports']:
- if '-' in item['name']:
- continue
- result.append(item['name'])
- return result
-
- @property
- def port_ranges(self):
- result = []
- for item in self._values['ports']:
- if '-' not in item['name']:
- continue
- result.append(item['name'])
- return result
-
-
-class UsableChanges(Changes):
- @property
- def ports(self):
- if self._values['ports'] is None and self._values['port_ranges'] is None:
- return None
- result = []
- if self._values['ports']:
- # The values of the 'key' index literally need to be string values.
- # If they are not, on BIG-IP 12.1.0 they will raise this REST exception.
- #
- # {
- # "code": 400,
- # "message": "one or more configuration identifiers must be provided",
- # "errorStack": [],
- # "apiError": 26214401
- # }
- result += [dict(name=str(x)) for x in self._values['ports']]
- if self._values['port_ranges']:
- result += [dict(name=str(x)) for x in self._values['port_ranges']]
- return result
-
- @property
- def port_lists(self):
- if self._values['port_lists'] is None:
- return None
- result = []
- for x in self._values['port_lists']:
- partition, name = x.split('/')[1:]
- result.append(dict(
- name=name,
- partition=partition
- ))
- return result
-
-
-class Difference(object):
- def __init__(self, want, have=None):
- self.want = want
- self.have = have
-
- def compare(self, param):
- try:
- result = getattr(self, param)
- return result
- except AttributeError:
- return self.__default(param)
-
- def __default(self, param):
- attr1 = getattr(self.want, param)
- try:
- attr2 = getattr(self.have, param)
- if attr1 != attr2:
- return attr1
- except AttributeError:
- return attr1
-
- @property
- def ports(self):
- if self.want.ports is None:
- return None
- elif self.have.ports is None:
- return self.want.ports
- if sorted(self.want.ports) != sorted(self.have.ports):
- return self.want.ports
-
- @property
- def port_lists(self):
- if self.want.port_lists is None:
- return None
- elif self.have.port_lists is None:
- return self.want.port_lists
- if sorted(self.want.port_lists) != sorted(self.have.port_lists):
- return self.want.port_lists
-
- @property
- def port_ranges(self):
- if self.want.port_ranges is None:
- return None
- elif self.have.port_ranges is None:
- return self.want.port_ranges
- if sorted(self.want.port_ranges) != sorted(self.have.port_ranges):
- return self.want.port_ranges
-
-
-class ModuleManager(object):
- def __init__(self, *args, **kwargs):
- self.module = kwargs.get('module', None)
- self.client = F5RestClient(**self.module.params)
- self.want = ModuleParameters(params=self.module.params)
- self.have = ApiParameters()
- self.changes = UsableChanges()
-
- def _set_changed_options(self):
- changed = {}
- for key in Parameters.returnables:
- if getattr(self.want, key) is not None:
- changed[key] = getattr(self.want, key)
- if changed:
- self.changes = UsableChanges(params=changed)
-
- def _update_changed_options(self):
- diff = Difference(self.want, self.have)
- updatables = Parameters.updatables
- changed = dict()
- for k in updatables:
- change = diff.compare(k)
- if change is None:
- continue
- else:
- if isinstance(change, dict):
- changed.update(change)
- else:
- changed[k] = change
- if changed:
- self.changes = UsableChanges(params=changed)
- return True
- return False
-
- def should_update(self):
- result = self._update_changed_options()
- if result:
- return True
- return False
-
- def exec_module(self):
- if not module_provisioned(self.client, 'afm'):
- raise F5ModuleError(
- "AFM must be provisioned to use this module."
- )
- changed = False
- result = dict()
- state = self.want.state
-
- if state == "present":
- changed = self.present()
- elif state == "absent":
- changed = self.absent()
-
- reportable = ReportableChanges(params=self.changes.to_return())
- changes = reportable.to_return()
- result.update(**changes)
- result.update(dict(changed=changed))
- self._announce_deprecations(result)
- return result
-
- def _announce_deprecations(self, result):
- warnings = result.pop('__warnings', [])
- for warning in warnings:
- self.module.deprecate(
- msg=warning['msg'],
- version=warning['version']
- )
-
- def present(self):
- if self.exists():
- return self.update()
- else:
- return self.create()
-
- def absent(self):
- if self.exists():
- return self.remove()
- return False
-
- def update(self):
- self.have = self.read_current_from_device()
- if not self.should_update():
- return False
- if self.module.check_mode:
- return True
- self.update_on_device()
- return True
-
- def remove(self):
- if self.module.check_mode:
- return True
- self.remove_from_device()
- if self.exists():
- raise F5ModuleError("Failed to delete the resource.")
- return True
-
- def create(self):
- self._set_changed_options()
- if self.module.check_mode:
- return True
- self.create_on_device()
- return True
-
- def exists(self):
- uri = "https://{0}:{1}/mgmt/tm/security/firewall/port-list/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(self.want.partition, self.want.name)
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError:
- return False
- if resp.status == 404 or 'code' in response and response['code'] == 404:
- return False
- return True
-
- def update_on_device(self):
- params = self.changes.api_params()
- uri = "https://{0}:{1}/mgmt/tm/security/firewall/port-list/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(self.want.partition, self.want.name)
- )
- resp = self.client.api.patch(uri, json=params)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- def read_current_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/security/firewall/port-list/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(self.want.partition, self.want.name)
- )
- resp = self.client.api.get(uri)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- return ApiParameters(params=response)
-
- def create_on_device(self):
- params = self.changes.api_params()
- params['name'] = self.want.name
- params['partition'] = self.want.partition
- uri = "https://{0}:{1}/mgmt/tm/security/firewall/port-list/".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.post(uri, json=params)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] in [400, 403]:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- return response['selfLink']
-
- def remove_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/security/firewall/port-list/{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(self.want.partition, self.want.name)
- )
- response = self.client.api.delete(uri)
- if response.status == 200:
- return True
- raise F5ModuleError(response.content)
-
-
-class ArgumentSpec(object):
- def __init__(self):
- self.supports_check_mode = True
- argument_spec = dict(
- name=dict(required=True),
- description=dict(),
- ports=dict(type='list'),
- port_ranges=dict(type='list'),
- port_lists=dict(type='list'),
- partition=dict(
- default='Common',
- fallback=(env_fallback, ['F5_PARTITION'])
- ),
- state=dict(
- default='present',
- choices=['present', 'absent']
- )
- )
- self.argument_spec = {}
- self.argument_spec.update(f5_argument_spec)
- self.argument_spec.update(argument_spec)
-
-
-def main():
- spec = ArgumentSpec()
-
- module = AnsibleModule(
- argument_spec=spec.argument_spec,
- supports_check_mode=spec.supports_check_mode
- )
-
- try:
- mm = ModuleManager(module=module)
- results = mm.exec_module()
- module.exit_json(**results)
- except F5ModuleError as ex:
- module.fail_json(msg=str(ex))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/f5/bigip_gtm_facts.py b/plugins/modules/network/f5/bigip_gtm_facts.py
deleted file mode 100644
index 7f93bc80ba..0000000000
--- a/plugins/modules/network/f5/bigip_gtm_facts.py
+++ /dev/null
@@ -1,986 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright: (c) 2017, F5 Networks Inc.
-# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['deprecated'],
- 'supported_by': 'certified'}
-
-DOCUMENTATION = r'''
----
-module: bigip_gtm_facts
-short_description: Collect facts from F5 BIG-IP GTM devices
-description:
- - Collect facts from F5 BIG-IP GTM devices.
-options:
- include:
- description:
- - Fact category to collect.
- required: True
- choices:
- - pool
- - wide_ip
- - server
- filter:
- description:
- - Perform regex filter of response. Filtering is done on the name of
- the resource. Valid filters are anything that can be provided to
- Python's C(re) module.
-deprecated:
- removed_in: '2.11'
- alternative: bigip_device_info
- why: >
- The bigip_gtm_facts module is an outlier as all facts are being collected
- in the bigip_device_info module. Additionally, the M(bigip_device_info)
- module is easier to maintain and use.
-extends_documentation_fragment:
-- f5networks.f5_modules.f5
-
-notes:
- - This module is deprecated. Use the C(bigip_device_info) module instead.
-author:
- - Tim Rupp (@caphrim007)
-'''
-
-EXAMPLES = r'''
-- name: Get pool facts
- bigip_gtm_facts:
- server: lb.mydomain.com
- user: admin
- password: secret
- include: pool
- filter: my_pool
- delegate_to: localhost
-'''
-
-RETURN = r'''
-wide_ip:
- description:
- Contains the lb method for the wide ip and the pools that are within the wide ip.
- returned: changed
- type: list
- sample:
- wide_ip:
- - enabled: True
- failure_rcode: noerror
- failure_rcode_response: disabled
- failure_rcode_ttl: 0
- full_path: /Common/foo.ok.com
- last_resort_pool: ""
- minimal_response: enabled
- name: foo.ok.com
- partition: Common
- persist_cidr_ipv4: 32
- persist_cidr_ipv6: 128
- persistence: disabled
- pool_lb_mode: round-robin
- pools:
- - name: d3qw
- order: 0
- partition: Common
- ratio: 1
- ttl_persistence: 3600
- type: naptr
-pool:
- description: Contains the pool object status and enabled status.
- returned: changed
- type: list
- sample:
- pool:
- - alternate_mode: round-robin
- dynamic_ratio: disabled
- enabled: True
- fallback_mode: return-to-dns
- full_path: /Common/d3qw
- load_balancing_mode: round-robin
- manual_resume: disabled
- max_answers_returned: 1
- members:
- - disabled: True
- flags: a
- full_path: ok3.com
- member_order: 0
- name: ok3.com
- order: 10
- preference: 10
- ratio: 1
- service: 80
- name: d3qw
- partition: Common
- qos_hit_ratio: 5
- qos_hops: 0
- qos_kilobytes_second: 3
- qos_lcs: 30
- qos_packet_rate: 1
- qos_rtt: 50
- qos_topology: 0
- qos_vs_capacity: 0
- qos_vs_score: 0
- availability_state: offline
- enabled_state: disabled
- ttl: 30
- type: naptr
- verify_member_availability: disabled
-server:
- description:
- Contains the virtual server enabled and availability status, and address.
- returned: changed
- type: list
- sample:
- server:
- - addresses:
- - device_name: /Common/qweqwe
- name: 10.10.10.10
- translation: none
- datacenter: /Common/xfxgh
- enabled: True
- expose_route_domains: no
- full_path: /Common/qweqwe
- iq_allow_path: yes
- iq_allow_service_check: yes
- iq_allow_snmp: yes
- limit_cpu_usage: 0
- limit_cpu_usage_status: disabled
- limit_max_bps: 0
- limit_max_bps_status: disabled
- limit_max_connections: 0
- limit_max_connections_status: disabled
- limit_max_pps: 0
- limit_max_pps_status: disabled
- limit_mem_avail: 0
- limit_mem_avail_status: disabled
- link_discovery: disabled
- monitor: /Common/bigip
- name: qweqwe
- partition: Common
- product: single-bigip
- virtual_server_discovery: disabled
- virtual_servers:
- - destination: 10.10.10.10:0
- enabled: True
- full_path: jsdfhsd
- limit_max_bps: 0
- limit_max_bps_status: disabled
- limit_max_connections: 0
- limit_max_connections_status: disabled
- limit_max_pps: 0
- limit_max_pps_status: disabled
- name: jsdfhsd
- translation_address: none
- translation_port: 0
-'''
-
-import re
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.six import iteritems
-from ansible.module_utils.parsing.convert_bool import BOOLEANS_TRUE
-from distutils.version import LooseVersion
-
-try:
- from f5.bigip import ManagementRoot
- from icontrol.exceptions import iControlUnexpectedHTTPError
- from f5.utils.responses.handlers import Stats
- HAS_F5SDK = True
-except ImportError:
- HAS_F5SDK = False
-
-try:
- from library.module_utils.network.f5.common import F5BaseClient
-except ImportError:
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import F5BaseClient
-
-try:
- from library.module_utils.network.f5.common import F5ModuleError
- from library.module_utils.network.f5.common import AnsibleF5Parameters
- from library.module_utils.network.f5.common import f5_argument_spec
-except ImportError:
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import F5ModuleError
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import AnsibleF5Parameters
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import f5_argument_spec
-
-
-class F5Client(F5BaseClient):
- def __init__(self, *args, **kwargs):
- super(F5Client, self).__init__(*args, **kwargs)
- self.provider = self.merge_provider_params()
-
- @property
- def api(self):
- if self._client:
- return self._client
-
- try:
- result = ManagementRoot(
- self.provider['server'],
- self.provider['user'],
- self.provider['password'],
- port=self.provider['server_port'],
- verify=self.provider['validate_certs'],
- token='tmos'
- )
- self._client = result
- return self._client
- except Exception as ex:
- error = 'Unable to connect to {0} on port {1}. The reported error was "{2}".'.format(
- self.provider['server'], self.provider['server_port'], str(ex)
- )
- raise F5ModuleError(error)
-
-
-class BaseManager(object):
- def __init__(self, *args, **kwargs):
- self.module = kwargs.get('module', None)
- self.client = kwargs.get('client', None)
- self.kwargs = kwargs
-
- self.types = dict(
- a_s='a',
- aaaas='aaaa',
- cnames='cname',
- mxs='mx',
- naptrs='naptr',
- srvs='srv'
- )
-
- def filter_matches_name(self, name):
- if self.want.filter is None:
- return True
- matches = re.match(self.want.filter, str(name))
- if matches:
- return True
- else:
- return False
-
- def version_is_less_than_12(self):
- version = self.client.api.tmos_version
- if LooseVersion(version) < LooseVersion('12.0.0'):
- return True
- else:
- return False
-
- def get_facts_from_collection(self, collection, collection_type=None):
- results = []
- for item in collection:
- if not self.filter_matches_name(item.name):
- continue
- facts = self.format_facts(item, collection_type)
- results.append(facts)
- return results
-
- def read_stats_from_device(self, resource):
- stats = Stats(resource.stats.load())
- return stats.stat
-
-
-class UntypedManager(BaseManager):
- def exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- filtered = [(k, v) for k, v in iteritems(attrs) if self.filter_matches_name(k)]
- if filtered:
- results.append(dict(filtered))
- return results
-
-
-class TypedManager(BaseManager):
- def exec_module(self):
- results = []
- for collection, type in iteritems(self.types):
- facts = self.read_facts(collection)
- if not facts:
- continue
- for x in facts:
- x.update({'type': type})
- for item in facts:
- attrs = item.to_return()
- filtered = [(k, v) for k, v in iteritems(attrs) if self.filter_matches_name(k)]
- if filtered:
- results.append(dict(filtered))
- return results
-
-
-class Parameters(AnsibleF5Parameters):
- @property
- def include(self):
- requested = self._values['include']
- valid = ['pool', 'wide_ip', 'server', 'all']
-
- if any(x for x in requested if x not in valid):
- raise F5ModuleError(
- "The valid 'include' choices are {0}".format(', '.join(valid))
- )
-
- if 'all' in requested:
- return ['all']
- else:
- return requested
-
-
-class BaseParameters(Parameters):
- @property
- def enabled(self):
- if self._values['enabled'] is None:
- return None
- elif self._values['enabled'] in BOOLEANS_TRUE:
- return True
- else:
- return False
-
- @property
- def disabled(self):
- if self._values['disabled'] is None:
- return None
- elif self._values['disabled'] in BOOLEANS_TRUE:
- return True
- else:
- return False
-
- def _remove_internal_keywords(self, resource):
- resource.pop('kind', None)
- resource.pop('generation', None)
- resource.pop('selfLink', None)
- resource.pop('isSubcollection', None)
- resource.pop('fullPath', None)
-
- def to_return(self):
- result = {}
- for returnable in self.returnables:
- result[returnable] = getattr(self, returnable)
- result = self._filter_params(result)
- return result
-
-
-class PoolParameters(BaseParameters):
- api_map = {
- 'alternateMode': 'alternate_mode',
- 'dynamicRatio': 'dynamic_ratio',
- 'fallbackMode': 'fallback_mode',
- 'fullPath': 'full_path',
- 'loadBalancingMode': 'load_balancing_mode',
- 'manualResume': 'manual_resume',
- 'maxAnswersReturned': 'max_answers_returned',
- 'qosHitRatio': 'qos_hit_ratio',
- 'qosHops': 'qos_hops',
- 'qosKilobytesSecond': 'qos_kilobytes_second',
- 'qosLcs': 'qos_lcs',
- 'qosPacketRate': 'qos_packet_rate',
- 'qosRtt': 'qos_rtt',
- 'qosTopology': 'qos_topology',
- 'qosVsCapacity': 'qos_vs_capacity',
- 'qosVsScore': 'qos_vs_score',
- 'verifyMemberAvailability': 'verify_member_availability',
- 'membersReference': 'members'
- }
-
- returnables = [
- 'alternate_mode', 'dynamic_ratio', 'enabled', 'disabled', 'fallback_mode',
- 'load_balancing_mode', 'manual_resume', 'max_answers_returned', 'members',
- 'name', 'partition', 'qos_hit_ratio', 'qos_hops', 'qos_kilobytes_second',
- 'qos_lcs', 'qos_packet_rate', 'qos_rtt', 'qos_topology', 'qos_vs_capacity',
- 'qos_vs_score', 'ttl', 'type', 'full_path', 'availability_state',
- 'enabled_state', 'availability_status'
- ]
-
- @property
- def max_answers_returned(self):
- if self._values['max_answers_returned'] is None:
- return None
- return int(self._values['max_answers_returned'])
-
- @property
- def members(self):
- result = []
- if self._values['members'] is None or 'items' not in self._values['members']:
- return result
- for item in self._values['members']['items']:
- self._remove_internal_keywords(item)
- if 'disabled' in item:
- if item['disabled'] in BOOLEANS_TRUE:
- item['disabled'] = True
- else:
- item['disabled'] = False
- if 'enabled' in item:
- if item['enabled'] in BOOLEANS_TRUE:
- item['enabled'] = True
- else:
- item['enabled'] = False
- if 'fullPath' in item:
- item['full_path'] = item.pop('fullPath')
- if 'memberOrder' in item:
- item['member_order'] = int(item.pop('memberOrder'))
- # Cast some attributes to integer
- for x in ['order', 'preference', 'ratio', 'service']:
- if x in item:
- item[x] = int(item[x])
- result.append(item)
- return result
-
- @property
- def qos_hit_ratio(self):
- if self._values['qos_hit_ratio'] is None:
- return None
- return int(self._values['qos_hit_ratio'])
-
- @property
- def qos_hops(self):
- if self._values['qos_hops'] is None:
- return None
- return int(self._values['qos_hops'])
-
- @property
- def qos_kilobytes_second(self):
- if self._values['qos_kilobytes_second'] is None:
- return None
- return int(self._values['qos_kilobytes_second'])
-
- @property
- def qos_lcs(self):
- if self._values['qos_lcs'] is None:
- return None
- return int(self._values['qos_lcs'])
-
- @property
- def qos_packet_rate(self):
- if self._values['qos_packet_rate'] is None:
- return None
- return int(self._values['qos_packet_rate'])
-
- @property
- def qos_rtt(self):
- if self._values['qos_rtt'] is None:
- return None
- return int(self._values['qos_rtt'])
-
- @property
- def qos_topology(self):
- if self._values['qos_topology'] is None:
- return None
- return int(self._values['qos_topology'])
-
- @property
- def qos_vs_capacity(self):
- if self._values['qos_vs_capacity'] is None:
- return None
- return int(self._values['qos_vs_capacity'])
-
- @property
- def qos_vs_score(self):
- if self._values['qos_vs_score'] is None:
- return None
- return int(self._values['qos_vs_score'])
-
- @property
- def availability_state(self):
- if self._values['stats'] is None:
- return None
- try:
- result = self._values['stats']['status_availabilityState']
- return result['description']
- except AttributeError:
- return None
-
- @property
- def enabled_state(self):
- if self._values['stats'] is None:
- return None
- try:
- result = self._values['stats']['status_enabledState']
- return result['description']
- except AttributeError:
- return None
-
- @property
- def availability_status(self):
- # This fact is a combination of the availability_state and enabled_state
- #
- # The purpose of the fact is to give a higher-level view of the availability
- # of the pool, that can be used in playbooks. If you need further detail,
- # consider using the following facts together.
- #
- # - availability_state
- # - enabled_state
- #
- if self.enabled_state == 'enabled':
- if self.availability_state == 'offline':
- return 'red'
- elif self.availability_state == 'available':
- return 'green'
- elif self.availability_state == 'unknown':
- return 'blue'
- else:
- return 'none'
- else:
- # disabled
- return 'black'
-
-
-class WideIpParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'failureRcode': 'failure_return_code',
- 'failureRcodeResponse': 'failure_return_code_response',
- 'failureRcodeTtl': 'failure_return_code_ttl',
- 'lastResortPool': 'last_resort_pool',
- 'minimalResponse': 'minimal_response',
- 'persistCidrIpv4': 'persist_cidr_ipv4',
- 'persistCidrIpv6': 'persist_cidr_ipv6',
- 'poolLbMode': 'pool_lb_mode',
- 'ttlPersistence': 'ttl_persistence'
- }
-
- returnables = [
- 'full_path', 'description', 'enabled', 'disabled', 'failure_return_code',
- 'failure_return_code_response', 'failure_return_code_ttl', 'last_resort_pool',
- 'minimal_response', 'persist_cidr_ipv4', 'persist_cidr_ipv6', 'pool_lb_mode',
- 'ttl_persistence', 'pools'
- ]
-
- @property
- def pools(self):
- result = []
- if self._values['pools'] is None:
- return []
- for pool in self._values['pools']:
- del pool['nameReference']
- for x in ['order', 'ratio']:
- if x in pool:
- pool[x] = int(pool[x])
- result.append(pool)
- return result
-
- @property
- def failure_return_code_ttl(self):
- if self._values['failure_return_code_ttl'] is None:
- return None
- return int(self._values['failure_return_code_ttl'])
-
- @property
- def persist_cidr_ipv4(self):
- if self._values['persist_cidr_ipv4'] is None:
- return None
- return int(self._values['persist_cidr_ipv4'])
-
- @property
- def persist_cidr_ipv6(self):
- if self._values['persist_cidr_ipv6'] is None:
- return None
- return int(self._values['persist_cidr_ipv6'])
-
- @property
- def ttl_persistence(self):
- if self._values['ttl_persistence'] is None:
- return None
- return int(self._values['ttl_persistence'])
-
-
-class ServerParameters(BaseParameters):
- api_map = {
- 'fullPath': 'full_path',
- 'exposeRouteDomains': 'expose_route_domains',
- 'iqAllowPath': 'iq_allow_path',
- 'iqAllowServiceCheck': 'iq_allow_service_check',
- 'iqAllowSnmp': 'iq_allow_snmp',
- 'limitCpuUsage': 'limit_cpu_usage',
- 'limitCpuUsageStatus': 'limit_cpu_usage_status',
- 'limitMaxBps': 'limit_max_bps',
- 'limitMaxBpsStatus': 'limit_max_bps_status',
- 'limitMaxConnections': 'limit_max_connections',
- 'limitMaxConnectionsStatus': 'limit_max_connections_status',
- 'limitMaxPps': 'limit_max_pps',
- 'limitMaxPpsStatus': 'limit_max_pps_status',
- 'limitMemAvail': 'limit_mem_available',
- 'limitMemAvailStatus': 'limit_mem_available_status',
- 'linkDiscovery': 'link_discovery',
- 'proberFallback': 'prober_fallback',
- 'proberPreference': 'prober_preference',
- 'virtualServerDiscovery': 'virtual_server_discovery',
- 'devicesReference': 'devices',
- 'virtualServersReference': 'virtual_servers'
- }
-
- returnables = [
- 'datacenter', 'enabled', 'disabled', 'expose_route_domains', 'iq_allow_path',
- 'full_path', 'iq_allow_service_check', 'iq_allow_snmp', 'limit_cpu_usage',
- 'limit_cpu_usage_status', 'limit_max_bps', 'limit_max_bps_status',
- 'limit_max_connections', 'limit_max_connections_status', 'limit_max_pps',
- 'limit_max_pps_status', 'limit_mem_available', 'limit_mem_available_status',
- 'link_discovery', 'monitor', 'product', 'prober_fallback', 'prober_preference',
- 'virtual_server_discovery', 'addresses', 'devices', 'virtual_servers'
- ]
-
- @property
- def product(self):
- if self._values['product'] is None:
- return None
- if self._values['product'] in ['single-bigip', 'redundant-bigip']:
- return 'bigip'
- return self._values['product']
-
- @property
- def devices(self):
- result = []
- if self._values['devices'] is None or 'items' not in self._values['devices']:
- return result
- for item in self._values['devices']['items']:
- self._remove_internal_keywords(item)
- if 'fullPath' in item:
- item['full_path'] = item.pop('fullPath')
- result.append(item)
- return result
-
- @property
- def virtual_servers(self):
- result = []
- if self._values['virtual_servers'] is None or 'items' not in self._values['virtual_servers']:
- return result
- for item in self._values['virtual_servers']['items']:
- self._remove_internal_keywords(item)
- if 'disabled' in item:
- if item['disabled'] in BOOLEANS_TRUE:
- item['disabled'] = True
- else:
- item['disabled'] = False
- if 'enabled' in item:
- if item['enabled'] in BOOLEANS_TRUE:
- item['enabled'] = True
- else:
- item['enabled'] = False
- if 'fullPath' in item:
- item['full_path'] = item.pop('fullPath')
- if 'limitMaxBps' in item:
- item['limit_max_bps'] = int(item.pop('limitMaxBps'))
- if 'limitMaxBpsStatus' in item:
- item['limit_max_bps_status'] = item.pop('limitMaxBpsStatus')
- if 'limitMaxConnections' in item:
- item['limit_max_connections'] = int(item.pop('limitMaxConnections'))
- if 'limitMaxConnectionsStatus' in item:
- item['limit_max_connections_status'] = item.pop('limitMaxConnectionsStatus')
- if 'limitMaxPps' in item:
- item['limit_max_pps'] = int(item.pop('limitMaxPps'))
- if 'limitMaxPpsStatus' in item:
- item['limit_max_pps_status'] = item.pop('limitMaxPpsStatus')
- if 'translationAddress' in item:
- item['translation_address'] = item.pop('translationAddress')
- if 'translationPort' in item:
- item['translation_port'] = int(item.pop('translationPort'))
- result.append(item)
- return result
-
- @property
- def limit_cpu_usage(self):
- if self._values['limit_cpu_usage'] is None:
- return None
- return int(self._values['limit_cpu_usage'])
-
- @property
- def limit_max_bps(self):
- if self._values['limit_max_bps'] is None:
- return None
- return int(self._values['limit_max_bps'])
-
- @property
- def limit_max_connections(self):
- if self._values['limit_max_connections'] is None:
- return None
- return int(self._values['limit_max_connections'])
-
- @property
- def limit_max_pps(self):
- if self._values['limit_max_pps'] is None:
- return None
- return int(self._values['limit_max_pps'])
-
- @property
- def limit_mem_available(self):
- if self._values['limit_mem_available'] is None:
- return None
- return int(self._values['limit_mem_available'])
-
-
-class PoolFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.module = kwargs.get('module', None)
- self.client = kwargs.get('client', None)
- super(PoolFactManager, self).__init__(**kwargs)
- self.kwargs = kwargs
-
- def exec_module(self):
- if self.version_is_less_than_12():
- manager = self.get_manager('untyped')
- else:
- manager = self.get_manager('typed')
- facts = manager.exec_module()
- result = dict(pool=facts)
- return result
-
- def get_manager(self, type):
- if type == 'typed':
- return TypedPoolFactManager(**self.kwargs)
- elif type == 'untyped':
- return UntypedPoolFactManager(**self.kwargs)
-
-
-class TypedPoolFactManager(TypedManager):
- def __init__(self, *args, **kwargs):
- self.module = kwargs.get('module', None)
- self.client = kwargs.get('client', None)
- super(TypedPoolFactManager, self).__init__(**kwargs)
- self.want = PoolParameters(params=self.module.params)
-
- def read_facts(self, collection):
- results = []
- collection = self.read_collection_from_device(collection)
- for resource in collection:
- attrs = resource.attrs
- attrs['stats'] = self.read_stats_from_device(resource)
- params = PoolParameters(params=attrs)
- results.append(params)
- return results
-
- def read_collection_from_device(self, collection_name):
- pools = self.client.api.tm.gtm.pools
- collection = getattr(pools, collection_name)
- result = collection.get_collection(
- requests_params=dict(
- params='expandSubcollections=true'
- )
- )
- return result
-
-
-class UntypedPoolFactManager(UntypedManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(UntypedPoolFactManager, self).__init__(**kwargs)
- self.want = PoolParameters(params=self.module.params)
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- attrs = resource.attrs
- attrs['stats'] = self.read_stats_from_device(resource)
- params = PoolParameters(params=attrs)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- result = self.client.api.tm.gtm.pools.get_collection(
- requests_params=dict(
- params='expandSubcollections=true'
- )
- )
- return result
-
-
-class WideIpFactManager(BaseManager):
- def exec_module(self):
- if self.version_is_less_than_12():
- manager = self.get_manager('untyped')
- else:
- manager = self.get_manager('typed')
- facts = manager.exec_module()
- result = dict(wide_ip=facts)
- return result
-
- def get_manager(self, type):
- if type == 'typed':
- return TypedWideIpFactManager(**self.kwargs)
- elif type == 'untyped':
- return UntypedWideIpFactManager(**self.kwargs)
-
-
-class TypedWideIpFactManager(TypedManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(TypedWideIpFactManager, self).__init__(**kwargs)
- self.want = WideIpParameters(params=self.module.params)
-
- def read_facts(self, collection):
- results = []
- collection = self.read_collection_from_device(collection)
- for resource in collection:
- attrs = resource.attrs
- params = WideIpParameters(params=attrs)
- results.append(params)
- return results
-
- def read_collection_from_device(self, collection_name):
- wideips = self.client.api.tm.gtm.wideips
- collection = getattr(wideips, collection_name)
- result = collection.get_collection(
- requests_params=dict(
- params='expandSubcollections=true'
- )
- )
- return result
-
-
-class UntypedWideIpFactManager(UntypedManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(UntypedWideIpFactManager, self).__init__(**kwargs)
- self.want = WideIpParameters(params=self.module.params)
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- attrs = resource.attrs
- params = WideIpParameters(params=attrs)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- result = self.client.api.tm.gtm.wideips.get_collection(
- requests_params=dict(
- params='expandSubcollections=true'
- )
- )
- return result
-
-
-class ServerFactManager(UntypedManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(ServerFactManager, self).__init__(**kwargs)
- self.want = ServerParameters(params=self.module.params)
-
- def exec_module(self):
- facts = super(ServerFactManager, self).exec_module()
- result = dict(server=facts)
- return result
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- attrs = resource.attrs
- params = ServerParameters(params=attrs)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- result = self.client.api.tm.gtm.servers.get_collection(
- requests_params=dict(
- params='expandSubcollections=true'
- )
- )
- return result
-
-
-class ModuleManager(object):
- def __init__(self, *args, **kwargs):
- self.module = kwargs.get('module', None)
- self.client = kwargs.get('client', None)
- self.kwargs = kwargs
- self.want = Parameters(params=self.module.params)
-
- def exec_module(self):
- if not self.gtm_provisioned():
- raise F5ModuleError(
- "GTM must be provisioned to use this module."
- )
-
- if 'all' in self.want.include:
- names = ['pool', 'wide_ip', 'server']
- else:
- names = self.want.include
- managers = [self.get_manager(name) for name in names]
- result = self.execute_managers(managers)
- if result:
- result['changed'] = True
- else:
- result['changed'] = False
- self._announce_deprecations()
- return result
-
- def _announce_deprecations(self):
- warnings = []
- if self.want:
- warnings += self.want._values.get('__warnings', [])
- for warning in warnings:
- self.module.deprecate(
- msg=warning['msg'],
- version=warning['version']
- )
-
- def execute_managers(self, managers):
- results = dict()
- for manager in managers:
- result = manager.exec_module()
- results.update(result)
- return results
-
- def get_manager(self, which):
- if 'pool' == which:
- return PoolFactManager(**self.kwargs)
- if 'wide_ip' == which:
- return WideIpFactManager(**self.kwargs)
- if 'server' == which:
- return ServerFactManager(**self.kwargs)
-
- def gtm_provisioned(self):
- resource = self.client.api.tm.sys.dbs.db.load(
- name='provisioned.cpu.gtm'
- )
- if int(resource.value) == 0:
- return False
- return True
-
-
-class ArgumentSpec(object):
- def __init__(self):
- self.supports_check_mode = False
- argument_spec = dict(
- include=dict(
- type='list',
- choices=[
- 'pool',
- 'wide_ip',
- 'server',
- ],
- required=True
- ),
- filter=dict()
- )
- self.argument_spec = {}
- self.argument_spec.update(f5_argument_spec)
- self.argument_spec.update(argument_spec)
-
-
-def main():
- spec = ArgumentSpec()
-
- module = AnsibleModule(
- argument_spec=spec.argument_spec,
- supports_check_mode=spec.supports_check_mode
- )
- if not HAS_F5SDK:
- module.fail_json(msg="The python f5-sdk module is required")
-
- client = F5Client(**module.params)
-
- try:
- mm = ModuleManager(module=module, client=client)
- results = mm.exec_module()
- module.exit_json(**results)
- except F5ModuleError as ex:
- module.fail_json(msg=str(ex))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/f5/bigip_iapplx_package.py b/plugins/modules/network/f5/bigip_iapplx_package.py
deleted file mode 120000
index 45a77871e2..0000000000
--- a/plugins/modules/network/f5/bigip_iapplx_package.py
+++ /dev/null
@@ -1 +0,0 @@
-bigip_lx_package.py
\ No newline at end of file
diff --git a/plugins/modules/network/f5/bigip_lx_package.py b/plugins/modules/network/f5/bigip_lx_package.py
deleted file mode 100644
index 2eb3b51b43..0000000000
--- a/plugins/modules/network/f5/bigip_lx_package.py
+++ /dev/null
@@ -1,481 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright: (c) 2017, F5 Networks Inc.
-# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'certified'}
-
-DOCUMENTATION = r'''
----
-module: bigip_lx_package
-short_description: Manages Javascript LX packages on a BIG-IP
-description:
- - Manages Javascript LX packages on a BIG-IP. This module will allow
- you to deploy LX packages to the BIG-IP and manage their lifecycle.
-options:
- package:
- description:
- - The LX package that you want to upload or remove. When C(state) is C(present),
- and you intend to use this module in a C(role), it is recommended that you use
- the C({{ role_path }}) variable. An example is provided in the C(EXAMPLES) section.
- - When C(state) is C(absent), it is not necessary for the package to exist on the
- Ansible controller. If the full path to the package is provided, the filename will
- specifically be cherry picked from it to properly remove the package.
- type: path
- state:
- description:
- - Whether the LX package should exist or not.
- type: str
- default: present
- choices:
- - present
- - absent
-notes:
- - Requires the rpm tool be installed on the host. This can be accomplished through
- different ways on each platform. On Debian based systems with C(apt);
- C(apt-get install rpm). On Mac with C(brew); C(brew install rpm).
- This command is already present on RedHat based systems.
- - Requires BIG-IP >= 12.1.0 because the required functionality is missing
- on versions earlier than that.
- - The module name C(bigip_iapplx_package) has been deprecated in favor of C(bigip_lx_package).
-requirements:
- - Requires BIG-IP >= 12.1.0
- - The 'rpm' tool installed on the Ansible controller
-extends_documentation_fragment:
-- f5networks.f5_modules.f5
-
-author:
- - Tim Rupp (@caphrim007)
- - Wojciech Wypior (@wojtek0806)
-'''
-
-EXAMPLES = r'''
-- name: Install AS3
- bigip_lx_package:
- package: f5-appsvcs-3.5.0-3.noarch.rpm
- provider:
- password: secret
- server: lb.mydomain.com
- user: admin
- delegate_to: localhost
-
-- name: Add an LX package stored in a role
- bigip_lx_package:
- package: "{{ roles_path }}/files/MyApp-0.1.0-0001.noarch.rpm'"
- provider:
- password: secret
- server: lb.mydomain.com
- user: admin
- delegate_to: localhost
-
-- name: Remove an LX package
- bigip_lx_package:
- package: MyApp-0.1.0-0001.noarch.rpm
- state: absent
- provider:
- password: secret
- server: lb.mydomain.com
- user: admin
- delegate_to: localhost
-'''
-
-RETURN = r'''
-# only common fields returned
-'''
-
-import os
-import time
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.urls import urlparse
-from distutils.version import LooseVersion
-
-try:
- from library.module_utils.network.f5.bigip import F5RestClient
- from library.module_utils.network.f5.common import F5ModuleError
- from library.module_utils.network.f5.common import AnsibleF5Parameters
- from library.module_utils.network.f5.common import f5_argument_spec
- from library.module_utils.network.f5.icontrol import tmos_version
- from library.module_utils.network.f5.icontrol import upload_file
-except ImportError:
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.bigip import F5RestClient
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import F5ModuleError
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import AnsibleF5Parameters
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import f5_argument_spec
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.icontrol import tmos_version
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.icontrol import upload_file
-
-
-class Parameters(AnsibleF5Parameters):
- api_attributes = []
- returnables = []
-
- @property
- def package(self):
- if self._values['package'] is None:
- return None
- return self._values['package']
-
- @property
- def package_file(self):
- if self._values['package'] is None:
- return None
- return os.path.basename(self._values['package'])
-
- @property
- def package_name(self):
- """Return a valid name for the package
-
- BIG-IP determines the package name by the content of the RPM info.
- It does not use the filename. Therefore, we do the same. This method
- is only used though when the file actually exists on your Ansible
- controller.
-
- If the package does not exist, then we instead use the filename
- portion of the 'package' argument that is provided.
-
- Non-existence typically occurs when using 'state' = 'absent'
-
- :return:
- """
- cmd = ['rpm', '-qp', '--queryformat', '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}', self.package]
- rc, out, err = self._module.run_command(cmd)
- if not out:
- return str(self.package_file)
- return out
-
- @property
- def package_root(self):
- if self._values['package'] is None:
- return None
- base = os.path.basename(self._values['package'])
- result = os.path.splitext(base)
- return result[0]
-
-
-class ApiParameters(Parameters):
- pass
-
-
-class ModuleParameters(Parameters):
- pass
-
-
-class Changes(Parameters):
- def to_return(self):
- result = {}
- try:
- for returnable in self.returnables:
- result[returnable] = getattr(self, returnable)
- result = self._filter_params(result)
- except Exception:
- pass
- return result
-
-
-class UsableChanges(Changes):
- pass
-
-
-class ReportableChanges(Changes):
- pass
-
-
-class ModuleManager(object):
- def __init__(self, *args, **kwargs):
- self.module = kwargs.get('module', None)
- self.client = F5RestClient(**self.module.params)
- self.want = ModuleParameters(module=self.module, params=self.module.params)
- self.changes = UsableChanges()
-
- def exec_module(self):
- result = dict()
- changed = False
- state = self.want.state
-
- version = tmos_version(self.client)
- if LooseVersion(version) <= LooseVersion('12.0.0'):
- raise F5ModuleError(
- "This version of BIG-IP is not supported."
- )
-
- if state == "present":
- changed = self.present()
- elif state == "absent":
- changed = self.absent()
-
- changes = self.changes.to_return()
- result.update(**changes)
- result.update(dict(changed=changed))
- return result
-
- def present(self):
- if self.exists():
- return False
- else:
- return self.create()
-
- def absent(self):
- changed = False
- if self.exists():
- changed = self.remove()
- return changed
-
- def remove(self):
- if self.module.check_mode:
- return True
- self.remove_from_device()
- if self.exists():
- raise F5ModuleError("Failed to delete the LX package.")
- return True
-
- def create(self):
- if self.module.check_mode:
- return True
- if not os.path.exists(self.want.package):
- if self.want.package.startswith('/'):
- raise F5ModuleError(
- "The specified LX package was not found at {0}.".format(self.want.package)
- )
- else:
- raise F5ModuleError(
- "The specified LX package was not found in {0}.".format(os.getcwd())
- )
- self.upload_to_device()
- self.create_on_device()
- self.enable_iapplx_on_device()
- self.remove_package_file_from_device()
- if self.exists():
- return True
- else:
- raise F5ModuleError("Failed to install LX package.")
-
- def exists(self):
- exists = False
- packages = self.get_installed_packages_on_device()
- if os.path.exists(self.want.package):
- exists = True
- for package in packages:
- if exists:
- if self.want.package_name == package['packageName']:
- return True
- else:
- if self.want.package_root == package['packageName']:
- return True
- return False
-
- def get_installed_packages_on_device(self):
- uri = "https://{0}:{1}/mgmt/shared/iapp/package-management-tasks".format(
- self.client.provider['server'],
- self.client.provider['server_port']
- )
- params = dict(operation='QUERY')
- resp = self.client.api.post(uri, json=params)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] in [400, 403]:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- path = urlparse(response["selfLink"]).path
- task = self._wait_for_task(path)
-
- if task['status'] == 'FINISHED':
- return task['queryResponse']
- raise F5ModuleError(
- "Failed to find the installed packages on the device."
- )
-
- def _wait_for_task(self, path):
- task = None
- for x in range(0, 60):
- task = self.check_task_on_device(path)
- if task['status'] in ['FINISHED', 'FAILED']:
- return task
- time.sleep(1)
- return task
-
- def check_task_on_device(self, path):
- uri = "https://{0}:{1}{2}".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- path
- )
- resp = self.client.api.get(uri)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- return response
-
- def upload_to_device(self):
- url = 'https://{0}:{1}/mgmt/shared/file-transfer/uploads'.format(
- self.client.provider['server'],
- self.client.provider['server_port']
- )
- try:
- upload_file(self.client, url, self.want.package)
- except F5ModuleError:
- raise F5ModuleError(
- "Failed to upload the file."
- )
-
- def remove_package_file_from_device(self):
- params = dict(
- command="run",
- utilCmdArgs="/var/config/rest/downloads/{0}".format(self.want.package_file)
- )
- uri = "https://{0}:{1}/mgmt/tm/util/unix-rm".format(
- self.client.provider['server'],
- self.client.provider['server_port']
- )
- resp = self.client.api.post(uri, json=params)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] in [400, 403]:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- def create_on_device(self):
- remote_path = "/var/config/rest/downloads/{0}".format(self.want.package_file)
- params = dict(
- operation='INSTALL', packageFilePath=remote_path
- )
- uri = "https://{0}:{1}/mgmt/shared/iapp/package-management-tasks".format(
- self.client.provider['server'],
- self.client.provider['server_port']
- )
-
- resp = self.client.api.post(uri, json=params)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] in [400, 403]:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- path = urlparse(response["selfLink"]).path
- task = self._wait_for_task(path)
-
- if task['status'] == 'FINISHED':
- return True
- else:
- raise F5ModuleError(task['errorMessage'])
-
- def remove_from_device(self):
- params = dict(
- operation='UNINSTALL',
- packageName=self.want.package_root
- )
- uri = "https://{0}:{1}/mgmt/shared/iapp/package-management-tasks".format(
- self.client.provider['server'],
- self.client.provider['server_port']
- )
-
- resp = self.client.api.post(uri, json=params)
-
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] in [400, 403]:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- path = urlparse(response["selfLink"]).path
- task = self._wait_for_task(path)
-
- if task['status'] == 'FINISHED':
- return True
- return False
-
- def enable_iapplx_on_device(self):
- params = dict(
- command="run",
- utilCmdArgs='-c "touch /var/config/rest/iapps/enable"'
- )
- uri = "https://{0}:{1}/mgmt/tm/util/bash".format(
- self.client.provider['server'],
- self.client.provider['server_port']
- )
- resp = self.client.api.post(uri, json=params)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] in [400, 403]:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
-
-class ArgumentSpec(object):
- def __init__(self):
- self.supports_check_mode = True
- argument_spec = dict(
- state=dict(
- default='present',
- choices=['present', 'absent']
- ),
- package=dict(type='path')
- )
- self.argument_spec = {}
- self.argument_spec.update(f5_argument_spec)
- self.argument_spec.update(argument_spec)
- self.required_if = [
- ['state', 'present', ['package']]
- ]
-
-
-def main():
- spec = ArgumentSpec()
-
- module = AnsibleModule(
- argument_spec=spec.argument_spec,
- supports_check_mode=spec.supports_check_mode,
- required_if=spec.required_if
- )
-
- try:
- mm = ModuleManager(module=module)
- results = mm.exec_module()
- module.exit_json(**results)
- except F5ModuleError as ex:
- module.fail_json(msg=str(ex))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/f5/bigip_security_address_list.py b/plugins/modules/network/f5/bigip_security_address_list.py
deleted file mode 120000
index 6bef19600f..0000000000
--- a/plugins/modules/network/f5/bigip_security_address_list.py
+++ /dev/null
@@ -1 +0,0 @@
-bigip_firewall_address_list.py
\ No newline at end of file
diff --git a/plugins/modules/network/f5/bigip_security_port_list.py b/plugins/modules/network/f5/bigip_security_port_list.py
deleted file mode 120000
index a78176b5bf..0000000000
--- a/plugins/modules/network/f5/bigip_security_port_list.py
+++ /dev/null
@@ -1 +0,0 @@
-bigip_firewall_port_list.py
\ No newline at end of file
diff --git a/plugins/modules/network/f5/bigip_traffic_group.py b/plugins/modules/network/f5/bigip_traffic_group.py
deleted file mode 120000
index 7caabb783b..0000000000
--- a/plugins/modules/network/f5/bigip_traffic_group.py
+++ /dev/null
@@ -1 +0,0 @@
-bigip_device_traffic_group.py
\ No newline at end of file
diff --git a/plugins/modules/network/f5/bigiq_device_facts.py b/plugins/modules/network/f5/bigiq_device_facts.py
deleted file mode 120000
index e6543531fc..0000000000
--- a/plugins/modules/network/f5/bigiq_device_facts.py
+++ /dev/null
@@ -1 +0,0 @@
-bigiq_device_info.py
\ No newline at end of file
diff --git a/plugins/modules/network/f5/bigiq_device_info.py b/plugins/modules/network/f5/bigiq_device_info.py
deleted file mode 100644
index 863fc4eccd..0000000000
--- a/plugins/modules/network/f5/bigiq_device_info.py
+++ /dev/null
@@ -1,2314 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2018 F5 Networks Inc.
-# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'certified'}
-
-DOCUMENTATION = r'''
----
-module: bigiq_device_info
-short_description: Collect information from F5 BIG-IQ devices
-description:
- - Collect information from F5 BIG-IQ devices.
- - This module was called C(bigiq_device_facts) before Ansible 2.9. The usage did not change.
-options:
- gather_subset:
- description:
- - When supplied, this argument will restrict the information returned to a given subset.
- - Can specify a list of values to include a larger subset.
- - Values can also be used with an initial C(!) to specify that a specific subset
- should not be collected.
- type: list
- required: True
- choices:
- - all
- - applications
- - managed-devices
- - purchased-pool-licenses
- - regkey-pools
- - system-info
- - vlans
- - "!all"
- - "!applications"
- - "!managed-devices"
- - "!purchased-pool-licenses"
- - "!regkey-pools"
- - "!system-info"
- - "!vlans"
-extends_documentation_fragment:
-- f5networks.f5_modules.f5
-
-author:
- - Tim Rupp (@caphrim007)
-'''
-
-EXAMPLES = r'''
-- name: Collect BIG-IQ information
- bigiq_device_info:
- gather_subset:
- - system-info
- - vlans
- provider:
- server: lb.mydomain.com
- user: admin
- password: secret
- delegate_to: localhost
-
-- name: Collect all BIG-IQ information
- bigiq_device_info:
- gather_subset:
- - all
- provider:
- server: lb.mydomain.com
- user: admin
- password: secret
- delegate_to: localhost
-
-- name: Collect all BIG-IP information except trunks
- bigiq_device_info:
- gather_subset:
- - all
- - "!trunks"
- provider:
- server: lb.mydomain.com
- user: admin
- password: secret
- delegate_to: localhost
-'''
-
-RETURN = r'''
-applications:
- description: Application related information
- returned: When C(managed-devices) is specified in C(gather_subset).
- type: complex
- contains:
- protection_mode:
- description:
- - The type of F5 Web Application Security Service protection on the application.
- returned: changed
- type: str
- sample: Not Protected
- id:
- description:
- - ID of the application as known to the BIG-IQ.
- returned: changed
- type: str
- sample: 996baae8-5d1d-3662-8a2d-3612fa2aceae
- name:
- description:
- - Name of the application.
- returned: changed
- type: str
- sample: site12http.example.com
- status:
- description:
- - Current state of the application.
- returned: changed
- type: str
- sample: DEPLOYED
- transactions_per_second:
- description:
- - Current measurement of Transactions Per second being handled by the application.
- returned: changed
- type: float
- sample: 0.87
- connections:
- description:
- - Current number of connections established to the application.
- returned: changed
- type: float
- sample: 3.06
- new_connections:
- description:
- - Number of new connections being established per second.
- returned: changed
- type: float
- sample: 0.35
- response_time:
- description:
- - Measured response time of the application in milliseconds.
- returned: changed
- type: float
- sample: 0.02
- health:
- description:
- - Health of the application.
- returned: changed
- type: str
- sample: Good
- active_alerts:
- description:
- - Number of alerts active on the application.
- returned: changed
- type: int
- sample: 0
- bad_traffic:
- description:
- - Percent of traffic to application that is determined to be 'bad'.
- - This value is dependent on C(protection_mode) being enabled.
- returned: changed
- type: float
- sample: 1.7498
- enhanced_analytics:
- description:
- - Whether enhanced analytics is enabled for the application or not.
- returned: changed
- type: bool
- sample: yes
- bad_traffic_growth:
- description:
- - Whether or not Bad Traffic Growth alerts are configured to be triggered or not.
- returned: changed
- type: bool
- sample: no
- sample: hash/dictionary of values
-managed_devices:
- description: Managed device related information.
- returned: When C(managed-devices) is specified in C(gather_subset).
- type: complex
- contains:
- address:
- description:
- - Address where the device was discovered.
- returned: changed
- type: str
- sample: 10.10.10.10
- build:
- description:
- - Build of the version.
- returned: changed
- type: str
- sample: 0.0.4
- device_uri:
- description:
- - URI to reach the management interface of the device.
- returned: changed
- type: str
- sample: "https://10.10.10.10:443"
- edition:
- description:
- - Edition string of the product version.
- returned: changed
- type: str
- sample: Final
- group_name:
- description:
- - BIG-IQ group that the device is a member of.
- returned: changed
- type: str
- sample: cm-bigip-allBigIpDevices
- hostname:
- description:
- - Discovered hostname of the device.
- returned: changed
- type: str
- sample: tier2labB1.lab.fp.foo.com
- https_port:
- description:
- - HTTPS port available on the management interface of the device.
- returned: changed
- type: int
- sample: 443
- is_clustered:
- description:
- - Whether the device is clustered or not.
- returned: changed
- type: bool
- sample: no
- is_license_expired:
- description:
- - Whether the license on the device is expired or not.
- returned: changed
- type: bool
- sample: yes
- is_virtual:
- description:
- - Whether the device is a virtual edition or not.
- returned: changed
- type: bool
- sample: yes
- machine_id:
- description:
- - Machine specific ID assigned to this device by BIG-IQ.
- returned: changed
- type: str
- sample: c141bc88-f734-4434-be64-a3e9ea98356e
- management_address:
- description:
- - IP address of the management interface on the device.
- returned: changed
- type: str
- sample: 10.10.10.10
- mcp_device_name:
- description:
- - Device name as known by MCPD on the BIG-IP.
- returned: changed
- type: str
- sample: /Common/tier2labB1.lab.fp.foo.com
- product:
- description:
- - Product that the managed device is identified as.
- returned: changed
- type: str
- sample: BIG-IP
- rest_framework_version:
- description:
- - REST framework version running on the device
- returned: changed
- type: str
- sample: 13.1.1-0.0.4
- self_link:
- description:
- - Internal reference to the managed device in BIG-IQ.
- returned: changed
- type: str
- sample: "https://localhost/mgmt/shared/resolver/device-groups/cm-bigip-allBigIpDevices/devices/c141bc88-f734-4434-be64-a3e9ea98356e"
- slots:
- description:
- - Volumes on the device and versions of software installed in those volumes.
- returned: changed
- type: complex
- sample: {"volume": "HD1.1", "product": "BIG-IP", "version": "13.1.1", "build": "0.0.4", "isActive": "yes"}
- state:
- description:
- - State of the device.
- returned: changed
- type: str
- sample: ACTIVE
- tags:
- description:
- - Misc tags that are assigned to the device.
- returned: changed
- type: complex
- sample: {'BIGIQ_tier_2_device': '2018-08-22T13:30:47.693-07:00', 'BIGIQ_SSG_name': 'tim-ssg'}
- trust_domain_guid:
- description:
- - GUID of the trust domain the device is part of.
- returned: changed
- type: str
- sample: 40ddf541-e604-4905-bde3005056813e36
- uuid:
- description:
- - UUID of the device in BIG-IQ.
- returned: changed
- type: str
- sample: c141bc88-f734-4434-be64-a3e9ea98356e
- version:
- description:
- - Version of TMOS installed on the device.
- returned: changed
- type: str
- sample: 13.1.1
- sample: hash/dictionary of values
-purchased_pool_licenses:
- description: Purchased Pool License related information.
- returned: When C(purchased-pool-licenses) is specified in C(gather_subset).
- type: complex
- contains:
- base_reg_key:
- description:
- - Base registration key of the purchased pool
- returned: changed
- type: str
- sample: XXXXX-XXXXX-XXXXX-XXXXX-XXXXXXX
- dossier:
- description:
- - Dossier of the purchased pool license
- returned: changed
- type: str
- sample: d6bd4b8ba5...e9a1a1199b73af9932948a
- free_device_licenses:
- description:
- - Number of free licenses remaining.
- returned: changed
- type: int
- sample: 34
- name:
- description:
- - Name of the purchased pool
- returned: changed
- type: str
- sample: my-pool1
- state:
- description:
- - State of the purchased pool license
- returned: changed
- type: str
- sample: LICENSED
- total_device_licenses:
- description:
- - Total number of licenses in the pool.
- returned: changed
- type: int
- sample: 40
- uuid:
- description:
- - UUID of the purchased pool license
- returned: changed
- type: str
- sample: b2112329-cba7-4f1f-9a26-fab9be416d60
- vendor:
- description:
- - Vendor who provided the license
- returned: changed
- type: str
- sample: F5 Networks, Inc
- licensed_date_time:
- description:
- - Timestamp that the pool was licensed.
- returned: changed
- type: str
- sample: "2018-09-10T00:00:00-07:00"
- licensed_version:
- description:
- - Version of BIG-IQ that is licensed.
- returned: changed
- type: str
- sample: 6.0.1
- evaluation_start_date_time:
- description:
- - Date that evaluation license starts.
- returned: changed
- type: str
- sample: "2018-09-09T00:00:00-07:00"
- evaluation_end_date_time:
- description:
- - Date that evaluation license ends.
- returned: changed
- type: str
- sample: "2018-10-11T00:00:00-07:00"
- license_end_date_time:
- description:
- - Date that the license expires.
- returned: changed
- type: str
- sample: "2018-10-11T00:00:00-07:00"
- license_start_date_time:
- description:
- - Date that the license starts.
- returned: changed
- type: str
- sample: "2018-09-09T00:00:00-07:00"
- registration_key:
- description:
- - Purchased pool license key.
- returned: changed
- type: str
- sample: XXXXX-XXXXX-XXXXX-XXXXX-XXXXXXX
- sample: hash/dictionary of values
-regkey_pools:
- description: Regkey Pool related information.
- returned: When C(regkey-pools) is specified in C(gather_subset).
- type: complex
- contains:
- name:
- description:
- - Name of the regkey pool.
- returned: changed
- type: str
- sample: pool1
- id:
- description:
- - ID of the regkey pool.
- returned: changed
- type: str
- sample: 4f9b565c-0831-4657-b6c2-6dde6182a502
- total_offerings:
- description:
- - Total number of offerings in the pool
- returned: changed
- type: int
- sample: 10
- offerings:
- description: List of the offerings in the pool.
- type: complex
- contains:
- dossier:
- description:
- - Dossier of the license.
- returned: changed
- type: str
- sample: d6bd4b8ba5...e9a1a1199b73af9932948a
- name:
- description:
- - Name of the regkey.
- returned: changed
- type: str
- sample: regkey1
- state:
- description:
- - State of the regkey license
- returned: changed
- type: str
- sample: LICENSED
- licensed_date_time:
- description:
- - Timestamp that the regkey was licensed.
- returned: changed
- type: str
- sample: "2018-09-10T00:00:00-07:00"
- licensed_version:
- description:
- - Version of BIG-IQ that is licensed.
- returned: changed
- type: str
- sample: 6.0.1
- evaluation_start_date_time:
- description:
- - Date that evaluation license starts.
- returned: changed
- type: str
- sample: "2018-09-09T00:00:00-07:00"
- evaluation_end_date_time:
- description:
- - Date that evaluation license ends.
- returned: changed
- type: str
- sample: "2018-10-11T00:00:00-07:00"
- license_end_date_time:
- description:
- - Date that the license expires.
- returned: changed
- type: str
- sample: "2018-10-11T00:00:00-07:00"
- license_start_date_time:
- description:
- - Date that the license starts.
- returned: changed
- type: str
- sample: "2018-09-09T00:00:00-07:00"
- registration_key:
- description:
- - Registration license key.
- returned: changed
- type: str
- sample: XXXXX-XXXXX-XXXXX-XXXXX-XXXXXXX
- sample: hash/dictionary of values
- sample: hash/dictionary of values
-system_info:
- description: System info related information.
- returned: When C(system-info) is specified in C(gather_subset).
- type: complex
- contains:
- base_mac_address:
- description:
- - Media Access Control address (MAC address) of the device.
- returned: changed
- type: str
- sample: "fa:16:3e:c3:42:6f"
- marketing_name:
- description:
- - Marketing name of the device platform.
- returned: changed
- type: str
- sample: BIG-IQ Virtual Edition
- time:
- description:
- - Mapping of the current time information to specific time-named keys.
- returned: changed
- type: complex
- contains:
- day:
- description:
- - The current day of the month, in numeric form.
- returned: changed
- type: int
- sample: 7
- hour:
- description:
- - The current hour of the day in 24-hour form.
- returned: changed
- type: int
- sample: 18
- minute:
- description:
- - The current minute of the hour.
- returned: changed
- type: int
- sample: 16
- month:
- description:
- - The current month, in numeric form.
- returned: changed
- type: int
- sample: 6
- second:
- description:
- - The current second of the minute.
- returned: changed
- type: int
- sample: 51
- year:
- description:
- - The current year in 4-digit form.
- returned: changed
- type: int
- sample: 2018
- hardware_information:
- description:
- - Information related to the hardware (drives and CPUs) of the system.
- type: complex
- returned: changed
- contains:
- model:
- description:
- - The model of the hardware.
- type: str
- sample: Virtual Disk
- name:
- description:
- - The name of the hardware.
- type: str
- sample: HD1
- type:
- description:
- - The type of hardware.
- type: str
- sample: physical-disk
- versions:
- description:
- - Hardware specific properties
- type: complex
- contains:
- name:
- description:
- - Name of the property
- type: str
- sample: Size
- version:
- description:
- - Value of the property
- type: str
- sample: 154.00G
- is_admin_password_changed:
- description:
- - Whether the admin password was changed from its default or not.
- returned: changed
- type: bool
- sample: yes
- is_root_password_changed:
- description:
- - Whether the root password was changed from its default or not.
- returned: changed
- type: bool
- sample: no
- is_system_setup:
- description:
- - Whether the system has been setup or not.
- returned: changed
- type: bool
- sample: yes
- package_edition:
- description:
- - Displays the software edition.
- returned: changed
- type: str
- sample: Point Release 7
- package_version:
- description:
- - A string combining the C(product_build) and C(product_build_date).
- type: str
- sample: "Build 0.0.1 - Tue May 15 15:26:30 PDT 2018"
- product_code:
- description:
- - Code identifying the product.
- type: str
- sample: BIG-IQ
- product_build:
- description:
- - Build version of the release version.
- type: str
- sample: 0.0.1
- product_version:
- description:
- - Major product version of the running software.
- type: str
- sample: 6.0.0
- product_built:
- description:
- - Unix timestamp of when the product was built.
- type: int
- sample: 180515152630
- product_build_date:
- description:
- - Human readable build date.
- type: str
- sample: "Tue May 15 15:26:30 PDT 2018"
- product_changelist:
- description:
- - Changelist that product branches from.
- type: int
- sample: 2557198
- product_jobid:
- description:
- - ID of the job that built the product version.
- type: int
- sample: 1012030
- chassis_serial:
- description:
- - Serial of the chassis
- type: str
- sample: 11111111-2222-3333-444444444444
- host_board_part_revision:
- description:
- - Revision of the host board.
- type: str
- host_board_serial:
- description:
- - Serial of the host board.
- type: str
- platform:
- description:
- - Platform identifier.
- type: str
- sample: Z100
- switch_board_part_revision:
- description:
- - Switch board revision.
- type: str
- switch_board_serial:
- description:
- - Serial of the switch board.
- type: str
- uptime:
- description:
- - Time, in seconds, since the system booted.
- type: int
- sample: 603202
- sample: hash/dictionary of values
-vlans:
- description: List of VLAN information.
- returned: When C(vlans) is specified in C(gather_subset).
- type: complex
- contains:
- auto_lasthop:
- description:
- - Allows the system to send return traffic to the MAC address that transmitted the
- request, even if the routing table points to a different network or interface.
- returned: changed
- type: str
- sample: enabled
- cmp_hash_algorithm:
- description:
- - Specifies how the traffic on the VLAN will be disaggregated.
- returned: changed
- type: str
- sample: default
- description:
- description:
- - Description of the VLAN.
- returned: changed
- type: str
- sample: My vlan
- failsafe_action:
- description:
- - Action for the system to take when the fail-safe mechanism is triggered.
- returned: changed
- type: str
- sample: reboot
- failsafe_enabled:
- description:
- - Whether failsafe is enabled or not.
- returned: changed
- type: bool
- sample: yes
- failsafe_timeout:
- description:
- - Number of seconds that an active unit can run without detecting network traffic
- on this VLAN before it starts a failover.
- returned: changed
- type: int
- sample: 90
- if_index:
- description:
- - Index assigned to this VLAN. It is a unique identifier assigned for all objects
- displayed in the SNMP IF-MIB.
- returned: changed
- type: int
- sample: 176
- learning_mode:
- description:
- - Whether switch ports placed in the VLAN are configured for switch learning,
- forwarding only, or dropped.
- returned: changed
- type: str
- sample: enable-forward
- interfaces:
- description:
- - List of tagged or untagged interfaces and trunks that you want to configure for the VLAN.
- returned: changed
- type: complex
- contains:
- full_path:
- description:
- - Full name of the resource as known to BIG-IP.
- returned: changed
- type: str
- sample: 1.3
- name:
- description:
- - Relative name of the resource in BIG-IP.
- returned: changed
- type: str
- sample: 1.3
- tagged:
- description:
- - Whether the interface is tagged or not.
- returned: changed
- type: bool
- sample: no
- mtu:
- description:
- - Specific maximum transition unit (MTU) for the VLAN.
- returned: changed
- type: int
- sample: 1500
- sflow_poll_interval:
- description:
- - Maximum interval in seconds between two pollings.
- returned: changed
- type: int
- sample: 0
- sflow_poll_interval_global:
- description:
- - Whether the global VLAN poll-interval setting, overrides the object-level
- poll-interval setting.
- returned: changed
- type: bool
- sample: no
- sflow_sampling_rate:
- description:
- - Ratio of packets observed to the samples generated.
- returned: changed
- type: int
- sample: 0
- sflow_sampling_rate_global:
- description:
- - Whether the global VLAN sampling-rate setting, overrides the object-level
- sampling-rate setting.
- returned: changed
- type: bool
- sample: yes
- source_check_enabled:
- description:
- - Specifies that only connections that have a return route in the routing table are accepted.
- returned: changed
- type: bool
- sample: yes
- true_mac_address:
- description:
- - Media access control (MAC) address for the lowest-numbered interface assigned to this VLAN.
- returned: changed
- type: str
- sample: "fa:16:3e:10:da:ff"
- tag:
- description:
- - Tag number for the VLAN.
- returned: changed
- type: int
- sample: 30
- sample: hash/dictionary of values
-'''
-
-import datetime
-import math
-import re
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.six import iteritems
-from ansible.module_utils.six import string_types
-
-try:
- from library.module_utils.network.f5.bigiq import F5RestClient
- from library.module_utils.network.f5.common import F5ModuleError
- from library.module_utils.network.f5.common import AnsibleF5Parameters
- from library.module_utils.network.f5.common import f5_argument_spec
- from library.module_utils.network.f5.common import fq_name
- from library.module_utils.network.f5.common import flatten_boolean
- from library.module_utils.network.f5.ipaddress import is_valid_ip
- from library.module_utils.network.f5.common import transform_name
-except ImportError:
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.bigiq import F5RestClient
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import F5ModuleError
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import AnsibleF5Parameters
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import f5_argument_spec
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import fq_name
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import flatten_boolean
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.ipaddress import is_valid_ip
- from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import transform_name
-
-
-def parseStats(entry):
- if 'description' in entry:
- return entry['description']
- elif 'value' in entry:
- return entry['value']
- elif 'entries' in entry or 'nestedStats' in entry and 'entries' in entry['nestedStats']:
- if 'entries' in entry:
- entries = entry['entries']
- else:
- entries = entry['nestedStats']['entries']
- result = None
-
- for name in entries:
- entry = entries[name]
- if 'https://localhost' in name:
- name = name.split('/')
- name = name[-1]
- if result and isinstance(result, list):
- result.append(parseStats(entry))
- elif result and isinstance(result, dict):
- result[name] = parseStats(entry)
- else:
- try:
- int(name)
- result = list()
- result.append(parseStats(entry))
- except ValueError:
- result = dict()
- result[name] = parseStats(entry)
- else:
- if '.' in name:
- names = name.split('.')
- key = names[0]
- value = names[1]
- if not result[key]:
- result[key] = {}
- result[key][value] = parseStats(entry)
- else:
- if result and isinstance(result, list):
- result.append(parseStats(entry))
- elif result and isinstance(result, dict):
- result[name] = parseStats(entry)
- else:
- try:
- int(name)
- result = list()
- result.append(parseStats(entry))
- except ValueError:
- result = dict()
- result[name] = parseStats(entry)
- return result
-
-
-class BaseManager(object):
- def __init__(self, *args, **kwargs):
- self.module = kwargs.get('module', None)
- self.client = kwargs.get('client', None)
- self.kwargs = kwargs
-
- def exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- return results
-
-
-class Parameters(AnsibleF5Parameters):
- @property
- def gather_subset(self):
- if isinstance(self._values['gather_subset'], string_types):
- self._values['gather_subset'] = [self._values['gather_subset']]
- elif not isinstance(self._values['gather_subset'], list):
- raise F5ModuleError(
- "The specified gather_subset must be a list."
- )
- tmp = list(set(self._values['gather_subset']))
- tmp.sort()
- self._values['gather_subset'] = tmp
-
- return self._values['gather_subset']
-
-
-class BaseParameters(Parameters):
- @property
- def enabled(self):
- return flatten_boolean(self._values['enabled'])
-
- @property
- def disabled(self):
- return flatten_boolean(self._values['disabled'])
-
- def _remove_internal_keywords(self, resource):
- resource.pop('kind', None)
- resource.pop('generation', None)
- resource.pop('selfLink', None)
- resource.pop('isSubcollection', None)
- resource.pop('fullPath', None)
-
- def to_return(self):
- result = {}
- for returnable in self.returnables:
- result[returnable] = getattr(self, returnable)
- result = self._filter_params(result)
- return result
-
-
-class ApplicationsParameters(BaseParameters):
- api_map = {
- 'protectionMode': 'protection_mode',
- 'transactionsPerSecond': 'transactions_per_second',
- 'newConnections': 'new_connections',
- 'responseTime': 'response_time',
- 'activeAlerts': 'active_alerts',
- 'badTraffic': 'bad_traffic',
- 'enhancedAnalytics': 'enhanced_analytics',
- 'badTrafficGrowth': 'bad_traffic_growth'
- }
-
- returnables = [
- 'protection_mode',
- 'id',
- 'name',
- 'status',
- 'transactions_per_second',
- 'connections',
- 'new_connections',
- 'response_time',
- 'health',
- 'active_alerts',
- 'bad_traffic',
- 'enhanced_analytics',
- 'bad_traffic_growth',
- ]
-
- @property
- def enhanced_analytics(self):
- return flatten_boolean(self._values['enhanced_analytics'])
-
- @property
- def bad_traffic_growth(self):
- return flatten_boolean(self._values['bad_traffic_growth'])
-
-
-class ApplicationsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(ApplicationsFactManager, self).__init__(**kwargs)
- self.want = ApplicationsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(applications=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['name'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = ApplicationsParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/ap/query/v1/tenants/default/reports/AllApplicationsList".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- try:
- return response['result']['items']
- except KeyError:
- return []
-
-
-class ManagedDevicesParameters(BaseParameters):
- api_map = {
- 'deviceUri': 'device_uri',
- 'groupName': 'group_name',
- 'httpsPort': 'https_port',
- 'isClustered': 'is_clustered',
- 'isLicenseExpired': 'is_license_expired',
- 'isVirtual': 'is_virtual',
- 'machineId': 'machine_id',
- 'managementAddress': 'management_address',
- 'mcpDeviceName': 'mcp_device_name',
- 'restFrameworkVersion': 'rest_framework_version',
- 'selfLink': 'self_link',
- 'trustDomainGuid': 'trust_domain_guid',
- }
-
- returnables = [
- 'address',
- 'build',
- 'device_uri',
- 'edition',
- 'group_name',
- 'hostname',
- 'https_port',
- 'is_clustered',
- 'is_license_expired',
- 'is_virtual',
- 'machine_id',
- 'management_address',
- 'mcp_device_name',
- 'product',
- 'rest_framework_version',
- 'self_link',
- 'slots',
- 'state',
- 'tags',
- 'trust_domain_guid',
- 'uuid',
- 'version',
- ]
-
- @property
- def slots(self):
- result = []
- if self._values['slots'] is None:
- return None
- for x in self._values['slots']:
- x['is_active'] = flatten_boolean(x.pop('isActive', False))
- result.append(x)
- return result
-
- @property
- def tags(self):
- if self._values['tags'] is None:
- return None
- result = dict((x['name'], x['value']) for x in self._values['tags'])
- return result
-
- @property
- def https_port(self):
- return int(self._values['https_port'])
-
- @property
- def is_clustered(self):
- return flatten_boolean(self._values['is_clustered'])
-
- @property
- def is_license_expired(self):
- return flatten_boolean(self._values['is_license_expired'])
-
- @property
- def is_virtual(self):
- return flatten_boolean(self._values['is_virtual'])
-
-
-class ManagedDevicesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(ManagedDevicesFactManager, self).__init__(**kwargs)
- self.want = ManagedDevicesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(managed_devices=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['hostname'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = ManagedDevicesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/shared/resolver/device-groups/cm-bigip-allBigIpDevices/devices".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class PurchasedPoolLicensesParameters(BaseParameters):
- api_map = {
- 'baseRegKey': 'base_reg_key',
- 'freeDeviceLicenses': 'free_device_licenses',
- 'licenseState': 'license_state',
- 'totalDeviceLicenses': 'total_device_licenses',
- }
-
- returnables = [
- 'base_reg_key',
- 'dossier',
- 'free_device_licenses',
- 'name',
- 'state',
- 'total_device_licenses',
- 'uuid',
-
- # license_state facts
- 'vendor',
- 'licensed_date_time',
- 'licensed_version',
- 'evaluation_start_date_time',
- 'evaluation_end_date_time',
- 'license_end_date_time',
- 'license_start_date_time',
- 'registration_key',
- ]
-
- @property
- def registration_key(self):
- try:
- return self._values['license_state']['registrationKey']
- except KeyError:
- return None
-
- @property
- def license_start_date_time(self):
- try:
- return self._values['license_state']['licenseStartDateTime']
- except KeyError:
- return None
-
- @property
- def license_end_date_time(self):
- try:
- return self._values['license_state']['licenseEndDateTime']
- except KeyError:
- return None
-
- @property
- def evaluation_end_date_time(self):
- try:
- return self._values['license_state']['evaluationEndDateTime']
- except KeyError:
- return None
-
- @property
- def evaluation_start_date_time(self):
- try:
- return self._values['license_state']['evaluationStartDateTime']
- except KeyError:
- return None
-
- @property
- def licensed_version(self):
- try:
- return self._values['license_state']['licensedVersion']
- except KeyError:
- return None
-
- @property
- def licensed_date_time(self):
- try:
- return self._values['license_state']['licensedDateTime']
- except KeyError:
- return None
-
- @property
- def vendor(self):
- try:
- return self._values['license_state']['vendor']
- except KeyError:
- return None
-
-
-class PurchasedPoolLicensesFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(PurchasedPoolLicensesFactManager, self).__init__(**kwargs)
- self.want = PurchasedPoolLicensesParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(purchased_pool_licenses=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['name'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = PurchasedPoolLicensesParameters(params=resource)
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/cm/device/licensing/pool/purchased-pool/licenses".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- try:
- return response['items']
- except KeyError:
- return []
-
-
-class RegkeyPoolsParameters(BaseParameters):
- api_map = {
-
- }
-
- returnables = [
- 'name',
- 'id',
- 'offerings',
- 'total_offerings',
- ]
-
-
-class RegkeyPoolsOfferingParameters(BaseParameters):
- api_map = {
- 'regKey': 'registration_key',
- 'licenseState': 'license_state',
- 'status': 'state',
- }
-
- returnables = [
- 'name',
- 'dossier',
- 'state',
-
- # license_state facts
- 'licensed_date_time',
- 'licensed_version',
- 'evaluation_start_date_time',
- 'evaluation_end_date_time',
- 'license_end_date_time',
- 'license_start_date_time',
- 'registration_key',
- ]
-
- @property
- def registration_key(self):
- try:
- return self._values['license_state']['registrationKey']
- except KeyError:
- return None
-
- @property
- def license_start_date_time(self):
- try:
- return self._values['license_state']['licenseStartDateTime']
- except KeyError:
- return None
-
- @property
- def license_end_date_time(self):
- try:
- return self._values['license_state']['licenseEndDateTime']
- except KeyError:
- return None
-
- @property
- def evaluation_end_date_time(self):
- try:
- return self._values['license_state']['evaluationEndDateTime']
- except KeyError:
- return None
-
- @property
- def evaluation_start_date_time(self):
- try:
- return self._values['license_state']['evaluationStartDateTime']
- except KeyError:
- return None
-
- @property
- def licensed_version(self):
- try:
- return self._values['license_state']['licensedVersion']
- except KeyError:
- return None
-
- @property
- def licensed_date_time(self):
- try:
- return self._values['license_state']['licensedDateTime']
- except KeyError:
- return None
-
- @property
- def vendor(self):
- try:
- return self._values['license_state']['vendor']
- except KeyError:
- return None
-
-
-class RegkeyPoolsFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(RegkeyPoolsFactManager, self).__init__(**kwargs)
- self.want = RegkeyPoolsParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(regkey_pools=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['name'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- params = RegkeyPoolsParameters(params=resource)
- offerings = self.read_offerings_from_device(resource['id'])
- params.update({'total_offerings': len(offerings)})
- for offering in offerings:
- params2 = RegkeyPoolsOfferingParameters(params=offering)
- params.update({'offerings': params2.to_return()})
- results.append(params)
- return results
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/cm/device/licensing/pool/regkey/licenses".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- try:
- return response['items']
- except KeyError:
- return []
-
- def read_offerings_from_device(self, license):
- uri = "https://{0}:{1}/mgmt/cm/device/licensing/pool/regkey/licenses/{2}/offerings".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- license,
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- try:
- return response['items']
- except KeyError:
- return []
-
-
-class SystemInfoParameters(BaseParameters):
- api_map = {
- 'isSystemSetup': 'is_system_setup',
- 'isAdminPasswordChanged': 'is_admin_password_changed',
- 'isRootPasswordChanged': 'is_root_password_changed'
- }
-
- returnables = [
- 'base_mac_address',
- 'chassis_serial',
- 'hardware_information',
- 'host_board_part_revision',
- 'host_board_serial',
- 'is_admin_password_changed',
- 'is_root_password_changed',
- 'is_system_setup',
- 'marketing_name',
- 'package_edition',
- 'package_version',
- 'platform',
- 'product_build',
- 'product_build_date',
- 'product_built',
- 'product_changelist',
- 'product_code',
- 'product_information',
- 'product_jobid',
- 'product_version',
- 'switch_board_part_revision',
- 'switch_board_serial',
- 'time',
- 'uptime',
- ]
-
- @property
- def is_admin_password_changed(self):
- return flatten_boolean(self._values['is_admin_password_changed'])
-
- @property
- def is_root_password_changed(self):
- return flatten_boolean(self._values['is_root_password_changed'])
-
- @property
- def is_system_setup(self):
- if self._values['is_system_setup'] is None:
- return 'no'
- return flatten_boolean(self._values['is_system_setup'])
-
- @property
- def chassis_serial(self):
- if self._values['system-info'] is None:
- return None
-
- # Yes, this is still called "bigip" even though this is querying the BIG-IQ
- # product. This is likely due to BIG-IQ inheriting TMOS.
- if 'bigipChassisSerialNum' not in self._values['system-info'][0]:
- return None
- return self._values['system-info'][0]['bigipChassisSerialNum']
-
- @property
- def switch_board_serial(self):
- if self._values['system-info'] is None:
- return None
- if 'switchBoardSerialNum' not in self._values['system-info'][0]:
- return None
- if self._values['system-info'][0]['switchBoardSerialNum'].strip() == '':
- return None
- return self._values['system-info'][0]['switchBoardSerialNum']
-
- @property
- def switch_board_part_revision(self):
- if self._values['system-info'] is None:
- return None
- if 'switchBoardPartRevNum' not in self._values['system-info'][0]:
- return None
- if self._values['system-info'][0]['switchBoardPartRevNum'].strip() == '':
- return None
- return self._values['system-info'][0]['switchBoardPartRevNum']
-
- @property
- def platform(self):
- if self._values['system-info'] is None:
- return None
- return self._values['system-info'][0]['platform']
-
- @property
- def host_board_serial(self):
- if self._values['system-info'] is None:
- return None
- if 'hostBoardSerialNum' not in self._values['system-info'][0]:
- return None
- if self._values['system-info'][0]['hostBoardSerialNum'].strip() == '':
- return None
- return self._values['system-info'][0]['hostBoardSerialNum']
-
- @property
- def host_board_part_revision(self):
- if self._values['system-info'] is None:
- return None
- if 'hostBoardPartRevNum' not in self._values['system-info'][0]:
- return None
- if self._values['system-info'][0]['hostBoardPartRevNum'].strip() == '':
- return None
- return self._values['system-info'][0]['hostBoardPartRevNum']
-
- @property
- def package_edition(self):
- return self._values['Edition']
-
- @property
- def package_version(self):
- return 'Build {0} - {1}'.format(self._values['Build'], self._values['Date'])
-
- @property
- def product_build(self):
- return self._values['Build']
-
- @property
- def product_build_date(self):
- return self._values['Date']
-
- @property
- def product_built(self):
- if 'version_info' not in self._values:
- return None
- if 'Built' in self._values['version_info']:
- return int(self._values['version_info']['Built'])
-
- @property
- def product_changelist(self):
- if 'version_info' not in self._values:
- return None
- if 'Changelist' in self._values['version_info']:
- return int(self._values['version_info']['Changelist'])
-
- @property
- def product_jobid(self):
- if 'version_info' not in self._values:
- return None
- if 'JobID' in self._values['version_info']:
- return int(self._values['version_info']['JobID'])
-
- @property
- def product_code(self):
- return self._values['Product']
-
- @property
- def product_version(self):
- return self._values['Version']
-
- @property
- def hardware_information(self):
- if self._values['hardware-version'] is None:
- return None
- self._transform_name_attribute(self._values['hardware-version'])
- result = [v for k, v in iteritems(self._values['hardware-version'])]
- return result
-
- def _transform_name_attribute(self, entry):
- if isinstance(entry, dict):
- for k, v in iteritems(entry):
- if k == 'tmName':
- entry['name'] = entry.pop('tmName')
- self._transform_name_attribute(v)
- elif isinstance(entry, list):
- for k in entry:
- if k == 'tmName':
- entry['name'] = entry.pop('tmName')
- self._transform_name_attribute(k)
- else:
- return
-
- @property
- def time(self):
- if self._values['fullDate'] is None:
- return None
- date = datetime.datetime.strptime(self._values['fullDate'], "%Y-%m-%dT%H:%M:%SZ")
- result = dict(
- day=date.day,
- hour=date.hour,
- minute=date.minute,
- month=date.month,
- second=date.second,
- year=date.year
- )
- return result
-
- @property
- def marketing_name(self):
- if self._values['platform'] is None:
- return None
- return self._values['platform'][0]['marketingName']
-
- @property
- def base_mac_address(self):
- if self._values['platform'] is None:
- return None
- return self._values['platform'][0]['baseMac']
-
-
-class SystemInfoFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(SystemInfoFactManager, self).__init__(**kwargs)
- self.want = SystemInfoParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(system_info=facts)
- return result
-
- def _exec_module(self):
- facts = self.read_facts()
- results = facts.to_return()
- return results
-
- def read_facts(self):
- collection = self.read_collection_from_device()
- params = SystemInfoParameters(params=collection)
- return params
-
- def read_collection_from_device(self):
- result = dict()
- tmp = self.read_hardware_info_from_device()
- if tmp:
- result.update(tmp)
-
- tmp = self.read_system_setup_from_device()
- if tmp:
- result.update(tmp)
-
- tmp = self.read_clock_info_from_device()
- if tmp:
- result.update(tmp)
-
- tmp = self.read_version_info_from_device()
- if tmp:
- result.update(tmp)
-
- tmp = self.read_uptime_info_from_device()
- if tmp:
- result.update(tmp)
-
- tmp = self.read_version_file_info_from_device()
- if tmp:
- result.update(tmp)
-
- return result
-
- def read_system_setup_from_device(self):
- uri = "https://{0}:{1}/mgmt/shared/system/setup".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
-
- return response
-
- def read_version_file_info_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/util/bash".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- args = dict(
- command='run',
- utilCmdArgs='-c "cat /VERSION"'
- )
- resp = self.client.api.post(uri, json=args)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- try:
- pattern = r'^(?P(Product|Build|Sequence|BaseBuild|Edition|Date|Built|Changelist|JobID))\:(?P.*)'
- result = response['commandResult'].strip()
- except KeyError:
- return None
-
- if 'No such file or directory' in result:
- return None
-
- lines = response['commandResult'].split("\n")
- result = dict()
- for line in lines:
- if not line:
- continue
- matches = re.match(pattern, line)
- if matches:
- result[matches.group('key')] = matches.group('value').strip()
-
- if result:
- return dict(
- version_info=result
- )
-
- def read_uptime_info_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/util/bash".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- args = dict(
- command='run',
- utilCmdArgs='-c "cat /proc/uptime"'
- )
- resp = self.client.api.post(uri, json=args)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- try:
- parts = response['commandResult'].strip().split(' ')
- return dict(
- uptime=math.floor(float(parts[0]))
- )
- except KeyError:
- pass
-
- def read_hardware_info_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/sys/hardware".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = parseStats(response)
- return result
-
- def read_clock_info_from_device(self):
- """Parses clock info from the REST API
-
- The clock stat returned from the REST API (at the time of 13.1.0.7)
- is similar to the following.
-
- {
- "kind": "tm:sys:clock:clockstats",
- "selfLink": "https://localhost/mgmt/tm/sys/clock?ver=13.1.0.4",
- "entries": {
- "https://localhost/mgmt/tm/sys/clock/0": {
- "nestedStats": {
- "entries": {
- "fullDate": {
- "description": "2018-06-05T13:38:33Z"
- }
- }
- }
- }
- }
- }
-
- Parsing this data using the ``parseStats`` method, yields a list of
- the clock stats in a format resembling that below.
-
- [{'fullDate': '2018-06-05T13:41:05Z'}]
-
- Therefore, this method cherry-picks the first entry from this list
- and returns it. There can be no other items in this list.
-
- Returns:
- A dict mapping keys to the corresponding clock stats. For
- example:
-
- {'fullDate': '2018-06-05T13:41:05Z'}
-
- There should never not be a clock stat, unless by chance it
- is removed from the API in the future, or changed to a different
- API endpoint.
-
- Raises:
- F5ModuleError: A non-successful HTTP code was returned or a JSON
- response was not found.
- """
- uri = "https://{0}:{1}/mgmt/tm/sys/clock".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = parseStats(response)
- if result is None:
- return None
- return result[0]
-
- def read_version_info_from_device(self):
- """Parses version info from the REST API
-
- The version stat returned from the REST API (at the time of 13.1.0.7)
- is similar to the following.
-
- {
- "kind": "tm:sys:version:versionstats",
- "selfLink": "https://localhost/mgmt/tm/sys/version?ver=13.1.0.4",
- "entries": {
- "https://localhost/mgmt/tm/sys/version/0": {
- "nestedStats": {
- "entries": {
- "Build": {
- "description": "0.0.6"
- },
- "Date": {
- "description": "Tue Mar 13 20:10:42 PDT 2018"
- },
- "Edition": {
- "description": "Point Release 4"
- },
- "Product": {
- "description": "BIG-IP"
- },
- "Title": {
- "description": "Main Package"
- },
- "Version": {
- "description": "13.1.0.4"
- }
- }
- }
- }
- }
- }
-
- Parsing this data using the ``parseStats`` method, yields a list of
- the clock stats in a format resembling that below.
-
- [{'Build': '0.0.6', 'Date': 'Tue Mar 13 20:10:42 PDT 2018',
- 'Edition': 'Point Release 4', 'Product': 'BIG-IP', 'Title': 'Main Package',
- 'Version': '13.1.0.4'}]
-
- Therefore, this method cherry-picks the first entry from this list
- and returns it. There can be no other items in this list.
-
- Returns:
- A dict mapping keys to the corresponding clock stats. For
- example:
-
- {'Build': '0.0.6', 'Date': 'Tue Mar 13 20:10:42 PDT 2018',
- 'Edition': 'Point Release 4', 'Product': 'BIG-IP', 'Title': 'Main Package',
- 'Version': '13.1.0.4'}
-
- There should never not be a version stat, unless by chance it
- is removed from the API in the future, or changed to a different
- API endpoint.
-
- Raises:
- F5ModuleError: A non-successful HTTP code was returned or a JSON
- response was not found.
- """
- uri = "https://{0}:{1}/mgmt/tm/sys/version".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = parseStats(response)
- if result is None:
- return None
- return result[0]
-
-
-class VlansParameters(BaseParameters):
- api_map = {
- 'autoLasthop': 'auto_lasthop',
- 'cmpHash': 'cmp_hash_algorithm',
- 'failsafeAction': 'failsafe_action',
- 'failsafe': 'failsafe_enabled',
- 'failsafeTimeout': 'failsafe_timeout',
- 'ifIndex': 'if_index',
- 'learning': 'learning_mode',
- 'interfacesReference': 'interfaces',
- 'sourceChecking': 'source_check_enabled',
- 'fullPath': 'full_path'
- }
-
- returnables = [
- 'full_path',
- 'name',
- 'auto_lasthop',
- 'cmp_hash_algorithm',
- 'description',
- 'failsafe_action',
- 'failsafe_enabled',
- 'failsafe_timeout',
- 'if_index',
- 'learning_mode',
- 'interfaces',
- 'mtu',
- 'sflow_poll_interval',
- 'sflow_poll_interval_global',
- 'sflow_sampling_rate',
- 'sflow_sampling_rate_global',
- 'source_check_enabled',
- 'true_mac_address',
- 'tag',
- ]
-
- @property
- def interfaces(self):
- if self._values['interfaces'] is None:
- return None
- if 'items' not in self._values['interfaces']:
- return None
- result = []
- for item in self._values['interfaces']['items']:
- tmp = dict(
- name=item['name'],
- full_path=item['fullPath']
- )
- if 'tagged' in item:
- tmp['tagged'] = 'yes'
- else:
- tmp['tagged'] = 'no'
- result.append(tmp)
- return result
-
- @property
- def sflow_poll_interval(self):
- return int(self._values['sflow']['pollInterval'])
-
- @property
- def sflow_poll_interval_global(self):
- return flatten_boolean(self._values['sflow']['pollIntervalGlobal'])
-
- @property
- def sflow_sampling_rate(self):
- return int(self._values['sflow']['samplingRate'])
-
- @property
- def sflow_sampling_rate_global(self):
- return flatten_boolean(self._values['sflow']['samplingRateGlobal'])
-
- @property
- def source_check_state(self):
- return flatten_boolean(self._values['source_check_state'])
-
- @property
- def true_mac_address(self):
- if self._values['stats']['macTrue'] in [None, 'none']:
- return None
- return self._values['stats']['macTrue']
-
- @property
- def tag(self):
- return self._values['stats']['id']
-
- @property
- def failsafe_enabled(self):
- return flatten_boolean(self._values['failsafe_enabled'])
-
-
-class VlansFactManager(BaseManager):
- def __init__(self, *args, **kwargs):
- self.client = kwargs.get('client', None)
- self.module = kwargs.get('module', None)
- super(VlansFactManager, self).__init__(**kwargs)
- self.want = VlansParameters(params=self.module.params)
-
- def exec_module(self):
- facts = self._exec_module()
- result = dict(vlans=facts)
- return result
-
- def _exec_module(self):
- results = []
- facts = self.read_facts()
- for item in facts:
- attrs = item.to_return()
- results.append(attrs)
- results = sorted(results, key=lambda k: k['full_path'])
- return results
-
- def read_facts(self):
- results = []
- collection = self.read_collection_from_device()
- for resource in collection:
- resource.update(self.read_stats(resource['fullPath']))
- params = VlansParameters(params=resource)
- results.append(params)
- return results
-
- def read_stats(self, resource):
- uri = "https://{0}:{1}/mgmt/tm/net/vlan/{2}/stats".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- transform_name(name=resource)
-
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- result = parseStats(response)
- return result
-
- def read_collection_from_device(self):
- uri = "https://{0}:{1}/mgmt/tm/net/vlan/?expandSubcollections=true".format(
- self.client.provider['server'],
- self.client.provider['server_port'],
- )
- resp = self.client.api.get(uri)
- try:
- response = resp.json()
- except ValueError as ex:
- raise F5ModuleError(str(ex))
-
- if 'code' in response and response['code'] == 400:
- if 'message' in response:
- raise F5ModuleError(response['message'])
- else:
- raise F5ModuleError(resp.content)
- if 'items' not in response:
- return []
- result = response['items']
- return result
-
-
-class ModuleManager(object):
- def __init__(self, *args, **kwargs):
- self.module = kwargs.get('module', None)
- self.client = kwargs.get('client', None)
- self.kwargs = kwargs
- self.want = Parameters(params=self.module.params)
- self.managers = {
- 'applications': dict(
- manager=ApplicationsFactManager,
- client=F5RestClient,
- ),
- 'managed-devices': dict(
- manager=ManagedDevicesFactManager,
- client=F5RestClient,
- ),
- 'purchased-pool-licenses': dict(
- manager=PurchasedPoolLicensesFactManager,
- client=F5RestClient,
- ),
- 'regkey-pools': dict(
- manager=RegkeyPoolsFactManager,
- client=F5RestClient,
- ),
- 'system-info': dict(
- manager=SystemInfoFactManager,
- client=F5RestClient,
- ),
- 'vlans': dict(
- manager=VlansFactManager,
- client=F5RestClient,
- ),
- }
-
- def exec_module(self):
- self.handle_all_keyword()
- res = self.check_valid_gather_subset(self.want.gather_subset)
- if res:
- invalid = ','.join(res)
- raise F5ModuleError(
- "The specified 'gather_subset' options are invalid: {0}".format(invalid)
- )
- result = self.filter_excluded_facts()
-
- managers = []
- for name in result:
- manager = self.get_manager(name)
- if manager:
- managers.append(manager)
-
- if not managers:
- result = dict(
- changed=False
- )
- return result
-
- result = self.execute_managers(managers)
- if result:
- result['changed'] = True
- else:
- result['changed'] = False
- return result
-
- def filter_excluded_facts(self):
- # Remove the excluded entries from the list of possible facts
- exclude = [x[1:] for x in self.want.gather_subset if x[0] == '!']
- include = [x for x in self.want.gather_subset if x[0] != '!']
- result = [x for x in include if x not in exclude]
- return result
-
- def handle_all_keyword(self):
- if 'all' not in self.want.gather_subset:
- return
- managers = list(self.managers.keys()) + self.want.gather_subset
- managers.remove('all')
- self.want.update({'gather_subset': managers})
-
- def check_valid_gather_subset(self, includes):
- """Check that the specified subset is valid
-
- The ``gather_subset`` parameter is specified as a "raw" field which means that
- any Python type could technically be provided
-
- :param includes:
- :return:
- """
- keys = self.managers.keys()
- result = []
- for x in includes:
- if x not in keys:
- if x[0] == '!':
- if x[1:] not in keys:
- result.append(x)
- else:
- result.append(x)
- return result
-
- def execute_managers(self, managers):
- results = dict()
- for manager in managers:
- result = manager.exec_module()
- results.update(result)
- return results
-
- def get_manager(self, which):
- result = {}
- info = self.managers.get(which, None)
- if not info:
- return result
- kwargs = dict()
- kwargs.update(self.kwargs)
-
- manager = info.get('manager', None)
- client = info.get('client', None)
- kwargs['client'] = client(**self.module.params)
- result = manager(**kwargs)
- return result
-
-
-class ArgumentSpec(object):
- def __init__(self):
- self.supports_check_mode = False
- argument_spec = dict(
- gather_subset=dict(
- type='list',
- required=True,
- choices=[
- # Meta choices
- 'all',
-
- # Non-meta choices
- 'applications',
- 'managed-devices',
- 'purchased-pool-licenses',
- 'regkey-pools',
- 'system-info',
- 'vlans',
-
- # Negations of meta choices
- '!all',
-
- # Negations of non-meta-choices
- '!applications',
- '!managed-devices',
- '!purchased-pool-licenses',
- '!regkey-pools',
- '!system-info',
- '!vlans',
- ]
- ),
- )
- self.argument_spec = {}
- self.argument_spec.update(f5_argument_spec)
- self.argument_spec.update(argument_spec)
-
-
-def main():
- spec = ArgumentSpec()
-
- module = AnsibleModule(
- argument_spec=spec.argument_spec,
- supports_check_mode=spec.supports_check_mode
- )
- if module._name == 'bigiq_device_facts':
- module.deprecate("The 'bigiq_device_facts' module has been renamed to 'bigiq_device_info'", version='2.13')
-
- try:
- mm = ModuleManager(module=module)
- results = mm.exec_module()
- module.exit_json(**results)
- except F5ModuleError as ex:
- module.fail_json(msg=str(ex))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/fortianalyzer/faz_device.py b/plugins/modules/network/fortianalyzer/faz_device.py
deleted file mode 100644
index 08a3615751..0000000000
--- a/plugins/modules/network/fortianalyzer/faz_device.py
+++ /dev/null
@@ -1,438 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- "metadata_version": "1.1",
- "status": ["preview"],
- "supported_by": "community"
-}
-
-DOCUMENTATION = '''
----
-module: faz_device
-author: Luke Weighall (@lweighall)
-short_description: Add or remove device
-description:
- - Add or remove a device or list of devices to FortiAnalyzer Device Manager. ADOM Capable.
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: true
- default: root
- type: str
-
- mode:
- description:
- - Add or delete devices. Or promote unregistered devices that are in the FortiAnalyzer "waiting pool"
- required: false
- default: add
- choices: ["add", "delete", "promote"]
- type: str
-
- device_username:
- description:
- - The username of the device being added to FortiAnalyzer.
- required: false
- type: str
-
- device_password:
- description:
- - The password of the device being added to FortiAnalyzer.
- required: false
- type: str
-
- device_ip:
- description:
- - The IP of the device being added to FortiAnalyzer.
- required: false
- type: str
-
- device_unique_name:
- description:
- - The desired "friendly" name of the device being added to FortiAnalyzer.
- required: false
- type: str
-
- device_serial:
- description:
- - The serial number of the device being added to FortiAnalyzer.
- required: false
- type: str
-
- os_type:
- description:
- - The os type of the device being added (default 0).
- required: true
- choices: ["unknown", "fos", "fsw", "foc", "fml", "faz", "fwb", "fch", "fct", "log", "fmg", "fsa", "fdd", "fac"]
- type: str
-
- mgmt_mode:
- description:
- - Management Mode of the device you are adding.
- choices: ["unreg", "fmg", "faz", "fmgfaz"]
- required: true
- type: str
-
- os_minor_vers:
- description:
- - Minor OS rev of the device.
- required: true
- type: str
-
- os_ver:
- description:
- - Major OS rev of the device
- required: true
- choices: ["unknown", "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "6.0"]
- type: str
-
- platform_str:
- description:
- - Required for determine the platform for VM platforms. ie FortiGate-VM64
- required: false
- type: str
-
- faz_quota:
- description:
- - Specifies the quota for the device in FAZ
- required: False
- type: str
-'''
-
-EXAMPLES = '''
-- name: DISCOVER AND ADD DEVICE A PHYSICAL FORTIGATE
- faz_device:
- adom: "root"
- device_username: "admin"
- device_password: "admin"
- device_ip: "10.10.24.201"
- device_unique_name: "FGT1"
- device_serial: "FGVM000000117994"
- state: "present"
- mgmt_mode: "faz"
- os_type: "fos"
- os_ver: "5.0"
- minor_rev: 6
-
-
-- name: DISCOVER AND ADD DEVICE A VIRTUAL FORTIGATE
- faz_device:
- adom: "root"
- device_username: "admin"
- device_password: "admin"
- device_ip: "10.10.24.202"
- device_unique_name: "FGT2"
- mgmt_mode: "faz"
- os_type: "fos"
- os_ver: "5.0"
- minor_rev: 6
- state: "present"
- platform_str: "FortiGate-VM64"
-
-- name: DELETE DEVICE FGT01
- faz_device:
- adom: "root"
- device_unique_name: "ansible-fgt01"
- mode: "delete"
-
-- name: DELETE DEVICE FGT02
- faz_device:
- adom: "root"
- device_unique_name: "ansible-fgt02"
- mode: "delete"
-
-- name: PROMOTE FGT01 IN FAZ BY IP
- faz_device:
- adom: "root"
- device_password: "fortinet"
- device_ip: "10.7.220.151"
- device_username: "ansible"
- mgmt_mode: "faz"
- mode: "promote"
-
-
-- name: PROMOTE FGT02 IN FAZ
- faz_device:
- adom: "root"
- device_password: "fortinet"
- device_unique_name: "ansible-fgt02"
- device_username: "ansible"
- mgmt_mode: "faz"
- mode: "promote"
-
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.community.general.plugins.module_utils.network.fortianalyzer.fortianalyzer import FortiAnalyzerHandler
-from ansible_collections.community.general.plugins.module_utils.network.fortianalyzer.common import FAZBaseException
-from ansible_collections.community.general.plugins.module_utils.network.fortianalyzer.common import FAZCommon
-from ansible_collections.community.general.plugins.module_utils.network.fortianalyzer.common import FAZMethods
-from ansible_collections.community.general.plugins.module_utils.network.fortianalyzer.common import DEFAULT_RESULT_OBJ
-from ansible_collections.community.general.plugins.module_utils.network.fortianalyzer.common import FAIL_SOCKET_MSG
-
-
-def faz_add_device(faz, paramgram):
- """
- This method is used to add devices to the faz or delete them
- """
-
- datagram = {
- "adom": paramgram["adom"],
- "device": {"adm_usr": paramgram["device_username"], "adm_pass": paramgram["device_password"],
- "ip": paramgram["ip"], "name": paramgram["device_unique_name"],
- "mgmt_mode": paramgram["mgmt_mode"], "os_type": paramgram["os_type"],
- "mr": paramgram["os_minor_vers"]}
- }
-
- if paramgram["platform_str"] is not None:
- datagram["device"]["platform_str"] = paramgram["platform_str"]
-
- if paramgram["sn"] is not None:
- datagram["device"]["sn"] = paramgram["sn"]
-
- if paramgram["device_action"] is not None:
- datagram["device"]["device_action"] = paramgram["device_action"]
-
- if paramgram["faz.quota"] is not None:
- datagram["device"]["faz.quota"] = paramgram["faz.quota"]
-
- url = '/dvm/cmd/add/device/'
- response = faz.process_request(url, datagram, FAZMethods.EXEC)
- return response
-
-
-def faz_delete_device(faz, paramgram):
- """
- This method deletes a device from the FAZ
- """
- datagram = {
- "adom": paramgram["adom"],
- "device": paramgram["device_unique_name"],
- }
-
- url = '/dvm/cmd/del/device/'
- response = faz.process_request(url, datagram, FAZMethods.EXEC)
- return response
-
-
-def faz_get_unknown_devices(faz):
- """
- This method gets devices with an unknown management type field
- """
-
- faz_filter = ["mgmt_mode", "==", "0"]
-
- datagram = {
- "filter": faz_filter
- }
-
- url = "/dvmdb/device"
- response = faz.process_request(url, datagram, FAZMethods.GET)
-
- return response
-
-
-def faz_approve_unregistered_device_by_ip(faz, paramgram):
- """
- This method approves unregistered devices by ip.
- """
- # TRY TO FIND DETAILS ON THIS UNREGISTERED DEVICE
- unknown_devices = faz_get_unknown_devices(faz)
- target_device = None
- if unknown_devices[0] == 0:
- for device in unknown_devices[1]:
- if device["ip"] == paramgram["ip"]:
- target_device = device
- else:
- return "No devices are waiting to be registered!"
-
- # now that we have the target device details...fill out the datagram and make the call to promote it
- if target_device is not None:
- target_device_paramgram = {
- "adom": paramgram["adom"],
- "ip": target_device["ip"],
- "device_username": paramgram["device_username"],
- "device_password": paramgram["device_password"],
- "device_unique_name": paramgram["device_unique_name"],
- "sn": target_device["sn"],
- "os_type": target_device["os_type"],
- "mgmt_mode": paramgram["mgmt_mode"],
- "os_minor_vers": target_device["mr"],
- "os_ver": target_device["os_ver"],
- "platform_str": target_device["platform_str"],
- "faz.quota": target_device["faz.quota"],
- "device_action": paramgram["device_action"]
- }
-
- add_device = faz_add_device(faz, target_device_paramgram)
- return add_device
-
- return str("Couldn't find the desired device with ip: " + str(paramgram["device_ip"]))
-
-
-def faz_approve_unregistered_device_by_name(faz, paramgram):
- # TRY TO FIND DETAILS ON THIS UNREGISTERED DEVICE
- unknown_devices = faz_get_unknown_devices(faz)
- target_device = None
- if unknown_devices[0] == 0:
- for device in unknown_devices[1]:
- if device["name"] == paramgram["device_unique_name"]:
- target_device = device
- else:
- return "No devices are waiting to be registered!"
-
- # now that we have the target device details...fill out the datagram and make the call to promote it
- if target_device is not None:
- target_device_paramgram = {
- "adom": paramgram["adom"],
- "ip": target_device["ip"],
- "device_username": paramgram["device_username"],
- "device_password": paramgram["device_password"],
- "device_unique_name": paramgram["device_unique_name"],
- "sn": target_device["sn"],
- "os_type": target_device["os_type"],
- "mgmt_mode": paramgram["mgmt_mode"],
- "os_minor_vers": target_device["mr"],
- "os_ver": target_device["os_ver"],
- "platform_str": target_device["platform_str"],
- "faz.quota": target_device["faz.quota"],
- "device_action": paramgram["device_action"]
- }
-
- add_device = faz_add_device(faz, target_device_paramgram)
- return add_device
-
- return str("Couldn't find the desired device with name: " + str(paramgram["device_unique_name"]))
-
-
-def main():
- argument_spec = dict(
- adom=dict(required=False, type="str", default="root"),
- mode=dict(choices=["add", "delete", "promote"], type="str", default="add"),
-
- device_ip=dict(required=False, type="str"),
- device_username=dict(required=False, type="str"),
- device_password=dict(required=False, type="str", no_log=True),
- device_unique_name=dict(required=False, type="str"),
- device_serial=dict(required=False, type="str"),
-
- os_type=dict(required=False, type="str", choices=["unknown", "fos", "fsw", "foc", "fml",
- "faz", "fwb", "fch", "fct", "log", "fmg",
- "fsa", "fdd", "fac"]),
- mgmt_mode=dict(required=False, type="str", choices=["unreg", "fmg", "faz", "fmgfaz"]),
- os_minor_vers=dict(required=False, type="str"),
- os_ver=dict(required=False, type="str", choices=["unknown", "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "6.0"]),
- platform_str=dict(required=False, type="str"),
- faz_quota=dict(required=False, type="str")
- )
-
- required_if = [
- ['mode', 'delete', ['device_unique_name']],
- ['mode', 'add', ['device_serial', 'device_username',
- 'device_password', 'device_unique_name', 'device_ip', 'mgmt_mode', 'platform_str']]
-
- ]
-
- module = AnsibleModule(argument_spec, supports_check_mode=True, required_if=required_if, )
-
- # START SESSION LOGIC
- paramgram = {
- "adom": module.params["adom"],
- "mode": module.params["mode"],
- "ip": module.params["device_ip"],
- "device_username": module.params["device_username"],
- "device_password": module.params["device_password"],
- "device_unique_name": module.params["device_unique_name"],
- "sn": module.params["device_serial"],
- "os_type": module.params["os_type"],
- "mgmt_mode": module.params["mgmt_mode"],
- "os_minor_vers": module.params["os_minor_vers"],
- "os_ver": module.params["os_ver"],
- "platform_str": module.params["platform_str"],
- "faz.quota": module.params["faz_quota"],
- "device_action": None
- }
- # INSERT THE PARAMGRAM INTO THE MODULE SO WHEN WE PASS IT TO MOD_UTILS.FortiManagerHandler IT HAS THAT INFO
-
- if paramgram["mode"] == "add":
- paramgram["device_action"] = "add_model"
- elif paramgram["mode"] == "promote":
- paramgram["device_action"] = "promote_unreg"
- module.paramgram = paramgram
-
- # TRY TO INIT THE CONNECTION SOCKET PATH AND FortiManagerHandler OBJECT AND TOOLS
- faz = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- faz = FortiAnalyzerHandler(connection, module)
- faz.tools = FAZCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- # BEGIN MODULE-SPECIFIC LOGIC -- THINGS NEED TO HAPPEN DEPENDING ON THE ENDPOINT AND OPERATION
- results = DEFAULT_RESULT_OBJ
-
- try:
- if paramgram["mode"] == "add":
- results = faz_add_device(faz, paramgram)
- except BaseException as err:
- raise FAZBaseException(msg="An error occurred trying to add the device. Error: " + str(err))
-
- try:
- if paramgram["mode"] == "promote":
- if paramgram["ip"] is not None:
- results = faz_approve_unregistered_device_by_ip(faz, paramgram)
- elif paramgram["device_unique_name"] is not None:
- results = faz_approve_unregistered_device_by_name(faz, paramgram)
- except BaseException as err:
- raise FAZBaseException(msg="An error occurred trying to promote the device. Error: " + str(err))
-
- try:
- if paramgram["mode"] == "delete":
- results = faz_delete_device(faz, paramgram)
- except BaseException as err:
- raise FAZBaseException(msg="An error occurred trying to delete the device. Error: " + str(err))
-
- # PROCESS RESULTS
- try:
- faz.govern_response(module=module, results=results,
- ansible_facts=faz.construct_ansible_facts(results, module.params, paramgram))
- except BaseException as err:
- raise FAZBaseException(msg="An error occurred with govern_response(). Error: " + str(err))
-
- # This should only be hit if faz.govern_response is missed or failed somehow. In fact. It should never be hit.
- # But it's here JIC.
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_device.py b/plugins/modules/network/fortimanager/fmgr_device.py
deleted file mode 100644
index c5262d01c5..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_device.py
+++ /dev/null
@@ -1,302 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- "metadata_version": "1.1",
- "status": ["preview"],
- "supported_by": "community"
-}
-
-DOCUMENTATION = '''
----
-module: fmgr_device
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Add or remove device from FortiManager.
-description:
- - Add or remove a device or list of devices from FortiManager Device Manager using JSON RPC API.
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: true
- default: root
-
- mode:
- description:
- - The desired mode of the specified object.
- required: false
- default: add
- choices: ["add", "delete"]
-
- blind_add:
- description:
- - When adding a device, module will check if it exists, and skip if it does.
- - If enabled, this option will stop the module from checking if it already exists, and blindly add the device.
- required: false
- default: "disable"
- choices: ["enable", "disable"]
-
- device_username:
- description:
- - The username of the device being added to FortiManager.
- required: false
-
- device_password:
- description:
- - The password of the device being added to FortiManager.
- required: false
-
- device_ip:
- description:
- - The IP of the device being added to FortiManager. Supports both IPv4 and IPv6.
- required: false
-
- device_unique_name:
- description:
- - The desired "friendly" name of the device being added to FortiManager.
- required: false
-
- device_serial:
- description:
- - The serial number of the device being added to FortiManager.
- required: false
-'''
-
-EXAMPLES = '''
-- name: DISCOVER AND ADD DEVICE FGT1
- fmgr_device:
- adom: "root"
- device_username: "admin"
- device_password: "admin"
- device_ip: "10.10.24.201"
- device_unique_name: "FGT1"
- device_serial: "FGVM000000117994"
- mode: "add"
- blind_add: "enable"
-
-- name: DISCOVER AND ADD DEVICE FGT2
- fmgr_device:
- adom: "root"
- device_username: "admin"
- device_password: "admin"
- device_ip: "10.10.24.202"
- device_unique_name: "FGT2"
- device_serial: "FGVM000000117992"
- mode: "delete"
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-
-
-def discover_device(fmgr, paramgram):
- """
- This method is used to discover devices before adding them to FMGR
-
- :param fmgr: The fmgr object instance from fmgr_utils.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
-
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- datagram = {
- "odd_request_form": "True",
- "device": {"adm_usr": paramgram["device_username"],
- "adm_pass": paramgram["device_password"],
- "ip": paramgram["device_ip"]}
- }
-
- url = '/dvm/cmd/discover/device/'
-
- response = fmgr.process_request(url, datagram, FMGRMethods.EXEC)
- return response
-
-
-def add_device(fmgr, paramgram):
- """
- This method is used to add devices to the FMGR
-
- :param fmgr: The fmgr object instance from fmgr_utils.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
-
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- datagram = {
- "adom": paramgram["adom"],
- "flags": ["create_task", "nonblocking"],
- "odd_request_form": "True",
- "device": {"adm_usr": paramgram["device_username"], "adm_pass": paramgram["device_password"],
- "ip": paramgram["device_ip"], "name": paramgram["device_unique_name"],
- "sn": paramgram["device_serial"], "mgmt_mode": "fmgfaz", "flags": 24}
- }
-
- url = '/dvm/cmd/add/device/'
- response = fmgr.process_request(url, datagram, FMGRMethods.EXEC)
- return response
-
-
-def delete_device(fmgr, paramgram):
- """
- This method deletes a device from the FMGR
-
- :param fmgr: The fmgr object instance from fmgr_utils.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
-
- :return: The response from the FortiManager
- :rtype: dict
- """
- datagram = {
- "adom": paramgram["adom"],
- "flags": ["create_task", "nonblocking"],
- "device": paramgram["device_unique_name"],
- }
-
- url = '/dvm/cmd/del/device/'
- response = fmgr.process_request(url, datagram, FMGRMethods.EXEC)
- return response
-
-
-def get_device(fmgr, paramgram):
- """
- This method attempts to find the firewall on FortiManager to see if it already exists.
-
- :param fmgr: The fmgr object instance from fmgr_utils.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
-
- :return: The response from the FortiManager
- :rtype: dict
- """
- datagram = {
- "adom": paramgram["adom"],
- "filter": ["name", "==", paramgram["device_unique_name"]],
- }
-
- url = '/dvmdb/adom/{adom}/device/{name}'.format(adom=paramgram["adom"],
- name=paramgram["device_unique_name"])
- response = fmgr.process_request(url, datagram, FMGRMethods.GET)
- return response
-
-
-def main():
- argument_spec = dict(
- adom=dict(required=False, type="str", default="root"),
- mode=dict(choices=["add", "delete"], type="str", default="add"),
- blind_add=dict(choices=["enable", "disable"], type="str", default="disable"),
- device_ip=dict(required=False, type="str"),
- device_username=dict(required=False, type="str"),
- device_password=dict(required=False, type="str", no_log=True),
- device_unique_name=dict(required=True, type="str"),
- device_serial=dict(required=False, type="str")
- )
-
- # BUILD MODULE OBJECT SO WE CAN BUILD THE PARAMGRAM
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
-
- # BUILD THE PARAMGRAM
- paramgram = {
- "device_ip": module.params["device_ip"],
- "device_username": module.params["device_username"],
- "device_password": module.params["device_password"],
- "device_unique_name": module.params["device_unique_name"],
- "device_serial": module.params["device_serial"],
- "adom": module.params["adom"],
- "mode": module.params["mode"]
- }
-
- # INSERT THE PARAMGRAM INTO THE MODULE SO WHEN WE PASS IT TO MOD_UTILS.FortiManagerHandler IT HAS THAT INFO
- module.paramgram = paramgram
-
- # TRY TO INIT THE CONNECTION SOCKET PATH AND FortiManagerHandler OBJECT AND TOOLS
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- # BEGIN MODULE-SPECIFIC LOGIC -- THINGS NEED TO HAPPEN DEPENDING ON THE ENDPOINT AND OPERATION
- results = DEFAULT_RESULT_OBJ
- try:
- if paramgram["mode"] == "add":
- # CHECK IF DEVICE EXISTS
- if module.params["blind_add"] == "disable":
- exists_results = get_device(fmgr, paramgram)
- fmgr.govern_response(module=module, results=exists_results, good_codes=(0, -3), changed=False,
- ansible_facts=fmgr.construct_ansible_facts(exists_results,
- module.params, paramgram))
-
- discover_results = discover_device(fmgr, paramgram)
- fmgr.govern_response(module=module, results=discover_results, stop_on_success=False,
- ansible_facts=fmgr.construct_ansible_facts(discover_results,
- module.params, paramgram))
-
- if discover_results[0] == 0:
- results = add_device(fmgr, paramgram)
- fmgr.govern_response(module=module, results=discover_results, stop_on_success=True,
- changed_if_success=True,
- ansible_facts=fmgr.construct_ansible_facts(discover_results,
- module.params, paramgram))
-
- if paramgram["mode"] == "delete":
- results = delete_device(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_device_config.py b/plugins/modules/network/fortimanager/fmgr_device_config.py
deleted file mode 100644
index 150fc85a80..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_device_config.py
+++ /dev/null
@@ -1,237 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- "metadata_version": "1.1",
- "status": ["preview"],
- "supported_by": "community"
-}
-
-DOCUMENTATION = '''
----
-module: fmgr_device_config
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Edit device configurations
-description:
- - Edit device configurations from FortiManager Device Manager using JSON RPC API.
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- device_unique_name:
- description:
- - The unique device's name that you are editing. A.K.A. Friendly name of the device in FortiManager.
- required: True
-
- device_hostname:
- description:
- - The device's new hostname.
- required: false
-
- install_config:
- description:
- - Tells FMGR to attempt to install the config after making it.
- required: false
- default: disable
-
- interface:
- description:
- - The interface/port number you are editing.
- required: false
-
- interface_ip:
- description:
- - The IP and subnet of the interface/port you are editing.
- required: false
-
- interface_allow_access:
- description:
- - Specify what protocols are allowed on the interface, comma-separated list (see examples).
- required: false
-'''
-
-EXAMPLES = '''
-- name: CHANGE HOSTNAME
- fmgr_device_config:
- device_hostname: "ChangedbyAnsible"
- device_unique_name: "FGT1"
-
-- name: EDIT INTERFACE INFORMATION
- fmgr_device_config:
- adom: "root"
- device_unique_name: "FGT2"
- interface: "port3"
- interface_ip: "10.1.1.1/24"
- interface_allow_access: "ping, telnet, https"
-
-- name: INSTALL CONFIG
- fmgr_device_config:
- adom: "root"
- device_unique_name: "FGT1"
- install_config: "enable"
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods
-
-
-def update_device_hostname(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- datagram = {
- "hostname": paramgram["device_hostname"]
- }
-
- url = "pm/config/device/{device_name}/global/system/global".format(device_name=paramgram["device_unique_name"])
- response = fmgr.process_request(url, datagram, FMGRMethods.UPDATE)
- return response
-
-
-def update_device_interface(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- access_list = list()
- allow_access_list = paramgram["interface_allow_access"].replace(' ', '')
- access_list = allow_access_list.split(',')
-
- datagram = {
- "allowaccess": access_list,
- "ip": paramgram["interface_ip"]
- }
-
- url = "/pm/config/device/{device_name}/global/system/interface" \
- "/{interface}".format(device_name=paramgram["device_unique_name"], interface=paramgram["interface"])
- response = fmgr.process_request(url, datagram, FMGRMethods.UPDATE)
- return response
-
-
-def exec_config(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- datagram = {
- "scope": {
- "name": paramgram["device_unique_name"]
- },
- "adom": paramgram["adom"],
- "flags": "none"
- }
-
- url = "/securityconsole/install/device"
- response = fmgr.process_request(url, datagram, FMGRMethods.EXEC)
- return response
-
-
-def main():
- argument_spec = dict(
- adom=dict(required=False, type="str", default="root"),
- device_unique_name=dict(required=True, type="str"),
- device_hostname=dict(required=False, type="str"),
- interface=dict(required=False, type="str"),
- interface_ip=dict(required=False, type="str"),
- interface_allow_access=dict(required=False, type="str"),
- install_config=dict(required=False, type="str", default="disable"),
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- paramgram = {
- "device_unique_name": module.params["device_unique_name"],
- "device_hostname": module.params["device_hostname"],
- "interface": module.params["interface"],
- "interface_ip": module.params["interface_ip"],
- "interface_allow_access": module.params["interface_allow_access"],
- "install_config": module.params["install_config"],
- "adom": module.params["adom"]
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- # BEGIN MODULE-SPECIFIC LOGIC -- THINGS NEED TO HAPPEN DEPENDING ON THE ENDPOINT AND OPERATION
- results = DEFAULT_RESULT_OBJ
- try:
- if paramgram["device_hostname"] is not None:
- results = update_device_hostname(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- if paramgram["interface_ip"] is not None or paramgram["interface_allow_access"] is not None:
- results = update_device_interface(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- if paramgram["install_config"] == "enable":
- results = exec_config(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_device_group.py b/plugins/modules/network/fortimanager/fmgr_device_group.py
deleted file mode 100644
index 9112f5ff3f..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_device_group.py
+++ /dev/null
@@ -1,329 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- "metadata_version": "1.1",
- "status": ["preview"],
- "supported_by": "community"
-}
-
-DOCUMENTATION = '''
----
-module: fmgr_device_group
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Alter FortiManager device groups.
-description:
- - Add or edit device groups and assign devices to device groups FortiManager Device Manager using JSON RPC API.
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- vdom:
- description:
- - The VDOM of the Fortigate you want to add, must match the device in FMGR. Usually root.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- grp_name:
- description:
- - The name of the device group.
- required: false
-
- grp_desc:
- description:
- - The description of the device group.
- required: false
-
- grp_members:
- description:
- - A comma separated list of device names or device groups to be added as members to the device group.
- - If Group Members are defined, and mode="delete", only group members will be removed.
- - If you want to delete a group itself, you must omit this parameter from the task in playbook.
- required: false
-
-'''
-
-
-EXAMPLES = '''
-- name: CREATE DEVICE GROUP
- fmgr_device_group:
- grp_name: "TestGroup"
- grp_desc: "CreatedbyAnsible"
- adom: "ansible"
- mode: "add"
-
-- name: CREATE DEVICE GROUP 2
- fmgr_device_group:
- grp_name: "AnsibleGroup"
- grp_desc: "CreatedbyAnsible"
- adom: "ansible"
- mode: "add"
-
-- name: ADD DEVICES TO DEVICE GROUP
- fmgr_device_group:
- mode: "add"
- grp_name: "TestGroup"
- grp_members: "FGT1,FGT2"
- adom: "ansible"
- vdom: "root"
-
-- name: REMOVE DEVICES TO DEVICE GROUP
- fmgr_device_group:
- mode: "delete"
- grp_name: "TestGroup"
- grp_members: "FGT1,FGT2"
- adom: "ansible"
-
-- name: DELETE DEVICE GROUP
- fmgr_device_group:
- grp_name: "AnsibleGroup"
- grp_desc: "CreatedbyAnsible"
- mode: "delete"
- adom: "ansible"
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-
-
-def get_groups(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- datagram = {
- "method": "get"
- }
-
- url = '/dvmdb/adom/{adom}/group'.format(adom=paramgram["adom"])
- response = fmgr.process_request(url, datagram, FMGRMethods.GET)
- return response
-
-
-def add_device_group(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- # INIT A BASIC OBJECTS
- response = DEFAULT_RESULT_OBJ
- url = ""
- mode = paramgram["mode"]
-
- datagram = {
- "name": paramgram["grp_name"],
- "desc": paramgram["grp_desc"],
- "os_type": "fos"
- }
-
- url = '/dvmdb/adom/{adom}/group'.format(adom=paramgram["adom"])
-
- # IF MODE = SET -- USE THE 'SET' API CALL MODE
- if mode == "set":
- response = fmgr.process_request(url, datagram, FMGRMethods.SET)
- # IF MODE = UPDATE -- USER THE 'UPDATE' API CALL MODE
- elif mode == "update":
- response = fmgr.process_request(url, datagram, FMGRMethods.UPDATE)
- # IF MODE = ADD -- USE THE 'ADD' API CALL MODE
- elif mode == "add":
- response = fmgr.process_request(url, datagram, FMGRMethods.ADD)
-
- return response
-
-
-def delete_device_group(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- # INIT A BASIC OBJECTS
- response = DEFAULT_RESULT_OBJ
- url = ""
-
- datagram = {
- "adom": paramgram["adom"],
- "name": paramgram["grp_name"]
- }
-
- url = '/dvmdb/adom/{adom}/group/{grp_name}'.format(adom=paramgram["adom"], grp_name=paramgram["grp_name"])
- response = fmgr.process_request(url, datagram, FMGRMethods.DELETE)
- return response
-
-
-def add_group_member(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- # INIT A BASIC OBJECTS
- response = DEFAULT_RESULT_OBJ
- url = ""
- device_member_list = paramgram["grp_members"].replace(' ', '')
- device_member_list = device_member_list.split(',')
-
- for dev_name in device_member_list:
- datagram = {'name': dev_name, 'vdom': paramgram["vdom"]}
-
- url = '/dvmdb/adom/{adom}/group/{grp_name}/object member'.format(adom=paramgram["adom"],
- grp_name=paramgram["grp_name"])
- response = fmgr.process_request(url, datagram, FMGRMethods.ADD)
-
- return response
-
-
-def delete_group_member(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- # INIT A BASIC OBJECTS
- response = DEFAULT_RESULT_OBJ
- url = ""
- device_member_list = paramgram["grp_members"].replace(' ', '')
- device_member_list = device_member_list.split(',')
-
- for dev_name in device_member_list:
- datagram = {'name': dev_name, 'vdom': paramgram["vdom"]}
-
- url = '/dvmdb/adom/{adom}/group/{grp_name}/object member'.format(adom=paramgram["adom"],
- grp_name=paramgram["grp_name"])
- response = fmgr.process_request(url, datagram, FMGRMethods.DELETE)
-
- return response
-
-
-def main():
- argument_spec = dict(
- adom=dict(required=False, type="str", default="root"),
- vdom=dict(required=False, type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
- grp_desc=dict(required=False, type="str"),
- grp_name=dict(required=True, type="str"),
- grp_members=dict(required=False, type="str"),
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- paramgram = {
- "mode": module.params["mode"],
- "grp_name": module.params["grp_name"],
- "grp_desc": module.params["grp_desc"],
- "grp_members": module.params["grp_members"],
- "adom": module.params["adom"],
- "vdom": module.params["vdom"]
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- # BEGIN MODULE-SPECIFIC LOGIC -- THINGS NEED TO HAPPEN DEPENDING ON THE ENDPOINT AND OPERATION
- results = DEFAULT_RESULT_OBJ
- try:
- # PROCESS THE GROUP ADDS FIRST
- if paramgram["grp_name"] is not None and paramgram["mode"] in ["add", "set", "update"]:
- # add device group
- results = add_device_group(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- # PROCESS THE GROUP MEMBER ADDS
- if paramgram["grp_members"] is not None and paramgram["mode"] in ["add", "set", "update"]:
- # assign devices to device group
- results = add_group_member(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- # PROCESS THE GROUP MEMBER DELETES
- if paramgram["grp_members"] is not None and paramgram["mode"] == "delete":
- # remove devices grom a group
- results = delete_group_member(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- # PROCESS THE GROUP DELETES, ONLY IF GRP_MEMBERS IS NOT NULL TOO
- if paramgram["grp_name"] is not None and paramgram["mode"] == "delete" and paramgram["grp_members"] is None:
- # delete device group
- results = delete_device_group(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_device_provision_template.py b/plugins/modules/network/fortimanager/fmgr_device_provision_template.py
deleted file mode 100644
index 5c3da9487c..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_device_provision_template.py
+++ /dev/null
@@ -1,1552 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- "metadata_version": "1.1",
- "status": ["preview"],
- "supported_by": "community"
-}
-
-DOCUMENTATION = '''
----
-module: fmgr_device_provision_template
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Manages Device Provisioning Templates in FortiManager.
-description:
- - Allows the editing and assignment of device provisioning templates in FortiManager.
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: true
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values.
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- device_unique_name:
- description:
- - The unique device's name that you are editing.
- required: True
-
- provisioning_template:
- description:
- - The provisioning template you want to apply (default = default).
- required: True
-
- provision_targets:
- description:
- - The friendly names of devices in FortiManager to assign the provisioning template to. CSV separated list.
- required: True
-
- snmp_status:
- description:
- - Enables or disables SNMP globally.
- required: False
- choices: ["enable", "disable"]
-
- snmp_v2c_query_port:
- description:
- - Sets the snmp v2c community query port.
- required: False
-
- snmp_v2c_trap_port:
- description:
- - Sets the snmp v2c community trap port.
- required: False
-
- snmp_v2c_status:
- description:
- - Enables or disables the v2c community specified.
- required: False
- choices: ["enable", "disable"]
-
- snmp_v2c_trap_status:
- description:
- - Enables or disables the v2c community specified for traps.
- required: False
- choices: ["enable", "disable"]
-
- snmp_v2c_query_status:
- description:
- - Enables or disables the v2c community specified for queries.
- required: False
- choices: ["enable", "disable"]
-
- snmp_v2c_name:
- description:
- - Specifies the v2c community name.
- required: False
-
- snmp_v2c_id:
- description:
- - Primary key for the snmp community. this must be unique!
- required: False
-
- snmp_v2c_trap_src_ipv4:
- description:
- - Source ip the traps should come from IPv4.
- required: False
-
- snmp_v2c_trap_hosts_ipv4:
- description: >
- - IPv4 addresses of the hosts that should get SNMP v2c traps, comma separated, must include mask
- ("10.7.220.59 255.255.255.255, 10.7.220.60 255.255.255.255").
- required: False
-
- snmp_v2c_query_hosts_ipv4:
- description: >
- - IPv4 addresses or subnets that are allowed to query SNMP v2c, comma separated
- ("10.7.220.59 255.255.255.0, 10.7.220.0 255.255.255.0").
- required: False
-
- snmpv3_auth_proto:
- description:
- - SNMPv3 auth protocol.
- required: False
- choices: ["md5", "sha"]
-
- snmpv3_auth_pwd:
- description:
- - SNMPv3 auth pwd __ currently not encrypted! ensure this file is locked down permissions wise!
- required: False
-
- snmpv3_name:
- description:
- - SNMPv3 user name.
- required: False
-
- snmpv3_notify_hosts:
- description:
- - List of ipv4 hosts to send snmpv3 traps to. Comma separated IPv4 list.
- required: False
-
- snmpv3_priv_proto:
- description:
- - SNMPv3 priv protocol.
- required: False
- choices: ["aes", "des", "aes256", "aes256cisco"]
-
- snmpv3_priv_pwd:
- description:
- - SNMPv3 priv pwd currently not encrypted! ensure this file is locked down permissions wise!
- required: False
-
- snmpv3_queries:
- description:
- - Allow snmpv3_queries.
- required: False
- choices: ["enable", "disable"]
-
- snmpv3_query_port:
- description:
- - SNMPv3 query port.
- required: False
-
- snmpv3_security_level:
- description:
- - SNMPv3 security level.
- required: False
- choices: ["no-auth-no-priv", "auth-no-priv", "auth-priv"]
-
- snmpv3_source_ip:
- description:
- - SNMPv3 source ipv4 address for traps.
- required: False
-
- snmpv3_status:
- description:
- - SNMPv3 user is enabled or disabled.
- required: False
- choices: ["enable", "disable"]
-
- snmpv3_trap_rport:
- description:
- - SNMPv3 trap remote port.
- required: False
-
- snmpv3_trap_status:
- description:
- - SNMPv3 traps is enabled or disabled.
- required: False
- choices: ["enable", "disable"]
-
- syslog_port:
- description:
- - Syslog port that will be set.
- required: False
-
- syslog_server:
- description:
- - Server the syslogs will be sent to.
- required: False
-
- syslog_status:
- description:
- - Enables or disables syslogs.
- required: False
- choices: ["enable", "disable"]
-
- syslog_mode:
- description:
- - Remote syslog logging over UDP/Reliable TCP.
- - choice | udp | Enable syslogging over UDP.
- - choice | legacy-reliable | Enable legacy reliable syslogging by RFC3195 (Reliable Delivery for Syslog).
- - choice | reliable | Enable reliable syslogging by RFC6587 (Transmission of Syslog Messages over TCP).
- required: false
- choices: ["udp", "legacy-reliable", "reliable"]
- default: "udp"
-
- syslog_filter:
- description:
- - Sets the logging level for syslog.
- required: False
- choices: ["emergency", "alert", "critical", "error", "warning", "notification", "information", "debug"]
-
- syslog_facility:
- description:
- - Remote syslog facility.
- - choice | kernel | Kernel messages.
- - choice | user | Random user-level messages.
- - choice | mail | Mail system.
- - choice | daemon | System daemons.
- - choice | auth | Security/authorization messages.
- - choice | syslog | Messages generated internally by syslog.
- - choice | lpr | Line printer subsystem.
- - choice | news | Network news subsystem.
- - choice | uucp | Network news subsystem.
- - choice | cron | Clock daemon.
- - choice | authpriv | Security/authorization messages (private).
- - choice | ftp | FTP daemon.
- - choice | ntp | NTP daemon.
- - choice | audit | Log audit.
- - choice | alert | Log alert.
- - choice | clock | Clock daemon.
- - choice | local0 | Reserved for local use.
- - choice | local1 | Reserved for local use.
- - choice | local2 | Reserved for local use.
- - choice | local3 | Reserved for local use.
- - choice | local4 | Reserved for local use.
- - choice | local5 | Reserved for local use.
- - choice | local6 | Reserved for local use.
- - choice | local7 | Reserved for local use.
- required: false
- choices: ["kernel", "user", "mail", "daemon", "auth", "syslog",
- "lpr", "news", "uucp", "cron", "authpriv", "ftp", "ntp", "audit",
- "alert", "clock", "local0", "local1", "local2", "local3", "local4", "local5", "local6", "local7"]
- default: "syslog"
-
- syslog_enc_algorithm:
- description:
- - Enable/disable reliable syslogging with TLS encryption.
- - choice | high | SSL communication with high encryption algorithms.
- - choice | low | SSL communication with low encryption algorithms.
- - choice | disable | Disable SSL communication.
- - choice | high-medium | SSL communication with high and medium encryption algorithms.
- required: false
- choices: ["high", "low", "disable", "high-medium"]
- default: "disable"
-
- syslog_certificate:
- description:
- - Certificate used to communicate with Syslog server if encryption on.
- required: false
-
- ntp_status:
- description:
- - Enables or disables ntp.
- required: False
- choices: ["enable", "disable"]
-
- ntp_sync_interval:
- description:
- - Sets the interval in minutes for ntp sync.
- required: False
-
- ntp_type:
- description:
- - Enables fortiguard servers or custom servers are the ntp source.
- required: False
- choices: ["fortiguard", "custom"]
-
- ntp_server:
- description:
- - Only used with custom ntp_type -- specifies IP of server to sync to -- comma separated ip addresses for multiples.
- required: False
-
- ntp_auth:
- description:
- - Enables or disables ntp authentication.
- required: False
- choices: ["enable", "disable"]
-
- ntp_auth_pwd:
- description:
- - Sets the ntp auth password.
- required: False
-
- ntp_v3:
- description:
- - Enables or disables ntpv3 (default is ntpv4).
- required: False
- choices: ["enable", "disable"]
-
- admin_https_redirect:
- description:
- - Enables or disables https redirect from http.
- required: False
- choices: ["enable", "disable"]
-
- admin_https_port:
- description:
- - SSL admin gui port number.
- required: False
-
- admin_http_port:
- description:
- - Non-SSL admin gui port number.
- required: False
-
- admin_timeout:
- description:
- - Admin timeout in minutes.
- required: False
-
- admin_language:
- description:
- - Sets the admin gui language.
- required: False
- choices: ["english", "simch", "japanese", "korean", "spanish", "trach", "french", "portuguese"]
-
- admin_switch_controller:
- description:
- - Enables or disables the switch controller.
- required: False
- choices: ["enable", "disable"]
-
- admin_gui_theme:
- description:
- - Changes the admin gui theme.
- required: False
- choices: ["green", "red", "blue", "melongene", "mariner"]
-
- admin_enable_fortiguard:
- description:
- - Enables FortiGuard security updates to their default settings.
- required: False
- choices: ["none", "direct", "this-fmg"]
-
- admin_fortianalyzer_target:
- description:
- - Configures faz target.
- required: False
-
- admin_fortiguard_target:
- description:
- - Configures fortiguard target.
- - admin_enable_fortiguard must be set to "direct".
- required: False
-
- smtp_username:
- description:
- - SMTP auth username.
- required: False
-
- smtp_password:
- description:
- - SMTP password.
- required: False
-
- smtp_port:
- description:
- - SMTP port number.
- required: False
-
- smtp_replyto:
- description:
- - SMTP reply to address.
- required: False
-
- smtp_conn_sec:
- description:
- - defines the ssl level for smtp.
- required: False
- choices: ["none", "starttls", "smtps"]
-
- smtp_server:
- description:
- - SMTP server ipv4 address.
- required: False
-
- smtp_source_ipv4:
- description:
- - SMTP source ip address.
- required: False
-
- smtp_validate_cert:
- description:
- - Enables or disables valid certificate checking for smtp.
- required: False
- choices: ["enable", "disable"]
-
- dns_suffix:
- description:
- - Sets the local dns domain suffix.
- required: False
-
- dns_primary_ipv4:
- description:
- - primary ipv4 dns forwarder.
- required: False
-
- dns_secondary_ipv4:
- description:
- - secondary ipv4 dns forwarder.
- required: False
-
- delete_provisioning_template:
- description:
- - If specified, all other options are ignored. The specified provisioning template will be deleted.
- required: False
-
-'''
-
-
-EXAMPLES = '''
-- name: SET SNMP SYSTEM INFO
- fmgr_device_provision_template:
- provisioning_template: "default"
- snmp_status: "enable"
- mode: "set"
-
-- name: SET SNMP SYSTEM INFO ANSIBLE ADOM
- fmgr_device_provision_template:
- provisioning_template: "default"
- snmp_status: "enable"
- mode: "set"
- adom: "ansible"
-
-- name: SET SNMP SYSTEM INFO different template (SNMPv2)
- fmgr_device_provision_template:
- provisioning_template: "ansibleTest"
- snmp_status: "enable"
- mode: "set"
- adom: "ansible"
- snmp_v2c_query_port: "162"
- snmp_v2c_trap_port: "161"
- snmp_v2c_status: "enable"
- snmp_v2c_trap_status: "enable"
- snmp_v2c_query_status: "enable"
- snmp_v2c_name: "ansibleV2c"
- snmp_v2c_id: "1"
- snmp_v2c_trap_src_ipv4: "10.7.220.41"
- snmp_v2c_trap_hosts_ipv4: "10.7.220.59 255.255.255.255, 10.7.220.60 255.255.255.255"
- snmp_v2c_query_hosts_ipv4: "10.7.220.59 255.255.255.255, 10.7.220.0 255.255.255.0"
-
-- name: SET SNMP SYSTEM INFO different template (SNMPv3)
- fmgr_device_provision_template:
- provisioning_template: "ansibleTest"
- snmp_status: "enable"
- mode: "set"
- adom: "ansible"
- snmpv3_auth_proto: "sha"
- snmpv3_auth_pwd: "fortinet"
- snmpv3_name: "ansibleSNMPv3"
- snmpv3_notify_hosts: "10.7.220.59,10.7.220.60"
- snmpv3_priv_proto: "aes256"
- snmpv3_priv_pwd: "fortinet"
- snmpv3_queries: "enable"
- snmpv3_query_port: "161"
- snmpv3_security_level: "auth_priv"
- snmpv3_source_ip: "0.0.0.0"
- snmpv3_status: "enable"
- snmpv3_trap_rport: "162"
- snmpv3_trap_status: "enable"
-
-- name: SET SYSLOG INFO
- fmgr_device_provision_template:
- provisioning_template: "ansibleTest"
- mode: "set"
- adom: "ansible"
- syslog_server: "10.7.220.59"
- syslog_port: "514"
- syslog_mode: "disable"
- syslog_status: "enable"
- syslog_filter: "information"
-
-- name: SET NTP TO FORTIGUARD
- fmgr_device_provision_template:
- provisioning_template: "ansibleTest"
- mode: "set"
- adom: "ansible"
- ntp_status: "enable"
- ntp_sync_interval: "60"
- type: "fortiguard"
-
-- name: SET NTP TO CUSTOM SERVER
- fmgr_device_provision_template:
- provisioning_template: "ansibleTest"
- mode: "set"
- adom: "ansible"
- ntp_status: "enable"
- ntp_sync_interval: "60"
- ntp_type: "custom"
- ntp_server: "10.7.220.32,10.7.220.1"
- ntp_auth: "enable"
- ntp_auth_pwd: "fortinet"
- ntp_v3: "disable"
-
-- name: SET ADMIN GLOBAL SETTINGS
- fmgr_device_provision_template:
- provisioning_template: "ansibleTest"
- mode: "set"
- adom: "ansible"
- admin_https_redirect: "enable"
- admin_https_port: "4433"
- admin_http_port: "8080"
- admin_timeout: "30"
- admin_language: "english"
- admin_switch_controller: "enable"
- admin_gui_theme: "blue"
- admin_enable_fortiguard: "direct"
- admin_fortiguard_target: "10.7.220.128"
- admin_fortianalyzer_target: "10.7.220.61"
-
-- name: SET CUSTOM SMTP SERVER
- fmgr_device_provision_template:
- provisioning_template: "ansibleTest"
- mode: "set"
- adom: "ansible"
- smtp_username: "ansible"
- smtp_password: "fortinet"
- smtp_port: "25"
- smtp_replyto: "ansible@do-not-reply.com"
- smtp_conn_sec: "starttls"
- smtp_server: "10.7.220.32"
- smtp_source_ipv4: "0.0.0.0"
- smtp_validate_cert: "disable"
-
-- name: SET DNS SERVERS
- fmgr_device_provision_template:
- provisioning_template: "ansibleTest"
- mode: "set"
- adom: "ansible"
- dns_suffix: "ansible.local"
- dns_primary_ipv4: "8.8.8.8"
- dns_secondary_ipv4: "4.4.4.4"
-
-- name: SET PROVISIONING TEMPLATE DEVICE TARGETS IN FORTIMANAGER
- fmgr_device_provision_template:
- provisioning_template: "ansibleTest"
- mode: "set"
- adom: "ansible"
- provision_targets: "FGT1, FGT2"
-
-- name: DELETE ENTIRE PROVISIONING TEMPLATE
- fmgr_device_provision_template:
- delete_provisioning_template: "ansibleTest"
- mode: "delete"
- adom: "ansible"
-
-'''
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-
-
-def get_devprof(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- response = DEFAULT_RESULT_OBJ
- datagram = {}
-
- url = "/pm/devprof/adom/{adom}/{name}".format(adom=paramgram["adom"], name=paramgram["provisioning_template"])
- response = fmgr.process_request(url, datagram, FMGRMethods.GET)
-
- return response
-
-
-def set_devprof(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- response = DEFAULT_RESULT_OBJ
- if paramgram["mode"] in ['set', 'add', 'update']:
- datagram = {
- "name": paramgram["provisioning_template"],
- "type": "devprof",
- "description": "CreatedByAnsible",
- }
- url = "/pm/devprof/adom/{adom}".format(adom=paramgram["adom"])
-
- elif paramgram["mode"] == "delete":
- datagram = {}
-
- url = "/pm/devprof/adom/{adom}/{name}".format(adom=paramgram["adom"],
- name=paramgram["delete_provisioning_template"])
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def get_devprof_scope(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- response = DEFAULT_RESULT_OBJ
- datagram = {
- "name": paramgram["provisioning_template"],
- "type": "devprof",
- "description": "CreatedByAnsible",
- }
-
- url = "/pm/devprof/adom/{adom}".format(adom=paramgram["adom"])
- response = fmgr.process_request(url, datagram, FMGRMethods.GET)
-
- return response
-
-
-def set_devprof_scope(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- response = DEFAULT_RESULT_OBJ
- if paramgram["mode"] in ['set', 'add', 'update']:
- datagram = {
- "name": paramgram["provisioning_template"],
- "type": "devprof",
- "description": "CreatedByAnsible",
- }
-
- targets = []
- for target in paramgram["provision_targets"].split(","):
- # split the host on the space to get the mask out
- new_target = {"name": target.strip()}
- targets.append(new_target)
-
- datagram["scope member"] = targets
-
- url = "/pm/devprof/adom/{adom}".format(adom=paramgram["adom"])
-
- elif paramgram["mode"] == "delete":
- datagram = {
- "name": paramgram["provisioning_template"],
- "type": "devprof",
- "description": "CreatedByAnsible",
- "scope member": paramgram["targets_to_add"]
- }
-
- url = "/pm/devprof/adom/{adom}".format(adom=paramgram["adom"])
-
- response = fmgr.process_request(url, datagram, FMGRMethods.SET)
- return response
-
-
-def set_devprof_snmp(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- paramgram["mode"] = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
- datagram = {
- "status": paramgram["snmp_status"]
- }
- url = "/pm/config/adom/{adom}/devprof/" \
- "{provisioning_template}/system/snmp/sysinfo".format(adom=adom,
- provisioning_template=paramgram["provisioning_template"])
-
- response = fmgr.process_request(url, datagram, FMGRMethods.SET)
- return response
-
-
-def set_devprof_snmp_v2c(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- paramgram["mode"] = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
- if paramgram["mode"] in ['set', 'add', 'update']:
- datagram = {
- "query-v2c-port": paramgram["snmp_v2c_query_port"],
- "trap-v2c-rport": paramgram["snmp_v2c_trap_port"],
- "status": paramgram["snmp_v2c_status"],
- "trap-v2c-status": paramgram["snmp_v2c_trap_status"],
- "query-v2c-status": paramgram["snmp_v2c_query_status"],
- "name": paramgram["snmp_v2c_name"],
- "id": paramgram["snmp_v2c_id"],
- "meta fields": dict(),
- "hosts": list(),
- "events": 411578417151,
- "query-v1-status": 0,
- "query-v1-port": 161,
- "trap-v1-status": 0,
- "trap-v1-lport": 162,
- "trap-v1-rport": 162,
- "trap-v2c-lport": 162,
- }
-
- # BUILD THE HOST STRINGS
- id_counter = 1
- if paramgram["snmp_v2c_trap_hosts_ipv4"] or paramgram["snmp_v2c_query_hosts_ipv4"]:
- hosts = []
- if paramgram["snmp_v2c_query_hosts_ipv4"]:
- for ipv4_host in paramgram["snmp_v2c_query_hosts_ipv4"].strip().split(","):
- # split the host on the space to get the mask out
- new_ipv4_host = {"ha-direct": "enable",
- "host-type": "query",
- "id": id_counter,
- "ip": ipv4_host.strip().split(),
- "meta fields": {},
- "source-ip": "0.0.0.0"}
- hosts.append(new_ipv4_host)
- id_counter += 1
-
- if paramgram["snmp_v2c_trap_hosts_ipv4"]:
- for ipv4_host in paramgram["snmp_v2c_trap_hosts_ipv4"].strip().split(","):
- # split the host on the space to get the mask out
- new_ipv4_host = {"ha-direct": "enable",
- "host-type": "trap",
- "id": id_counter,
- "ip": ipv4_host.strip().split(),
- "meta fields": {},
- "source-ip": paramgram["snmp_v2c_trap_src_ipv4"]}
- hosts.append(new_ipv4_host)
- id_counter += 1
- datagram["hosts"] = hosts
-
- url = "/pm/config/adom/{adom}/devprof/" \
- "{provisioning_template}/system/snmp/community".format(adom=adom,
- provisioning_template=paramgram[
- "provisioning_template"])
- elif paramgram["mode"] == "delete":
- datagram = {
- "confirm": 1
- }
-
- url = "/pm/config/adom/{adom}/" \
- "devprof/{provisioning_template}/" \
- "system/snmp/community/{snmp_v2c_id}".format(adom=adom,
- provisioning_template=paramgram["provisioning_template"],
- snmp_v2c_id=paramgram["snmp_v2c_id"])
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def set_devprof_snmp_v3(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- paramgram["mode"] = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
- if paramgram["mode"] in ['set', 'add', 'update']:
- datagram = {}
- datagram["auth-pwd"] = paramgram["snmpv3_auth_pwd"]
- datagram["priv-pwd"] = paramgram["snmpv3_priv_pwd"]
- datagram["trap-rport"] = paramgram["snmpv3_trap_rport"]
- datagram["query-port"] = paramgram["snmpv3_query_port"]
- datagram["name"] = paramgram["snmpv3_name"]
- datagram["notify-hosts"] = paramgram["snmpv3_notify_hosts"].strip().split(",")
- datagram["events"] = 1647387997183
- datagram["trap-lport"] = 162
-
- datagram["source-ip"] = paramgram["snmpv3_source_ip"]
- datagram["ha-direct"] = 0
-
- url = "/pm/config/adom/{adom}/" \
- "devprof/{provisioning_template}/" \
- "system/snmp/user".format(adom=adom,
- provisioning_template=paramgram["provisioning_template"])
- elif paramgram["mode"] == "delete":
- datagram = {
- "confirm": 1
- }
-
- url = "/pm/config/adom/{adom}/devprof/" \
- "{provisioning_template}/system/snmp" \
- "/user/{snmpv3_name}".format(adom=adom,
- provisioning_template=paramgram["provisioning_template"],
- snmpv3_name=paramgram["snmpv3_name"])
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def set_devprof_syslog(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- paramgram["mode"] = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
-
- datagram = {
- "status": paramgram["syslog_status"],
- "port": paramgram["syslog_port"],
- "server": paramgram["syslog_server"],
- "mode": paramgram["syslog_mode"],
- "facility": paramgram["syslog_facility"]
- }
-
- if paramgram["mode"] in ['set', 'add', 'update']:
- if paramgram["syslog_enc_algorithm"] in ["high", "low", "high-medium"] \
- and paramgram["syslog_certificate"] is not None:
- datagram["certificate"] = paramgram["certificate"]
- datagram["enc-algorithm"] = paramgram["syslog_enc_algorithm"]
-
- url = "/pm/config/adom/{adom}/" \
- "devprof/{provisioning_template}/" \
- "log/syslogd/setting".format(adom=adom,
- provisioning_template=paramgram["provisioning_template"])
- elif paramgram["mode"] == "delete":
- url = "/pm/config/adom/{adom}/" \
- "devprof/{provisioning_template}/" \
- "log/syslogd/setting".format(adom=adom,
- provisioning_template=paramgram["provisioning_template"])
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def set_devprof_syslog_filter(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- paramgram["mode"] = paramgram["mode"]
- adom = paramgram["adom"]
- datagram = {
- "severity": paramgram["syslog_filter"]
- }
- response = DEFAULT_RESULT_OBJ
-
- url = "/pm/config/adom/{adom}" \
- "/devprof/{provisioning_template}" \
- "/log/syslogd/filter".format(adom=adom,
- provisioning_template=paramgram["provisioning_template"])
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def set_devprof_ntp(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- paramgram["mode"] = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
-
- # IF SET TO FORTIGUARD, BUILD A STRING SPECIFIC TO THAT
- if paramgram["ntp_type"] == "fortiguard":
- datagram = {}
- if paramgram["ntp_status"] == "enable":
- datagram["ntpsync"] = 1
- if paramgram["ntp_status"] == "disable":
- datagram["ntpsync"] = 0
- if paramgram["ntp_sync_interval"] is None:
- datagram["syncinterval"] = 1
- else:
- datagram["syncinterval"] = paramgram["ntp_sync_interval"]
-
- datagram["type"] = 0
-
- # IF THE NTP TYPE IS CUSTOM BUILD THE SERVER LIST
- if paramgram["ntp_type"] == "custom":
- id_counter = 0
- key_counter = 0
- ntpservers = []
- datagram = {}
- if paramgram["ntp_status"] == "enable":
- datagram["ntpsync"] = 1
- if paramgram["ntp_status"] == "disable":
- datagram["ntpsync"] = 0
- try:
- datagram["syncinterval"] = paramgram["ntp_sync_interval"]
- except BaseException:
- datagram["syncinterval"] = 1
- datagram["type"] = 1
-
- for server in paramgram["ntp_server"].strip().split(","):
- id_counter += 1
- server_fields = dict()
-
- key_counter += 1
- if paramgram["ntp_auth"] == "enable":
- server_fields["authentication"] = 1
- server_fields["key"] = paramgram["ntp_auth_pwd"]
- server_fields["key-id"] = key_counter
- else:
- server_fields["authentication"] = 0
- server_fields["key"] = ""
- server_fields["key-id"] = key_counter
-
- if paramgram["ntp_v3"] == "enable":
- server_fields["ntp_v3"] = 1
- else:
- server_fields["ntp_v3"] = 0
-
- # split the host on the space to get the mask out
- new_ntp_server = {"authentication": server_fields["authentication"],
- "id": id_counter, "key": server_fields["key"],
- "key-id": id_counter, "ntpv3": server_fields["ntp_v3"],
- "server": server}
- ntpservers.append(new_ntp_server)
- datagram["ntpserver"] = ntpservers
-
- url = "/pm/config/adom/{adom}" \
- "/devprof/{provisioning_template}" \
- "/system/ntp".format(adom=adom,
- provisioning_template=paramgram["provisioning_template"])
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def set_devprof_admin(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- paramgram["mode"] = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
- datagram = {
- "admin-https-redirect": paramgram["admin_https_redirect"],
- "admin-port": paramgram["admin_http_port"],
- "admin-sport": paramgram["admin_https_port"],
- "admintimeout": paramgram["admin_timeout"],
- "language": paramgram["admin_language"],
- "gui-theme": paramgram["admin_gui_theme"],
- "switch-controller": paramgram["admin_switch_controller"],
- }
- url = "/pm/config/adom/{adom}" \
- "/devprof/{provisioning_template}" \
- "/system/global".format(adom=adom,
- provisioning_template=paramgram["provisioning_template"])
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def set_devprof_smtp(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- paramgram["mode"] = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
- datagram = {
- "port": paramgram["smtp_port"],
- "reply-to": paramgram["smtp_replyto"],
- "server": paramgram["smtp_server"],
- "source-ip": paramgram["smtp_source_ipv4"]
- }
-
- if paramgram["smtp_username"]:
- datagram["authenticate"] = 1
- datagram["username"] = paramgram["smtp_username"]
- datagram["password"] = paramgram["smtp_password"]
-
- if paramgram["smtp_conn_sec"] == "none":
- datagram["security"] = 0
- if paramgram["smtp_conn_sec"] == "starttls":
- datagram["security"] = 1
- if paramgram["smtp_conn_sec"] == "smtps":
- datagram["security"] = 2
-
- if paramgram["smtp_validate_cert"] == "enable":
- datagram["validate-server"] = 1
- else:
- datagram["validate-server"] = 0
-
- url = "/pm/config/adom/{adom}" \
- "/devprof/{provisioning_template}" \
- "/system/email-server".format(adom=adom,
- provisioning_template=paramgram["provisioning_template"])
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def set_devprof_dns(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- paramgram["mode"] = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
- datagram = {
- "domain": paramgram["dns_suffix"],
- "primary": paramgram["dns_primary_ipv4"],
- "secondary": paramgram["dns_secondary_ipv4"],
- }
- url = "/pm/config/adom/{adom}" \
- "/devprof/{provisioning_template}" \
- "/system/dns".format(adom=adom,
- provisioning_template=paramgram["provisioning_template"])
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def set_devprof_toggle_fg(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- paramgram["mode"] = paramgram["mode"]
- adom = paramgram["adom"]
- response = DEFAULT_RESULT_OBJ
- datagram = {}
- if paramgram["admin_enable_fortiguard"] in ["direct", "this-fmg"]:
- datagram["include-default-servers"] = "enable"
- elif paramgram["admin_enable_fortiguard"] == "none":
- datagram["include-default-servers"] = "disable"
-
- datagram["server-list"] = list()
-
- url = "/pm/config/adom/{adom}" \
- "/devprof/{provisioning_template}" \
- "/system/central-management".format(adom=adom,
- provisioning_template=paramgram["provisioning_template"])
- response = fmgr.process_request(url, datagram, FMGRMethods.SET)
-
- return response
-
-
-def set_devprof_fg(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- paramgram["mode"] = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
- datagram = {
- "target": paramgram["admin_enable_fortiguard"],
- "target-ip": None
- }
-
- if paramgram["mode"] in ['set', 'add', 'update']:
- if paramgram["admin_fortiguard_target"] is not None and datagram["target"] == "direct":
- datagram["target-ip"] = paramgram["admin_fortiguard_target"]
-
- url = "/pm/config/adom/{adom}" \
- "/devprof/{provisioning_template}" \
- "/device/profile/fortiguard".format(adom=adom,
- provisioning_template=paramgram["provisioning_template"])
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def set_devprof_faz(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- paramgram["mode"] = paramgram["mode"]
- adom = paramgram["adom"]
- response = DEFAULT_RESULT_OBJ
- datagram = {
- "target-ip": paramgram["admin_fortianalyzer_target"],
- "target": "others",
- }
- url = "/pm/config/adom/{adom}" \
- "/devprof/{provisioning_template}" \
- "/device/profile/fortianalyzer".format(adom=adom,
- provisioning_template=paramgram["provisioning_template"])
- if paramgram["mode"] == "delete":
- datagram["hastarget"] = "False"
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def main():
- argument_spec = dict(
- adom=dict(required=False, type="str"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
-
- provisioning_template=dict(required=False, type="str"),
- provision_targets=dict(required=False, type="str"),
-
- device_unique_name=dict(required=False, type="str"),
- snmp_status=dict(required=False, type="str", choices=["enable", "disable"]),
- snmp_v2c_query_port=dict(required=False, type="int"),
- snmp_v2c_trap_port=dict(required=False, type="int"),
- snmp_v2c_status=dict(required=False, type="str", choices=["enable", "disable"]),
- snmp_v2c_trap_status=dict(required=False, type="str", choices=["enable", "disable"]),
- snmp_v2c_query_status=dict(required=False, type="str", choices=["enable", "disable"]),
- snmp_v2c_name=dict(required=False, type="str", no_log=True),
- snmp_v2c_id=dict(required=False, type="int"),
- snmp_v2c_trap_src_ipv4=dict(required=False, type="str"),
- snmp_v2c_trap_hosts_ipv4=dict(required=False, type="str"),
- snmp_v2c_query_hosts_ipv4=dict(required=False, type="str"),
-
- snmpv3_auth_proto=dict(required=False, type="str", choices=["md5", "sha"]),
- snmpv3_auth_pwd=dict(required=False, type="str", no_log=True),
- snmpv3_name=dict(required=False, type="str"),
- snmpv3_notify_hosts=dict(required=False, type="str"),
- snmpv3_priv_proto=dict(required=False, type="str", choices=["aes", "des", "aes256", "aes256cisco"]),
- snmpv3_priv_pwd=dict(required=False, type="str", no_log=True),
- snmpv3_queries=dict(required=False, type="str", choices=["enable", "disable"]),
- snmpv3_query_port=dict(required=False, type="int"),
- snmpv3_security_level=dict(required=False, type="str",
- choices=["no-auth-no-priv", "auth-no-priv", "auth-priv"]),
- snmpv3_source_ip=dict(required=False, type="str"),
- snmpv3_status=dict(required=False, type="str", choices=["enable", "disable"]),
- snmpv3_trap_rport=dict(required=False, type="int"),
- snmpv3_trap_status=dict(required=False, type="str", choices=["enable", "disable"]),
-
- syslog_port=dict(required=False, type="int"),
- syslog_server=dict(required=False, type="str"),
- syslog_mode=dict(required=False, type="str", choices=["udp", "legacy-reliable", "reliable"], default="udp"),
- syslog_status=dict(required=False, type="str", choices=["enable", "disable"]),
- syslog_filter=dict(required=False, type="str", choices=["emergency", "alert", "critical", "error",
- "warning", "notification", "information", "debug"]),
- syslog_enc_algorithm=dict(required=False, type="str", choices=["high", "low", "disable", "high-medium"],
- default="disable"),
- syslog_facility=dict(required=False, type="str", choices=["kernel", "user", "mail", "daemon", "auth",
- "syslog", "lpr", "news", "uucp", "cron", "authpriv",
- "ftp", "ntp", "audit", "alert", "clock", "local0",
- "local1", "local2", "local3", "local4", "local5",
- "local6", "local7"], default="syslog"),
- syslog_certificate=dict(required=False, type="str"),
-
- ntp_status=dict(required=False, type="str", choices=["enable", "disable"]),
- ntp_sync_interval=dict(required=False, type="int"),
- ntp_type=dict(required=False, type="str", choices=["fortiguard", "custom"]),
- ntp_server=dict(required=False, type="str"),
- ntp_auth=dict(required=False, type="str", choices=["enable", "disable"]),
- ntp_auth_pwd=dict(required=False, type="str", no_log=True),
- ntp_v3=dict(required=False, type="str", choices=["enable", "disable"]),
-
- admin_https_redirect=dict(required=False, type="str", choices=["enable", "disable"]),
- admin_https_port=dict(required=False, type="int"),
- admin_http_port=dict(required=False, type="int"),
- admin_timeout=dict(required=False, type="int"),
- admin_language=dict(required=False, type="str",
- choices=["english", "simch", "japanese", "korean",
- "spanish", "trach", "french", "portuguese"]),
- admin_switch_controller=dict(required=False, type="str", choices=["enable", "disable"]),
- admin_gui_theme=dict(required=False, type="str", choices=["green", "red", "blue", "melongene", "mariner"]),
- admin_enable_fortiguard=dict(required=False, type="str", choices=["none", "direct", "this-fmg"]),
- admin_fortianalyzer_target=dict(required=False, type="str"),
- admin_fortiguard_target=dict(required=False, type="str"),
-
- smtp_username=dict(required=False, type="str"),
- smtp_password=dict(required=False, type="str", no_log=True),
- smtp_port=dict(required=False, type="int"),
- smtp_replyto=dict(required=False, type="str"),
- smtp_conn_sec=dict(required=False, type="str", choices=["none", "starttls", "smtps"]),
- smtp_server=dict(required=False, type="str"),
- smtp_source_ipv4=dict(required=False, type="str"),
- smtp_validate_cert=dict(required=False, type="str", choices=["enable", "disable"]),
-
- dns_suffix=dict(required=False, type="str"),
- dns_primary_ipv4=dict(required=False, type="str"),
- dns_secondary_ipv4=dict(required=False, type="str"),
- delete_provisioning_template=dict(required=False, type="str")
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- paramgram = {
- "adom": module.params["adom"],
- "mode": module.params["mode"],
- "provision_targets": module.params["provision_targets"],
- "provisioning_template": module.params["provisioning_template"],
-
- "snmp_status": module.params["snmp_status"],
- "snmp_v2c_query_port": module.params["snmp_v2c_query_port"],
- "snmp_v2c_trap_port": module.params["snmp_v2c_trap_port"],
- "snmp_v2c_status": module.params["snmp_v2c_status"],
- "snmp_v2c_trap_status": module.params["snmp_v2c_trap_status"],
- "snmp_v2c_query_status": module.params["snmp_v2c_query_status"],
- "snmp_v2c_name": module.params["snmp_v2c_name"],
- "snmp_v2c_id": module.params["snmp_v2c_id"],
- "snmp_v2c_trap_src_ipv4": module.params["snmp_v2c_trap_src_ipv4"],
- "snmp_v2c_trap_hosts_ipv4": module.params["snmp_v2c_trap_hosts_ipv4"],
- "snmp_v2c_query_hosts_ipv4": module.params["snmp_v2c_query_hosts_ipv4"],
-
- "snmpv3_auth_proto": module.params["snmpv3_auth_proto"],
- "snmpv3_auth_pwd": module.params["snmpv3_auth_pwd"],
- "snmpv3_name": module.params["snmpv3_name"],
- "snmpv3_notify_hosts": module.params["snmpv3_notify_hosts"],
- "snmpv3_priv_proto": module.params["snmpv3_priv_proto"],
- "snmpv3_priv_pwd": module.params["snmpv3_priv_pwd"],
- "snmpv3_queries": module.params["snmpv3_queries"],
- "snmpv3_query_port": module.params["snmpv3_query_port"],
- "snmpv3_security_level": module.params["snmpv3_security_level"],
- "snmpv3_source_ip": module.params["snmpv3_source_ip"],
- "snmpv3_status": module.params["snmpv3_status"],
- "snmpv3_trap_rport": module.params["snmpv3_trap_rport"],
- "snmpv3_trap_status": module.params["snmpv3_trap_status"],
-
- "syslog_port": module.params["syslog_port"],
- "syslog_server": module.params["syslog_server"],
- "syslog_mode": module.params["syslog_mode"],
- "syslog_status": module.params["syslog_status"],
- "syslog_filter": module.params["syslog_filter"],
- "syslog_facility": module.params["syslog_facility"],
- "syslog_enc_algorithm": module.params["syslog_enc_algorithm"],
- "syslog_certificate": module.params["syslog_certificate"],
-
- "ntp_status": module.params["ntp_status"],
- "ntp_sync_interval": module.params["ntp_sync_interval"],
- "ntp_type": module.params["ntp_type"],
- "ntp_server": module.params["ntp_server"],
- "ntp_auth": module.params["ntp_auth"],
- "ntp_auth_pwd": module.params["ntp_auth_pwd"],
- "ntp_v3": module.params["ntp_v3"],
-
- "admin_https_redirect": module.params["admin_https_redirect"],
- "admin_https_port": module.params["admin_https_port"],
- "admin_http_port": module.params["admin_http_port"],
- "admin_timeout": module.params["admin_timeout"],
- "admin_language": module.params["admin_language"],
- "admin_switch_controller": module.params["admin_switch_controller"],
- "admin_gui_theme": module.params["admin_gui_theme"],
- "admin_enable_fortiguard": module.params["admin_enable_fortiguard"],
- "admin_fortianalyzer_target": module.params["admin_fortianalyzer_target"],
- "admin_fortiguard_target": module.params["admin_fortiguard_target"],
-
- "smtp_username": module.params["smtp_username"],
- "smtp_password": module.params["smtp_password"],
- "smtp_port": module.params["smtp_port"],
- "smtp_replyto": module.params["smtp_replyto"],
- "smtp_conn_sec": module.params["smtp_conn_sec"],
- "smtp_server": module.params["smtp_server"],
- "smtp_source_ipv4": module.params["smtp_source_ipv4"],
- "smtp_validate_cert": module.params["smtp_validate_cert"],
-
- "dns_suffix": module.params["dns_suffix"],
- "dns_primary_ipv4": module.params["dns_primary_ipv4"],
- "dns_secondary_ipv4": module.params["dns_secondary_ipv4"],
- "delete_provisioning_template": module.params["delete_provisioning_template"]
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- results = DEFAULT_RESULT_OBJ
- try:
- # CHECK IF WE ARE DELETING AN ENTIRE TEMPLATE. IF THAT'S THE CASE DO IT FIRST AND IGNORE THE REST.
- if paramgram["delete_provisioning_template"] is not None:
- results = set_devprof(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0, -10, -1],
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram),
- stop_on_success=True)
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # CHECK TO SEE IF THE DEVPROF TEMPLATE EXISTS
- devprof = get_devprof(fmgr, paramgram)
- if devprof[0] != 0:
- results = set_devprof(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0, -2], stop_on_success=False,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # PROCESS THE SNMP SETTINGS IF THE SNMP_STATUS VARIABLE IS SET
- if paramgram["snmp_status"] is not None:
- results = set_devprof_snmp(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- # PROCESS THE SNMP V2C COMMUNITY SETTINGS IF THEY ARE ALL HERE
- if all(v is not None for v in (paramgram["snmp_v2c_query_port"], paramgram["snmp_v2c_trap_port"],
- paramgram["snmp_v2c_status"], paramgram["snmp_v2c_trap_status"],
- paramgram["snmp_v2c_query_status"], paramgram["snmp_v2c_name"],
- paramgram["snmp_v2c_id"])):
- results = set_devprof_snmp_v2c(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0, -10033], stop_on_success=True,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- # PROCESS THE SNMPV3 USER IF THERE
- if all(v is not None for v in (
- [paramgram["snmpv3_auth_proto"], paramgram["snmpv3_auth_pwd"], paramgram["snmpv3_name"],
- paramgram["snmpv3_notify_hosts"], paramgram["snmpv3_priv_proto"],
- paramgram["snmpv3_priv_pwd"],
- paramgram["snmpv3_queries"],
- paramgram["snmpv3_query_port"], paramgram["snmpv3_security_level"],
- paramgram["snmpv3_source_ip"],
- paramgram["snmpv3_status"], paramgram["snmpv3_trap_rport"], paramgram["snmpv3_trap_status"]])):
-
- results = set_devprof_snmp_v3(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0, -10033, -10000, -3],
- stop_on_success=True,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # PROCESS THE SYSLOG SETTINGS IF THE ALL THE NEEDED SYSLOG VARIABLES ARE PRESENT
- if all(v is not None for v in [paramgram["syslog_port"], paramgram["syslog_mode"],
- paramgram["syslog_server"], paramgram["syslog_status"]]):
- # enable syslog in the devprof template
- results = set_devprof_syslog(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0, -10033, -10000, -3],
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # IF THE SYSLOG FILTER IS PRESENT THEN RUN THAT
- if paramgram["syslog_filter"] is not None:
- results = set_devprof_syslog_filter(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0],
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # PROCESS NTP OPTIONS
- if paramgram["ntp_status"]:
- # VALIDATE INPUT
- if paramgram["ntp_type"] == "custom" and paramgram["ntp_server"] is None:
- module.exit_json(msg="You requested custom NTP type but did not provide ntp_server parameter.")
- if paramgram["ntp_auth"] == "enable" and paramgram["ntp_auth_pwd"] is None:
- module.exit_json(
- msg="You requested NTP Authentication but did not provide ntp_auth_pwd parameter.")
-
- results = set_devprof_ntp(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0],
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
- try:
- # PROCESS THE ADMIN OPTIONS
- if any(v is not None for v in (
- paramgram["admin_https_redirect"], paramgram["admin_https_port"], paramgram["admin_http_port"],
- paramgram["admin_timeout"],
- paramgram["admin_language"], paramgram["admin_switch_controller"],
- paramgram["admin_gui_theme"])):
-
- results = set_devprof_admin(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # PROCESS FORTIGUARD OPTIONS
- if paramgram["admin_enable_fortiguard"] is not None:
-
- results = set_devprof_toggle_fg(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- results = set_devprof_fg(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # PROCESS THE SMTP OPTIONS
- if all(v is not None for v in (
- paramgram["smtp_username"], paramgram["smtp_password"], paramgram["smtp_port"],
- paramgram["smtp_replyto"],
- paramgram["smtp_conn_sec"], paramgram["smtp_server"],
- paramgram["smtp_source_ipv4"], paramgram["smtp_validate_cert"])):
-
- results = set_devprof_smtp(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # PROCESS THE DNS OPTIONS
- if any(v is not None for v in
- (paramgram["dns_suffix"], paramgram["dns_primary_ipv4"], paramgram["dns_secondary_ipv4"])):
- results = set_devprof_dns(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # PROCESS THE admin_fortianalyzer_target OPTIONS
- if paramgram["admin_fortianalyzer_target"] is not None:
-
- results = set_devprof_faz(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # PROCESS THE PROVISIONING TEMPLATE TARGET PARAMETER
- if paramgram["provision_targets"] is not None:
- if paramgram["mode"] != "delete":
- results = set_devprof_scope(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- if paramgram["mode"] == "delete":
- # WE NEED TO FIGURE OUT WHAT'S THERE FIRST, BEFORE WE CAN RUN THIS
- targets_to_add = list()
- try:
- current_scope = get_devprof_scope(fmgr, paramgram)
- targets_to_remove = paramgram["provision_targets"].strip().split(",")
- targets = current_scope[1][1]["scope member"]
- for target in targets:
- if target["name"] not in targets_to_remove:
- target_append = {"name": target["name"]}
- targets_to_add.append(target_append)
- except BaseException:
- pass
- paramgram["targets_to_add"] = targets_to_add
- results = set_devprof_scope(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0, -10033, -10000, -3],
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_fwobj_address.py b/plugins/modules/network/fortimanager/fmgr_fwobj_address.py
deleted file mode 100644
index 58b23cf847..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_fwobj_address.py
+++ /dev/null
@@ -1,667 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- "metadata_version": "1.1",
- "status": ["preview"],
- "supported_by": "community"
-}
-
-DOCUMENTATION = '''
----
-module: fmgr_fwobj_address
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Allows the management of firewall objects in FortiManager
-description:
- - Allows for the management of IPv4, IPv6, and multicast address objects within FortiManager.
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- allow_routing:
- description:
- - Enable/disable use of this address in the static route configuration.
- choices: ['enable', 'disable']
- default: 'disable'
-
- associated_interface:
- description:
- - Associated interface name.
-
- cache_ttl:
- description:
- - Minimal TTL of individual IP addresses in FQDN cache. Only applies when type = wildcard-fqdn.
-
- color:
- description:
- - Color of the object in FortiManager GUI.
- - Takes integers 1-32
- default: 22
-
- comment:
- description:
- - Comment for the object in FortiManager.
-
- country:
- description:
- - Country name. Required if type = geographic.
-
- end_ip:
- description:
- - End IP. Only used when ipv4 = iprange.
-
- group_members:
- description:
- - Address group member. If this is defined w/out group_name, the operation will fail.
-
- group_name:
- description:
- - Address group name. If this is defined in playbook task, all other options are ignored.
-
- ipv4:
- description:
- - Type of IPv4 Object.
- - Must not be specified with either multicast or IPv6 parameters.
- choices: ['ipmask', 'iprange', 'fqdn', 'wildcard', 'geography', 'wildcard-fqdn', 'group']
-
- ipv4addr:
- description:
- - IP and network mask. If only defining one IP use this parameter. (i.e. 10.7.220.30/255.255.255.255)
- - Can also define subnets (i.e. 10.7.220.0/255.255.255.0)
- - Also accepts CIDR (i.e. 10.7.220.0/24)
- - If Netmask is omitted after IP address, /32 is assumed.
- - When multicast is set to Broadcast Subnet the ipv4addr parameter is used to specify the subnet.
-
- ipv6:
- description:
- - Puts module into IPv6 mode.
- - Must not be specified with either ipv4 or multicast parameters.
- choices: ['ip', 'iprange', 'group']
-
- ipv6addr:
- description:
- - IPv6 address in full. (i.e. 2001:0db8:85a3:0000:0000:8a2e:0370:7334)
-
- fqdn:
- description:
- - Fully qualified domain name.
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- choices: ['add', 'set', 'delete']
- default: add
-
- multicast:
- description:
- - Manages Multicast Address Objects.
- - Sets either a Multicast IP Range or a Broadcast Subnet.
- - Must not be specified with either ipv4 or ipv6 parameters.
- - When set to Broadcast Subnet the ipv4addr parameter is used to specify the subnet.
- - Can create IPv4 Multicast Objects (multicastrange and broadcastmask options -- uses start/end-ip and ipv4addr).
- choices: ['multicastrange', 'broadcastmask', 'ip6']
-
- name:
- description:
- - Friendly Name Address object name in FortiManager.
-
- obj_id:
- description:
- - Object ID for NSX.
-
- start_ip:
- description:
- - Start IP. Only used when ipv4 = iprange.
-
- visibility:
- description:
- - Enable/disable address visibility.
- choices: ['enable', 'disable']
- default: 'enable'
-
- wildcard:
- description:
- - IP address and wildcard netmask. Required if ipv4 = wildcard.
-
- wildcard_fqdn:
- description:
- - Wildcard FQDN. Required if ipv4 = wildcard-fqdn.
-'''
-
-EXAMPLES = '''
-- name: ADD IPv4 IP ADDRESS OBJECT
- fmgr_fwobj_address:
- ipv4: "ipmask"
- ipv4addr: "10.7.220.30/32"
- name: "ansible_v4Obj"
- comment: "Created by Ansible"
- color: "6"
-
-- name: ADD IPv4 IP ADDRESS OBJECT MORE OPTIONS
- fmgr_fwobj_address:
- ipv4: "ipmask"
- ipv4addr: "10.7.220.34/32"
- name: "ansible_v4Obj_MORE"
- comment: "Created by Ansible"
- color: "6"
- allow_routing: "enable"
- cache_ttl: "180"
- associated_interface: "port1"
- obj_id: "123"
-
-- name: ADD IPv4 IP ADDRESS SUBNET OBJECT
- fmgr_fwobj_address:
- ipv4: "ipmask"
- ipv4addr: "10.7.220.0/255.255.255.128"
- name: "ansible_subnet"
- comment: "Created by Ansible"
- mode: "set"
-
-- name: ADD IPv4 IP ADDRESS RANGE OBJECT
- fmgr_fwobj_address:
- ipv4: "iprange"
- start_ip: "10.7.220.1"
- end_ip: "10.7.220.125"
- name: "ansible_range"
- comment: "Created by Ansible"
-
-- name: ADD IPv4 IP ADDRESS WILDCARD OBJECT
- fmgr_fwobj_address:
- ipv4: "wildcard"
- wildcard: "10.7.220.30/255.255.255.255"
- name: "ansible_wildcard"
- comment: "Created by Ansible"
-
-- name: ADD IPv4 IP ADDRESS WILDCARD FQDN OBJECT
- fmgr_fwobj_address:
- ipv4: "wildcard-fqdn"
- wildcard_fqdn: "*.myds.com"
- name: "Synology myds DDNS service"
- comment: "Created by Ansible"
-
-- name: ADD IPv4 IP ADDRESS FQDN OBJECT
- fmgr_fwobj_address:
- ipv4: "fqdn"
- fqdn: "ansible.com"
- name: "ansible_fqdn"
- comment: "Created by Ansible"
-
-- name: ADD IPv4 IP ADDRESS GEO OBJECT
- fmgr_fwobj_address:
- ipv4: "geography"
- country: "usa"
- name: "ansible_geo"
- comment: "Created by Ansible"
-
-- name: ADD IPv6 ADDRESS
- fmgr_fwobj_address:
- ipv6: "ip"
- ipv6addr: "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
- name: "ansible_v6Obj"
- comment: "Created by Ansible"
-
-- name: ADD IPv6 ADDRESS RANGE
- fmgr_fwobj_address:
- ipv6: "iprange"
- start_ip: "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
- end_ip: "2001:0db8:85a3:0000:0000:8a2e:0370:7446"
- name: "ansible_v6range"
- comment: "Created by Ansible"
-
-- name: ADD IPv4 IP ADDRESS GROUP
- fmgr_fwobj_address:
- ipv4: "group"
- group_name: "ansibleIPv4Group"
- group_members: "ansible_fqdn, ansible_wildcard, ansible_range"
-
-- name: ADD IPv6 IP ADDRESS GROUP
- fmgr_fwobj_address:
- ipv6: "group"
- group_name: "ansibleIPv6Group"
- group_members: "ansible_v6Obj, ansible_v6range"
-
-- name: ADD MULTICAST RANGE
- fmgr_fwobj_address:
- multicast: "multicastrange"
- start_ip: "224.0.0.251"
- end_ip: "224.0.0.251"
- name: "ansible_multicastrange"
- comment: "Created by Ansible"
-
-- name: ADD BROADCAST SUBNET
- fmgr_fwobj_address:
- multicast: "broadcastmask"
- ipv4addr: "10.7.220.0/24"
- name: "ansible_broadcastSubnet"
- comment: "Created by Ansible"
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-
-import re
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-
-
-def fmgr_fwobj_ipv4(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if paramgram["mode"] in ['set', 'add']:
- # CREATE THE DATAGRAM DICTIONARY
- # ENSURE THE DATAGRAM KEYS MATCH THE JSON API GUIDE ATTRIBUTES, NOT WHAT IS IN ANSIBLE
- # SOME PARAMETERS SHOWN IN THIS DICTIONARY WE DON'T EVEN ASK THE USER FOR IN PLAYBOOKS BUT ARE REQUIRED
- datagram = {
- "comment": paramgram["comment"],
- "associated-interface": paramgram["associated-interface"],
- "cache-ttl": paramgram["cache-ttl"],
- "name": paramgram["name"],
- "allow-routing": paramgram["allow-routing"],
- "color": paramgram["color"],
- "meta fields": {},
- "dynamic_mapping": [],
- "visibility": paramgram["allow-routing"],
- "type": paramgram["ipv4"],
- }
-
- # SET THE CORRECT URL BASED ON THE TYPE (WE'RE DOING GROUPS IN THIS METHOD, TOO)
- if datagram["type"] == "group":
- url = '/pm/config/adom/{adom}/obj/firewall/addrgrp'.format(adom=paramgram["adom"])
- else:
- url = '/pm/config/adom/{adom}/obj/firewall/address'.format(adom=paramgram["adom"])
-
- #########################
- # IF type = 'ipmask'
- #########################
- if datagram["type"] == "ipmask":
- # CREATE THE SUBNET LIST OBJECT
- subnet = []
- # EVAL THE IPV4ADDR INPUT AND SPLIT THE IP ADDRESS FROM THE MASK AND APPEND THEM TO THE SUBNET LIST
- for subnets in paramgram["ipv4addr"].split("/"):
- subnet.append(subnets)
-
- # CHECK THAT THE SECOND ENTRY IN THE SUBNET LIST (WHAT WAS TO THE RIGHT OF THE / CHARACTER)
- # IS IN SUBNET MASK FORMAT AND NOT CIDR FORMAT.
- # IF IT IS IN CIDR FORMAT, WE NEED TO CONVERT IT TO SUBNET BIT MASK FORMAT FOR THE JSON API
- if not re.match(r'\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}', subnet[1]):
- # IF THE SUBNET PARAMETER INPUT DIDN'T LOOK LIKE xxx.xxx.xxx.xxx TO REGEX...
- # ... RUN IT THROUGH THE CIDR_TO_NETMASK() FUNCTION
- mask = fmgr._tools.cidr_to_netmask(subnet[1])
- # AND THEN UPDATE THE SUBNET LIST OBJECT
- subnet[1] = mask
-
- # INCLUDE THE SUBNET LIST OBJECT IN THE DATAGRAM DICTIONARY TO BE SUBMITTED
- datagram["subnet"] = subnet
-
- #########################
- # IF type = 'iprange'
- #########################
- if datagram["type"] == "iprange":
- datagram["start-ip"] = paramgram["start-ip"]
- datagram["end-ip"] = paramgram["end-ip"]
- datagram["subnet"] = ["0.0.0.0", "0.0.0.0"]
-
- #########################
- # IF type = 'geography'
- #########################
- if datagram["type"] == "geography":
- datagram["country"] = paramgram["country"]
-
- #########################
- # IF type = 'wildcard'
- #########################
- if datagram["type"] == "wildcard":
-
- subnet = []
- for subnets in paramgram["wildcard"].split("/"):
- subnet.append(subnets)
-
- if not re.match(r'\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}', subnet[1]):
- mask = fmgr._tools.cidr_to_netmask(subnet[1])
- subnet[1] = mask
-
- datagram["wildcard"] = subnet
-
- #########################
- # IF type = 'wildcard-fqdn'
- #########################
- if datagram["type"] == "wildcard-fqdn":
- datagram["wildcard-fqdn"] = paramgram["wildcard-fqdn"]
-
- #########################
- # IF type = 'fqdn'
- #########################
- if datagram["type"] == "fqdn":
- datagram["fqdn"] = paramgram["fqdn"]
-
- #########################
- # IF type = 'group'
- #########################
- if datagram["type"] == "group":
- datagram = {
- "comment": paramgram["comment"],
- "name": paramgram["group_name"],
- "color": paramgram["color"],
- "meta fields": {},
- "dynamic_mapping": [],
- "visibility": paramgram["visibility"]
- }
-
- members = []
- group_members = paramgram["group_members"].replace(" ", "")
- try:
- for member in group_members.split(","):
- members.append(member)
- except Exception:
- pass
-
- datagram["member"] = members
-
- # EVAL THE MODE PARAMETER FOR DELETE
- if paramgram["mode"] == "delete":
- # IF A GROUP, SET THE CORRECT NAME AND URL FOR THE GROUP ENDPOINT
- if paramgram["ipv4"] == "group":
- datagram = {}
- url = '/pm/config/adom/{adom}/obj/firewall/addrgrp/{name}'.format(adom=paramgram["adom"],
- name=paramgram["group_name"])
- # OTHERWISE WE'RE JUST GOING TO USE THE ADDRESS ENDPOINT
- else:
- datagram = {}
- url = '/pm/config/adom/{adom}/obj/firewall/address/{name}'.format(adom=paramgram["adom"],
- name=paramgram["name"])
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def fmgr_fwobj_ipv6(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if paramgram["mode"] in ['set', 'add']:
- # CREATE THE DATAGRAM DICTIONARY
- # ENSURE THE DATAGRAM KEYS MATCH THE JSON API GUIDE ATTRIBUTES, NOT WHAT IS IN ANSIBLE
- # SOME PARAMETERS SHOWN IN THIS DICTIONARY WE DON'T EVEN ASK THE USER FOR IN PLAYBOOKS BUT ARE REQUIRED
- datagram = {
- "comment": paramgram["comment"],
- "name": paramgram["name"],
- "color": paramgram["color"],
- "dynamic_mapping": [],
- "visibility": paramgram["visibility"],
- "type": paramgram["ipv6"]
- }
-
- # SET THE CORRECT URL BASED ON THE TYPE (WE'RE DOING GROUPS IN THIS METHOD, TOO)
- if datagram["type"] == "group":
- url = '/pm/config/adom/{adom}/obj/firewall/addrgrp6'.format(adom=paramgram["adom"])
- else:
- url = '/pm/config/adom/{adom}/obj/firewall/address6'.format(adom=paramgram["adom"])
-
- #########################
- # IF type = 'ip'
- #########################
- if datagram["type"] == "ip":
- datagram["type"] = "ipprefix"
- datagram["ip6"] = paramgram["ipv6addr"]
-
- #########################
- # IF type = 'iprange'
- #########################
- if datagram["type"] == "iprange":
- datagram["start-ip"] = paramgram["start-ip"]
- datagram["end-ip"] = paramgram["end-ip"]
-
- #########################
- # IF type = 'group'
- #########################
- if datagram["type"] == "group":
- datagram = None
- datagram = {
- "comment": paramgram["comment"],
- "name": paramgram["group_name"],
- "color": paramgram["color"],
- "visibility": paramgram["visibility"]
- }
-
- members = []
- group_members = paramgram["group_members"].replace(" ", "")
- try:
- for member in group_members.split(","):
- members.append(member)
- except Exception:
- pass
-
- datagram["member"] = members
-
- # EVAL THE MODE PARAMETER FOR DELETE
- if paramgram["mode"] == "delete":
- # IF A GROUP, SET THE CORRECT NAME AND URL FOR THE GROUP ENDPOINT
- if paramgram["ipv6"] == "group":
- datagram = {}
- url = '/pm/config/adom/{adom}/obj/firewall/addrgrp6/{name}'.format(adom=paramgram["adom"],
- name=paramgram["group_name"])
- # OTHERWISE WE'RE JUST GOING TO USE THE ADDRESS ENDPOINT
- else:
- datagram = {}
- url = '/pm/config/adom/{adom}/obj/firewall/address6/{name}'.format(adom=paramgram["adom"],
- name=paramgram["name"])
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def fmgr_fwobj_multicast(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if paramgram["mode"] in ['set', 'add']:
- # CREATE THE DATAGRAM DICTIONARY
- # ENSURE THE DATAGRAM KEYS MATCH THE JSON API GUIDE ATTRIBUTES, NOT WHAT IS IN ANSIBLE
- # SOME PARAMETERS SHOWN IN THIS DICTIONARY WE DON'T EVEN ASK THE USER FOR IN PLAYBOOKS BUT ARE REQUIRED
- datagram = {
- "associated-interface": paramgram["associated-interface"],
- "comment": paramgram["comment"],
- "name": paramgram["name"],
- "color": paramgram["color"],
- "type": paramgram["multicast"],
- "visibility": paramgram["visibility"],
- }
-
- # SET THE CORRECT URL
- url = '/pm/config/adom/{adom}/obj/firewall/multicast-address'.format(adom=paramgram["adom"])
-
- #########################
- # IF type = 'multicastrange'
- #########################
- if paramgram["multicast"] == "multicastrange":
- datagram["start-ip"] = paramgram["start-ip"]
- datagram["end-ip"] = paramgram["end-ip"]
- datagram["subnet"] = ["0.0.0.0", "0.0.0.0"]
-
- #########################
- # IF type = 'broadcastmask'
- #########################
- if paramgram["multicast"] == "broadcastmask":
- # EVAL THE IPV4ADDR INPUT AND SPLIT THE IP ADDRESS FROM THE MASK AND APPEND THEM TO THE SUBNET LIST
- subnet = []
- for subnets in paramgram["ipv4addr"].split("/"):
- subnet.append(subnets)
- # CHECK THAT THE SECOND ENTRY IN THE SUBNET LIST (WHAT WAS TO THE RIGHT OF THE / CHARACTER)
- # IS IN SUBNET MASK FORMAT AND NOT CIDR FORMAT.
- # IF IT IS IN CIDR FORMAT, WE NEED TO CONVERT IT TO SUBNET BIT MASK FORMAT FOR THE JSON API
- if not re.match(r'\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}', subnet[1]):
- # IF THE SUBNET PARAMETER INPUT DIDN'T LOOK LIKE 255.255.255.255 TO REGEX...
- # ... RUN IT THROUGH THE fmgr_cidr_to_netmask() FUNCTION
- mask = fmgr._tools.cidr_to_netmask(subnet[1])
- # AND THEN UPDATE THE SUBNET LIST OBJECT
- subnet[1] = mask
-
- # INCLUDE THE SUBNET LIST OBJECT IN THE DATAGRAM DICTIONARY TO BE SUBMITTED
- datagram["subnet"] = subnet
-
- # EVAL THE MODE PARAMETER FOR DELETE
- if paramgram["mode"] == "delete":
- datagram = {
- "name": paramgram["name"]
- }
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/firewall/multicast-address/{name}'.format(adom=paramgram["adom"],
- name=paramgram["name"])
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def main():
- argument_spec = dict(
- adom=dict(required=False, type="str", default="root"),
- mode=dict(choices=["add", "set", "delete"], type="str", default="add"),
-
- allow_routing=dict(required=False, type="str", choices=['enable', 'disable'], default="disable"),
- associated_interface=dict(required=False, type="str"),
- cache_ttl=dict(required=False, type="str"),
- color=dict(required=False, type="str", default=22),
- comment=dict(required=False, type="str"),
- country=dict(required=False, type="str"),
- fqdn=dict(required=False, type="str"),
- name=dict(required=False, type="str"),
- start_ip=dict(required=False, type="str"),
- end_ip=dict(required=False, type="str"),
- ipv4=dict(required=False, type="str", choices=['ipmask', 'iprange', 'fqdn', 'wildcard',
- 'geography', 'wildcard-fqdn', 'group']),
- visibility=dict(required=False, type="str", choices=['enable', 'disable'], default="enable"),
- wildcard=dict(required=False, type="str"),
- wildcard_fqdn=dict(required=False, type="str"),
- ipv6=dict(required=False, type="str", choices=['ip', 'iprange', 'group']),
- group_members=dict(required=False, type="str"),
- group_name=dict(required=False, type="str"),
- ipv4addr=dict(required=False, type="str"),
- ipv6addr=dict(required=False, type="str"),
- multicast=dict(required=False, type="str", choices=['multicastrange', 'broadcastmask', 'ip6']),
- obj_id=dict(required=False, type="str"),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False,
- mutually_exclusive=[
- ['ipv4', 'ipv6'],
- ['ipv4', 'multicast'],
- ['ipv6', 'multicast']
- ])
- paramgram = {
- "adom": module.params["adom"],
- "allow-routing": module.params["allow_routing"],
- "associated-interface": module.params["associated_interface"],
- "cache-ttl": module.params["cache_ttl"],
- "color": module.params["color"],
- "comment": module.params["comment"],
- "country": module.params["country"],
- "end-ip": module.params["end_ip"],
- "fqdn": module.params["fqdn"],
- "name": module.params["name"],
- "start-ip": module.params["start_ip"],
- "visibility": module.params["visibility"],
- "wildcard": module.params["wildcard"],
- "wildcard-fqdn": module.params["wildcard_fqdn"],
- "ipv6": module.params["ipv6"],
- "ipv4": module.params["ipv4"],
- "group_members": module.params["group_members"],
- "group_name": module.params["group_name"],
- "ipv4addr": module.params["ipv4addr"],
- "ipv6addr": module.params["ipv6addr"],
- "multicast": module.params["multicast"],
- "mode": module.params["mode"],
- "obj-id": module.params["obj_id"],
- }
-
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr._tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- results = DEFAULT_RESULT_OBJ
- try:
- if paramgram["ipv4"]:
- results = fmgr_fwobj_ipv4(fmgr, paramgram)
-
- elif paramgram["ipv6"]:
- results = fmgr_fwobj_ipv6(fmgr, paramgram)
-
- elif paramgram["multicast"]:
- results = fmgr_fwobj_multicast(fmgr, paramgram)
-
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- if results is not None:
- return module.exit_json(**results[1])
- else:
- return module.exit_json(msg="Couldn't find a proper ipv4 or ipv6 or multicast parameter "
- "to run in the logic tree. Exiting...")
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_fwobj_ippool.py b/plugins/modules/network/fortimanager/fmgr_fwobj_ippool.py
deleted file mode 100644
index d0c3e11faf..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_fwobj_ippool.py
+++ /dev/null
@@ -1,446 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_fwobj_ippool
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Allows the editing of IP Pool Objects within FortiManager.
-description:
- - Allows users to add/edit/delete IP Pool Objects.
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- type:
- description:
- - IP pool type (overload, one-to-one, fixed port range, or port block allocation).
- - choice | overload | IP addresses in the IP pool can be shared by clients.
- - choice | one-to-one | One to one mapping.
- - choice | fixed-port-range | Fixed port range.
- - choice | port-block-allocation | Port block allocation.
- required: false
- choices: ["overload", "one-to-one", "fixed-port-range", "port-block-allocation"]
-
- startip:
- description:
- - First IPv4 address (inclusive) in the range for the address pool (format xxx.xxx.xxx.xxx, Default| 0.0.0.0).
- required: false
-
- source_startip:
- description:
- - First IPv4 address (inclusive) in the range of the source addresses to be translated (format xxx.xxx.xxx.xxx,
- Default| 0.0.0.0).
- required: false
-
- source_endip:
- description:
- - Final IPv4 address (inclusive) in the range of the source addresses to be translated (format xxx.xxx.xxx.xxx,
- Default| 0.0.0.0).
- required: false
-
- permit_any_host:
- description:
- - Enable/disable full cone NAT.
- - choice | disable | Disable full cone NAT.
- - choice | enable | Enable full cone NAT.
- required: false
- choices: ["disable", "enable"]
-
- pba_timeout:
- description:
- - Port block allocation timeout (seconds).
- required: false
-
- num_blocks_per_user:
- description:
- - Number of addresses blocks that can be used by a user (1 to 128, default = 8).
- required: false
-
- name:
- description:
- - IP pool name.
- required: false
-
- endip:
- description:
- - Final IPv4 address (inclusive) in the range for the address pool (format xxx.xxx.xxx.xxx, Default| 0.0.0.0).
- required: false
-
- comments:
- description:
- - Comment.
- required: false
-
- block_size:
- description:
- - Number of addresses in a block (64 to 4096, default = 128).
- required: false
-
- associated_interface:
- description:
- - Associated interface name.
- required: false
-
- arp_reply:
- description:
- - Enable/disable replying to ARP requests when an IP Pool is added to a policy (default = enable).
- - choice | disable | Disable ARP reply.
- - choice | enable | Enable ARP reply.
- required: false
- choices: ["disable", "enable"]
-
- arp_intf:
- description:
- - Select an interface from available options that will reply to ARP requests. (If blank, any is selected).
- required: false
-
- dynamic_mapping:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameter.ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- dynamic_mapping_arp_intf:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
-
- dynamic_mapping_arp_reply:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_associated_interface:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
-
- dynamic_mapping_block_size:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
-
- dynamic_mapping_comments:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
-
- dynamic_mapping_endip:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
-
- dynamic_mapping_num_blocks_per_user:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
-
- dynamic_mapping_pba_timeout:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
-
- dynamic_mapping_permit_any_host:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_source_endip:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
-
- dynamic_mapping_source_startip:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
-
- dynamic_mapping_startip:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
-
- dynamic_mapping_type:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
- choices: ["overload", "one-to-one", "fixed-port-range", "port-block-allocation"]
-
-
-'''
-
-EXAMPLES = '''
-- name: ADD FMGR_FIREWALL_IPPOOL Overload
- fmgr_fwobj_ippool:
- mode: "add"
- adom: "ansible"
- name: "Ansible_pool4_overload"
- comments: "Created by ansible"
- type: "overload"
-
- # OPTIONS FOR ALL MODES
- startip: "10.10.10.10"
- endip: "10.10.10.100"
- arp_reply: "enable"
-
-- name: ADD FMGR_FIREWALL_IPPOOL one-to-one
- fmgr_fwobj_ippool:
- mode: "add"
- adom: "ansible"
- name: "Ansible_pool4_121"
- comments: "Created by ansible"
- type: "one-to-one"
-
- # OPTIONS FOR ALL MODES
- startip: "10.10.20.10"
- endip: "10.10.20.100"
- arp_reply: "enable"
-
-- name: ADD FMGR_FIREWALL_IPPOOL FIXED PORT RANGE
- fmgr_fwobj_ippool:
- mode: "add"
- adom: "ansible"
- name: "Ansible_pool4_fixed_port"
- comments: "Created by ansible"
- type: "fixed-port-range"
-
- # OPTIONS FOR ALL MODES
- startip: "10.10.40.10"
- endip: "10.10.40.100"
- arp_reply: "enable"
- # FIXED PORT RANGE OPTIONS
- source_startip: "192.168.20.1"
- source_endip: "192.168.20.20"
-
-- name: ADD FMGR_FIREWALL_IPPOOL PORT BLOCK ALLOCATION
- fmgr_fwobj_ippool:
- mode: "add"
- adom: "ansible"
- name: "Ansible_pool4_port_block_allocation"
- comments: "Created by ansible"
- type: "port-block-allocation"
-
- # OPTIONS FOR ALL MODES
- startip: "10.10.30.10"
- endip: "10.10.30.100"
- arp_reply: "enable"
- # PORT BLOCK ALLOCATION OPTIONS
- block_size: "128"
- num_blocks_per_user: "1"
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-
-###############
-# START METHODS
-###############
-
-
-def fmgr_fwobj_ippool_modify(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- mode = paramgram["mode"]
- adom = paramgram["adom"]
- # INIT A BASIC OBJECTS
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
-
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if mode in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/obj/firewall/ippool'.format(adom=adom)
- datagram = scrub_dict(prepare_dict(paramgram))
-
- # EVAL THE MODE PARAMETER FOR DELETE
- elif mode == "delete":
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/firewall/ippool/{name}'.format(adom=adom, name=paramgram["name"])
- datagram = {}
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
-
- return response
-
-
-#############
-# END METHODS
-#############
-
-
-def main():
- argument_spec = dict(
- adom=dict(type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
-
- type=dict(required=False, type="str", choices=["overload",
- "one-to-one",
- "fixed-port-range",
- "port-block-allocation"]),
- startip=dict(required=False, type="str"),
- source_startip=dict(required=False, type="str"),
- source_endip=dict(required=False, type="str"),
- permit_any_host=dict(required=False, type="str", choices=["disable", "enable"]),
- pba_timeout=dict(required=False, type="int"),
- num_blocks_per_user=dict(required=False, type="int"),
- name=dict(required=False, type="str"),
- endip=dict(required=False, type="str"),
- comments=dict(required=False, type="str"),
- block_size=dict(required=False, type="int"),
- associated_interface=dict(required=False, type="str"),
- arp_reply=dict(required=False, type="str", choices=["disable", "enable"]),
- arp_intf=dict(required=False, type="str"),
- dynamic_mapping=dict(required=False, type="list"),
- dynamic_mapping_arp_intf=dict(required=False, type="str"),
- dynamic_mapping_arp_reply=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_associated_interface=dict(required=False, type="str"),
- dynamic_mapping_block_size=dict(required=False, type="int"),
- dynamic_mapping_comments=dict(required=False, type="str"),
- dynamic_mapping_endip=dict(required=False, type="str"),
- dynamic_mapping_num_blocks_per_user=dict(required=False, type="int"),
- dynamic_mapping_pba_timeout=dict(required=False, type="int"),
- dynamic_mapping_permit_any_host=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_source_endip=dict(required=False, type="str"),
- dynamic_mapping_source_startip=dict(required=False, type="str"),
- dynamic_mapping_startip=dict(required=False, type="str"),
- dynamic_mapping_type=dict(required=False, type="str", choices=["overload",
- "one-to-one",
- "fixed-port-range",
- "port-block-allocation"]),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "type": module.params["type"],
- "startip": module.params["startip"],
- "source-startip": module.params["source_startip"],
- "source-endip": module.params["source_endip"],
- "permit-any-host": module.params["permit_any_host"],
- "pba-timeout": module.params["pba_timeout"],
- "num-blocks-per-user": module.params["num_blocks_per_user"],
- "name": module.params["name"],
- "endip": module.params["endip"],
- "comments": module.params["comments"],
- "block-size": module.params["block_size"],
- "associated-interface": module.params["associated_interface"],
- "arp-reply": module.params["arp_reply"],
- "arp-intf": module.params["arp_intf"],
- "dynamic_mapping": {
- "arp-intf": module.params["dynamic_mapping_arp_intf"],
- "arp-reply": module.params["dynamic_mapping_arp_reply"],
- "associated-interface": module.params["dynamic_mapping_associated_interface"],
- "block-size": module.params["dynamic_mapping_block_size"],
- "comments": module.params["dynamic_mapping_comments"],
- "endip": module.params["dynamic_mapping_endip"],
- "num-blocks-per-user": module.params["dynamic_mapping_num_blocks_per_user"],
- "pba-timeout": module.params["dynamic_mapping_pba_timeout"],
- "permit-any-host": module.params["dynamic_mapping_permit_any_host"],
- "source-endip": module.params["dynamic_mapping_source_endip"],
- "source-startip": module.params["dynamic_mapping_source_startip"],
- "startip": module.params["dynamic_mapping_startip"],
- "type": module.params["dynamic_mapping_type"],
- }
- }
-
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- list_overrides = ['dynamic_mapping']
- paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides,
- paramgram=paramgram, module=module)
- # UPDATE THE CHANGED PARAMGRAM
- module.paramgram = paramgram
-
- results = DEFAULT_RESULT_OBJ
- try:
- results = fmgr_fwobj_ippool_modify(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_fwobj_ippool6.py b/plugins/modules/network/fortimanager/fmgr_fwobj_ippool6.py
deleted file mode 100644
index 45d1f471a2..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_fwobj_ippool6.py
+++ /dev/null
@@ -1,227 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_fwobj_ippool6
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Allows the editing of IP Pool Objects within FortiManager.
-description:
- - Allows users to add/edit/delete IPv6 Pool Objects.
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- startip:
- description:
- - First IPv6 address (inclusive) in the range for the address pool.
- required: false
-
- name:
- description:
- - IPv6 IP pool name.
- required: false
-
- endip:
- description:
- - Final IPv6 address (inclusive) in the range for the address pool.
- required: false
-
- comments:
- description:
- - Comment.
- required: false
-
- dynamic_mapping:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- dynamic_mapping_comments:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
-
- dynamic_mapping_endip:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
-
- dynamic_mapping_startip:
- description:
- - Dynamic Mapping clone of original suffixed parameter.
- required: false
-
-
-'''
-
-EXAMPLES = '''
-- name: ADD FMGR_FIREWALL_IPPOOL6
- fmgr_firewall_ippool6:
- mode: "add"
- adom: "ansible"
- startip:
- name: "IPv6 IPPool"
- endip:
- comments: "Created by Ansible"
-
-- name: DELETE FMGR_FIREWALL_IPPOOL6
- fmgr_firewall_ippool6:
- mode: "delete"
- adom: "ansible"
- name: "IPv6 IPPool"
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-
-def fmgr_fwobj_ippool6_modify(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- mode = paramgram["mode"]
- adom = paramgram["adom"]
- # INIT A BASIC OBJECTS
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
-
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if mode in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/obj/firewall/ippool6'.format(adom=adom)
- datagram = scrub_dict(prepare_dict(paramgram))
-
- # EVAL THE MODE PARAMETER FOR DELETE
- elif mode == "delete":
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/firewall/ippool6/{name}'.format(adom=adom, name=paramgram["name"])
- datagram = {}
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def main():
- argument_spec = dict(
- adom=dict(type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
- startip=dict(required=False, type="str"),
- name=dict(required=False, type="str"),
- endip=dict(required=False, type="str"),
- comments=dict(required=False, type="str"),
- dynamic_mapping=dict(required=False, type="list"),
- dynamic_mapping_comments=dict(required=False, type="str"),
- dynamic_mapping_endip=dict(required=False, type="str"),
- dynamic_mapping_startip=dict(required=False, type="str"),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "startip": module.params["startip"],
- "name": module.params["name"],
- "endip": module.params["endip"],
- "comments": module.params["comments"],
- "dynamic_mapping": {
- "comments": module.params["dynamic_mapping_comments"],
- "endip": module.params["dynamic_mapping_endip"],
- "startip": module.params["dynamic_mapping_startip"],
- }
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- list_overrides = ['dynamic_mapping']
- paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides,
- paramgram=paramgram, module=module)
-
- results = DEFAULT_RESULT_OBJ
-
- try:
- results = fmgr_fwobj_ippool6_modify(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_fwobj_service.py b/plugins/modules/network/fortimanager/fmgr_fwobj_service.py
deleted file mode 100644
index 7ee1e62f8c..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_fwobj_service.py
+++ /dev/null
@@ -1,623 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- "metadata_version": "1.1",
- "status": ["preview"],
- "supported_by": "community"
-}
-
-DOCUMENTATION = '''
----
-module: fmgr_fwobj_service
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Manages FortiManager Firewall Service Objects.
-description:
- - Manages FortiManager Firewall Service Objects.
-
-options:
- adom:
- description:
- -The ADOM the configuration should belong to.
- required: false
- default: root
-
- app_category:
- description:
- - Application category ID.
- required: false
-
- app_service_type:
- description:
- - Application service type.
- required: false
-
- application:
- description:
- - Application ID.
- required: false
-
- category:
- description:
- - Service category.
- required: false
-
- check_reset_range:
- description:
- - Enable disable RST check.
- required: false
-
- color:
- description:
- - GUI icon color.
- required: false
- default: 22
-
- comment:
- description:
- - Comment.
- required: false
-
- custom_type:
- description:
- - Tells module what kind of custom service to be added.
- choices: ['tcp_udp_sctp', 'icmp', 'icmp6', 'ip', 'http', 'ftp', 'connect', 'socks_tcp', 'socks_udp', 'all']
- default: all
- required: false
-
- explicit_proxy:
- description:
- - Enable/disable explicit web proxy service.
- choices: ['enable', 'disable']
- default: 'disable'
- required: false
-
- fqdn:
- description:
- - Fully qualified domain name.
- required: false
- default: ""
-
- group_name:
- description:
- - Name of the Service Group.
- required: false
-
- group_member:
- description:
- - Comma-Seperated list of members' names.
- required: false
-
- icmp_code:
- description:
- - ICMP code.
- required: false
-
- icmp_type:
- description:
- - ICMP type.
- required: false
-
- iprange:
- description:
- - Start IP-End IP.
- required: false
- default: "0.0.0.0"
-
- name:
- description:
- - Custom service name.
- required: false
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- choices: ['add', 'set', 'delete']
- default: add
- required: false
-
- object_type:
- description:
- - Tells module if we are adding a custom service, category, or group.
- choices: ['custom', 'group', 'category']
- required: false
-
- protocol:
- description:
- - Protocol type.
- required: false
-
- protocol_number:
- description:
- - IP protocol number.
- required: false
-
- sctp_portrange:
- description:
- - Multiple SCTP port ranges. Comma separated list of destination ports to add (i.e. '443,80').
- - Syntax is
- - If no sourcePort is defined, it assumes all of them.
- - Ranges can be defined with a hyphen -
- - Examples -- '443' (destPort 443 only) '443:1000-2000' (destPort 443 from source ports 1000-2000).
- - String multiple together in same quotes, comma separated. ('443:1000-2000, 80:1000-2000').
- required: false
-
- session_ttl:
- description:
- - Session TTL (300 - 604800, 0 = default).
- required: false
- default: 0
-
- tcp_halfclose_timer:
- description:
- - TCP half close timeout (1 - 86400 sec, 0 = default).
- required: false
- default: 0
-
- tcp_halfopen_timer:
- description:
- - TCP half close timeout (1 - 86400 sec, 0 = default).
- required: false
- default: 0
-
- tcp_portrange:
- description:
- - Comma separated list of destination ports to add (i.e. '443,80').
- - Syntax is
- - If no sourcePort is defined, it assumes all of them.
- - Ranges can be defined with a hyphen -
- - Examples -- '443' (destPort 443 only) '443:1000-2000' (destPort 443 from source ports 1000-2000).
- - String multiple together in same quotes, comma separated. ('443:1000-2000, 80:1000-2000').
- required: false
-
- tcp_timewait_timer:
- description:
- - TCP half close timeout (1 - 300 sec, 0 = default).
- required: false
- default: 0
-
- udp_idle_timer:
- description:
- - TCP half close timeout (0 - 86400 sec, 0 = default).
- required: false
- default: 0
-
- udp_portrange:
- description:
- - Comma separated list of destination ports to add (i.e. '443,80').
- - Syntax is
- - If no sourcePort is defined, it assumes all of them.
- - Ranges can be defined with a hyphen -
- - Examples -- '443' (destPort 443 only) '443:1000-2000' (destPort 443 from source ports 1000-2000).
- - String multiple together in same quotes, comma separated. ('443:1000-2000, 80:1000-2000').
- required: false
-
- visibility:
- description:
- - Enable/disable service visibility.
- required: false
- choices: ["enable", "disable"]
- default: "enable"
-
-'''
-
-EXAMPLES = '''
-- name: ADD A CUSTOM SERVICE FOR TCP/UDP/SCP
- fmgr_fwobj_service:
- adom: "ansible"
- name: "ansible_custom_service"
- object_type: "custom"
- custom_type: "tcp_udp_sctp"
- tcp_portrange: "443"
- udp_portrange: "51"
- sctp_portrange: "100"
-
-- name: ADD A CUSTOM SERVICE FOR TCP/UDP/SCP WITH SOURCE RANGES AND MULTIPLES
- fmgr_fwobj_service:
- adom: "ansible"
- name: "ansible_custom_serviceWithSource"
- object_type: "custom"
- custom_type: "tcp_udp_sctp"
- tcp_portrange: "443:2000-1000,80-82:10000-20000"
- udp_portrange: "51:100-200,162:200-400"
- sctp_portrange: "100:2000-2500"
-
-- name: ADD A CUSTOM SERVICE FOR ICMP
- fmgr_fwobj_service:
- adom: "ansible"
- name: "ansible_custom_icmp"
- object_type: "custom"
- custom_type: "icmp"
- icmp_type: "8"
- icmp_code: "3"
-
-- name: ADD A CUSTOM SERVICE FOR ICMP6
- fmgr_fwobj_service:
- adom: "ansible"
- name: "ansible_custom_icmp6"
- object_type: "custom"
- custom_type: "icmp6"
- icmp_type: "5"
- icmp_code: "1"
-
-- name: ADD A CUSTOM SERVICE FOR IP - GRE
- fmgr_fwobj_service:
- adom: "ansible"
- name: "ansible_custom_icmp6"
- object_type: "custom"
- custom_type: "ip"
- protocol_number: "47"
-
-- name: ADD A CUSTOM PROXY FOR ALL WITH SOURCE RANGES AND MULTIPLES
- fmgr_fwobj_service:
- adom: "ansible"
- name: "ansible_custom_proxy_all"
- object_type: "custom"
- custom_type: "all"
- explicit_proxy: "enable"
- tcp_portrange: "443:2000-1000,80-82:10000-20000"
- iprange: "www.ansible.com"
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-
-def fmgr_fwobj_service_custom(fmgr, paramgram):
- """
- description:
- - the tcp and udp-portrange parameters are in a list when there are multiple. they are not in a list when they
- singular or by themselves (only 1 was listed)
- - the syntax for this is (destPort:sourcePort). Ranges are (xxxx-xxxx) i.e. 443:443, or 443:1000-2000.
- - if you leave out the second field after the colon (source port) it assumes any source port (which is usual)
- - multiples would look like ['443:1000-2000','80']
- - a single would look simple like "443:1000-2000" without the list around it ( a string!)
- - the protocol parameter is the protocol NUMBER, not the string of it.
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- response = DEFAULT_RESULT_OBJ
- if paramgram["mode"] in ['set', 'add']:
- # SET THE URL FOR ADD / SET
- url = '/pm/config/adom/{adom}/obj/firewall/service/custom'.format(adom=paramgram["adom"])
- # BUILD THE DEFAULT DATAGRAM
- datagram = {
- # ADVANCED OPTIONS
- "app-category": paramgram["app-category"],
- "app-service-type": paramgram["app-service-type"],
- "application": paramgram["application"],
- "category": paramgram["category"],
- "check-reset-range": paramgram["check-reset-range"],
- "color": paramgram["color"],
- "session-ttl": paramgram["session-ttl"],
- "tcp-halfclose-timer": paramgram["tcp-halfclose-timer"],
- "tcp-halfopen-timer": paramgram["tcp-halfopen-timer"],
- "tcp-timewait-timer": paramgram["tcp-timewait-timer"],
- "udp-idle-timer": paramgram["udp-idle-timer"],
- "visibility": paramgram["visibility"],
- "comment": paramgram["comment"],
- "proxy": paramgram["explicit-proxy"],
- "name": paramgram["name"]
- }
-
- if datagram["proxy"] == "disable":
- #######################################
- # object-type = "TCP/UDP/SCTP"
- #######################################
- if paramgram["custom_type"] == "tcp_udp_sctp":
- datagram["protocol"] = "TCP/UDP/SCTP"
- # PROCESS PORT RANGES TO PUT INTO THE PROPER SYNTAX
- if paramgram["tcp-portrange"] is not None:
- tcp_list = []
- for tcp in paramgram["tcp-portrange"].split(","):
- tcp = tcp.strip()
- tcp_list.append(tcp)
- datagram["tcp-portrange"] = tcp_list
-
- if paramgram["udp-portrange"] is not None:
- udp_list = []
- for udp in paramgram["udp-portrange"].split(","):
- udp = udp.strip()
- udp_list.append(udp)
- datagram["udp-portrange"] = udp_list
-
- if paramgram["sctp-portrange"] is not None:
- sctp_list = []
- for sctp in paramgram["sctp-portrange"].split(","):
- sctp = sctp.strip()
- sctp_list.append(sctp)
- datagram["sctp-portrange"] = sctp_list
-
- #######################################
- # object-type = "ICMP"
- #######################################
- if paramgram["custom_type"] == "icmp":
- datagram["icmpcode"] = paramgram["icmp_code"]
- datagram["icmptype"] = paramgram["icmp_type"]
- datagram["protocol"] = "ICMP"
-
- #######################################
- # object-type = "ICMP6"
- #######################################
- if paramgram["custom_type"] == "icmp6":
- datagram["icmpcode"] = paramgram["icmp_code"]
- datagram["icmptype"] = paramgram["icmp_type"]
- datagram["protocol"] = "ICMP6"
-
- #######################################
- # object-type = "IP"
- #######################################
- if paramgram["custom_type"] == "ip":
- datagram["protocol"] = "IP"
- datagram["protocol-number"] = paramgram["protocol-number"]
-
- #######################################
- # object-type in any of the explicit proxy options
- #######################################
- if datagram["proxy"] == "enable":
- datagram["protocol"] = paramgram["custom_type"].upper()
- datagram["iprange"] = paramgram["iprange"]
-
- # PROCESS PROXY TCP PORT RANGES TO PUT INTO THE PROPER SYNTAX
- if paramgram["tcp-portrange"] is not None:
- tcp_list = []
- for tcp in paramgram["tcp-portrange"].split(","):
- tcp = tcp.strip()
- tcp_list.append(tcp)
- datagram["tcp-portrange"] = tcp_list
-
- if paramgram["mode"] == "delete":
- datagram = {
- "name": paramgram["name"]
- }
- # SET DELETE URL
- url = '/pm/config/adom/{adom}/obj/firewall/service/custom' \
- '/{name}'.format(adom=paramgram["adom"], name=paramgram["name"])
-
- datagram = scrub_dict(datagram)
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def fmgr_fwobj_service_group(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- response = DEFAULT_RESULT_OBJ
- if paramgram["mode"] in ['set', 'add']:
- url = '/pm/config/adom/{adom}/obj/firewall/service/group'.format(adom=paramgram["adom"])
- datagram = {
- "name": paramgram["group-name"],
- "comment": paramgram["comment"],
- "proxy": paramgram["explicit-proxy"],
- "color": paramgram["color"]
- }
-
- members = paramgram["group-member"]
- member = []
- for obj in members.split(","):
- member.append(obj.strip())
- datagram["member"] = member
-
- if paramgram["mode"] == "delete":
- datagram = {
- "name": paramgram["name"]
- }
- # SET DELETE URL
- url = '/pm/config/adom/{adom}/obj/firewall/service/group' \
- '/{name}'.format(adom=paramgram["adom"], name=paramgram["group-name"])
-
- datagram = scrub_dict(datagram)
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def fmgr_fwobj_service_category(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- response = DEFAULT_RESULT_OBJ
- if paramgram["mode"] in ['set', 'add']:
- url = '/pm/config/adom/{adom}/obj/firewall/service/category'.format(adom=paramgram["adom"])
- # GET RID OF ANY WHITESPACE
- category = paramgram["category"]
- category = category.strip()
-
- datagram = {
- "name": paramgram["category"],
- "comment": "Created by Ansible"
- }
-
- # IF MODE = DELETE
- if paramgram["mode"] == "delete":
- datagram = {
- "name": paramgram["name"]
- }
- # SET DELETE URL
- url = '/pm/config/adom/{adom}/obj/firewall/service/category' \
- '/{name}'.format(adom=paramgram["adom"], name=paramgram["category"])
-
- datagram = scrub_dict(datagram)
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def main():
- argument_spec = dict(
- adom=dict(required=False, type="str", default="root"),
- mode=dict(required=False, type="str", choices=['add', 'set', 'delete'], default="add"),
- app_category=dict(required=False, type="str"),
- app_service_type=dict(required=False, type="str"),
- application=dict(required=False, type="str"),
- category=dict(required=False, type="str"),
- check_reset_range=dict(required=False, type="str"),
- color=dict(required=False, type="int", default=22),
- comment=dict(required=False, type="str"),
- custom_type=dict(required=False, type="str", choices=['tcp_udp_sctp', 'icmp', 'icmp6', 'ip', 'http', 'ftp',
- 'connect', 'socks_tcp', 'socks_udp', 'all'],
- default="all"),
- explicit_proxy=dict(required=False, type="str", choices=['enable', 'disable'], default="disable"),
- fqdn=dict(required=False, type="str", default=""),
- group_name=dict(required=False, type="str"),
- group_member=dict(required=False, type="str"),
- icmp_code=dict(required=False, type="int"),
- icmp_type=dict(required=False, type="int"),
- iprange=dict(required=False, type="str", default="0.0.0.0"),
- name=dict(required=False, type="str"),
- protocol=dict(required=False, type="str"),
- protocol_number=dict(required=False, type="int"),
- sctp_portrange=dict(required=False, type="str"),
- session_ttl=dict(required=False, type="int", default=0),
- object_type=dict(required=False, type="str", choices=['custom', 'group', 'category']),
- tcp_halfclose_timer=dict(required=False, type="int", default=0),
- tcp_halfopen_timer=dict(required=False, type="int", default=0),
- tcp_portrange=dict(required=False, type="str"),
- tcp_timewait_timer=dict(required=False, type="int", default=0),
- udp_idle_timer=dict(required=False, type="int", default=0),
- udp_portrange=dict(required=False, type="str"),
- visibility=dict(required=False, type="str", default="enable", choices=["enable", "disable"]),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE DATAGRAM
- paramgram = {
- "adom": module.params["adom"],
- "app-category": module.params["app_category"],
- "app-service-type": module.params["app_service_type"],
- "application": module.params["application"],
- "category": module.params["category"],
- "check-reset-range": module.params["check_reset_range"],
- "color": module.params["color"],
- "comment": module.params["comment"],
- "custom_type": module.params["custom_type"],
- "explicit-proxy": module.params["explicit_proxy"],
- "fqdn": module.params["fqdn"],
- "group-name": module.params["group_name"],
- "group-member": module.params["group_member"],
- "icmp_code": module.params["icmp_code"],
- "icmp_type": module.params["icmp_type"],
- "iprange": module.params["iprange"],
- "name": module.params["name"],
- "mode": module.params["mode"],
- "protocol": module.params["protocol"],
- "protocol-number": module.params["protocol_number"],
- "sctp-portrange": module.params["sctp_portrange"],
- "object_type": module.params["object_type"],
- "session-ttl": module.params["session_ttl"],
- "tcp-halfclose-timer": module.params["tcp_halfclose_timer"],
- "tcp-halfopen-timer": module.params["tcp_halfopen_timer"],
- "tcp-portrange": module.params["tcp_portrange"],
- "tcp-timewait-timer": module.params["tcp_timewait_timer"],
- "udp-idle-timer": module.params["udp_idle_timer"],
- "udp-portrange": module.params["udp_portrange"],
- "visibility": module.params["visibility"],
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- results = DEFAULT_RESULT_OBJ
-
- try:
- # CHECK FOR CATEGORIES TO ADD
- # THIS IS ONLY WHEN OBJECT_TYPE ISN'T SPECIFICALLY ADDING A CATEGORY!
- # WE NEED TO ADD THE CATEGORY BEFORE ADDING THE OBJECT
- # IF ANY category ARE DEFINED AND MODE IS ADD OR SET LETS ADD THOSE
- # THIS IS A "BLIND ADD" AND THE EXIT CODE FOR OBJECT ALREADY EXISTS IS TREATED AS A PASS
- if paramgram["category"] is not None and paramgram["mode"] in ['add', 'set'] \
- and paramgram["object_type"] != "category":
- category_add = fmgr_fwobj_service_category(fmgr, paramgram)
- fmgr.govern_response(module=module, results=category_add,
- ansible_facts=fmgr.construct_ansible_facts(category_add, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # IF OBJECT_TYPE IS CATEGORY...
- if paramgram["object_type"] == 'category':
- results = fmgr_fwobj_service_category(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0, -2, -3],
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # IF OBJECT_TYPE IS CUSTOM...
- if paramgram["object_type"] == 'custom':
- results = fmgr_fwobj_service_custom(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0, -2, -3],
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # IF OBJECT_TYPE IS GROUP...
- if paramgram["object_type"] == 'group':
- results = fmgr_fwobj_service_group(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, good_codes=[0, -2, -3],
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_fwobj_vip.py b/plugins/modules/network/fortimanager/fmgr_fwobj_vip.py
deleted file mode 100644
index a03b4e0b0f..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_fwobj_vip.py
+++ /dev/null
@@ -1,2428 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_fwobj_vip
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Manages Virtual IPs objects in FortiManager
-description:
- - Manages Virtual IP objects in FortiManager for IPv4
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- websphere_server:
- description:
- - Enable to add an HTTP header to indicate SSL offloading for a WebSphere server.
- - choice | disable | Do not add HTTP header indicating SSL offload for WebSphere server.
- - choice | enable | Add HTTP header indicating SSL offload for WebSphere server.
- required: false
- choices: ["disable", "enable"]
-
- weblogic_server:
- description:
- - Enable to add an HTTP header to indicate SSL offloading for a WebLogic server.
- - choice | disable | Do not add HTTP header indicating SSL offload for WebLogic server.
- - choice | enable | Add HTTP header indicating SSL offload for WebLogic server.
- required: false
- choices: ["disable", "enable"]
-
- type:
- description:
- - Configure a static NAT, load balance, server load balance, DNS translation, or FQDN VIP.
- - choice | static-nat | Static NAT.
- - choice | load-balance | Load balance.
- - choice | server-load-balance | Server load balance.
- - choice | dns-translation | DNS translation.
- - choice | fqdn | FQDN Translation
- required: false
- choices: ["static-nat", "load-balance", "server-load-balance", "dns-translation", "fqdn"]
-
- ssl_server_session_state_type:
- description:
- - How to expire SSL sessions for the segment of the SSL connection between the server and the FortiGate.
- - choice | disable | Do not keep session states.
- - choice | time | Expire session states after this many minutes.
- - choice | count | Expire session states when this maximum is reached.
- - choice | both | Expire session states based on time or count, whichever occurs first.
- required: false
- choices: ["disable", "time", "count", "both"]
-
- ssl_server_session_state_timeout:
- description:
- - Number of minutes to keep FortiGate to Server SSL session state.
- required: false
-
- ssl_server_session_state_max:
- description:
- - Maximum number of FortiGate to Server SSL session states to keep.
- required: false
-
- ssl_server_min_version:
- description:
- - Lowest SSL/TLS version acceptable from a server. Use the client setting by default.
- - choice | ssl-3.0 | SSL 3.0.
- - choice | tls-1.0 | TLS 1.0.
- - choice | tls-1.1 | TLS 1.1.
- - choice | tls-1.2 | TLS 1.2.
- - choice | client | Use same value as client configuration.
- required: false
- choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"]
-
- ssl_server_max_version:
- description:
- - Highest SSL/TLS version acceptable from a server. Use the client setting by default.
- - choice | ssl-3.0 | SSL 3.0.
- - choice | tls-1.0 | TLS 1.0.
- - choice | tls-1.1 | TLS 1.1.
- - choice | tls-1.2 | TLS 1.2.
- - choice | client | Use same value as client configuration.
- required: false
- choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"]
-
- ssl_server_algorithm:
- description:
- - Permitted encryption algorithms for the server side of SSL full mode sessions according to encryption strength
- - choice | high | High encryption. Allow only AES and ChaCha.
- - choice | low | Low encryption. Allow AES, ChaCha, 3DES, RC4, and DES.
- - choice | medium | Medium encryption. Allow AES, ChaCha, 3DES, and RC4.
- - choice | custom | Custom encryption. Use ssl-server-cipher-suites to select the cipher suites that are allowed.
- - choice | client | Use the same encryption algorithms for both client and server sessions.
- required: false
- choices: ["high", "low", "medium", "custom", "client"]
-
- ssl_send_empty_frags:
- description:
- - Enable/disable sending empty fragments to avoid CBC IV attacks (SSL 3.0 & TLS 1.0 only).
- - choice | disable | Do not send empty fragments.
- - choice | enable | Send empty fragments.
- required: false
- choices: ["disable", "enable"]
-
- ssl_pfs:
- description:
- - Select the cipher suites that can be used for SSL perfect forward secrecy (PFS).
- - choice | require | Allow only Diffie-Hellman cipher-suites, so PFS is applied.
- - choice | deny | Allow only non-Diffie-Hellman cipher-suites, so PFS is not applied.
- - choice | allow | Allow use of any cipher suite so PFS may or may not be used depending on the cipher suite
- required: false
- choices: ["require", "deny", "allow"]
-
- ssl_mode:
- description:
- - Apply SSL offloading mode
- - choice | half | Client to FortiGate SSL.
- - choice | full | Client to FortiGate and FortiGate to Server SSL.
- required: false
- choices: ["half", "full"]
-
- ssl_min_version:
- description:
- - Lowest SSL/TLS version acceptable from a client.
- - choice | ssl-3.0 | SSL 3.0.
- - choice | tls-1.0 | TLS 1.0.
- - choice | tls-1.1 | TLS 1.1.
- - choice | tls-1.2 | TLS 1.2.
- required: false
- choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]
-
- ssl_max_version:
- description:
- - Highest SSL/TLS version acceptable from a client.
- - choice | ssl-3.0 | SSL 3.0.
- - choice | tls-1.0 | TLS 1.0.
- - choice | tls-1.1 | TLS 1.1.
- - choice | tls-1.2 | TLS 1.2.
- required: false
- choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]
-
- ssl_http_match_host:
- description:
- - Enable/disable HTTP host matching for location conversion.
- - choice | disable | Do not match HTTP host.
- - choice | enable | Match HTTP host in response header.
- required: false
- choices: ["disable", "enable"]
-
- ssl_http_location_conversion:
- description:
- - Enable to replace HTTP with HTTPS in the reply's Location HTTP header field.
- - choice | disable | Disable HTTP location conversion.
- - choice | enable | Enable HTTP location conversion.
- required: false
- choices: ["disable", "enable"]
-
- ssl_hsts_include_subdomains:
- description:
- - Indicate that HSTS header applies to all subdomains.
- - choice | disable | HSTS header does not apply to subdomains.
- - choice | enable | HSTS header applies to subdomains.
- required: false
- choices: ["disable", "enable"]
-
- ssl_hsts_age:
- description:
- - Number of seconds the client should honour the HSTS setting.
- required: false
-
- ssl_hsts:
- description:
- - Enable/disable including HSTS header in response.
- - choice | disable | Do not add a HSTS header to each a HTTP response.
- - choice | enable | Add a HSTS header to each HTTP response.
- required: false
- choices: ["disable", "enable"]
-
- ssl_hpkp_report_uri:
- description:
- - URL to report HPKP violations to.
- required: false
-
- ssl_hpkp_primary:
- description:
- - Certificate to generate primary HPKP pin from.
- required: false
-
- ssl_hpkp_include_subdomains:
- description:
- - Indicate that HPKP header applies to all subdomains.
- - choice | disable | HPKP header does not apply to subdomains.
- - choice | enable | HPKP header applies to subdomains.
- required: false
- choices: ["disable", "enable"]
-
- ssl_hpkp_backup:
- description:
- - Certificate to generate backup HPKP pin from.
- required: false
-
- ssl_hpkp_age:
- description:
- - Number of seconds the client should honour the HPKP setting.
- required: false
-
- ssl_hpkp:
- description:
- - Enable/disable including HPKP header in response.
- - choice | disable | Do not add a HPKP header to each HTTP response.
- - choice | enable | Add a HPKP header to each a HTTP response.
- - choice | report-only | Add a HPKP Report-Only header to each HTTP response.
- required: false
- choices: ["disable", "enable", "report-only"]
-
- ssl_dh_bits:
- description:
- - Number of bits to use in the Diffie-Hellman exchange for RSA encryption of SSL sessions.
- - choice | 768 | 768-bit Diffie-Hellman prime.
- - choice | 1024 | 1024-bit Diffie-Hellman prime.
- - choice | 1536 | 1536-bit Diffie-Hellman prime.
- - choice | 2048 | 2048-bit Diffie-Hellman prime.
- - choice | 3072 | 3072-bit Diffie-Hellman prime.
- - choice | 4096 | 4096-bit Diffie-Hellman prime.
- required: false
- choices: ["768", "1024", "1536", "2048", "3072", "4096"]
-
- ssl_client_session_state_type:
- description:
- - How to expire SSL sessions for the segment of the SSL connection between the client and the FortiGate.
- - choice | disable | Do not keep session states.
- - choice | time | Expire session states after this many minutes.
- - choice | count | Expire session states when this maximum is reached.
- - choice | both | Expire session states based on time or count, whichever occurs first.
- required: false
- choices: ["disable", "time", "count", "both"]
-
- ssl_client_session_state_timeout:
- description:
- - Number of minutes to keep client to FortiGate SSL session state.
- required: false
-
- ssl_client_session_state_max:
- description:
- - Maximum number of client to FortiGate SSL session states to keep.
- required: false
-
- ssl_client_renegotiation:
- description:
- - Allow, deny, or require secure renegotiation of client sessions to comply with RFC 5746.
- - choice | deny | Abort any client initiated SSL re-negotiation attempt.
- - choice | allow | Allow a SSL client to renegotiate.
- - choice | secure | Abort any client initiated SSL re-negotiation attempt that does not use RFC 5746.
- required: false
- choices: ["deny", "allow", "secure"]
-
- ssl_client_fallback:
- description:
- - Enable/disable support for preventing Downgrade Attacks on client connections (RFC 7507).
- - choice | disable | Disable.
- - choice | enable | Enable.
- required: false
- choices: ["disable", "enable"]
-
- ssl_certificate:
- description:
- - The name of the SSL certificate to use for SSL acceleration.
- required: false
-
- ssl_algorithm:
- description:
- - Permitted encryption algorithms for SSL sessions according to encryption strength.
- - choice | high | High encryption. Allow only AES and ChaCha.
- - choice | medium | Medium encryption. Allow AES, ChaCha, 3DES, and RC4.
- - choice | low | Low encryption. Allow AES, ChaCha, 3DES, RC4, and DES.
- - choice | custom | Custom encryption. Use config ssl-cipher-suites to select the cipher suites that are allowed.
- required: false
- choices: ["high", "medium", "low", "custom"]
-
- srcintf_filter:
- description:
- - Interfaces to which the VIP applies. Separate the names with spaces.
- required: false
-
- src_filter:
- description:
- - Source address filter. Each address must be either an IP/subnet (x.x.x.x/n) or a range (x.x.x.x-y.y.y.y).
- - Separate addresses with spaces.
- required: false
-
- service:
- description:
- - Service name.
- required: false
-
- server_type:
- description:
- - Protocol to be load balanced by the virtual server (also called the server load balance virtual IP).
- - choice | http | HTTP
- - choice | https | HTTPS
- - choice | ssl | SSL
- - choice | tcp | TCP
- - choice | udp | UDP
- - choice | ip | IP
- - choice | imaps | IMAPS
- - choice | pop3s | POP3S
- - choice | smtps | SMTPS
- required: false
- choices: ["http", "https", "ssl", "tcp", "udp", "ip", "imaps", "pop3s", "smtps"]
-
- protocol:
- description:
- - Protocol to use when forwarding packets.
- - choice | tcp | TCP.
- - choice | udp | UDP.
- - choice | sctp | SCTP.
- - choice | icmp | ICMP.
- required: false
- choices: ["tcp", "udp", "sctp", "icmp"]
-
- portmapping_type:
- description:
- - Port mapping type.
- - choice | 1-to-1 | One to one.
- - choice | m-to-n | Many to many.
- required: false
- choices: ["1-to-1", "m-to-n"]
-
- portforward:
- description:
- - Enable/disable port forwarding.
- - choice | disable | Disable port forward.
- - choice | enable | Enable port forward.
- required: false
- choices: ["disable", "enable"]
-
- persistence:
- description:
- - Configure how to make sure that clients connect to the same server every time they make a request that is part
- - of the same session.
- - choice | none | None.
- - choice | http-cookie | HTTP cookie.
- - choice | ssl-session-id | SSL session ID.
- required: false
- choices: ["none", "http-cookie", "ssl-session-id"]
-
- outlook_web_access:
- description:
- - Enable to add the Front-End-Https header for Microsoft Outlook Web Access.
- - choice | disable | Disable Outlook Web Access support.
- - choice | enable | Enable Outlook Web Access support.
- required: false
- choices: ["disable", "enable"]
-
- nat_source_vip:
- description:
- - Enable to prevent unintended servers from using a virtual IP.
- - Disable to use the actual IP address of the server as the source address.
- - choice | disable | Do not force to NAT as VIP.
- - choice | enable | Force to NAT as VIP.
- required: false
- choices: ["disable", "enable"]
-
- name:
- description:
- - Virtual IP name.
- required: false
-
- monitor:
- description:
- - Name of the health check monitor to use when polling to determine a virtual server's connectivity status.
- required: false
-
- max_embryonic_connections:
- description:
- - Maximum number of incomplete connections.
- required: false
-
- mappedport:
- description:
- - Port number range on the destination network to which the external port number range is mapped.
- required: false
-
- mappedip:
- description:
- - IP address or address range on the destination network to which the external IP address is mapped.
- required: false
-
- mapped_addr:
- description:
- - Mapped FQDN address name.
- required: false
-
- ldb_method:
- description:
- - Method used to distribute sessions to real servers.
- - choice | static | Distribute to server based on source IP.
- - choice | round-robin | Distribute to server based round robin order.
- - choice | weighted | Distribute to server based on weight.
- - choice | least-session | Distribute to server with lowest session count.
- - choice | least-rtt | Distribute to server with lowest Round-Trip-Time.
- - choice | first-alive | Distribute to the first server that is alive.
- - choice | http-host | Distribute to server based on host field in HTTP header.
- required: false
- choices: ["static", "round-robin", "weighted", "least-session", "least-rtt", "first-alive", "http-host"]
-
- https_cookie_secure:
- description:
- - Enable/disable verification that inserted HTTPS cookies are secure.
- - choice | disable | Do not mark cookie as secure, allow sharing between an HTTP and HTTPS connection.
- - choice | enable | Mark inserted cookie as secure, cookie can only be used for HTTPS a connection.
- required: false
- choices: ["disable", "enable"]
-
- http_multiplex:
- description:
- - Enable/disable HTTP multiplexing.
- - choice | disable | Disable HTTP session multiplexing.
- - choice | enable | Enable HTTP session multiplexing.
- required: false
- choices: ["disable", "enable"]
-
- http_ip_header_name:
- description:
- - For HTTP multiplexing, enter a custom HTTPS header name. The orig client IP address is added to this header.
- - If empty, X-Forwarded-For is used.
- required: false
-
- http_ip_header:
- description:
- - For HTTP multiplexing, enable to add the original client IP address in the XForwarded-For HTTP header.
- - choice | disable | Disable adding HTTP header.
- - choice | enable | Enable adding HTTP header.
- required: false
- choices: ["disable", "enable"]
-
- http_cookie_share:
- description:
- - Control sharing of cookies across virtual servers. same-ip means a cookie from one virtual server can be used
- - by another. Disable stops cookie sharing.
- - choice | disable | Only allow HTTP cookie to match this virtual server.
- - choice | same-ip | Allow HTTP cookie to match any virtual server with same IP.
- required: false
- choices: ["disable", "same-ip"]
-
- http_cookie_path:
- description:
- - Limit HTTP cookie persistence to the specified path.
- required: false
-
- http_cookie_generation:
- description:
- - Generation of HTTP cookie to be accepted. Changing invalidates all existing cookies.
- required: false
-
- http_cookie_domain_from_host:
- description:
- - Enable/disable use of HTTP cookie domain from host field in HTTP.
- - choice | disable | Disable use of HTTP cookie domain from host field in HTTP (use http-cooke-domain setting).
- - choice | enable | Enable use of HTTP cookie domain from host field in HTTP.
- required: false
- choices: ["disable", "enable"]
-
- http_cookie_domain:
- description:
- - Domain that HTTP cookie persistence should apply to.
- required: false
-
- http_cookie_age:
- description:
- - Time in minutes that client web browsers should keep a cookie. Default is 60 seconds. 0 = no time limit.
- required: false
-
- gratuitous_arp_interval:
- description:
- - Enable to have the VIP send gratuitous ARPs. 0=disabled. Set from 5 up to 8640000 seconds to enable.
- required: false
-
- extport:
- description:
- - Incoming port number range that you want to map to a port number range on the destination network.
- required: false
-
- extip:
- description:
- - IP address or address range on the external interface that you want to map to an address or address range on t
- - he destination network.
- required: false
-
- extintf:
- description:
- - Interface connected to the source network that receives the packets that will be forwarded to the destination
- - network.
- required: false
-
- extaddr:
- description:
- - External FQDN address name.
- required: false
-
- dns_mapping_ttl:
- description:
- - DNS mapping TTL (Set to zero to use TTL in DNS response, default = 0).
- required: false
-
- comment:
- description:
- - Comment.
- required: false
-
- color:
- description:
- - Color of icon on the GUI.
- required: false
-
- arp_reply:
- description:
- - Enable to respond to ARP requests for this virtual IP address. Enabled by default.
- - choice | disable | Disable ARP reply.
- - choice | enable | Enable ARP reply.
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- dynamic_mapping_arp_reply:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_color:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_comment:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_dns_mapping_ttl:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_extaddr:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_extintf:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_extip:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_extport:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_gratuitous_arp_interval:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_http_cookie_age:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_http_cookie_domain:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_http_cookie_domain_from_host:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_http_cookie_generation:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_http_cookie_path:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_http_cookie_share:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | same-ip |
- required: false
- choices: ["disable", "same-ip"]
-
- dynamic_mapping_http_ip_header:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_http_ip_header_name:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_http_multiplex:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_https_cookie_secure:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_ldb_method:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | static |
- - choice | round-robin |
- - choice | weighted |
- - choice | least-session |
- - choice | least-rtt |
- - choice | first-alive |
- - choice | http-host |
- required: false
- choices: ["static", "round-robin", "weighted", "least-session", "least-rtt", "first-alive", "http-host"]
-
- dynamic_mapping_mapped_addr:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_mappedip:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_mappedport:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_max_embryonic_connections:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_monitor:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_nat_source_vip:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_outlook_web_access:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_persistence:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | none |
- - choice | http-cookie |
- - choice | ssl-session-id |
- required: false
- choices: ["none", "http-cookie", "ssl-session-id"]
-
- dynamic_mapping_portforward:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_portmapping_type:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | 1-to-1 |
- - choice | m-to-n |
- required: false
- choices: ["1-to-1", "m-to-n"]
-
- dynamic_mapping_protocol:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | tcp |
- - choice | udp |
- - choice | sctp |
- - choice | icmp |
- required: false
- choices: ["tcp", "udp", "sctp", "icmp"]
-
- dynamic_mapping_server_type:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | http |
- - choice | https |
- - choice | ssl |
- - choice | tcp |
- - choice | udp |
- - choice | ip |
- - choice | imaps |
- - choice | pop3s |
- - choice | smtps |
- required: false
- choices: ["http", "https", "ssl", "tcp", "udp", "ip", "imaps", "pop3s", "smtps"]
-
- dynamic_mapping_service:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_src_filter:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_srcintf_filter:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_ssl_algorithm:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | high |
- - choice | medium |
- - choice | low |
- - choice | custom |
- required: false
- choices: ["high", "medium", "low", "custom"]
-
- dynamic_mapping_ssl_certificate:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_ssl_client_fallback:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_ssl_client_renegotiation:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | deny |
- - choice | allow |
- - choice | secure |
- required: false
- choices: ["deny", "allow", "secure"]
-
- dynamic_mapping_ssl_client_session_state_max:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_ssl_client_session_state_timeout:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_ssl_client_session_state_type:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | time |
- - choice | count |
- - choice | both |
- required: false
- choices: ["disable", "time", "count", "both"]
-
- dynamic_mapping_ssl_dh_bits:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | 768 |
- - choice | 1024 |
- - choice | 1536 |
- - choice | 2048 |
- - choice | 3072 |
- - choice | 4096 |
- required: false
- choices: ["768", "1024", "1536", "2048", "3072", "4096"]
-
- dynamic_mapping_ssl_hpkp:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- - choice | report-only |
- required: false
- choices: ["disable", "enable", "report-only"]
-
- dynamic_mapping_ssl_hpkp_age:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_ssl_hpkp_backup:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_ssl_hpkp_include_subdomains:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_ssl_hpkp_primary:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_ssl_hpkp_report_uri:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_ssl_hsts:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_ssl_hsts_age:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_ssl_hsts_include_subdomains:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_ssl_http_location_conversion:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_ssl_http_match_host:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_ssl_max_version:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | ssl-3.0 |
- - choice | tls-1.0 |
- - choice | tls-1.1 |
- - choice | tls-1.2 |
- required: false
- choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]
-
- dynamic_mapping_ssl_min_version:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | ssl-3.0 |
- - choice | tls-1.0 |
- - choice | tls-1.1 |
- - choice | tls-1.2 |
- required: false
- choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]
-
- dynamic_mapping_ssl_mode:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | half |
- - choice | full |
- required: false
- choices: ["half", "full"]
-
- dynamic_mapping_ssl_pfs:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | require |
- - choice | deny |
- - choice | allow |
- required: false
- choices: ["require", "deny", "allow"]
-
- dynamic_mapping_ssl_send_empty_frags:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_ssl_server_algorithm:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | high |
- - choice | low |
- - choice | medium |
- - choice | custom |
- - choice | client |
- required: false
- choices: ["high", "low", "medium", "custom", "client"]
-
- dynamic_mapping_ssl_server_max_version:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | ssl-3.0 |
- - choice | tls-1.0 |
- - choice | tls-1.1 |
- - choice | tls-1.2 |
- - choice | client |
- required: false
- choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"]
-
- dynamic_mapping_ssl_server_min_version:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | ssl-3.0 |
- - choice | tls-1.0 |
- - choice | tls-1.1 |
- - choice | tls-1.2 |
- - choice | client |
- required: false
- choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"]
-
- dynamic_mapping_ssl_server_session_state_max:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_ssl_server_session_state_timeout:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_ssl_server_session_state_type:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | time |
- - choice | count |
- - choice | both |
- required: false
- choices: ["disable", "time", "count", "both"]
-
- dynamic_mapping_type:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | static-nat |
- - choice | load-balance |
- - choice | server-load-balance |
- - choice | dns-translation |
- - choice | fqdn |
- required: false
- choices: ["static-nat", "load-balance", "server-load-balance", "dns-translation", "fqdn"]
-
- dynamic_mapping_weblogic_server:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_websphere_server:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- required: false
- choices: ["disable", "enable"]
-
- dynamic_mapping_realservers_client_ip:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_realservers_healthcheck:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | disable |
- - choice | enable |
- - choice | vip |
- required: false
- choices: ["disable", "enable", "vip"]
-
- dynamic_mapping_realservers_holddown_interval:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_realservers_http_host:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_realservers_ip:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_realservers_max_connections:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_realservers_monitor:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_realservers_port:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_realservers_seq:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_realservers_status:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | active |
- - choice | standby |
- - choice | disable |
- required: false
- choices: ["active", "standby", "disable"]
-
- dynamic_mapping_realservers_weight:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- required: false
-
- dynamic_mapping_ssl_cipher_suites_cipher:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - choice | TLS-RSA-WITH-RC4-128-MD5 |
- - choice | TLS-RSA-WITH-RC4-128-SHA |
- - choice | TLS-RSA-WITH-DES-CBC-SHA |
- - choice | TLS-RSA-WITH-3DES-EDE-CBC-SHA |
- - choice | TLS-RSA-WITH-AES-128-CBC-SHA |
- - choice | TLS-RSA-WITH-AES-256-CBC-SHA |
- - choice | TLS-RSA-WITH-AES-128-CBC-SHA256 |
- - choice | TLS-RSA-WITH-AES-256-CBC-SHA256 |
- - choice | TLS-RSA-WITH-CAMELLIA-128-CBC-SHA |
- - choice | TLS-RSA-WITH-CAMELLIA-256-CBC-SHA |
- - choice | TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256 |
- - choice | TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256 |
- - choice | TLS-RSA-WITH-SEED-CBC-SHA |
- - choice | TLS-RSA-WITH-ARIA-128-CBC-SHA256 |
- - choice | TLS-RSA-WITH-ARIA-256-CBC-SHA384 |
- - choice | TLS-DHE-RSA-WITH-DES-CBC-SHA |
- - choice | TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA |
- - choice | TLS-DHE-RSA-WITH-AES-128-CBC-SHA |
- - choice | TLS-DHE-RSA-WITH-AES-256-CBC-SHA |
- - choice | TLS-DHE-RSA-WITH-AES-128-CBC-SHA256 |
- - choice | TLS-DHE-RSA-WITH-AES-256-CBC-SHA256 |
- - choice | TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA |
- - choice | TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA |
- - choice | TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256 |
- - choice | TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256 |
- - choice | TLS-DHE-RSA-WITH-SEED-CBC-SHA |
- - choice | TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256 |
- - choice | TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384 |
- - choice | TLS-ECDHE-RSA-WITH-RC4-128-SHA |
- - choice | TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA |
- - choice | TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA |
- - choice | TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA |
- - choice | TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256 |
- - choice | TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256 |
- - choice | TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256 |
- - choice | TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 |
- - choice | TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 |
- - choice | TLS-DHE-DSS-WITH-AES-128-CBC-SHA |
- - choice | TLS-DHE-DSS-WITH-AES-256-CBC-SHA |
- - choice | TLS-DHE-DSS-WITH-AES-128-CBC-SHA256 |
- - choice | TLS-DHE-DSS-WITH-AES-128-GCM-SHA256 |
- - choice | TLS-DHE-DSS-WITH-AES-256-CBC-SHA256 |
- - choice | TLS-DHE-DSS-WITH-AES-256-GCM-SHA384 |
- - choice | TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256 |
- - choice | TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256 |
- - choice | TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384 |
- - choice | TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384 |
- - choice | TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA |
- - choice | TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256 |
- - choice | TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 |
- - choice | TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384 |
- - choice | TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384 |
- - choice | TLS-RSA-WITH-AES-128-GCM-SHA256 |
- - choice | TLS-RSA-WITH-AES-256-GCM-SHA384 |
- - choice | TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA |
- - choice | TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA |
- - choice | TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256 |
- - choice | TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256 |
- - choice | TLS-DHE-DSS-WITH-SEED-CBC-SHA |
- - choice | TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256 |
- - choice | TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384 |
- - choice | TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256 |
- - choice | TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384 |
- - choice | TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256 |
- - choice | TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384 |
- - choice | TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA |
- - choice | TLS-DHE-DSS-WITH-DES-CBC-SHA |
- required: false
- choices: ["TLS-RSA-WITH-RC4-128-MD5",
- "TLS-RSA-WITH-RC4-128-SHA",
- "TLS-RSA-WITH-DES-CBC-SHA",
- "TLS-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-RSA-WITH-AES-128-CBC-SHA",
- "TLS-RSA-WITH-AES-256-CBC-SHA",
- "TLS-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-RSA-WITH-AES-256-CBC-SHA256",
- "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-RSA-WITH-SEED-CBC-SHA",
- "TLS-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-DHE-RSA-WITH-DES-CBC-SHA",
- "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-128-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-256-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256",
- "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-DHE-RSA-WITH-SEED-CBC-SHA",
- "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-RC4-128-SHA",
- "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-DHE-DSS-WITH-AES-128-CBC-SHA",
- "TLS-DHE-DSS-WITH-AES-256-CBC-SHA",
- "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256",
- "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256",
- "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384",
- "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA",
- "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256",
- "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256",
- "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384",
- "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384",
- "TLS-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-DHE-DSS-WITH-SEED-CBC-SHA",
- "TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA",
- "TLS-DHE-DSS-WITH-DES-CBC-SHA"]
-
- dynamic_mapping_ssl_cipher_suites_versions:
- description:
- - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent.
- - FLAG Based Options. Specify multiple in list form.
- - flag | ssl-3.0 |
- - flag | tls-1.0 |
- - flag | tls-1.1 |
- - flag | tls-1.2 |
- required: false
- choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]
-
- realservers:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- realservers_client_ip:
- description:
- - Only clients in this IP range can connect to this real server.
- required: false
-
- realservers_healthcheck:
- description:
- - Enable to check the responsiveness of the real server before forwarding traffic.
- - choice | disable | Disable per server health check.
- - choice | enable | Enable per server health check.
- - choice | vip | Use health check defined in VIP.
- required: false
- choices: ["disable", "enable", "vip"]
-
- realservers_holddown_interval:
- description:
- - Time in seconds that the health check monitor monitors an unresponsive server that should be active.
- required: false
-
- realservers_http_host:
- description:
- - HTTP server domain name in HTTP header.
- required: false
-
- realservers_ip:
- description:
- - IP address of the real server.
- required: false
-
- realservers_max_connections:
- description:
- - Max number of active connections that can be directed to the real server. When reached, sessions are sent to
- - their real servers.
- required: false
-
- realservers_monitor:
- description:
- - Name of the health check monitor to use when polling to determine a virtual server's connectivity status.
- required: false
-
- realservers_port:
- description:
- - Port for communicating with the real server. Required if port forwarding is enabled.
- required: false
-
- realservers_seq:
- description:
- - Real Server Sequence Number
- required: false
-
- realservers_status:
- description:
- - Set the status of the real server to active so that it can accept traffic.
- - Or on standby or disabled so no traffic is sent.
- - choice | active | Server status active.
- - choice | standby | Server status standby.
- - choice | disable | Server status disable.
- required: false
- choices: ["active", "standby", "disable"]
-
- realservers_weight:
- description:
- - Weight of the real server. If weighted load balancing is enabled, the server with the highest weight gets more
- - connections.
- required: false
-
- ssl_cipher_suites:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- ssl_cipher_suites_cipher:
- description:
- - Cipher suite name.
- - choice | TLS-RSA-WITH-RC4-128-MD5 | Cipher suite TLS-RSA-WITH-RC4-128-MD5.
- - choice | TLS-RSA-WITH-RC4-128-SHA | Cipher suite TLS-RSA-WITH-RC4-128-SHA.
- - choice | TLS-RSA-WITH-DES-CBC-SHA | Cipher suite TLS-RSA-WITH-DES-CBC-SHA.
- - choice | TLS-RSA-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-RSA-WITH-3DES-EDE-CBC-SHA.
- - choice | TLS-RSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-RSA-WITH-AES-128-CBC-SHA.
- - choice | TLS-RSA-WITH-AES-256-CBC-SHA | Cipher suite TLS-RSA-WITH-AES-256-CBC-SHA.
- - choice | TLS-RSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-RSA-WITH-AES-128-CBC-SHA256.
- - choice | TLS-RSA-WITH-AES-256-CBC-SHA256 | Cipher suite TLS-RSA-WITH-AES-256-CBC-SHA256.
- - choice | TLS-RSA-WITH-CAMELLIA-128-CBC-SHA | Cipher suite TLS-RSA-WITH-CAMELLIA-128-CBC-SHA.
- - choice | TLS-RSA-WITH-CAMELLIA-256-CBC-SHA | Cipher suite TLS-RSA-WITH-CAMELLIA-256-CBC-SHA.
- - choice | TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256 | Cipher suite TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256.
- - choice | TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256 | Cipher suite TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256.
- - choice | TLS-RSA-WITH-SEED-CBC-SHA | Cipher suite TLS-RSA-WITH-SEED-CBC-SHA.
- - choice | TLS-RSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-RSA-WITH-ARIA-128-CBC-SHA256.
- - choice | TLS-RSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-RSA-WITH-ARIA-256-CBC-SHA384.
- - choice | TLS-DHE-RSA-WITH-DES-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-DES-CBC-SHA.
- - choice | TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA.
- - choice | TLS-DHE-RSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-AES-128-CBC-SHA.
- - choice | TLS-DHE-RSA-WITH-AES-256-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-AES-256-CBC-SHA.
- - choice | TLS-DHE-RSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-AES-128-CBC-SHA256.
- - choice | TLS-DHE-RSA-WITH-AES-256-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-AES-256-CBC-SHA256.
- - choice | TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA.
- - choice | TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA.
- - choice | TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256.
- - choice | TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256.
- - choice | TLS-DHE-RSA-WITH-SEED-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-SEED-CBC-SHA.
- - choice | TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256.
- - choice | TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384.
- - choice | TLS-ECDHE-RSA-WITH-RC4-128-SHA | Cipher suite TLS-ECDHE-RSA-WITH-RC4-128-SHA.
- - choice | TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA.
- - choice | TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA.
- - choice | TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA | Cipher suite TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA.
- - choice | TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256.
- - choice | TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256 | Cipher suite TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256.
- - choice | TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256 | Cipher suite TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256.
- - choice | TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-DHE-RSA-WITH-AES-128-GCM-SHA256.
- - choice | TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-DHE-RSA-WITH-AES-256-GCM-SHA384.
- - choice | TLS-DHE-DSS-WITH-AES-128-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-AES-128-CBC-SHA.
- - choice | TLS-DHE-DSS-WITH-AES-256-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-AES-256-CBC-SHA.
- - choice | TLS-DHE-DSS-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-AES-128-CBC-SHA256.
- - choice | TLS-DHE-DSS-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-DHE-DSS-WITH-AES-128-GCM-SHA256.
- - choice | TLS-DHE-DSS-WITH-AES-256-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-AES-256-CBC-SHA256.
- - choice | TLS-DHE-DSS-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-DHE-DSS-WITH-AES-256-GCM-SHA384.
- - choice | TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256.
- - choice | TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256.
- - choice | TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384 | Cipher suite TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384.
- - choice | TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384.
- - choice | TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA.
- - choice | TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256.
- - choice | TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256.
- - choice | TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384.
- - choice | TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384.
- - choice | TLS-RSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-RSA-WITH-AES-128-GCM-SHA256.
- - choice | TLS-RSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-RSA-WITH-AES-256-GCM-SHA384.
- - choice | TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA | Cipher suite TLS-DSS-RSA-WITH-CAMELLIA-128-CBC-SHA.
- - choice | TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA.
- - choice | TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256.
- - choice | TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256.
- - choice | TLS-DHE-DSS-WITH-SEED-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-SEED-CBC-SHA.
- - choice | TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256.
- - choice | TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384.
- - choice | TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256.
- - choice | TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384.
- - choice | TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC_SHA256.
- - choice | TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC_SHA384.
- - choice | TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA.
- - choice | TLS-DHE-DSS-WITH-DES-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-DES-CBC-SHA.
- required: false
- choices: ["TLS-RSA-WITH-RC4-128-MD5",
- "TLS-RSA-WITH-RC4-128-SHA",
- "TLS-RSA-WITH-DES-CBC-SHA",
- "TLS-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-RSA-WITH-AES-128-CBC-SHA",
- "TLS-RSA-WITH-AES-256-CBC-SHA",
- "TLS-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-RSA-WITH-AES-256-CBC-SHA256",
- "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-RSA-WITH-SEED-CBC-SHA",
- "TLS-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-DHE-RSA-WITH-DES-CBC-SHA",
- "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-128-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-256-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256",
- "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-DHE-RSA-WITH-SEED-CBC-SHA",
- "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-RC4-128-SHA",
- "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-DHE-DSS-WITH-AES-128-CBC-SHA",
- "TLS-DHE-DSS-WITH-AES-256-CBC-SHA",
- "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256",
- "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256",
- "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384",
- "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA",
- "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256",
- "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256",
- "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384",
- "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384",
- "TLS-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-DHE-DSS-WITH-SEED-CBC-SHA",
- "TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA",
- "TLS-DHE-DSS-WITH-DES-CBC-SHA"]
-
- ssl_cipher_suites_versions:
- description:
- - SSL/TLS versions that the cipher suite can be used with.
- - FLAG Based Options. Specify multiple in list form.
- - flag | ssl-3.0 | SSL 3.0.
- - flag | tls-1.0 | TLS 1.0.
- - flag | tls-1.1 | TLS 1.1.
- - flag | tls-1.2 | TLS 1.2.
- required: false
- choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]
-
- ssl_server_cipher_suites:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- ssl_server_cipher_suites_cipher:
- description:
- - Cipher suite name.
- - choice | TLS-RSA-WITH-RC4-128-MD5 | Cipher suite TLS-RSA-WITH-RC4-128-MD5.
- - choice | TLS-RSA-WITH-RC4-128-SHA | Cipher suite TLS-RSA-WITH-RC4-128-SHA.
- - choice | TLS-RSA-WITH-DES-CBC-SHA | Cipher suite TLS-RSA-WITH-DES-CBC-SHA.
- - choice | TLS-RSA-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-RSA-WITH-3DES-EDE-CBC-SHA.
- - choice | TLS-RSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-RSA-WITH-AES-128-CBC-SHA.
- - choice | TLS-RSA-WITH-AES-256-CBC-SHA | Cipher suite TLS-RSA-WITH-AES-256-CBC-SHA.
- - choice | TLS-RSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-RSA-WITH-AES-128-CBC-SHA256.
- - choice | TLS-RSA-WITH-AES-256-CBC-SHA256 | Cipher suite TLS-RSA-WITH-AES-256-CBC-SHA256.
- - choice | TLS-RSA-WITH-CAMELLIA-128-CBC-SHA | Cipher suite TLS-RSA-WITH-CAMELLIA-128-CBC-SHA.
- - choice | TLS-RSA-WITH-CAMELLIA-256-CBC-SHA | Cipher suite TLS-RSA-WITH-CAMELLIA-256-CBC-SHA.
- - choice | TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256 | Cipher suite TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256.
- - choice | TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256 | Cipher suite TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256.
- - choice | TLS-RSA-WITH-SEED-CBC-SHA | Cipher suite TLS-RSA-WITH-SEED-CBC-SHA.
- - choice | TLS-RSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-RSA-WITH-ARIA-128-CBC-SHA256.
- - choice | TLS-RSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-RSA-WITH-ARIA-256-CBC-SHA384.
- - choice | TLS-DHE-RSA-WITH-DES-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-DES-CBC-SHA.
- - choice | TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA.
- - choice | TLS-DHE-RSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-AES-128-CBC-SHA.
- - choice | TLS-DHE-RSA-WITH-AES-256-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-AES-256-CBC-SHA.
- - choice | TLS-DHE-RSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-AES-128-CBC-SHA256.
- - choice | TLS-DHE-RSA-WITH-AES-256-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-AES-256-CBC-SHA256.
- - choice | TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA.
- - choice | TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA.
- - choice | TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256.
- - choice | TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256.
- - choice | TLS-DHE-RSA-WITH-SEED-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-SEED-CBC-SHA.
- - choice | TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256.
- - choice | TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384.
- - choice | TLS-ECDHE-RSA-WITH-RC4-128-SHA | Cipher suite TLS-ECDHE-RSA-WITH-RC4-128-SHA.
- - choice | TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA.
- - choice | TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA.
- - choice | TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA | Cipher suite TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA.
- - choice | TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256.
- - choice | TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256 | Suite TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256.
- - choice | TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256 | Cipher suite TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256.
- - choice | TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-DHE-RSA-WITH-AES-128-GCM-SHA256.
- - choice | TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-DHE-RSA-WITH-AES-256-GCM-SHA384.
- - choice | TLS-DHE-DSS-WITH-AES-128-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-AES-128-CBC-SHA.
- - choice | TLS-DHE-DSS-WITH-AES-256-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-AES-256-CBC-SHA.
- - choice | TLS-DHE-DSS-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-AES-128-CBC-SHA256.
- - choice | TLS-DHE-DSS-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-DHE-DSS-WITH-AES-128-GCM-SHA256.
- - choice | TLS-DHE-DSS-WITH-AES-256-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-AES-256-CBC-SHA256.
- - choice | TLS-DHE-DSS-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-DHE-DSS-WITH-AES-256-GCM-SHA384.
- - choice | TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256.
- - choice | TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256.
- - choice | TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384 | Cipher suite TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384.
- - choice | TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384.
- - choice | TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA.
- - choice | TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256.
- - choice | TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256.
- - choice | TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384.
- - choice | TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384.
- - choice | TLS-RSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-RSA-WITH-AES-128-GCM-SHA256.
- - choice | TLS-RSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-RSA-WITH-AES-256-GCM-SHA384.
- - choice | TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA | Cipher suite TLS-DSS-RSA-WITH-CAMELLIA-128-CBC-SHA.
- - choice | TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA.
- - choice | TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256.
- - choice | TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256.
- - choice | TLS-DHE-DSS-WITH-SEED-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-SEED-CBC-SHA.
- - choice | TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256.
- - choice | TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384.
- - choice | TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256.
- - choice | TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384.
- - choice | TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC_SHA256.
- - choice | TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC_SHA384.
- - choice | TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA.
- - choice | TLS-DHE-DSS-WITH-DES-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-DES-CBC-SHA.
- required: false
- choices: ["TLS-RSA-WITH-RC4-128-MD5",
- "TLS-RSA-WITH-RC4-128-SHA",
- "TLS-RSA-WITH-DES-CBC-SHA",
- "TLS-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-RSA-WITH-AES-128-CBC-SHA",
- "TLS-RSA-WITH-AES-256-CBC-SHA",
- "TLS-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-RSA-WITH-AES-256-CBC-SHA256",
- "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-RSA-WITH-SEED-CBC-SHA",
- "TLS-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-DHE-RSA-WITH-DES-CBC-SHA",
- "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-128-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-256-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256",
- "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-DHE-RSA-WITH-SEED-CBC-SHA",
- "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-RC4-128-SHA",
- "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-DHE-DSS-WITH-AES-128-CBC-SHA",
- "TLS-DHE-DSS-WITH-AES-256-CBC-SHA",
- "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256",
- "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256",
- "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384",
- "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA",
- "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256",
- "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256",
- "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384",
- "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384",
- "TLS-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-DHE-DSS-WITH-SEED-CBC-SHA",
- "TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA",
- "TLS-DHE-DSS-WITH-DES-CBC-SHA"]
-
- ssl_server_cipher_suites_priority:
- description:
- - SSL/TLS cipher suites priority.
- required: false
-
- ssl_server_cipher_suites_versions:
- description:
- - SSL/TLS versions that the cipher suite can be used with.
- - FLAG Based Options. Specify multiple in list form.
- - flag | ssl-3.0 | SSL 3.0.
- - flag | tls-1.0 | TLS 1.0.
- - flag | tls-1.1 | TLS 1.1.
- - flag | tls-1.2 | TLS 1.2.
- required: false
- choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]
-
-
-'''
-
-EXAMPLES = '''
-# BASIC FULL STATIC NAT MAPPING
-- name: EDIT FMGR_FIREWALL_VIP SNAT
- fmgr_fwobj_vip:
- name: "Basic StaticNAT Map"
- mode: "set"
- adom: "ansible"
- type: "static-nat"
- extip: "82.72.192.185"
- extintf: "any"
- mappedip: "10.7.220.25"
- comment: "Created by Ansible"
- color: "17"
-
-# BASIC PORT PNAT MAPPING
-- name: EDIT FMGR_FIREWALL_VIP PNAT
- fmgr_fwobj_vip:
- name: "Basic PNAT Map Port 10443"
- mode: "set"
- adom: "ansible"
- type: "static-nat"
- extip: "82.72.192.185"
- extport: "10443"
- extintf: "any"
- portforward: "enable"
- protocol: "tcp"
- mappedip: "10.7.220.25"
- mappedport: "443"
- comment: "Created by Ansible"
- color: "17"
-
-# BASIC DNS TRANSLATION NAT
-- name: EDIT FMGR_FIREWALL_DNST
- fmgr_fwobj_vip:
- name: "Basic DNS Translation"
- mode: "set"
- adom: "ansible"
- type: "dns-translation"
- extip: "192.168.0.1-192.168.0.100"
- extintf: "dmz"
- mappedip: "3.3.3.0/24, 4.0.0.0/24"
- comment: "Created by Ansible"
- color: "12"
-
-# BASIC FQDN NAT
-- name: EDIT FMGR_FIREWALL_FQDN
- fmgr_fwobj_vip:
- name: "Basic FQDN Translation"
- mode: "set"
- adom: "ansible"
- type: "fqdn"
- mapped_addr: "google-play"
- comment: "Created by Ansible"
- color: "5"
-
-# DELETE AN ENTRY
-- name: DELETE FMGR_FIREWALL_VIP PNAT
- fmgr_fwobj_vip:
- name: "Basic PNAT Map Port 10443"
- mode: "delete"
- adom: "ansible"
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-
-def fmgr_firewall_vip_modify(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- mode = paramgram["mode"]
- adom = paramgram["adom"]
- # INIT A BASIC OBJECTS
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
-
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if mode in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/obj/firewall/vip'.format(adom=adom)
- datagram = scrub_dict(prepare_dict(paramgram))
-
- # EVAL THE MODE PARAMETER FOR DELETE
- elif mode == "delete":
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/firewall/vip/{name}'.format(adom=adom, name=paramgram["name"])
- datagram = {}
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-#############
-# END METHODS
-#############
-
-
-def main():
- argument_spec = dict(
- adom=dict(type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
-
- websphere_server=dict(required=False, type="str", choices=["disable", "enable"]),
- weblogic_server=dict(required=False, type="str", choices=["disable", "enable"]),
- type=dict(required=False, type="str",
- choices=["static-nat", "load-balance", "server-load-balance", "dns-translation", "fqdn"]),
- ssl_server_session_state_type=dict(required=False, type="str", choices=["disable", "time", "count", "both"]),
- ssl_server_session_state_timeout=dict(required=False, type="int"),
- ssl_server_session_state_max=dict(required=False, type="int"),
- ssl_server_min_version=dict(required=False, type="str",
- choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"]),
- ssl_server_max_version=dict(required=False, type="str",
- choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"]),
- ssl_server_algorithm=dict(required=False, type="str", choices=["high", "low", "medium", "custom", "client"]),
- ssl_send_empty_frags=dict(required=False, type="str", choices=["disable", "enable"]),
- ssl_pfs=dict(required=False, type="str", choices=["require", "deny", "allow"]),
- ssl_mode=dict(required=False, type="str", choices=["half", "full"]),
- ssl_min_version=dict(required=False, type="str", choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]),
- ssl_max_version=dict(required=False, type="str", choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]),
- ssl_http_match_host=dict(required=False, type="str", choices=["disable", "enable"]),
- ssl_http_location_conversion=dict(required=False, type="str", choices=["disable", "enable"]),
- ssl_hsts_include_subdomains=dict(required=False, type="str", choices=["disable", "enable"]),
- ssl_hsts_age=dict(required=False, type="int"),
- ssl_hsts=dict(required=False, type="str", choices=["disable", "enable"]),
- ssl_hpkp_report_uri=dict(required=False, type="str"),
- ssl_hpkp_primary=dict(required=False, type="str"),
- ssl_hpkp_include_subdomains=dict(required=False, type="str", choices=["disable", "enable"]),
- ssl_hpkp_backup=dict(required=False, type="str"),
- ssl_hpkp_age=dict(required=False, type="int"),
- ssl_hpkp=dict(required=False, type="str", choices=["disable", "enable", "report-only"]),
- ssl_dh_bits=dict(required=False, type="str", choices=["768", "1024", "1536", "2048", "3072", "4096"]),
- ssl_client_session_state_type=dict(required=False, type="str", choices=["disable", "time", "count", "both"]),
- ssl_client_session_state_timeout=dict(required=False, type="int"),
- ssl_client_session_state_max=dict(required=False, type="int"),
- ssl_client_renegotiation=dict(required=False, type="str", choices=["deny", "allow", "secure"]),
- ssl_client_fallback=dict(required=False, type="str", choices=["disable", "enable"]),
- ssl_certificate=dict(required=False, type="str"),
- ssl_algorithm=dict(required=False, type="str", choices=["high", "medium", "low", "custom"]),
- srcintf_filter=dict(required=False, type="str"),
- src_filter=dict(required=False, type="str"),
- service=dict(required=False, type="str"),
- server_type=dict(required=False, type="str",
- choices=["http", "https", "ssl", "tcp", "udp", "ip", "imaps", "pop3s", "smtps"]),
- protocol=dict(required=False, type="str", choices=["tcp", "udp", "sctp", "icmp"]),
- portmapping_type=dict(required=False, type="str", choices=["1-to-1", "m-to-n"]),
- portforward=dict(required=False, type="str", choices=["disable", "enable"]),
- persistence=dict(required=False, type="str", choices=["none", "http-cookie", "ssl-session-id"]),
- outlook_web_access=dict(required=False, type="str", choices=["disable", "enable"]),
- nat_source_vip=dict(required=False, type="str", choices=["disable", "enable"]),
- name=dict(required=False, type="str"),
- monitor=dict(required=False, type="str"),
- max_embryonic_connections=dict(required=False, type="int"),
- mappedport=dict(required=False, type="str"),
- mappedip=dict(required=False, type="str"),
- mapped_addr=dict(required=False, type="str"),
- ldb_method=dict(required=False, type="str",
- choices=["static", "round-robin", "weighted", "least-session", "least-rtt", "first-alive",
- "http-host"]),
- https_cookie_secure=dict(required=False, type="str", choices=["disable", "enable"]),
- http_multiplex=dict(required=False, type="str", choices=["disable", "enable"]),
- http_ip_header_name=dict(required=False, type="str"),
- http_ip_header=dict(required=False, type="str", choices=["disable", "enable"]),
- http_cookie_share=dict(required=False, type="str", choices=["disable", "same-ip"]),
- http_cookie_path=dict(required=False, type="str"),
- http_cookie_generation=dict(required=False, type="int"),
- http_cookie_domain_from_host=dict(required=False, type="str", choices=["disable", "enable"]),
- http_cookie_domain=dict(required=False, type="str"),
- http_cookie_age=dict(required=False, type="int"),
- gratuitous_arp_interval=dict(required=False, type="int"),
- extport=dict(required=False, type="str"),
- extip=dict(required=False, type="str"),
- extintf=dict(required=False, type="str"),
- extaddr=dict(required=False, type="str"),
- dns_mapping_ttl=dict(required=False, type="int"),
- comment=dict(required=False, type="str"),
- color=dict(required=False, type="int"),
- arp_reply=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping=dict(required=False, type="list"),
- dynamic_mapping_arp_reply=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_color=dict(required=False, type="int"),
- dynamic_mapping_comment=dict(required=False, type="str"),
- dynamic_mapping_dns_mapping_ttl=dict(required=False, type="int"),
- dynamic_mapping_extaddr=dict(required=False, type="str"),
- dynamic_mapping_extintf=dict(required=False, type="str"),
- dynamic_mapping_extip=dict(required=False, type="str"),
- dynamic_mapping_extport=dict(required=False, type="str"),
- dynamic_mapping_gratuitous_arp_interval=dict(required=False, type="int"),
- dynamic_mapping_http_cookie_age=dict(required=False, type="int"),
- dynamic_mapping_http_cookie_domain=dict(required=False, type="str"),
- dynamic_mapping_http_cookie_domain_from_host=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_http_cookie_generation=dict(required=False, type="int"),
- dynamic_mapping_http_cookie_path=dict(required=False, type="str"),
- dynamic_mapping_http_cookie_share=dict(required=False, type="str", choices=["disable", "same-ip"]),
- dynamic_mapping_http_ip_header=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_http_ip_header_name=dict(required=False, type="str"),
- dynamic_mapping_http_multiplex=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_https_cookie_secure=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_ldb_method=dict(required=False, type="str", choices=["static",
- "round-robin",
- "weighted",
- "least-session",
- "least-rtt",
- "first-alive",
- "http-host"]),
- dynamic_mapping_mapped_addr=dict(required=False, type="str"),
- dynamic_mapping_mappedip=dict(required=False, type="str"),
- dynamic_mapping_mappedport=dict(required=False, type="str"),
- dynamic_mapping_max_embryonic_connections=dict(required=False, type="int"),
- dynamic_mapping_monitor=dict(required=False, type="str"),
- dynamic_mapping_nat_source_vip=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_outlook_web_access=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_persistence=dict(required=False, type="str", choices=["none", "http-cookie", "ssl-session-id"]),
- dynamic_mapping_portforward=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_portmapping_type=dict(required=False, type="str", choices=["1-to-1", "m-to-n"]),
- dynamic_mapping_protocol=dict(required=False, type="str", choices=["tcp", "udp", "sctp", "icmp"]),
- dynamic_mapping_server_type=dict(required=False, type="str",
- choices=["http", "https", "ssl", "tcp", "udp", "ip", "imaps", "pop3s",
- "smtps"]),
- dynamic_mapping_service=dict(required=False, type="str"),
- dynamic_mapping_src_filter=dict(required=False, type="str"),
- dynamic_mapping_srcintf_filter=dict(required=False, type="str"),
- dynamic_mapping_ssl_algorithm=dict(required=False, type="str", choices=["high", "medium", "low", "custom"]),
- dynamic_mapping_ssl_certificate=dict(required=False, type="str"),
- dynamic_mapping_ssl_client_fallback=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_ssl_client_renegotiation=dict(required=False, type="str", choices=["deny", "allow", "secure"]),
- dynamic_mapping_ssl_client_session_state_max=dict(required=False, type="int"),
- dynamic_mapping_ssl_client_session_state_timeout=dict(required=False, type="int"),
- dynamic_mapping_ssl_client_session_state_type=dict(required=False, type="str",
- choices=["disable", "time", "count", "both"]),
- dynamic_mapping_ssl_dh_bits=dict(required=False, type="str",
- choices=["768", "1024", "1536", "2048", "3072", "4096"]),
- dynamic_mapping_ssl_hpkp=dict(required=False, type="str", choices=["disable", "enable", "report-only"]),
- dynamic_mapping_ssl_hpkp_age=dict(required=False, type="int"),
- dynamic_mapping_ssl_hpkp_backup=dict(required=False, type="str"),
- dynamic_mapping_ssl_hpkp_include_subdomains=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_ssl_hpkp_primary=dict(required=False, type="str"),
- dynamic_mapping_ssl_hpkp_report_uri=dict(required=False, type="str"),
- dynamic_mapping_ssl_hsts=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_ssl_hsts_age=dict(required=False, type="int"),
- dynamic_mapping_ssl_hsts_include_subdomains=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_ssl_http_location_conversion=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_ssl_http_match_host=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_ssl_max_version=dict(required=False, type="str",
- choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]),
- dynamic_mapping_ssl_min_version=dict(required=False, type="str",
- choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]),
- dynamic_mapping_ssl_mode=dict(required=False, type="str", choices=["half", "full"]),
- dynamic_mapping_ssl_pfs=dict(required=False, type="str", choices=["require", "deny", "allow"]),
- dynamic_mapping_ssl_send_empty_frags=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_ssl_server_algorithm=dict(required=False, type="str",
- choices=["high", "low", "medium", "custom", "client"]),
- dynamic_mapping_ssl_server_max_version=dict(required=False, type="str",
- choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"]),
- dynamic_mapping_ssl_server_min_version=dict(required=False, type="str",
- choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"]),
- dynamic_mapping_ssl_server_session_state_max=dict(required=False, type="int"),
- dynamic_mapping_ssl_server_session_state_timeout=dict(required=False, type="int"),
- dynamic_mapping_ssl_server_session_state_type=dict(required=False, type="str",
- choices=["disable", "time", "count", "both"]),
- dynamic_mapping_type=dict(required=False, type="str",
- choices=["static-nat", "load-balance", "server-load-balance", "dns-translation",
- "fqdn"]),
- dynamic_mapping_weblogic_server=dict(required=False, type="str", choices=["disable", "enable"]),
- dynamic_mapping_websphere_server=dict(required=False, type="str", choices=["disable", "enable"]),
-
- dynamic_mapping_realservers_client_ip=dict(required=False, type="str"),
- dynamic_mapping_realservers_healthcheck=dict(required=False, type="str", choices=["disable", "enable", "vip"]),
- dynamic_mapping_realservers_holddown_interval=dict(required=False, type="int"),
- dynamic_mapping_realservers_http_host=dict(required=False, type="str"),
- dynamic_mapping_realservers_ip=dict(required=False, type="str"),
- dynamic_mapping_realservers_max_connections=dict(required=False, type="int"),
- dynamic_mapping_realservers_monitor=dict(required=False, type="str"),
- dynamic_mapping_realservers_port=dict(required=False, type="int"),
- dynamic_mapping_realservers_seq=dict(required=False, type="str"),
- dynamic_mapping_realservers_status=dict(required=False, type="str", choices=["active", "standby", "disable"]),
- dynamic_mapping_realservers_weight=dict(required=False, type="int"),
-
- dynamic_mapping_ssl_cipher_suites_cipher=dict(required=False,
- type="str",
- choices=["TLS-RSA-WITH-RC4-128-MD5",
- "TLS-RSA-WITH-RC4-128-SHA",
- "TLS-RSA-WITH-DES-CBC-SHA",
- "TLS-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-RSA-WITH-AES-128-CBC-SHA",
- "TLS-RSA-WITH-AES-256-CBC-SHA",
- "TLS-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-RSA-WITH-AES-256-CBC-SHA256",
- "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-RSA-WITH-SEED-CBC-SHA",
- "TLS-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-DHE-RSA-WITH-DES-CBC-SHA",
- "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-128-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-256-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256",
- "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-DHE-RSA-WITH-SEED-CBC-SHA",
- "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-RC4-128-SHA",
- "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-DHE-DSS-WITH-AES-128-CBC-SHA",
- "TLS-DHE-DSS-WITH-AES-256-CBC-SHA",
- "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256",
- "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256",
- "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384",
- "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA",
- "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256",
- "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256",
- "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384",
- "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384",
- "TLS-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-DHE-DSS-WITH-SEED-CBC-SHA",
- "TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA",
- "TLS-DHE-DSS-WITH-DES-CBC-SHA"]),
- dynamic_mapping_ssl_cipher_suites_versions=dict(required=False, type="str",
- choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]),
- realservers=dict(required=False, type="list"),
- realservers_client_ip=dict(required=False, type="str"),
- realservers_healthcheck=dict(required=False, type="str", choices=["disable", "enable", "vip"]),
- realservers_holddown_interval=dict(required=False, type="int"),
- realservers_http_host=dict(required=False, type="str"),
- realservers_ip=dict(required=False, type="str"),
- realservers_max_connections=dict(required=False, type="int"),
- realservers_monitor=dict(required=False, type="str"),
- realservers_port=dict(required=False, type="int"),
- realservers_seq=dict(required=False, type="str"),
- realservers_status=dict(required=False, type="str", choices=["active", "standby", "disable"]),
- realservers_weight=dict(required=False, type="int"),
- ssl_cipher_suites=dict(required=False, type="list"),
- ssl_cipher_suites_cipher=dict(required=False,
- type="str",
- choices=["TLS-RSA-WITH-RC4-128-MD5",
- "TLS-RSA-WITH-RC4-128-SHA",
- "TLS-RSA-WITH-DES-CBC-SHA",
- "TLS-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-RSA-WITH-AES-128-CBC-SHA",
- "TLS-RSA-WITH-AES-256-CBC-SHA",
- "TLS-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-RSA-WITH-AES-256-CBC-SHA256",
- "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-RSA-WITH-SEED-CBC-SHA",
- "TLS-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-DHE-RSA-WITH-DES-CBC-SHA",
- "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-128-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-256-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256",
- "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-DHE-RSA-WITH-SEED-CBC-SHA",
- "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-RC4-128-SHA",
- "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-DHE-DSS-WITH-AES-128-CBC-SHA",
- "TLS-DHE-DSS-WITH-AES-256-CBC-SHA",
- "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256",
- "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256",
- "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384",
- "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA",
- "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256",
- "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256",
- "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384",
- "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384",
- "TLS-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-DHE-DSS-WITH-SEED-CBC-SHA",
- "TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA",
- "TLS-DHE-DSS-WITH-DES-CBC-SHA"]),
- ssl_cipher_suites_versions=dict(required=False, type="str",
- choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]),
- ssl_server_cipher_suites=dict(required=False, type="list"),
- ssl_server_cipher_suites_cipher=dict(required=False,
- type="str",
- choices=["TLS-RSA-WITH-RC4-128-MD5",
- "TLS-RSA-WITH-RC4-128-SHA",
- "TLS-RSA-WITH-DES-CBC-SHA",
- "TLS-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-RSA-WITH-AES-128-CBC-SHA",
- "TLS-RSA-WITH-AES-256-CBC-SHA",
- "TLS-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-RSA-WITH-AES-256-CBC-SHA256",
- "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-RSA-WITH-SEED-CBC-SHA",
- "TLS-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-DHE-RSA-WITH-DES-CBC-SHA",
- "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-128-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-256-CBC-SHA",
- "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256",
- "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-DHE-RSA-WITH-SEED-CBC-SHA",
- "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-RC4-128-SHA",
- "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA",
- "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
- "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-DHE-DSS-WITH-AES-128-CBC-SHA",
- "TLS-DHE-DSS-WITH-AES-256-CBC-SHA",
- "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256",
- "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256",
- "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384",
- "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256",
- "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA",
- "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256",
- "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256",
- "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384",
- "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384",
- "TLS-RSA-WITH-AES-128-GCM-SHA256",
- "TLS-RSA-WITH-AES-256-GCM-SHA384",
- "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA",
- "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA",
- "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256",
- "TLS-DHE-DSS-WITH-SEED-CBC-SHA",
- "TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256",
- "TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256",
- "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384",
- "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA",
- "TLS-DHE-DSS-WITH-DES-CBC-SHA"]),
- ssl_server_cipher_suites_priority=dict(required=False, type="str"),
- ssl_server_cipher_suites_versions=dict(required=False, type="str",
- choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "websphere-server": module.params["websphere_server"],
- "weblogic-server": module.params["weblogic_server"],
- "type": module.params["type"],
- "ssl-server-session-state-type": module.params["ssl_server_session_state_type"],
- "ssl-server-session-state-timeout": module.params["ssl_server_session_state_timeout"],
- "ssl-server-session-state-max": module.params["ssl_server_session_state_max"],
- "ssl-server-min-version": module.params["ssl_server_min_version"],
- "ssl-server-max-version": module.params["ssl_server_max_version"],
- "ssl-server-algorithm": module.params["ssl_server_algorithm"],
- "ssl-send-empty-frags": module.params["ssl_send_empty_frags"],
- "ssl-pfs": module.params["ssl_pfs"],
- "ssl-mode": module.params["ssl_mode"],
- "ssl-min-version": module.params["ssl_min_version"],
- "ssl-max-version": module.params["ssl_max_version"],
- "ssl-http-match-host": module.params["ssl_http_match_host"],
- "ssl-http-location-conversion": module.params["ssl_http_location_conversion"],
- "ssl-hsts-include-subdomains": module.params["ssl_hsts_include_subdomains"],
- "ssl-hsts-age": module.params["ssl_hsts_age"],
- "ssl-hsts": module.params["ssl_hsts"],
- "ssl-hpkp-report-uri": module.params["ssl_hpkp_report_uri"],
- "ssl-hpkp-primary": module.params["ssl_hpkp_primary"],
- "ssl-hpkp-include-subdomains": module.params["ssl_hpkp_include_subdomains"],
- "ssl-hpkp-backup": module.params["ssl_hpkp_backup"],
- "ssl-hpkp-age": module.params["ssl_hpkp_age"],
- "ssl-hpkp": module.params["ssl_hpkp"],
- "ssl-dh-bits": module.params["ssl_dh_bits"],
- "ssl-client-session-state-type": module.params["ssl_client_session_state_type"],
- "ssl-client-session-state-timeout": module.params["ssl_client_session_state_timeout"],
- "ssl-client-session-state-max": module.params["ssl_client_session_state_max"],
- "ssl-client-renegotiation": module.params["ssl_client_renegotiation"],
- "ssl-client-fallback": module.params["ssl_client_fallback"],
- "ssl-certificate": module.params["ssl_certificate"],
- "ssl-algorithm": module.params["ssl_algorithm"],
- "srcintf-filter": module.params["srcintf_filter"],
- "src-filter": module.params["src_filter"],
- "service": module.params["service"],
- "server-type": module.params["server_type"],
- "protocol": module.params["protocol"],
- "portmapping-type": module.params["portmapping_type"],
- "portforward": module.params["portforward"],
- "persistence": module.params["persistence"],
- "outlook-web-access": module.params["outlook_web_access"],
- "nat-source-vip": module.params["nat_source_vip"],
- "name": module.params["name"],
- "monitor": module.params["monitor"],
- "max-embryonic-connections": module.params["max_embryonic_connections"],
- "mappedport": module.params["mappedport"],
- "mappedip": module.params["mappedip"],
- "mapped-addr": module.params["mapped_addr"],
- "ldb-method": module.params["ldb_method"],
- "https-cookie-secure": module.params["https_cookie_secure"],
- "http-multiplex": module.params["http_multiplex"],
- "http-ip-header-name": module.params["http_ip_header_name"],
- "http-ip-header": module.params["http_ip_header"],
- "http-cookie-share": module.params["http_cookie_share"],
- "http-cookie-path": module.params["http_cookie_path"],
- "http-cookie-generation": module.params["http_cookie_generation"],
- "http-cookie-domain-from-host": module.params["http_cookie_domain_from_host"],
- "http-cookie-domain": module.params["http_cookie_domain"],
- "http-cookie-age": module.params["http_cookie_age"],
- "gratuitous-arp-interval": module.params["gratuitous_arp_interval"],
- "extport": module.params["extport"],
- "extip": module.params["extip"],
- "extintf": module.params["extintf"],
- "extaddr": module.params["extaddr"],
- "dns-mapping-ttl": module.params["dns_mapping_ttl"],
- "comment": module.params["comment"],
- "color": module.params["color"],
- "arp-reply": module.params["arp_reply"],
- "dynamic_mapping": {
- "arp-reply": module.params["dynamic_mapping_arp_reply"],
- "color": module.params["dynamic_mapping_color"],
- "comment": module.params["dynamic_mapping_comment"],
- "dns-mapping-ttl": module.params["dynamic_mapping_dns_mapping_ttl"],
- "extaddr": module.params["dynamic_mapping_extaddr"],
- "extintf": module.params["dynamic_mapping_extintf"],
- "extip": module.params["dynamic_mapping_extip"],
- "extport": module.params["dynamic_mapping_extport"],
- "gratuitous-arp-interval": module.params["dynamic_mapping_gratuitous_arp_interval"],
- "http-cookie-age": module.params["dynamic_mapping_http_cookie_age"],
- "http-cookie-domain": module.params["dynamic_mapping_http_cookie_domain"],
- "http-cookie-domain-from-host": module.params["dynamic_mapping_http_cookie_domain_from_host"],
- "http-cookie-generation": module.params["dynamic_mapping_http_cookie_generation"],
- "http-cookie-path": module.params["dynamic_mapping_http_cookie_path"],
- "http-cookie-share": module.params["dynamic_mapping_http_cookie_share"],
- "http-ip-header": module.params["dynamic_mapping_http_ip_header"],
- "http-ip-header-name": module.params["dynamic_mapping_http_ip_header_name"],
- "http-multiplex": module.params["dynamic_mapping_http_multiplex"],
- "https-cookie-secure": module.params["dynamic_mapping_https_cookie_secure"],
- "ldb-method": module.params["dynamic_mapping_ldb_method"],
- "mapped-addr": module.params["dynamic_mapping_mapped_addr"],
- "mappedip": module.params["dynamic_mapping_mappedip"],
- "mappedport": module.params["dynamic_mapping_mappedport"],
- "max-embryonic-connections": module.params["dynamic_mapping_max_embryonic_connections"],
- "monitor": module.params["dynamic_mapping_monitor"],
- "nat-source-vip": module.params["dynamic_mapping_nat_source_vip"],
- "outlook-web-access": module.params["dynamic_mapping_outlook_web_access"],
- "persistence": module.params["dynamic_mapping_persistence"],
- "portforward": module.params["dynamic_mapping_portforward"],
- "portmapping-type": module.params["dynamic_mapping_portmapping_type"],
- "protocol": module.params["dynamic_mapping_protocol"],
- "server-type": module.params["dynamic_mapping_server_type"],
- "service": module.params["dynamic_mapping_service"],
- "src-filter": module.params["dynamic_mapping_src_filter"],
- "srcintf-filter": module.params["dynamic_mapping_srcintf_filter"],
- "ssl-algorithm": module.params["dynamic_mapping_ssl_algorithm"],
- "ssl-certificate": module.params["dynamic_mapping_ssl_certificate"],
- "ssl-client-fallback": module.params["dynamic_mapping_ssl_client_fallback"],
- "ssl-client-renegotiation": module.params["dynamic_mapping_ssl_client_renegotiation"],
- "ssl-client-session-state-max": module.params["dynamic_mapping_ssl_client_session_state_max"],
- "ssl-client-session-state-timeout": module.params["dynamic_mapping_ssl_client_session_state_timeout"],
- "ssl-client-session-state-type": module.params["dynamic_mapping_ssl_client_session_state_type"],
- "ssl-dh-bits": module.params["dynamic_mapping_ssl_dh_bits"],
- "ssl-hpkp": module.params["dynamic_mapping_ssl_hpkp"],
- "ssl-hpkp-age": module.params["dynamic_mapping_ssl_hpkp_age"],
- "ssl-hpkp-backup": module.params["dynamic_mapping_ssl_hpkp_backup"],
- "ssl-hpkp-include-subdomains": module.params["dynamic_mapping_ssl_hpkp_include_subdomains"],
- "ssl-hpkp-primary": module.params["dynamic_mapping_ssl_hpkp_primary"],
- "ssl-hpkp-report-uri": module.params["dynamic_mapping_ssl_hpkp_report_uri"],
- "ssl-hsts": module.params["dynamic_mapping_ssl_hsts"],
- "ssl-hsts-age": module.params["dynamic_mapping_ssl_hsts_age"],
- "ssl-hsts-include-subdomains": module.params["dynamic_mapping_ssl_hsts_include_subdomains"],
- "ssl-http-location-conversion": module.params["dynamic_mapping_ssl_http_location_conversion"],
- "ssl-http-match-host": module.params["dynamic_mapping_ssl_http_match_host"],
- "ssl-max-version": module.params["dynamic_mapping_ssl_max_version"],
- "ssl-min-version": module.params["dynamic_mapping_ssl_min_version"],
- "ssl-mode": module.params["dynamic_mapping_ssl_mode"],
- "ssl-pfs": module.params["dynamic_mapping_ssl_pfs"],
- "ssl-send-empty-frags": module.params["dynamic_mapping_ssl_send_empty_frags"],
- "ssl-server-algorithm": module.params["dynamic_mapping_ssl_server_algorithm"],
- "ssl-server-max-version": module.params["dynamic_mapping_ssl_server_max_version"],
- "ssl-server-min-version": module.params["dynamic_mapping_ssl_server_min_version"],
- "ssl-server-session-state-max": module.params["dynamic_mapping_ssl_server_session_state_max"],
- "ssl-server-session-state-timeout": module.params["dynamic_mapping_ssl_server_session_state_timeout"],
- "ssl-server-session-state-type": module.params["dynamic_mapping_ssl_server_session_state_type"],
- "type": module.params["dynamic_mapping_type"],
- "weblogic-server": module.params["dynamic_mapping_weblogic_server"],
- "websphere-server": module.params["dynamic_mapping_websphere_server"],
- "realservers": {
- "client-ip": module.params["dynamic_mapping_realservers_client_ip"],
- "healthcheck": module.params["dynamic_mapping_realservers_healthcheck"],
- "holddown-interval": module.params["dynamic_mapping_realservers_holddown_interval"],
- "http-host": module.params["dynamic_mapping_realservers_http_host"],
- "ip": module.params["dynamic_mapping_realservers_ip"],
- "max-connections": module.params["dynamic_mapping_realservers_max_connections"],
- "monitor": module.params["dynamic_mapping_realservers_monitor"],
- "port": module.params["dynamic_mapping_realservers_port"],
- "seq": module.params["dynamic_mapping_realservers_seq"],
- "status": module.params["dynamic_mapping_realservers_status"],
- "weight": module.params["dynamic_mapping_realservers_weight"],
- },
- "ssl-cipher-suites": {
- "cipher": module.params["dynamic_mapping_ssl_cipher_suites_cipher"],
- "versions": module.params["dynamic_mapping_ssl_cipher_suites_versions"],
- },
- },
- "realservers": {
- "client-ip": module.params["realservers_client_ip"],
- "healthcheck": module.params["realservers_healthcheck"],
- "holddown-interval": module.params["realservers_holddown_interval"],
- "http-host": module.params["realservers_http_host"],
- "ip": module.params["realservers_ip"],
- "max-connections": module.params["realservers_max_connections"],
- "monitor": module.params["realservers_monitor"],
- "port": module.params["realservers_port"],
- "seq": module.params["realservers_seq"],
- "status": module.params["realservers_status"],
- "weight": module.params["realservers_weight"],
- },
- "ssl-cipher-suites": {
- "cipher": module.params["ssl_cipher_suites_cipher"],
- "versions": module.params["ssl_cipher_suites_versions"],
- },
- "ssl-server-cipher-suites": {
- "cipher": module.params["ssl_server_cipher_suites_cipher"],
- "priority": module.params["ssl_server_cipher_suites_priority"],
- "versions": module.params["ssl_server_cipher_suites_versions"],
- }
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- list_overrides = ['dynamic_mapping', 'realservers', 'ssl-cipher-suites', 'ssl-server-cipher-suites']
- paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides,
- paramgram=paramgram, module=module)
-
- results = DEFAULT_RESULT_OBJ
- try:
- results = fmgr_firewall_vip_modify(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_fwpol_ipv4.py b/plugins/modules/network/fortimanager/fmgr_fwpol_ipv4.py
deleted file mode 100644
index 27063bf276..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_fwpol_ipv4.py
+++ /dev/null
@@ -1,1359 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_fwpol_ipv4
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Allows the add/delete of Firewall Policies on Packages in FortiManager.
-description:
- - Allows the add/delete of Firewall Policies on Packages in FortiManager.
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- package_name:
- description:
- - The policy package you want to modify
- required: false
- default: "default"
-
- fail_on_missing_dependency:
- description:
- - Normal behavior is to "skip" tasks that fail dependency checks, so other tasks can run.
- - If set to "enabled" if a failed dependency check happeens, Ansible will exit as with failure instead of skip.
- required: false
- default: "disable"
- choices: ["enable", "disable"]
-
- wsso:
- description:
- - Enable/disable WiFi Single Sign On (WSSO).
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- webfilter_profile:
- description:
- - Name of an existing Web filter profile.
- required: false
-
- webcache_https:
- description:
- - Enable/disable web cache for HTTPS.
- - choice | disable | Disable web cache for HTTPS.
- - choice | enable | Enable web cache for HTTPS.
- required: false
- choices: ["disable", "enable"]
-
- webcache:
- description:
- - Enable/disable web cache.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- wccp:
- description:
- - Enable/disable forwarding traffic matching this policy to a configured WCCP server.
- - choice | disable | Disable WCCP setting.
- - choice | enable | Enable WCCP setting.
- required: false
- choices: ["disable", "enable"]
-
- wanopt_profile:
- description:
- - WAN optimization profile.
- required: false
-
- wanopt_peer:
- description:
- - WAN optimization peer.
- required: false
-
- wanopt_passive_opt:
- description:
- - WAN optimization passive mode options. This option decides what IP address will be used to connect server.
- - choice | default | Allow client side WAN opt peer to decide.
- - choice | transparent | Use address of client to connect to server.
- - choice | non-transparent | Use local FortiGate address to connect to server.
- required: false
- choices: ["default", "transparent", "non-transparent"]
-
- wanopt_detection:
- description:
- - WAN optimization auto-detection mode.
- - choice | active | Active WAN optimization peer auto-detection.
- - choice | passive | Passive WAN optimization peer auto-detection.
- - choice | off | Turn off WAN optimization peer auto-detection.
- required: false
- choices: ["active", "passive", "off"]
-
- wanopt:
- description:
- - Enable/disable WAN optimization.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- waf_profile:
- description:
- - Name of an existing Web application firewall profile.
- required: false
-
- vpntunnel:
- description:
- - Policy-based IPsec VPN | name of the IPsec VPN Phase 1.
- required: false
-
- voip_profile:
- description:
- - Name of an existing VoIP profile.
- required: false
-
- vlan_filter:
- description:
- - Set VLAN filters.
- required: false
-
- vlan_cos_rev:
- description:
- - VLAN reverse direction user priority | 255 passthrough, 0 lowest, 7 highest..
- required: false
-
- vlan_cos_fwd:
- description:
- - VLAN forward direction user priority | 255 passthrough, 0 lowest, 7 highest.
- required: false
-
- utm_status:
- description:
- - Enable to add one or more security profiles (AV, IPS, etc.) to the firewall policy.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- users:
- description:
- - Names of individual users that can authenticate with this policy.
- required: false
-
- url_category:
- description:
- - URL category ID list.
- required: false
-
- traffic_shaper_reverse:
- description:
- - Reverse traffic shaper.
- required: false
-
- traffic_shaper:
- description:
- - Traffic shaper.
- required: false
-
- timeout_send_rst:
- description:
- - Enable/disable sending RST packets when TCP sessions expire.
- - choice | disable | Disable sending of RST packet upon TCP session expiration.
- - choice | enable | Enable sending of RST packet upon TCP session expiration.
- required: false
- choices: ["disable", "enable"]
-
- tcp_session_without_syn:
- description:
- - Enable/disable creation of TCP session without SYN flag.
- - choice | all | Enable TCP session without SYN.
- - choice | data-only | Enable TCP session data only.
- - choice | disable | Disable TCP session without SYN.
- required: false
- choices: ["all", "data-only", "disable"]
-
- tcp_mss_sender:
- description:
- - Sender TCP maximum segment size (MSS).
- required: false
-
- tcp_mss_receiver:
- description:
- - Receiver TCP maximum segment size (MSS).
- required: false
-
- status:
- description:
- - Enable or disable this policy.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- ssl_ssh_profile:
- description:
- - Name of an existing SSL SSH profile.
- required: false
-
- ssl_mirror_intf:
- description:
- - SSL mirror interface name.
- required: false
-
- ssl_mirror:
- description:
- - Enable to copy decrypted SSL traffic to a FortiGate interface (called SSL mirroring).
- - choice | disable | Disable SSL mirror.
- - choice | enable | Enable SSL mirror.
- required: false
- choices: ["disable", "enable"]
-
- ssh_filter_profile:
- description:
- - Name of an existing SSH filter profile.
- required: false
-
- srcintf:
- description:
- - Incoming (ingress) interface.
- required: false
-
- srcaddr_negate:
- description:
- - When enabled srcaddr specifies what the source address must NOT be.
- - choice | disable | Disable source address negate.
- - choice | enable | Enable source address negate.
- required: false
- choices: ["disable", "enable"]
-
- srcaddr:
- description:
- - Source address and address group names.
- required: false
-
- spamfilter_profile:
- description:
- - Name of an existing Spam filter profile.
- required: false
-
- session_ttl:
- description:
- - TTL in seconds for sessions accepted by this policy (0 means use the system default session TTL).
- required: false
-
- service_negate:
- description:
- - When enabled service specifies what the service must NOT be.
- - choice | disable | Disable negated service match.
- - choice | enable | Enable negated service match.
- required: false
- choices: ["disable", "enable"]
-
- service:
- description:
- - Service and service group names.
- required: false
-
- send_deny_packet:
- description:
- - Enable to send a reply when a session is denied or blocked by a firewall policy.
- - choice | disable | Disable deny-packet sending.
- - choice | enable | Enable deny-packet sending.
- required: false
- choices: ["disable", "enable"]
-
- schedule_timeout:
- description:
- - Enable to force current sessions to end when the schedule object times out.
- - choice | disable | Disable schedule timeout.
- - choice | enable | Enable schedule timeout.
- required: false
- choices: ["disable", "enable"]
-
- schedule:
- description:
- - Schedule name.
- required: false
-
- scan_botnet_connections:
- description:
- - Block or monitor connections to Botnet servers or disable Botnet scanning.
- - choice | disable | Do not scan connections to botnet servers.
- - choice | block | Block connections to botnet servers.
- - choice | monitor | Log connections to botnet servers.
- required: false
- choices: ["disable", "block", "monitor"]
-
- rtp_nat:
- description:
- - Enable Real Time Protocol (RTP) NAT.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- rtp_addr:
- description:
- - Address names if this is an RTP NAT policy.
- required: false
-
- rsso:
- description:
- - Enable/disable RADIUS single sign-on (RSSO).
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- replacemsg_override_group:
- description:
- - Override the default replacement message group for this policy.
- required: false
-
- redirect_url:
- description:
- - URL users are directed to after seeing and accepting the disclaimer or authenticating.
- required: false
-
- radius_mac_auth_bypass:
- description:
- - Enable MAC authentication bypass. The bypassed MAC address must be received from RADIUS server.
- - choice | disable | Disable MAC authentication bypass.
- - choice | enable | Enable MAC authentication bypass.
- required: false
- choices: ["disable", "enable"]
-
- profile_type:
- description:
- - Determine whether the firewall policy allows security profile groups or single profiles only.
- - choice | single | Do not allow security profile groups.
- - choice | group | Allow security profile groups.
- required: false
- choices: ["single", "group"]
-
- profile_protocol_options:
- description:
- - Name of an existing Protocol options profile.
- required: false
-
- profile_group:
- description:
- - Name of profile group.
- required: false
-
- poolname:
- description:
- - IP Pool names.
- required: false
-
- policyid:
- description:
- - Policy ID.
- required: false
-
- permit_stun_host:
- description:
- - Accept UDP packets from any Session Traversal Utilities for NAT (STUN) host.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- permit_any_host:
- description:
- - Accept UDP packets from any host.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- per_ip_shaper:
- description:
- - Per-IP traffic shaper.
- required: false
-
- outbound:
- description:
- - Policy-based IPsec VPN | only traffic from the internal network can initiate a VPN.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- ntlm_guest:
- description:
- - Enable/disable NTLM guest user access.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- ntlm_enabled_browsers:
- description:
- - HTTP-User-Agent value of supported browsers.
- required: false
-
- ntlm:
- description:
- - Enable/disable NTLM authentication.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- np_acceleration:
- description:
- - Enable/disable UTM Network Processor acceleration.
- - choice | disable | Disable UTM Network Processor acceleration.
- - choice | enable | Enable UTM Network Processor acceleration.
- required: false
- choices: ["disable", "enable"]
-
- natoutbound:
- description:
- - Policy-based IPsec VPN | apply source NAT to outbound traffic.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- natip:
- description:
- - Policy-based IPsec VPN | source NAT IP address for outgoing traffic.
- required: false
-
- natinbound:
- description:
- - Policy-based IPsec VPN | apply destination NAT to inbound traffic.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- nat:
- description:
- - Enable/disable source NAT.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- name:
- description:
- - Policy name.
- required: false
-
- mms_profile:
- description:
- - Name of an existing MMS profile.
- required: false
-
- match_vip:
- description:
- - Enable to match packets that have had their destination addresses changed by a VIP.
- - choice | disable | Do not match DNATed packet.
- - choice | enable | Match DNATed packet.
- required: false
- choices: ["disable", "enable"]
-
- logtraffic_start:
- description:
- - Record logs when a session starts and ends.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- logtraffic:
- description:
- - Enable or disable logging. Log all sessions or security profile sessions.
- - choice | disable | Disable all logging for this policy.
- - choice | all | Log all sessions accepted or denied by this policy.
- - choice | utm | Log traffic that has a security profile applied to it.
- required: false
- choices: ["disable", "all", "utm"]
-
- learning_mode:
- description:
- - Enable to allow everything, but log all of the meaningful data for security information gathering.
- - choice | disable | Disable learning mode in firewall policy.
- - choice | enable | Enable learning mode in firewall policy.
- required: false
- choices: ["disable", "enable"]
-
- label:
- description:
- - Label for the policy that appears when the GUI is in Section View mode.
- required: false
-
- ips_sensor:
- description:
- - Name of an existing IPS sensor.
- required: false
-
- ippool:
- description:
- - Enable to use IP Pools for source NAT.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- internet_service_src_negate:
- description:
- - When enabled internet-service-src specifies what the service must NOT be.
- - choice | disable | Disable negated Internet Service source match.
- - choice | enable | Enable negated Internet Service source match.
- required: false
- choices: ["disable", "enable"]
-
- internet_service_src_id:
- description:
- - Internet Service source ID.
- required: false
-
- internet_service_src_custom:
- description:
- - Custom Internet Service source name.
- required: false
-
- internet_service_src:
- description:
- - Enable/disable use of Internet Services in source for this policy. If enabled, source address is not used.
- - choice | disable | Disable use of Internet Services source in policy.
- - choice | enable | Enable use of Internet Services source in policy.
- required: false
- choices: ["disable", "enable"]
-
- internet_service_negate:
- description:
- - When enabled internet-service specifies what the service must NOT be.
- - choice | disable | Disable negated Internet Service match.
- - choice | enable | Enable negated Internet Service match.
- required: false
- choices: ["disable", "enable"]
-
- internet_service_id:
- description:
- - Internet Service ID.
- required: false
-
- internet_service_custom:
- description:
- - Custom Internet Service name.
- required: false
-
- internet_service:
- description:
- - Enable/disable use of Internet Services for this policy. If enabled, dstaddr and service are not used.
- - choice | disable | Disable use of Internet Services in policy.
- - choice | enable | Enable use of Internet Services in policy.
- required: false
- choices: ["disable", "enable"]
-
- inbound:
- description:
- - Policy-based IPsec VPN | only traffic from the remote network can initiate a VPN.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- identity_based_route:
- description:
- - Name of identity-based routing rule.
- required: false
-
- icap_profile:
- description:
- - Name of an existing ICAP profile.
- required: false
-
- gtp_profile:
- description:
- - GTP profile.
- required: false
-
- groups:
- description:
- - Names of user groups that can authenticate with this policy.
- required: false
-
- global_label:
- description:
- - Label for the policy that appears when the GUI is in Global View mode.
- required: false
-
- fsso_agent_for_ntlm:
- description:
- - FSSO agent to use for NTLM authentication.
- required: false
-
- fsso:
- description:
- - Enable/disable Fortinet Single Sign-On.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- fixedport:
- description:
- - Enable to prevent source NAT from changing a session's source port.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- firewall_session_dirty:
- description:
- - How to handle sessions if the configuration of this firewall policy changes.
- - choice | check-all | Flush all current sessions accepted by this policy.
- - choice | check-new | Continue to allow sessions already accepted by this policy.
- required: false
- choices: ["check-all", "check-new"]
-
- dstintf:
- description:
- - Outgoing (egress) interface.
- required: false
-
- dstaddr_negate:
- description:
- - When enabled dstaddr specifies what the destination address must NOT be.
- - choice | disable | Disable destination address negate.
- - choice | enable | Enable destination address negate.
- required: false
- choices: ["disable", "enable"]
-
- dstaddr:
- description:
- - Destination address and address group names.
- required: false
-
- dsri:
- description:
- - Enable DSRI to ignore HTTP server responses.
- - choice | disable | Disable DSRI.
- - choice | enable | Enable DSRI.
- required: false
- choices: ["disable", "enable"]
-
- dscp_value:
- description:
- - DSCP value.
- required: false
-
- dscp_negate:
- description:
- - Enable negated DSCP match.
- - choice | disable | Disable DSCP negate.
- - choice | enable | Enable DSCP negate.
- required: false
- choices: ["disable", "enable"]
-
- dscp_match:
- description:
- - Enable DSCP check.
- - choice | disable | Disable DSCP check.
- - choice | enable | Enable DSCP check.
- required: false
- choices: ["disable", "enable"]
-
- dnsfilter_profile:
- description:
- - Name of an existing DNS filter profile.
- required: false
-
- dlp_sensor:
- description:
- - Name of an existing DLP sensor.
- required: false
-
- disclaimer:
- description:
- - Enable/disable user authentication disclaimer.
- - choice | disable | Disable user authentication disclaimer.
- - choice | enable | Enable user authentication disclaimer.
- required: false
- choices: ["disable", "enable"]
-
- diffservcode_rev:
- description:
- - Change packet's reverse (reply) DiffServ to this value.
- required: false
-
- diffservcode_forward:
- description:
- - Change packet's DiffServ to this value.
- required: false
-
- diffserv_reverse:
- description:
- - Enable to change packet's reverse (reply) DiffServ values to the specified diffservcode-rev value.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- diffserv_forward:
- description:
- - Enable to change packet's DiffServ values to the specified diffservcode-forward value.
- - choice | disable | Disable WAN optimization.
- - choice | enable | Enable WAN optimization.
- required: false
- choices: ["disable", "enable"]
-
- devices:
- description:
- - Names of devices or device groups that can be matched by the policy.
- required: false
-
- delay_tcp_npu_session:
- description:
- - Enable TCP NPU session delay to guarantee packet order of 3-way handshake.
- - choice | disable | Disable TCP NPU session delay in order to guarantee packet order of 3-way handshake.
- - choice | enable | Enable TCP NPU session delay in order to guarantee packet order of 3-way handshake.
- required: false
- choices: ["disable", "enable"]
-
- custom_log_fields:
- description:
- - Custom fields to append to log messages for this policy.
- required: false
-
- comments:
- description:
- - Comment.
- required: false
-
- capture_packet:
- description:
- - Enable/disable capture packets.
- - choice | disable | Disable capture packets.
- - choice | enable | Enable capture packets.
- required: false
- choices: ["disable", "enable"]
-
- captive_portal_exempt:
- description:
- - Enable to exempt some users from the captive portal.
- - choice | disable | Disable exemption of captive portal.
- - choice | enable | Enable exemption of captive portal.
- required: false
- choices: ["disable", "enable"]
-
- block_notification:
- description:
- - Enable/disable block notification.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- av_profile:
- description:
- - Name of an existing Antivirus profile.
- required: false
-
- auto_asic_offload:
- description:
- - Enable/disable offloading security profile processing to CP processors.
- - choice | disable | Disable ASIC offloading.
- - choice | enable | Enable auto ASIC offloading.
- required: false
- choices: ["disable", "enable"]
-
- auth_redirect_addr:
- description:
- - HTTP-to-HTTPS redirect address for firewall authentication.
- required: false
-
- auth_path:
- description:
- - Enable/disable authentication-based routing.
- - choice | disable | Disable authentication-based routing.
- - choice | enable | Enable authentication-based routing.
- required: false
- choices: ["disable", "enable"]
-
- auth_cert:
- description:
- - HTTPS server certificate for policy authentication.
- required: false
-
- application_list:
- description:
- - Name of an existing Application list.
- required: false
-
- application:
- description:
- - Application ID list.
- required: false
-
- app_group:
- description:
- - Application group names.
- required: false
-
- app_category:
- description:
- - Application category ID list.
- required: false
-
- action:
- description:
- - Policy action (allow/deny/ipsec).
- - choice | deny | Blocks sessions that match the firewall policy.
- - choice | accept | Allows session that match the firewall policy.
- - choice | ipsec | Firewall policy becomes a policy-based IPsec VPN policy.
- required: false
- choices: ["deny", "accept", "ipsec"]
-
- vpn_dst_node:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED. This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- required: false
-
- vpn_dst_node_host:
- description:
- - VPN Destination Node Host.
- required: false
-
- vpn_dst_node_seq:
- description:
- - VPN Destination Node Seq.
- required: false
-
- vpn_dst_node_subnet:
- description:
- - VPN Destination Node Seq.
- required: false
-
- vpn_src_node:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED. This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- required: false
-
- vpn_src_node_host:
- description:
- - VPN Source Node Host.
- required: false
-
- vpn_src_node_seq:
- description:
- - VPN Source Node Seq.
- required: false
-
- vpn_src_node_subnet:
- description:
- - VPN Source Node.
- required: false
-
-
-'''
-
-EXAMPLES = '''
-- name: ADD VERY BASIC IPV4 POLICY WITH NO NAT (WIDE OPEN)
- fmgr_fwpol_ipv4:
- mode: "set"
- adom: "ansible"
- package_name: "default"
- name: "Basic_IPv4_Policy"
- comments: "Created by Ansible"
- action: "accept"
- dstaddr: "all"
- srcaddr: "all"
- dstintf: "any"
- srcintf: "any"
- logtraffic: "utm"
- service: "ALL"
- schedule: "always"
-
-- name: ADD VERY BASIC IPV4 POLICY WITH NAT AND MULTIPLE ENTRIES
- fmgr_fwpol_ipv4:
- mode: "set"
- adom: "ansible"
- package_name: "default"
- name: "Basic_IPv4_Policy_2"
- comments: "Created by Ansible"
- action: "accept"
- dstaddr: "google-play"
- srcaddr: "all"
- dstintf: "any"
- srcintf: "any"
- logtraffic: "utm"
- service: "HTTP, HTTPS"
- schedule: "always"
- nat: "enable"
- users: "karen, kevin"
-
-- name: ADD VERY BASIC IPV4 POLICY WITH NAT AND MULTIPLE ENTRIES AND SEC PROFILES
- fmgr_fwpol_ipv4:
- mode: "set"
- adom: "ansible"
- package_name: "default"
- name: "Basic_IPv4_Policy_3"
- comments: "Created by Ansible"
- action: "accept"
- dstaddr: "google-play, autoupdate.opera.com"
- srcaddr: "corp_internal"
- dstintf: "zone_wan1, zone_wan2"
- srcintf: "zone_int1"
- logtraffic: "utm"
- service: "HTTP, HTTPS"
- schedule: "always"
- nat: "enable"
- users: "karen, kevin"
- av_profile: "sniffer-profile"
- ips_sensor: "default"
-
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-
-def fmgr_firewall_policy_modify(fmgr, paramgram):
- """
- fmgr_firewall_policy -- Add/Set/Deletes Firewall Policy Objects defined in the "paramgram"
-
- :param fmgr: The fmgr object instance from fmgr_utils.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
-
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- mode = paramgram["mode"]
- adom = paramgram["adom"]
- # INIT A BASIC OBJECTS
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
-
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if mode in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/pkg/{pkg}/firewall/policy'.format(adom=adom, pkg=paramgram["package_name"])
- datagram = scrub_dict((prepare_dict(paramgram)))
- del datagram["package_name"]
- datagram = fmgr._tools.split_comma_strings_into_lists(datagram)
-
- # EVAL THE MODE PARAMETER FOR DELETE
- elif mode == "delete":
- url = '/pm/config/adom/{adom}/pkg/{pkg}/firewall' \
- '/policy/{policyid}'.format(adom=paramgram["adom"],
- pkg=paramgram["package_name"],
- policyid=paramgram["policyid"])
- datagram = {
- "policyid": paramgram["policyid"]
- }
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-#############
-# END METHODS
-#############
-
-
-def main():
- argument_spec = dict(
- adom=dict(type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
- package_name=dict(type="str", required=False, default="default"),
- fail_on_missing_dependency=dict(type="str", required=False, default="disable", choices=["enable",
- "disable"]),
- wsso=dict(required=False, type="str", choices=["disable", "enable"]),
- webfilter_profile=dict(required=False, type="str"),
- webcache_https=dict(required=False, type="str", choices=["disable", "enable"]),
- webcache=dict(required=False, type="str", choices=["disable", "enable"]),
- wccp=dict(required=False, type="str", choices=["disable", "enable"]),
- wanopt_profile=dict(required=False, type="str"),
- wanopt_peer=dict(required=False, type="str"),
- wanopt_passive_opt=dict(required=False, type="str", choices=["default", "transparent", "non-transparent"]),
- wanopt_detection=dict(required=False, type="str", choices=["active", "passive", "off"]),
- wanopt=dict(required=False, type="str", choices=["disable", "enable"]),
- waf_profile=dict(required=False, type="str"),
- vpntunnel=dict(required=False, type="str"),
- voip_profile=dict(required=False, type="str"),
- vlan_filter=dict(required=False, type="str"),
- vlan_cos_rev=dict(required=False, type="int"),
- vlan_cos_fwd=dict(required=False, type="int"),
- utm_status=dict(required=False, type="str", choices=["disable", "enable"]),
- users=dict(required=False, type="str"),
- url_category=dict(required=False, type="str"),
- traffic_shaper_reverse=dict(required=False, type="str"),
- traffic_shaper=dict(required=False, type="str"),
- timeout_send_rst=dict(required=False, type="str", choices=["disable", "enable"]),
- tcp_session_without_syn=dict(required=False, type="str", choices=["all", "data-only", "disable"]),
- tcp_mss_sender=dict(required=False, type="int"),
- tcp_mss_receiver=dict(required=False, type="int"),
- status=dict(required=False, type="str", choices=["disable", "enable"]),
- ssl_ssh_profile=dict(required=False, type="str"),
- ssl_mirror_intf=dict(required=False, type="str"),
- ssl_mirror=dict(required=False, type="str", choices=["disable", "enable"]),
- ssh_filter_profile=dict(required=False, type="str"),
- srcintf=dict(required=False, type="str"),
- srcaddr_negate=dict(required=False, type="str", choices=["disable", "enable"]),
- srcaddr=dict(required=False, type="str"),
- spamfilter_profile=dict(required=False, type="str"),
- session_ttl=dict(required=False, type="int"),
- service_negate=dict(required=False, type="str", choices=["disable", "enable"]),
- service=dict(required=False, type="str"),
- send_deny_packet=dict(required=False, type="str", choices=["disable", "enable"]),
- schedule_timeout=dict(required=False, type="str", choices=["disable", "enable"]),
- schedule=dict(required=False, type="str"),
- scan_botnet_connections=dict(required=False, type="str", choices=["disable", "block", "monitor"]),
- rtp_nat=dict(required=False, type="str", choices=["disable", "enable"]),
- rtp_addr=dict(required=False, type="str"),
- rsso=dict(required=False, type="str", choices=["disable", "enable"]),
- replacemsg_override_group=dict(required=False, type="str"),
- redirect_url=dict(required=False, type="str"),
- radius_mac_auth_bypass=dict(required=False, type="str", choices=["disable", "enable"]),
- profile_type=dict(required=False, type="str", choices=["single", "group"]),
- profile_protocol_options=dict(required=False, type="str"),
- profile_group=dict(required=False, type="str"),
- poolname=dict(required=False, type="str"),
- policyid=dict(required=False, type="str"),
- permit_stun_host=dict(required=False, type="str", choices=["disable", "enable"]),
- permit_any_host=dict(required=False, type="str", choices=["disable", "enable"]),
- per_ip_shaper=dict(required=False, type="str"),
- outbound=dict(required=False, type="str", choices=["disable", "enable"]),
- ntlm_guest=dict(required=False, type="str", choices=["disable", "enable"]),
- ntlm_enabled_browsers=dict(required=False, type="str"),
- ntlm=dict(required=False, type="str", choices=["disable", "enable"]),
- np_acceleration=dict(required=False, type="str", choices=["disable", "enable"]),
- natoutbound=dict(required=False, type="str", choices=["disable", "enable"]),
- natip=dict(required=False, type="str"),
- natinbound=dict(required=False, type="str", choices=["disable", "enable"]),
- nat=dict(required=False, type="str", choices=["disable", "enable"]),
- name=dict(required=False, type="str"),
- mms_profile=dict(required=False, type="str"),
- match_vip=dict(required=False, type="str", choices=["disable", "enable"]),
- logtraffic_start=dict(required=False, type="str", choices=["disable", "enable"]),
- logtraffic=dict(required=False, type="str", choices=["disable", "all", "utm"]),
- learning_mode=dict(required=False, type="str", choices=["disable", "enable"]),
- label=dict(required=False, type="str"),
- ips_sensor=dict(required=False, type="str"),
- ippool=dict(required=False, type="str", choices=["disable", "enable"]),
- internet_service_src_negate=dict(required=False, type="str", choices=["disable", "enable"]),
- internet_service_src_id=dict(required=False, type="str"),
- internet_service_src_custom=dict(required=False, type="str"),
- internet_service_src=dict(required=False, type="str", choices=["disable", "enable"]),
- internet_service_negate=dict(required=False, type="str", choices=["disable", "enable"]),
- internet_service_id=dict(required=False, type="str"),
- internet_service_custom=dict(required=False, type="str"),
- internet_service=dict(required=False, type="str", choices=["disable", "enable"]),
- inbound=dict(required=False, type="str", choices=["disable", "enable"]),
- identity_based_route=dict(required=False, type="str"),
- icap_profile=dict(required=False, type="str"),
- gtp_profile=dict(required=False, type="str"),
- groups=dict(required=False, type="str"),
- global_label=dict(required=False, type="str"),
- fsso_agent_for_ntlm=dict(required=False, type="str"),
- fsso=dict(required=False, type="str", choices=["disable", "enable"]),
- fixedport=dict(required=False, type="str", choices=["disable", "enable"]),
- firewall_session_dirty=dict(required=False, type="str", choices=["check-all", "check-new"]),
- dstintf=dict(required=False, type="str"),
- dstaddr_negate=dict(required=False, type="str", choices=["disable", "enable"]),
- dstaddr=dict(required=False, type="str"),
- dsri=dict(required=False, type="str", choices=["disable", "enable"]),
- dscp_value=dict(required=False, type="str"),
- dscp_negate=dict(required=False, type="str", choices=["disable", "enable"]),
- dscp_match=dict(required=False, type="str", choices=["disable", "enable"]),
- dnsfilter_profile=dict(required=False, type="str"),
- dlp_sensor=dict(required=False, type="str"),
- disclaimer=dict(required=False, type="str", choices=["disable", "enable"]),
- diffservcode_rev=dict(required=False, type="str"),
- diffservcode_forward=dict(required=False, type="str"),
- diffserv_reverse=dict(required=False, type="str", choices=["disable", "enable"]),
- diffserv_forward=dict(required=False, type="str", choices=["disable", "enable"]),
- devices=dict(required=False, type="str"),
- delay_tcp_npu_session=dict(required=False, type="str", choices=["disable", "enable"]),
- custom_log_fields=dict(required=False, type="str"),
- comments=dict(required=False, type="str"),
- capture_packet=dict(required=False, type="str", choices=["disable", "enable"]),
- captive_portal_exempt=dict(required=False, type="str", choices=["disable", "enable"]),
- block_notification=dict(required=False, type="str", choices=["disable", "enable"]),
- av_profile=dict(required=False, type="str"),
- auto_asic_offload=dict(required=False, type="str", choices=["disable", "enable"]),
- auth_redirect_addr=dict(required=False, type="str"),
- auth_path=dict(required=False, type="str", choices=["disable", "enable"]),
- auth_cert=dict(required=False, type="str"),
- application_list=dict(required=False, type="str"),
- application=dict(required=False, type="str"),
- app_group=dict(required=False, type="str"),
- app_category=dict(required=False, type="str"),
- action=dict(required=False, type="str", choices=["deny", "accept", "ipsec"]),
- vpn_dst_node=dict(required=False, type="list"),
- vpn_dst_node_host=dict(required=False, type="str"),
- vpn_dst_node_seq=dict(required=False, type="str"),
- vpn_dst_node_subnet=dict(required=False, type="str"),
- vpn_src_node=dict(required=False, type="list"),
- vpn_src_node_host=dict(required=False, type="str"),
- vpn_src_node_seq=dict(required=False, type="str"),
- vpn_src_node_subnet=dict(required=False, type="str"),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "package_name": module.params["package_name"],
- "wsso": module.params["wsso"],
- "webfilter-profile": module.params["webfilter_profile"],
- "webcache-https": module.params["webcache_https"],
- "webcache": module.params["webcache"],
- "wccp": module.params["wccp"],
- "wanopt-profile": module.params["wanopt_profile"],
- "wanopt-peer": module.params["wanopt_peer"],
- "wanopt-passive-opt": module.params["wanopt_passive_opt"],
- "wanopt-detection": module.params["wanopt_detection"],
- "wanopt": module.params["wanopt"],
- "waf-profile": module.params["waf_profile"],
- "vpntunnel": module.params["vpntunnel"],
- "voip-profile": module.params["voip_profile"],
- "vlan-filter": module.params["vlan_filter"],
- "vlan-cos-rev": module.params["vlan_cos_rev"],
- "vlan-cos-fwd": module.params["vlan_cos_fwd"],
- "utm-status": module.params["utm_status"],
- "users": module.params["users"],
- "url-category": module.params["url_category"],
- "traffic-shaper-reverse": module.params["traffic_shaper_reverse"],
- "traffic-shaper": module.params["traffic_shaper"],
- "timeout-send-rst": module.params["timeout_send_rst"],
- "tcp-session-without-syn": module.params["tcp_session_without_syn"],
- "tcp-mss-sender": module.params["tcp_mss_sender"],
- "tcp-mss-receiver": module.params["tcp_mss_receiver"],
- "status": module.params["status"],
- "ssl-ssh-profile": module.params["ssl_ssh_profile"],
- "ssl-mirror-intf": module.params["ssl_mirror_intf"],
- "ssl-mirror": module.params["ssl_mirror"],
- "ssh-filter-profile": module.params["ssh_filter_profile"],
- "srcintf": module.params["srcintf"],
- "srcaddr-negate": module.params["srcaddr_negate"],
- "srcaddr": module.params["srcaddr"],
- "spamfilter-profile": module.params["spamfilter_profile"],
- "session-ttl": module.params["session_ttl"],
- "service-negate": module.params["service_negate"],
- "service": module.params["service"],
- "send-deny-packet": module.params["send_deny_packet"],
- "schedule-timeout": module.params["schedule_timeout"],
- "schedule": module.params["schedule"],
- "scan-botnet-connections": module.params["scan_botnet_connections"],
- "rtp-nat": module.params["rtp_nat"],
- "rtp-addr": module.params["rtp_addr"],
- "rsso": module.params["rsso"],
- "replacemsg-override-group": module.params["replacemsg_override_group"],
- "redirect-url": module.params["redirect_url"],
- "radius-mac-auth-bypass": module.params["radius_mac_auth_bypass"],
- "profile-type": module.params["profile_type"],
- "profile-protocol-options": module.params["profile_protocol_options"],
- "profile-group": module.params["profile_group"],
- "poolname": module.params["poolname"],
- "policyid": module.params["policyid"],
- "permit-stun-host": module.params["permit_stun_host"],
- "permit-any-host": module.params["permit_any_host"],
- "per-ip-shaper": module.params["per_ip_shaper"],
- "outbound": module.params["outbound"],
- "ntlm-guest": module.params["ntlm_guest"],
- "ntlm-enabled-browsers": module.params["ntlm_enabled_browsers"],
- "ntlm": module.params["ntlm"],
- "np-acceleration": module.params["np_acceleration"],
- "natoutbound": module.params["natoutbound"],
- "natip": module.params["natip"],
- "natinbound": module.params["natinbound"],
- "nat": module.params["nat"],
- "name": module.params["name"],
- "mms-profile": module.params["mms_profile"],
- "match-vip": module.params["match_vip"],
- "logtraffic-start": module.params["logtraffic_start"],
- "logtraffic": module.params["logtraffic"],
- "learning-mode": module.params["learning_mode"],
- "label": module.params["label"],
- "ips-sensor": module.params["ips_sensor"],
- "ippool": module.params["ippool"],
- "internet-service-src-negate": module.params["internet_service_src_negate"],
- "internet-service-src-id": module.params["internet_service_src_id"],
- "internet-service-src-custom": module.params["internet_service_src_custom"],
- "internet-service-src": module.params["internet_service_src"],
- "internet-service-negate": module.params["internet_service_negate"],
- "internet-service-id": module.params["internet_service_id"],
- "internet-service-custom": module.params["internet_service_custom"],
- "internet-service": module.params["internet_service"],
- "inbound": module.params["inbound"],
- "identity-based-route": module.params["identity_based_route"],
- "icap-profile": module.params["icap_profile"],
- "gtp-profile": module.params["gtp_profile"],
- "groups": module.params["groups"],
- "global-label": module.params["global_label"],
- "fsso-agent-for-ntlm": module.params["fsso_agent_for_ntlm"],
- "fsso": module.params["fsso"],
- "fixedport": module.params["fixedport"],
- "firewall-session-dirty": module.params["firewall_session_dirty"],
- "dstintf": module.params["dstintf"],
- "dstaddr-negate": module.params["dstaddr_negate"],
- "dstaddr": module.params["dstaddr"],
- "dsri": module.params["dsri"],
- "dscp-value": module.params["dscp_value"],
- "dscp-negate": module.params["dscp_negate"],
- "dscp-match": module.params["dscp_match"],
- "dnsfilter-profile": module.params["dnsfilter_profile"],
- "dlp-sensor": module.params["dlp_sensor"],
- "disclaimer": module.params["disclaimer"],
- "diffservcode-rev": module.params["diffservcode_rev"],
- "diffservcode-forward": module.params["diffservcode_forward"],
- "diffserv-reverse": module.params["diffserv_reverse"],
- "diffserv-forward": module.params["diffserv_forward"],
- "devices": module.params["devices"],
- "delay-tcp-npu-session": module.params["delay_tcp_npu_session"],
- "custom-log-fields": module.params["custom_log_fields"],
- "comments": module.params["comments"],
- "capture-packet": module.params["capture_packet"],
- "captive-portal-exempt": module.params["captive_portal_exempt"],
- "block-notification": module.params["block_notification"],
- "av-profile": module.params["av_profile"],
- "auto-asic-offload": module.params["auto_asic_offload"],
- "auth-redirect-addr": module.params["auth_redirect_addr"],
- "auth-path": module.params["auth_path"],
- "auth-cert": module.params["auth_cert"],
- "application-list": module.params["application_list"],
- "application": module.params["application"],
- "app-group": module.params["app_group"],
- "app-category": module.params["app_category"],
- "action": module.params["action"],
- "vpn_dst_node": {
- "host": module.params["vpn_dst_node_host"],
- "seq": module.params["vpn_dst_node_seq"],
- "subnet": module.params["vpn_dst_node_subnet"],
- },
- "vpn_src_node": {
- "host": module.params["vpn_src_node_host"],
- "seq": module.params["vpn_src_node_seq"],
- "subnet": module.params["vpn_src_node_subnet"],
- }
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- list_overrides = ['vpn_dst_node', 'vpn_src_node']
- paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides,
- paramgram=paramgram, module=module)
-
- # BEGIN MODULE-SPECIFIC LOGIC -- THINGS NEED TO HAPPEN DEPENDING ON THE ENDPOINT AND OPERATION
- results = DEFAULT_RESULT_OBJ
- try:
- if paramgram["mode"] == "delete":
- # WE NEED TO GET THE POLICY ID FROM THE NAME OF THE POLICY TO DELETE IT
- url = '/pm/config/adom/{adom}/pkg/{pkg}/firewall' \
- '/policy/'.format(adom=paramgram["adom"],
- pkg=paramgram["package_name"])
- datagram = {
- "filter": ["name", "==", paramgram["name"]]
- }
- response = fmgr.process_request(url, datagram, FMGRMethods.GET)
- try:
- if response[1][0]["policyid"]:
- policy_id = response[1][0]["policyid"]
- paramgram["policyid"] = policy_id
- except BaseException:
- fmgr.return_response(module=module, results=response, good_codes=[0, ], stop_on_success=True,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram),
- msg="Couldn't find policy ID number for policy name specified.")
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- results = fmgr_firewall_policy_modify(fmgr, paramgram)
- if module.params["fail_on_missing_dependency"] == "disable":
- fmgr.govern_response(module=module, results=results, good_codes=[0, -9998],
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- if module.params["fail_on_missing_dependency"] == "enable" and results[0] == -10131:
- fmgr.govern_response(module=module, results=results, good_codes=[0, ], failed=True, skipped=False,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_fwpol_package.py b/plugins/modules/network/fortimanager/fmgr_fwpol_package.py
deleted file mode 100644
index d70b9b9fd8..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_fwpol_package.py
+++ /dev/null
@@ -1,485 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- "metadata_version": "1.1",
- "status": ["preview"],
- "supported_by": "community"
-}
-
-DOCUMENTATION = '''
----
-module: fmgr_fwpol_package
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Manages FortiManager Firewall Policies Packages.
-description:
- - Manages FortiManager Firewall Policies Packages. Policy Packages contain one or more Firewall Policies/Rules and
- are distritbuted via FortiManager to Fortigates.
- - This module controls the creation/edit/delete/assign of these packages.
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- choices: ['add', 'set', 'delete']
- default: add
-
- name:
- description:
- - Name of the FortiManager package or folder.
- required: True
-
- object_type:
- description:
- - Are we managing packages or folders, or installing packages?
- required: True
- choices: ['pkg','folder','install']
-
- package_folder:
- description:
- - Name of the folder you want to put the package into.
- required: false
-
- central_nat:
- description:
- - Central NAT setting.
- required: false
- choices: ['enable', 'disable']
- default: disable
-
- fwpolicy_implicit_log:
- description:
- - Implicit Log setting for all IPv4 policies in package.
- required: false
- choices: ['enable', 'disable']
- default: disable
-
- fwpolicy6_implicit_log:
- description:
- - Implicit Log setting for all IPv6 policies in package.
- required: false
- choices: ['enable', 'disable']
- default: disable
-
- inspection_mode:
- description:
- - Inspection mode setting for the policies flow or proxy.
- required: false
- choices: ['flow', 'proxy']
- default: flow
-
- ngfw_mode:
- description:
- - NGFW mode setting for the policies flow or proxy.
- required: false
- choices: ['profile-based', 'policy-based']
- default: profile-based
-
- ssl_ssh_profile:
- description:
- - if policy-based ngfw-mode, refer to firewall ssl-ssh-profile.
- required: false
-
- scope_members:
- description:
- - The devices or scope that you want to assign this policy package to.
- required: false
-
- scope_members_vdom:
- description:
- - The members VDOM you want to assign the package to.
- required: false
- default: root
-
- parent_folder:
- description:
- - The parent folder name you want to add this object under.
- required: false
-
-'''
-
-
-EXAMPLES = '''
-- name: CREATE BASIC POLICY PACKAGE
- fmgr_fwpol_package:
- adom: "ansible"
- mode: "add"
- name: "testPackage"
- object_type: "pkg"
-
-- name: ADD PACKAGE WITH TARGETS
- fmgr_fwpol_package:
- mode: "add"
- adom: "ansible"
- name: "ansibleTestPackage1"
- object_type: "pkg"
- inspection_mode: "flow"
- ngfw_mode: "profile-based"
- scope_members: "seattle-fgt02, seattle-fgt03"
-
-- name: ADD FOLDER
- fmgr_fwpol_package:
- mode: "add"
- adom: "ansible"
- name: "ansibleTestFolder1"
- object_type: "folder"
-
-- name: ADD PACKAGE INTO PARENT FOLDER
- fmgr_fwpol_package:
- mode: "set"
- adom: "ansible"
- name: "ansibleTestPackage2"
- object_type: "pkg"
- parent_folder: "ansibleTestFolder1"
-
-- name: ADD FOLDER INTO PARENT FOLDER
- fmgr_fwpol_package:
- mode: "set"
- adom: "ansible"
- name: "ansibleTestFolder2"
- object_type: "folder"
- parent_folder: "ansibleTestFolder1"
-
-- name: INSTALL PACKAGE
- fmgr_fwpol_package:
- mode: "set"
- adom: "ansible"
- name: "ansibleTestPackage1"
- object_type: "install"
- scope_members: "seattle-fgt03, seattle-fgt02"
-
-- name: REMOVE PACKAGE
- fmgr_fwpol_package:
- mode: "delete"
- adom: "ansible"
- name: "ansibleTestPackage1"
- object_type: "pkg"
-
-- name: REMOVE NESTED PACKAGE
- fmgr_fwpol_package:
- mode: "delete"
- adom: "ansible"
- name: "ansibleTestPackage2"
- object_type: "pkg"
- parent_folder: "ansibleTestFolder1"
-
-- name: REMOVE NESTED FOLDER
- fmgr_fwpol_package:
- mode: "delete"
- adom: "ansible"
- name: "ansibleTestFolder2"
- object_type: "folder"
- parent_folder: "ansibleTestFolder1"
-
-- name: REMOVE FOLDER
- fmgr_fwpol_package:
- mode: "delete"
- adom: "ansible"
- name: "ansibleTestFolder1"
- object_type: "folder"
-'''
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods
-
-
-def fmgr_fwpol_package(fmgr, paramgram):
- """
- This function will create FMGR Firewall Policy Packages, or delete them. It is also capable of assigning packages.
- This function DOES NOT install the package. See the function fmgr_fwpol_package_install()
-
- :param fmgr: The fmgr object instance from fmgr_utils.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
-
- :return: The response from the FortiManager
- :rtype: dict
- """
- if paramgram["mode"] in ['set', 'add']:
- url = '/pm/pkg/adom/{adom}'.format(adom=paramgram["adom"])
- members_list = []
-
- # CHECK FOR SCOPE MEMBERS AND CREATE THAT DICT
- if paramgram["scope_members"] is not None:
- members = FMGRCommon.split_comma_strings_into_lists(paramgram["scope_members"])
- for member in members:
- scope_dict = {
- "name": member,
- "vdom": paramgram["scope_members_vdom"],
- }
- members_list.append(scope_dict)
-
- # IF PARENT FOLDER IS NOT DEFINED
- if paramgram["parent_folder"] is None:
- datagram = {
- "type": paramgram["object_type"],
- "name": paramgram["name"],
- "scope member": members_list,
- "package settings": {
- "central-nat": paramgram["central-nat"],
- "fwpolicy-implicit-log": paramgram["fwpolicy-implicit-log"],
- "fwpolicy6-implicit-log": paramgram["fwpolicy6-implicit-log"],
- "inspection-mode": paramgram["inspection-mode"],
- "ngfw-mode": paramgram["ngfw-mode"],
- }
- }
-
- if paramgram["ngfw-mode"] == "policy-based" and paramgram["ssl-ssh-profile"] is not None:
- datagram["package settings"]["ssl-ssh-profile"] = paramgram["ssl-ssh-profile"]
-
- # IF PARENT FOLDER IS DEFINED
- if paramgram["parent_folder"] is not None:
- datagram = {
- "type": "folder",
- "name": paramgram["parent_folder"],
- "subobj": [{
- "name": paramgram["name"],
- "scope member": members_list,
- "type": "pkg",
- "package settings": {
- "central-nat": paramgram["central-nat"],
- "fwpolicy-implicit-log": paramgram["fwpolicy-implicit-log"],
- "fwpolicy6-implicit-log": paramgram["fwpolicy6-implicit-log"],
- "inspection-mode": paramgram["inspection-mode"],
- "ngfw-mode": paramgram["ngfw-mode"],
- }
- }]
- }
-
- # NORMAL DELETE NO PARENT
- if paramgram["mode"] == "delete" and paramgram["parent_folder"] is None:
- datagram = {
- "name": paramgram["name"]
- }
- # SET DELETE URL
- url = '/pm/pkg/adom/{adom}/{name}'.format(adom=paramgram["adom"], name=paramgram["name"])
-
- # DELETE WITH PARENT
- if paramgram["mode"] == "delete" and paramgram["parent_folder"] is not None:
- datagram = {
- "name": paramgram["name"]
- }
- # SET DELETE URL
- url = '/pm/pkg/adom/{adom}/{parent_folder}/{name}'.format(adom=paramgram["adom"],
- name=paramgram["name"],
- parent_folder=paramgram["parent_folder"])
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def fmgr_fwpol_package_folder(fmgr, paramgram):
- """
- This function will create folders for firewall packages. It can create down to two levels deep.
- We haven't yet tested for any more layers below two levels.
- parent_folders for multiple levels may need to defined as "level1/level2/level3" for the URL parameters and such.
-
- :param fmgr: The fmgr object instance from fmgr_utils.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
-
- :return: The response from the FortiManager
- :rtype: dict
- """
- if paramgram["mode"] in ['set', 'add']:
- url = '/pm/pkg/adom/{adom}'.format(adom=paramgram["adom"])
- # IF PARENT FOLDER IS NOT DEFINED
- if paramgram["parent_folder"] is None:
- datagram = {
- "type": paramgram["object_type"],
- "name": paramgram["name"],
- }
-
- # IF PARENT FOLDER IS DEFINED
- if paramgram["parent_folder"] is not None:
- datagram = {
- "type": paramgram["object_type"],
- "name": paramgram["parent_folder"],
- "subobj": [{
- "name": paramgram["name"],
- "type": paramgram["object_type"],
-
- }]
- }
- # NORMAL DELETE NO PARENT
- if paramgram["mode"] == "delete" and paramgram["parent_folder"] is None:
- datagram = {
- "name": paramgram["name"]
- }
- # SET DELETE URL
- url = '/pm/pkg/adom/{adom}/{name}'.format(adom=paramgram["adom"], name=paramgram["name"])
-
- # DELETE WITH PARENT
- if paramgram["mode"] == "delete" and paramgram["parent_folder"] is not None:
- datagram = {
- "name": paramgram["name"]
- }
- # SET DELETE URL
- url = '/pm/pkg/adom/{adom}/{parent_folder}/{name}'.format(adom=paramgram["adom"],
- name=paramgram["name"],
- parent_folder=paramgram["parent_folder"])
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-def fmgr_fwpol_package_install(fmgr, paramgram):
- """
- This method/function installs FMGR FW Policy Packages to the scope members defined in the playbook.
-
- :param fmgr: The fmgr object instance from fmgr_utils.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
-
- :return: The response from the FortiManager
- :rtype: dict
- """
- # INIT BLANK MEMBERS LIST
- members_list = []
- # USE THE PARSE CSV FUNCTION TO GET A LIST FORMAT OF THE MEMBERS
- members = FMGRCommon.split_comma_strings_into_lists(paramgram["scope_members"])
- # USE THAT LIST TO BUILD THE DICTIONARIES NEEDED, AND ADD TO THE BLANK MEMBERS LIST
- for member in members:
- scope_dict = {
- "name": member,
- "vdom": paramgram["scope_members_vdom"],
- }
- members_list.append(scope_dict)
- # THEN FOR THE DATAGRAM, USING THE MEMBERS LIST CREATED ABOVE
- datagram = {
- "adom": paramgram["adom"],
- "pkg": paramgram["name"],
- "scope": members_list
- }
- # EXECUTE THE INSTALL REQUEST
- url = '/securityconsole/install/package'
- response = fmgr.process_request(url, datagram, FMGRMethods.EXEC)
- return response
-
-
-def main():
- argument_spec = dict(
- adom=dict(required=False, type="str", default="root"),
- mode=dict(choices=["add", "set", "delete"], type="str", default="add"),
-
- name=dict(required=False, type="str"),
- object_type=dict(required=True, type="str", choices=['pkg', 'folder', 'install']),
- package_folder=dict(required=False, type="str"),
- central_nat=dict(required=False, type="str", default="disable", choices=['enable', 'disable']),
- fwpolicy_implicit_log=dict(required=False, type="str", default="disable", choices=['enable', 'disable']),
- fwpolicy6_implicit_log=dict(required=False, type="str", default="disable", choices=['enable', 'disable']),
- inspection_mode=dict(required=False, type="str", default="flow", choices=['flow', 'proxy']),
- ngfw_mode=dict(required=False, type="str", default="profile-based", choices=['profile-based', 'policy-based']),
- ssl_ssh_profile=dict(required=False, type="str"),
- scope_members=dict(required=False, type="str"),
- scope_members_vdom=dict(required=False, type="str", default="root"),
- parent_folder=dict(required=False, type="str"),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE DATAGRAM
- paramgram = {
- "adom": module.params["adom"],
- "name": module.params["name"],
- "mode": module.params["mode"],
- "object_type": module.params["object_type"],
- "package-folder": module.params["package_folder"],
- "central-nat": module.params["central_nat"],
- "fwpolicy-implicit-log": module.params["fwpolicy_implicit_log"],
- "fwpolicy6-implicit-log": module.params["fwpolicy6_implicit_log"],
- "inspection-mode": module.params["inspection_mode"],
- "ngfw-mode": module.params["ngfw_mode"],
- "ssl-ssh-profile": module.params["ssl_ssh_profile"],
- "scope_members": module.params["scope_members"],
- "scope_members_vdom": module.params["scope_members_vdom"],
- "parent_folder": module.params["parent_folder"],
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- # BEGIN MODULE-SPECIFIC LOGIC -- THINGS NEED TO HAPPEN DEPENDING ON THE ENDPOINT AND OPERATION
- results = DEFAULT_RESULT_OBJ
-
- try:
- if paramgram["object_type"] == "pkg":
- results = fmgr_fwpol_package(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # IF THE object_type IS FOLDER LETS RUN THAT METHOD
- if paramgram["object_type"] == "folder":
- results = fmgr_fwpol_package_folder(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # IF THE object_type IS INSTALL AND NEEDED PARAMETERS ARE DEFINED INSTALL THE PACKAGE
- if paramgram["scope_members"] is not None and paramgram["name"] is not None and\
- paramgram["object_type"] == "install":
- results = fmgr_fwpol_package_install(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_ha.py b/plugins/modules/network/fortimanager/fmgr_ha.py
deleted file mode 100644
index cac6697453..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_ha.py
+++ /dev/null
@@ -1,355 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- "metadata_version": "1.1",
- "status": ["preview"],
- "supported_by": "community"
-}
-
-DOCUMENTATION = '''
----
-module: fmgr_ha
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Manages the High-Availability State of FortiManager Clusters and Nodes.
-description: Change HA state or settings of FortiManager nodes (Standalone/Master/Slave).
-
-options:
- fmgr_ha_mode:
- description:
- - Sets the role of the FortiManager host for HA.
- required: false
- choices: ["standalone", "master", "slave"]
-
- fmgr_ha_peer_ipv4:
- description:
- - Sets the IPv4 address of a HA peer.
- required: false
-
- fmgr_ha_peer_ipv6:
- description:
- - Sets the IPv6 address of a HA peer.
- required: false
-
- fmgr_ha_peer_sn:
- description:
- - Sets the HA Peer Serial Number.
- required: false
-
- fmgr_ha_peer_status:
- description:
- - Sets the peer status to enable or disable.
- required: false
- choices: ["enable", "disable"]
-
- fmgr_ha_cluster_pw:
- description:
- - Sets the password for the HA cluster. Only required once. System remembers between HA mode switches.
- required: false
-
- fmgr_ha_cluster_id:
- description:
- - Sets the ID number of the HA cluster. Defaults to 1.
- required: false
- default: 1
-
- fmgr_ha_hb_threshold:
- description:
- - Sets heartbeat lost threshold (1-255).
- required: false
- default: 3
-
- fmgr_ha_hb_interval:
- description:
- - Sets the heartbeat interval (1-255).
- required: false
- default: 5
-
- fmgr_ha_file_quota:
- description:
- - Sets the File quota in MB (2048-20480).
- required: false
- default: 4096
-'''
-
-
-EXAMPLES = '''
-- name: SET FORTIMANAGER HA NODE TO MASTER
- fmgr_ha:
- fmgr_ha_mode: "master"
- fmgr_ha_cluster_pw: "fortinet"
- fmgr_ha_cluster_id: "1"
-
-- name: SET FORTIMANAGER HA NODE TO SLAVE
- fmgr_ha:
- fmgr_ha_mode: "slave"
- fmgr_ha_cluster_pw: "fortinet"
- fmgr_ha_cluster_id: "1"
-
-- name: SET FORTIMANAGER HA NODE TO STANDALONE
- fmgr_ha:
- fmgr_ha_mode: "standalone"
-
-- name: ADD FORTIMANAGER HA PEER
- fmgr_ha:
- fmgr_ha_peer_ipv4: "192.168.1.254"
- fmgr_ha_peer_sn: "FMG-VM1234567890"
- fmgr_ha_peer_status: "enable"
-
-- name: CREATE CLUSTER ON MASTER
- fmgr_ha:
- fmgr_ha_mode: "master"
- fmgr_ha_cluster_pw: "fortinet"
- fmgr_ha_cluster_id: "1"
- fmgr_ha_hb_threshold: "10"
- fmgr_ha_hb_interval: "15"
- fmgr_ha_file_quota: "2048"
-'''
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-
-
-def fmgr_set_ha_mode(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- # INIT A BASIC OBJECTS
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
-
- if paramgram["fmgr_ha_cluster_pw"] is not None and str(paramgram["fmgr_ha_mode"].lower()) != "standalone":
- datagram = {
- "mode": paramgram["fmgr_ha_mode"],
- "file-quota": paramgram["fmgr_ha_file_quota"],
- "hb-interval": paramgram["fmgr_ha_hb_interval"],
- "hb-lost-threshold": paramgram["fmgr_ha_hb_threshold"],
- "password": paramgram["fmgr_ha_cluster_pw"],
- "clusterid": paramgram["fmgr_ha_cluster_id"]
- }
- elif str(paramgram["fmgr_ha_mode"].lower()) == "standalone":
- datagram = {
- "mode": paramgram["fmgr_ha_mode"],
- "file-quota": paramgram["fmgr_ha_file_quota"],
- "hb-interval": paramgram["fmgr_ha_hb_interval"],
- "hb-lost-threshold": paramgram["fmgr_ha_hb_threshold"],
- "clusterid": paramgram["fmgr_ha_cluster_id"]
- }
-
- url = '/cli/global/system/ha'
- response = fmgr.process_request(url, datagram, FMGRMethods.SET)
- return response
-
-
-def fmgr_get_ha_peer_list(fmgr):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- # INIT A BASIC OBJECTS
- response = DEFAULT_RESULT_OBJ
-
- datagram = {}
- paramgram = {}
-
- url = '/cli/global/system/ha/peer/'
- response = fmgr.process_request(url, datagram, FMGRMethods.GET)
- return response
-
-
-def fmgr_set_ha_peer(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- datagram = {
- "ip": paramgram["fmgr_ha_peer_ipv4"],
- "ip6": paramgram["fmgr_ha_peer_ipv6"],
- "serial-number": paramgram["fmgr_ha_peer_sn"],
- "status": paramgram["fmgr_ha_peer_status"],
- "id": paramgram["peer_id"]
- }
-
- url = '/cli/global/system/ha/peer/'
- response = fmgr.process_request(url, datagram, FMGRMethods.SET)
- return response
-
-
-def main():
- argument_spec = dict(
- fmgr_ha_mode=dict(required=False, type="str", choices=["standalone", "master", "slave"]),
- fmgr_ha_cluster_pw=dict(required=False, type="str", no_log=True),
- fmgr_ha_peer_status=dict(required=False, type="str", choices=["enable", "disable"]),
- fmgr_ha_peer_sn=dict(required=False, type="str"),
- fmgr_ha_peer_ipv4=dict(required=False, type="str"),
- fmgr_ha_peer_ipv6=dict(required=False, type="str"),
- fmgr_ha_hb_threshold=dict(required=False, type="int", default=3),
- fmgr_ha_hb_interval=dict(required=False, type="int", default=5),
- fmgr_ha_file_quota=dict(required=False, type="int", default=4096),
- fmgr_ha_cluster_id=dict(required=False, type="int", default=1)
- )
-
- required_if = [
- ['fmgr_ha_peer_ipv4', 'present', ['fmgr_ha_peer_sn', 'fmgr_ha_peer_status']],
- ['fmgr_ha_peer_ipv6', 'present', ['fmgr_ha_peer_sn', 'fmgr_ha_peer_status']],
- ['fmgr_ha_mode', 'master', ['fmgr_ha_cluster_pw', 'fmgr_ha_cluster_id']],
- ['fmgr_ha_mode', 'slave', ['fmgr_ha_cluster_pw', 'fmgr_ha_cluster_id']],
- ]
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, required_if=required_if)
- paramgram = {
- "fmgr_ha_mode": module.params["fmgr_ha_mode"],
- "fmgr_ha_cluster_pw": module.params["fmgr_ha_cluster_pw"],
- "fmgr_ha_peer_status": module.params["fmgr_ha_peer_status"],
- "fmgr_ha_peer_sn": module.params["fmgr_ha_peer_sn"],
- "fmgr_ha_peer_ipv4": module.params["fmgr_ha_peer_ipv4"],
- "fmgr_ha_peer_ipv6": module.params["fmgr_ha_peer_ipv6"],
- "fmgr_ha_hb_threshold": module.params["fmgr_ha_hb_threshold"],
- "fmgr_ha_hb_interval": module.params["fmgr_ha_hb_interval"],
- "fmgr_ha_file_quota": module.params["fmgr_ha_file_quota"],
- "fmgr_ha_cluster_id": module.params["fmgr_ha_cluster_id"],
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- # INIT FLAGS AND COUNTERS
- get_ha_peers = 0
- results = DEFAULT_RESULT_OBJ
- try:
- if any(v is not None for v in (paramgram["fmgr_ha_peer_sn"], paramgram["fmgr_ha_peer_ipv4"],
- paramgram["fmgr_ha_peer_ipv6"], paramgram["fmgr_ha_peer_status"])):
- get_ha_peers = 1
- except Exception as err:
- raise FMGBaseException(err)
- try:
- # IF HA MODE IS NOT NULL, SWITCH THAT
- if paramgram["fmgr_ha_mode"] is not None:
- if (str.lower(paramgram["fmgr_ha_mode"]) != "standalone" and paramgram["fmgr_ha_cluster_pw"] is not None)\
- or str.lower(paramgram["fmgr_ha_mode"]) == "standalone":
- results = fmgr_set_ha_mode(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, stop_on_success=False,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- elif str.lower(paramgram["fmgr_ha_mode"]) != "standalone" and\
- paramgram["fmgr_ha_mode"] is not None and\
- paramgram["fmgr_ha_cluster_pw"] is None:
- module.exit_json(msg="If setting HA Mode of MASTER or SLAVE, you must specify a cluster password")
-
- except Exception as err:
- raise FMGBaseException(err)
- # IF GET_HA_PEERS IS ENABLED, LETS PROCESS THE PEERS
- try:
- if get_ha_peers == 1:
- # GET THE CURRENT LIST OF PEERS FROM THE NODE
- peers = fmgr_get_ha_peer_list(fmgr)
- # GET LENGTH OF RETURNED PEERS LIST AND ADD ONE FOR THE NEXT ID
- paramgram["next_peer_id"] = len(peers[1]) + 1
- # SET THE ACTUAL NUMBER OF PEERS
- num_of_peers = len(peers[1])
- # SET THE PEER ID FOR DISABLE METHOD
- paramgram["peer_id"] = len(peers) - 1
- # SET THE PEER LOOPCOUNT TO 1 TO START THE LOOP
- peer_loopcount = 1
-
- # LOOP THROUGH PEERS TO FIND THE SERIAL NUMBER MATCH TO GET THE RIGHT PEER ID
- # IDEA BEING WE DON'T WANT TO SUBMIT A BAD peer_id THAT DOESN'T JIVE WITH CURRENT DB ON FMG
- # SO LETS SEARCH FOR IT, AND IF WE FIND IT, WE WILL CHANGE THE PEER ID VARIABLES TO MATCH
- # IF NOT FOUND, LIFE GOES ON AND WE ASSUME THAT WE'RE ADDING A PEER
- # AT WHICH POINT THE next_peer_id VARIABLE WILL HAVE THE RIGHT PRIMARY KEY
-
- if paramgram["fmgr_ha_peer_sn"] is not None:
- while peer_loopcount <= num_of_peers:
- # GET THE SERIAL NUMBER FOR CURRENT PEER IN LOOP TO COMPARE TO SN IN PLAYBOOK
- try:
- sn_compare = peers[1][peer_loopcount - 1]["serial-number"]
- # IF THE SN IN THE PEERS MATCHES THE PLAYBOOK SN, SET THE IDS
- if sn_compare == paramgram["fmgr_ha_peer_sn"]:
- paramgram["peer_id"] = peer_loopcount
- paramgram["next_peer_id"] = paramgram["peer_id"]
- except Exception as err:
- raise FMGBaseException(err)
- # ADVANCE THE LOOP AND REPEAT UNTIL DONE
- peer_loopcount += 1
-
- # IF THE PEER STATUS ISN'T IN THE PLAYBOOK, ASSUME ITS ENABLE
- if paramgram["fmgr_ha_peer_status"] is None:
- paramgram["fmgr_ha_peer_status"] = "enable"
-
- # IF THE PEER STATUS IS ENABLE, USE THE next_peer_id IN THE API CALL FOR THE ID
- if paramgram["fmgr_ha_peer_status"] == "enable":
- results = fmgr_set_ha_peer(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, stop_on_success=True,
- ansible_facts=fmgr.construct_ansible_facts(results,
- module.params, paramgram))
-
- # IF THE PEER STATUS IS DISABLE, WE HAVE TO HANDLE THAT A BIT DIFFERENTLY
- # JUST USING TWO DIFFERENT peer_id 's HERE
- if paramgram["fmgr_ha_peer_status"] == "disable":
- results = fmgr_set_ha_peer(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, stop_on_success=True,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_provisioning.py b/plugins/modules/network/fortimanager/fmgr_provisioning.py
deleted file mode 100644
index 28fa5fbabd..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_provisioning.py
+++ /dev/null
@@ -1,364 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_provisioning
-author: Andrew Welsh (@Ghilli3)
-short_description: Provision devices via FortiMananger
-description:
- - Add model devices on the FortiManager using jsonrpc API and have them pre-configured,
- so when central management is configured, the configuration is pushed down to the
- registering devices
-
-options:
- adom:
- description:
- - The administrative domain (admon) the configuration belongs to
- required: true
- vdom:
- description:
- - The virtual domain (vdom) the configuration belongs to
- host:
- description:
- - The FortiManager's Address.
- required: true
- username:
- description:
- - The username to log into the FortiManager
- required: true
- password:
- description:
- - The password associated with the username account.
- required: false
-
- policy_package:
- description:
- - The name of the policy package to be assigned to the device.
- required: True
- name:
- description:
- - The name of the device to be provisioned.
- required: True
- group:
- description:
- - The name of the device group the provisioned device can belong to.
- required: False
- serial:
- description:
- - The serial number of the device that will be provisioned.
- required: True
- platform:
- description:
- - The platform of the device, such as model number or VM.
- required: True
- description:
- description:
- - Description of the device to be provisioned.
- required: False
- os_version:
- description:
- - The Fortinet OS version to be used for the device, such as 5.0 or 6.0.
- required: True
- minor_release:
- description:
- - The minor release number such as 6.X.1, as X being the minor release.
- required: False
- patch_release:
- description:
- - The patch release number such as 6.0.X, as X being the patch release.
- required: False
- os_type:
- description:
- - The Fortinet OS type to be pushed to the device, such as 'FOS' for FortiOS.
- required: True
-'''
-
-EXAMPLES = '''
-- name: Create FGT1 Model Device
- fmgr_provisioning:
- host: "{{ inventory_hostname }}"
- username: "{{ username }}"
- password: "{{ password }}"
- adom: "root"
- vdom: "root"
- policy_package: "default"
- name: "FGT1"
- group: "Ansible"
- serial: "FGVM000000117994"
- platform: "FortiGate-VM64"
- description: "Provisioned by Ansible"
- os_version: '6.0'
- minor_release: 0
- patch_release: 0
- os_type: 'fos'
-
-
-- name: Create FGT2 Model Device
- fmgr_provisioning:
- host: "{{ inventory_hostname }}"
- username: "{{ username }}"
- password: "{{ password }}"
- adom: "root"
- vdom: "root"
- policy_package: "test_pp"
- name: "FGT2"
- group: "Ansible"
- serial: "FGVM000000117992"
- platform: "FortiGate-VM64"
- description: "Provisioned by Ansible"
- os_version: '5.0'
- minor_release: 6
- patch_release: 0
- os_type: 'fos'
-
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import AnsibleFortiManager
-
-# check for pyFMG lib
-try:
- from pyFMG.fortimgr import FortiManager
- HAS_PYFMGR = True
-except ImportError:
- HAS_PYFMGR = False
-
-
-def dev_group_exists(fmg, dev_grp_name, adom):
- datagram = {
- 'adom': adom,
- 'name': dev_grp_name,
- }
-
- url = '/dvmdb/adom/{adom}/group/{dev_grp_name}'.format(adom=adom, dev_grp_name=dev_grp_name)
- response = fmg.get(url, datagram)
- return response
-
-
-def prov_template_exists(fmg, prov_template, adom, vdom):
- datagram = {
- 'name': prov_template,
- 'adom': adom,
- }
-
- url = '/pm/devprof/adom/{adom}/devprof/{name}'.format(adom=adom, name=prov_template)
- response = fmg.get(url, datagram)
- return response
-
-
-def create_model_device(fmg, name, serial, group, platform, os_version,
- os_type, minor_release, patch_release=0, adom='root'):
- datagram = {
- 'adom': adom,
- 'flags': ['create_task', 'nonblocking'],
- 'groups': [{'name': group, 'vdom': 'root'}],
- 'device': {
- 'mr': minor_release,
- 'name': name,
- 'sn': serial,
- 'mgmt_mode': 'fmg',
- 'device action': 'add_model',
- 'platform_str': platform,
- 'os_ver': os_version,
- 'os_type': os_type,
- 'patch': patch_release,
- 'desc': 'Provisioned by Ansible',
- }
- }
-
- url = '/dvm/cmd/add/device'
- response = fmg.execute(url, datagram)
- return response
-
-
-def update_flags(fmg, name):
- datagram = {
- 'flags': ['is_model', 'linked_to_model']
- }
- url = 'dvmdb/device/{name}'.format(name=name)
- response = fmg.update(url, datagram)
- return response
-
-
-def assign_provision_template(fmg, template, adom, target):
- datagram = {
- 'name': template,
- 'type': 'devprof',
- 'description': 'Provisioned by Ansible',
- 'scope member': [{'name': target}]
- }
- url = "/pm/devprof/adom/{adom}".format(adom=adom)
- response = fmg.update(url, datagram)
- return response
-
-
-def set_devprof_scope(self, provisioning_template, adom, provision_targets):
- """
- GET the DevProf (check to see if exists)
- """
- fields = dict()
- targets = []
- fields["name"] = provisioning_template
- fields["type"] = "devprof"
- fields["description"] = "CreatedByAnsible"
-
- for target in provision_targets.strip().split(","):
- # split the host on the space to get the mask out
- new_target = {"name": target}
- targets.append(new_target)
-
- fields["scope member"] = targets
-
- body = {"method": "set", "params": [{"url": "/pm/devprof/adom/{adom}".format(adom=adom),
- "data": fields, "session": self.session}]}
- response = self.make_request(body).json()
- return response
-
-
-def assign_dev_grp(fmg, grp_name, device_name, vdom, adom):
- datagram = {
- 'name': device_name,
- 'vdom': vdom,
- }
- url = "/dvmdb/adom/{adom}/group/{grp_name}/object member".format(adom=adom, grp_name=grp_name)
- response = fmg.set(url, datagram)
- return response
-
-
-def update_install_target(fmg, device, pp='default', vdom='root', adom='root'):
- datagram = {
- 'scope member': [{'name': device, 'vdom': vdom}],
- 'type': 'pkg'
- }
- url = '/pm/pkg/adom/{adom}/{pkg_name}'.format(adom=adom, pkg_name=pp)
- response = fmg.update(url, datagram)
- return response
-
-
-def install_pp(fmg, device, pp='default', vdom='root', adom='root'):
- datagram = {
- 'adom': adom,
- 'flags': 'nonblocking',
- 'pkg': pp,
- 'scope': [{'name': device, 'vdom': vdom}],
- }
- url = 'securityconsole/install/package'
- response = fmg.execute(url, datagram)
- return response
-
-
-def main():
-
- argument_spec = dict(
- adom=dict(required=False, type="str"),
- vdom=dict(required=False, type="str"),
- host=dict(required=True, type="str"),
- password=dict(fallback=(env_fallback, ["ANSIBLE_NET_PASSWORD"]), no_log=True),
- username=dict(fallback=(env_fallback, ["ANSIBLE_NET_USERNAME"]), no_log=True),
-
- policy_package=dict(required=False, type="str"),
- name=dict(required=False, type="str"),
- group=dict(required=False, type="str"),
- serial=dict(required=True, type="str"),
- platform=dict(required=True, type="str"),
- description=dict(required=False, type="str"),
- os_version=dict(required=True, type="str"),
- minor_release=dict(required=False, type="str"),
- patch_release=dict(required=False, type="str"),
- os_type=dict(required=False, type="str"),
-
- )
-
- module = AnsibleModule(argument_spec, supports_check_mode=True, )
-
- # check if params are set
- if module.params["host"] is None or module.params["username"] is None:
- module.fail_json(msg="Host and username are required for connection")
-
- # check if login failed
- fmg = AnsibleFortiManager(module, module.params["host"], module.params["username"], module.params["password"])
- response = fmg.login()
-
- if "FortiManager instance connnected" not in str(response):
- module.fail_json(msg="Connection to FortiManager Failed")
- else:
-
- if module.params["policy_package"] is None:
- module.params["policy_package"] = 'default'
- if module.params["adom"] is None:
- module.params["adom"] = 'root'
- if module.params["vdom"] is None:
- module.params["vdom"] = 'root'
- if module.params["platform"] is None:
- module.params["platform"] = 'FortiGate-VM64'
- if module.params["os_type"] is None:
- module.params["os_type"] = 'fos'
-
- results = create_model_device(fmg,
- module.params["name"],
- module.params["serial"],
- module.params["group"],
- module.params["platform"],
- module.params["os_ver"],
- module.params["os_type"],
- module.params["minor_release"],
- module.params["patch_release"],
- module.params["adom"])
- if results[0] != 0:
- module.fail_json(msg="Create model failed", **results)
-
- results = update_flags(fmg, module.params["name"])
- if results[0] != 0:
- module.fail_json(msg="Update device flags failed", **results)
-
- # results = assign_dev_grp(fmg, 'Ansible', 'FGVM000000117992', 'root', 'root')
- # if not results[0] == 0:
- # module.fail_json(msg="Setting device group failed", **results)
-
- results = update_install_target(fmg, module.params["name"], module.params["policy_package"])
- if results[0] != 0:
- module.fail_json(msg="Adding device target to package failed", **results)
-
- results = install_pp(fmg, module.params["name"], module.params["policy_package"])
- if results[0] != 0:
- module.fail_json(msg="Installing policy package failed", **results)
-
- fmg.logout()
-
- # results is returned as a tuple
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_query.py b/plugins/modules/network/fortimanager/fmgr_query.py
deleted file mode 100644
index d87be8b474..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_query.py
+++ /dev/null
@@ -1,430 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- "metadata_version": "1.1",
- "status": ["preview"],
- "supported_by": "community"
-}
-
-DOCUMENTATION = '''
----
-module: fmgr_query
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author: Luke Weighall (@lweighall)
-short_description: Query FortiManager data objects for use in Ansible workflows.
-description:
- - Provides information on data objects within FortiManager so that playbooks can perform conditionals.
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- object:
- description:
- - The data object we wish to query (device, package, rule, etc). Will expand choices as improves.
- required: true
- choices:
- - device
- - cluster_nodes
- - task
- - custom
-
- custom_endpoint:
- description:
- - ADVANCED USERS ONLY! REQUIRES KNOWLEDGE OF FMGR JSON API!
- - The HTTP Endpoint on FortiManager you wish to GET from.
- required: false
-
- custom_dict:
- description:
- - ADVANCED USERS ONLY! REQUIRES KNOWLEDGE OF FMGR JSON API!
- - DICTIONARY JSON FORMAT ONLY -- Custom dictionary/datagram to send to the endpoint.
- required: false
-
- device_ip:
- description:
- - The IP of the device you want to query.
- required: false
-
- device_unique_name:
- description:
- - The desired "friendly" name of the device you want to query.
- required: false
-
- device_serial:
- description:
- - The serial number of the device you want to query.
- required: false
-
- task_id:
- description:
- - The ID of the task you wish to query status on. If left blank and object = 'task' a list of tasks are returned.
- required: false
-
- nodes:
- description:
- - A LIST of firewalls in the cluster you want to verify i.e. ["firewall_A","firewall_B"].
- required: false
-'''
-
-
-EXAMPLES = '''
-- name: QUERY FORTIGATE DEVICE BY IP
- fmgr_query:
- object: "device"
- adom: "ansible"
- device_ip: "10.7.220.41"
-
-- name: QUERY FORTIGATE DEVICE BY SERIAL
- fmgr_query:
- adom: "ansible"
- object: "device"
- device_serial: "FGVM000000117992"
-
-- name: QUERY FORTIGATE DEVICE BY FRIENDLY NAME
- fmgr_query:
- adom: "ansible"
- object: "device"
- device_unique_name: "ansible-fgt01"
-
-- name: VERIFY CLUSTER MEMBERS AND STATUS
- fmgr_query:
- adom: "ansible"
- object: "cluster_nodes"
- device_unique_name: "fgt-cluster01"
- nodes: ["ansible-fgt01", "ansible-fgt02", "ansible-fgt03"]
-
-- name: GET STATUS OF TASK ID
- fmgr_query:
- adom: "ansible"
- object: "task"
- task_id: "3"
-
-- name: USE CUSTOM TYPE TO QUERY AVAILABLE SCRIPTS
- fmgr_query:
- adom: "ansible"
- object: "custom"
- custom_endpoint: "/dvmdb/adom/ansible/script"
- custom_dict: { "type": "cli" }
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-
-
-def fmgr_get_custom(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- # IF THE CUSTOM DICTIONARY (OFTEN CONTAINING FILTERS) IS DEFINED CREATED THAT
- if paramgram["custom_dict"] is not None:
- datagram = paramgram["custom_dict"]
- else:
- datagram = dict()
-
- # SET THE CUSTOM ENDPOINT PROVIDED
- url = paramgram["custom_endpoint"]
- # MAKE THE CALL AND RETURN RESULTS
- response = fmgr.process_request(url, datagram, FMGRMethods.GET)
- return response
-
-
-def fmgr_get_task_status(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- # IF THE TASK_ID IS DEFINED, THEN GET THAT SPECIFIC TASK
- # OTHERWISE, GET ALL RECENT TASKS IN A LIST
- if paramgram["task_id"] is not None:
-
- datagram = {
- "adom": paramgram["adom"]
- }
- url = '/task/task/{task_id}'.format(task_id=paramgram["task_id"])
- response = fmgr.process_request(url, datagram, FMGRMethods.GET)
- else:
- datagram = {
- "adom": paramgram["adom"]
- }
- url = '/task/task'
- response = fmgr.process_request(url, datagram, FMGRMethods.GET)
- return response
-
-
-def fmgr_get_device(fmgr, paramgram):
- """
- This method is used to get information on devices. This will not work on HA_SLAVE nodes, only top level devices.
- Such as cluster objects and standalone devices.
-
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- # FIRST TRY TO RUN AN UPDATE ON THE DEVICE
- # RUN A QUICK CLUSTER REFRESH/UPDATE ATTEMPT TO ENSURE WE'RE GETTING THE LATEST INFORMOATION
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
-
- update_url = '/dvm/cmd/update/device'
- update_dict = {
- "adom": paramgram['adom'],
- "device": paramgram['device_unique_name'],
- "flags": "create_task"
- }
- # DO THE UPDATE CALL
- fmgr.process_request(update_url, update_dict, FMGRMethods.EXEC)
-
- # SET THE URL
- url = '/dvmdb/adom/{adom}/device'.format(adom=paramgram["adom"])
- device_found = 0
- response = []
-
- # TRY TO FIND IT FIRST BY SERIAL NUMBER
- if paramgram["device_serial"] is not None:
- datagram = {
- "filter": ["sn", "==", paramgram["device_serial"]]
- }
- response = fmgr.process_request(url, datagram, FMGRMethods.GET)
- if len(response[1]) >= 0:
- device_found = 1
-
- # CHECK IF ANYTHING WAS RETURNED, IF NOT TRY DEVICE NAME PARAMETER
- if device_found == 0 and paramgram["device_unique_name"] is not None:
- datagram = {
- "filter": ["name", "==", paramgram["device_unique_name"]]
- }
- response = fmgr.process_request(url, datagram, FMGRMethods.GET)
- if len(response[1]) >= 0:
- device_found = 1
-
- # CHECK IF ANYTHING WAS RETURNED, IF NOT TRY DEVICE IP ADDRESS
- if device_found == 0 and paramgram["device_ip"] is not None:
- datagram = {
- "filter": ["ip", "==", paramgram["device_ip"]]
- }
- response = fmgr.process_request(url, datagram, FMGRMethods.GET)
- if len(response[1]) >= 0:
- device_found = 1
-
- return response
-
-
-def fmgr_get_cluster_nodes(fmgr, paramgram):
- """
- This method is used to get information on devices. This WILL work on HA_SLAVE nodes, but NOT top level standalone
- devices.
- Such as cluster objects and standalone devices.
-
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
- # USE THE DEVICE METHOD TO GET THE CLUSTER INFORMATION SO WE CAN SEE THE HA_SLAVE NODES
- response = fmgr_get_device(fmgr, paramgram)
- # CHECK FOR HA_SLAVE NODES, IF CLUSTER IS MISSING COMPLETELY THEN QUIT
- try:
- returned_nodes = response[1][0]["ha_slave"]
- num_of_nodes = len(returned_nodes)
- except Exception:
- error_msg = {"cluster_status": "MISSING"}
- return error_msg
-
- # INIT LOOP RESOURCES
- loop_count = 0
- good_nodes = []
- expected_nodes = list(paramgram["nodes"])
- missing_nodes = list(paramgram["nodes"])
- bad_status_nodes = []
-
- # LOOP THROUGH THE NODES AND GET THEIR STATUS TO BUILD THE RETURN JSON OBJECT
- # WE'RE ALSO CHECKING THE NODES IF THEY ARE BAD STATUS, OR PLAIN MISSING
- while loop_count < num_of_nodes:
- node_append = {
- "node_name": returned_nodes[loop_count]["name"],
- "node_serial": returned_nodes[loop_count]["sn"],
- "node_parent": returned_nodes[loop_count]["did"],
- "node_status": returned_nodes[loop_count]["status"],
- }
- # IF THE NODE IS IN THE EXPECTED NODES LIST AND WORKING THEN ADD IT TO GOOD NODES LIST
- if node_append["node_name"] in expected_nodes and node_append["node_status"] == 1:
- good_nodes.append(node_append["node_name"])
- # IF THE NODE IS IN THE EXPECTED NODES LIST BUT NOT WORKING THEN ADDED IT TO BAD_STATUS_NODES
- # IF THE NODE STATUS IS NOT 1 THEN ITS BAD
- if node_append["node_name"] in expected_nodes and node_append["node_status"] != 1:
- bad_status_nodes.append(node_append["node_name"])
- # REMOVE THE NODE FROM MISSING NODES LIST IF NOTHING IS WRONG WITH NODE -- LEAVING US A LIST OF
- # NOT WORKING NODES
- missing_nodes.remove(node_append["node_name"])
- loop_count += 1
-
- # BUILD RETURN OBJECT FROM NODE LISTS
- nodes = {
- "good_nodes": good_nodes,
- "expected_nodes": expected_nodes,
- "missing_nodes": missing_nodes,
- "bad_nodes": bad_status_nodes,
- "query_status": "good",
- }
- if len(nodes["good_nodes"]) == len(nodes["expected_nodes"]):
- nodes["cluster_status"] = "OK"
- else:
- nodes["cluster_status"] = "NOT-COMPLIANT"
- return nodes
-
-
-def main():
- argument_spec = dict(
- adom=dict(required=False, type="str", default="root"),
- object=dict(required=True, type="str", choices=["device", "cluster_nodes", "task", "custom"]),
- custom_endpoint=dict(required=False, type="str"),
- custom_dict=dict(required=False, type="dict"),
- device_ip=dict(required=False, type="str"),
- device_unique_name=dict(required=False, type="str"),
- device_serial=dict(required=False, type="str"),
- nodes=dict(required=False, type="list"),
- task_id=dict(required=False, type="str")
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- paramgram = {
- "adom": module.params["adom"],
- "object": module.params["object"],
- "device_ip": module.params["device_ip"],
- "device_unique_name": module.params["device_unique_name"],
- "device_serial": module.params["device_serial"],
- "nodes": module.params["nodes"],
- "task_id": module.params["task_id"],
- "custom_endpoint": module.params["custom_endpoint"],
- "custom_dict": module.params["custom_dict"]
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- results = DEFAULT_RESULT_OBJ
-
- try:
- # IF OBJECT IS DEVICE
- if paramgram["object"] == "device" and any(v is not None for v in [paramgram["device_unique_name"],
- paramgram["device_serial"],
- paramgram["device_ip"]]):
- results = fmgr_get_device(fmgr, paramgram)
- if results[0] not in [0]:
- module.fail_json(msg="Device query failed!")
- elif len(results[1]) == 0:
- module.exit_json(msg="Device NOT FOUND!")
- else:
- module.exit_json(msg="Device Found", **results[1][0])
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # IF OBJECT IS CLUSTER_NODES
- if paramgram["object"] == "cluster_nodes" and paramgram["nodes"] is not None:
- results = fmgr_get_cluster_nodes(fmgr, paramgram)
- if results["cluster_status"] == "MISSING":
- module.exit_json(msg="No cluster device found!", **results)
- elif results["query_status"] == "good":
- module.exit_json(msg="Cluster Found - Showing Nodes", **results)
- elif results is None:
- module.fail_json(msg="Query FAILED -- Check module or playbook syntax")
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # IF OBJECT IS TASK
- if paramgram["object"] == "task":
- results = fmgr_get_task_status(fmgr, paramgram)
- if results[0] != 0:
- module.fail_json(**results[1])
- if results[0] == 0:
- module.exit_json(**results[1])
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- # IF OBJECT IS CUSTOM
- if paramgram["object"] == "custom":
- results = fmgr_get_custom(fmgr, paramgram)
- if results[0] != 0:
- module.fail_json(msg="QUERY FAILED -- Please check syntax check JSON guide if needed.")
- if results[0] == 0:
- results_len = len(results[1])
- if results_len > 0:
- results_combine = dict()
- if isinstance(results[1], dict):
- results_combine["results"] = results[1]
- if isinstance(results[1], list):
- results_combine["results"] = results[1][0:results_len]
- module.exit_json(msg="Custom Query Success", **results_combine)
- else:
- module.exit_json(msg="NO RESULTS")
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_script.py b/plugins/modules/network/fortimanager/fmgr_script.py
deleted file mode 100644
index 0a23480715..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_script.py
+++ /dev/null
@@ -1,266 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_script
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author: Andrew Welsh (@Ghilli3)
-short_description: Add/Edit/Delete and execute scripts
-description: Create/edit/delete scripts and execute the scripts on the FortiManager using jsonrpc API
-
-options:
- adom:
- description:
- - The administrative domain (admon) the configuration belongs to
- required: true
-
- vdom:
- description:
- - The virtual domain (vdom) the configuration belongs to
-
- mode:
- description:
- - The desired mode of the specified object. Execute will run the script.
- required: false
- default: "add"
- choices: ["add", "delete", "execute", "set"]
-
- script_name:
- description:
- - The name of the script.
- required: True
-
- script_type:
- description:
- - The type of script (CLI or TCL).
- required: false
-
- script_target:
- description:
- - The target of the script to be run.
- required: false
-
- script_description:
- description:
- - The description of the script.
- required: false
-
- script_content:
- description:
- - The script content that will be executed.
- required: false
-
- script_scope:
- description:
- - (datasource) The devices that the script will run on, can have both device member and device group member.
- required: false
-
- script_package:
- description:
- - (datasource) Policy package object to run the script against
- required: false
-'''
-
-EXAMPLES = '''
-- name: CREATE SCRIPT
- fmgr_script:
- adom: "root"
- script_name: "TestScript"
- script_type: "cli"
- script_target: "remote_device"
- script_description: "Create by Ansible"
- script_content: "get system status"
-
-- name: EXECUTE SCRIPT
- fmgr_script:
- adom: "root"
- script_name: "TestScript"
- mode: "execute"
- script_scope: "FGT1,FGT2"
-
-- name: DELETE SCRIPT
- fmgr_script:
- adom: "root"
- script_name: "TestScript"
- mode: "delete"
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-
-
-def set_script(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- datagram = {
- 'content': paramgram["script_content"],
- 'desc': paramgram["script_description"],
- 'name': paramgram["script_name"],
- 'target': paramgram["script_target"],
- 'type': paramgram["script_type"],
- }
-
- url = '/dvmdb/adom/{adom}/script/'.format(adom=paramgram["adom"])
- response = fmgr.process_request(url, datagram, FMGRMethods.SET)
- return response
-
-
-def delete_script(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- datagram = {
- 'name': paramgram["script_name"],
- }
-
- url = '/dvmdb/adom/{adom}/script/{script_name}'.format(adom=paramgram["adom"], script_name=paramgram["script_name"])
- response = fmgr.process_request(url, datagram, FMGRMethods.DELETE)
- return response
-
-
-def execute_script(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- scope_list = list()
- scope = paramgram["script_scope"].replace(' ', '')
- scope = scope.split(',')
- for dev_name in scope:
- scope_list.append({'name': dev_name, 'vdom': paramgram["vdom"]})
-
- datagram = {
- 'adom': paramgram["adom"],
- 'script': paramgram["script_name"],
- 'package': paramgram["script_package"],
- 'scope': scope_list,
- }
-
- url = '/dvmdb/adom/{adom}/script/execute'.format(adom=paramgram["adom"])
- response = fmgr.process_request(url, datagram, FMGRMethods.EXEC)
- return response
-
-
-def main():
- argument_spec = dict(
- adom=dict(required=False, type="str", default="root"),
- vdom=dict(required=False, type="str", default="root"),
- mode=dict(choices=["add", "execute", "set", "delete"], type="str", default="add"),
- script_name=dict(required=True, type="str"),
- script_type=dict(required=False, type="str"),
- script_target=dict(required=False, type="str"),
- script_description=dict(required=False, type="str"),
- script_content=dict(required=False, type="str"),
- script_scope=dict(required=False, type="str"),
- script_package=dict(required=False, type="str"),
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- paramgram = {
- "script_name": module.params["script_name"],
- "script_type": module.params["script_type"],
- "script_target": module.params["script_target"],
- "script_description": module.params["script_description"],
- "script_content": module.params["script_content"],
- "script_scope": module.params["script_scope"],
- "script_package": module.params["script_package"],
- "adom": module.params["adom"],
- "vdom": module.params["vdom"],
- "mode": module.params["mode"],
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- results = DEFAULT_RESULT_OBJ
-
- try:
- if paramgram["mode"] in ['add', 'set']:
- results = set_script(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, msg="Operation Finished",
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, module.params))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- if paramgram["mode"] == "execute":
- results = execute_script(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, msg="Operation Finished",
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, module.params))
- except Exception as err:
- raise FMGBaseException(err)
-
- try:
- if paramgram["mode"] == "delete":
- results = delete_script(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results, msg="Operation Finished",
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, module.params))
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_secprof_appctrl.py b/plugins/modules/network/fortimanager/fmgr_secprof_appctrl.py
deleted file mode 100644
index 7a3d567477..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_secprof_appctrl.py
+++ /dev/null
@@ -1,520 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_secprof_appctrl
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Manage application control security profiles
-description:
- - Manage application control security profiles within FortiManager
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- unknown_application_log:
- description:
- - Enable/disable logging for unknown applications.
- - choice | disable | Disable logging for unknown applications.
- - choice | enable | Enable logging for unknown applications.
- required: false
- choices: ["disable", "enable"]
-
- unknown_application_action:
- description:
- - Pass or block traffic from unknown applications.
- - choice | pass | Pass or allow unknown applications.
- - choice | block | Drop or block unknown applications.
- required: false
- choices: ["pass", "block"]
-
- replacemsg_group:
- description:
- - Replacement message group.
- required: false
-
- p2p_black_list:
- description:
- - NO DESCRIPTION PARSED ENTER MANUALLY
- - FLAG Based Options. Specify multiple in list form.
- - flag | skype | Skype.
- - flag | edonkey | Edonkey.
- - flag | bittorrent | Bit torrent.
- required: false
- choices: ["skype", "edonkey", "bittorrent"]
-
- other_application_log:
- description:
- - Enable/disable logging for other applications.
- - choice | disable | Disable logging for other applications.
- - choice | enable | Enable logging for other applications.
- required: false
- choices: ["disable", "enable"]
-
- other_application_action:
- description:
- - Action for other applications.
- - choice | pass | Allow sessions matching an application in this application list.
- - choice | block | Block sessions matching an application in this application list.
- required: false
- choices: ["pass", "block"]
-
- options:
- description:
- - NO DESCRIPTION PARSED ENTER MANUALLY
- - FLAG Based Options. Specify multiple in list form.
- - flag | allow-dns | Allow DNS.
- - flag | allow-icmp | Allow ICMP.
- - flag | allow-http | Allow generic HTTP web browsing.
- - flag | allow-ssl | Allow generic SSL communication.
- - flag | allow-quic | Allow QUIC.
- required: false
- choices: ["allow-dns", "allow-icmp", "allow-http", "allow-ssl", "allow-quic"]
-
- name:
- description:
- - List name.
- required: false
-
- extended_log:
- description:
- - Enable/disable extended logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- deep_app_inspection:
- description:
- - Enable/disable deep application inspection.
- - choice | disable | Disable deep application inspection.
- - choice | enable | Enable deep application inspection.
- required: false
- choices: ["disable", "enable"]
-
- comment:
- description:
- - comments
- required: false
-
- app_replacemsg:
- description:
- - Enable/disable replacement messages for blocked applications.
- - choice | disable | Disable replacement messages for blocked applications.
- - choice | enable | Enable replacement messages for blocked applications.
- required: false
- choices: ["disable", "enable"]
-
- entries:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED. This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, OMIT THE USE OF THIS PARAMETER
- - AND USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- entries_action:
- description:
- - Pass or block traffic, or reset connection for traffic from this application.
- - choice | pass | Pass or allow matching traffic.
- - choice | block | Block or drop matching traffic.
- - choice | reset | Reset sessions for matching traffic.
- required: false
- choices: ["pass", "block", "reset"]
-
- entries_application:
- description:
- - ID of allowed applications.
- required: false
-
- entries_behavior:
- description:
- - Application behavior filter.
- required: false
-
- entries_category:
- description:
- - Category ID list.
- required: false
-
- entries_log:
- description:
- - Enable/disable logging for this application list.
- - choice | disable | Disable logging.
- - choice | enable | Enable logging.
- required: false
- choices: ["disable", "enable"]
-
- entries_log_packet:
- description:
- - Enable/disable packet logging.
- - choice | disable | Disable packet logging.
- - choice | enable | Enable packet logging.
- required: false
- choices: ["disable", "enable"]
-
- entries_per_ip_shaper:
- description:
- - Per-IP traffic shaper.
- required: false
-
- entries_popularity:
- description:
- - Application popularity filter (1 - 5, from least to most popular).
- - FLAG Based Options. Specify multiple in list form.
- - flag | 1 | Popularity level 1.
- - flag | 2 | Popularity level 2.
- - flag | 3 | Popularity level 3.
- - flag | 4 | Popularity level 4.
- - flag | 5 | Popularity level 5.
- required: false
- choices: ["1", "2", "3", "4", "5"]
-
- entries_protocols:
- description:
- - Application protocol filter.
- required: false
-
- entries_quarantine:
- description:
- - Quarantine method.
- - choice | none | Quarantine is disabled.
- - choice | attacker | Block all traffic sent from attacker's IP address.
- - The attacker's IP address is also added to the banned user list. The target's address is not affected.
- required: false
- choices: ["none", "attacker"]
-
- entries_quarantine_expiry:
- description:
- - Duration of quarantine. (Format ###d##h##m, minimum 1m, maximum 364d23h59m, default = 5m).
- - Requires quarantine set to attacker.
- required: false
-
- entries_quarantine_log:
- description:
- - Enable/disable quarantine logging.
- - choice | disable | Disable quarantine logging.
- - choice | enable | Enable quarantine logging.
- required: false
- choices: ["disable", "enable"]
-
- entries_rate_count:
- description:
- - Count of the rate.
- required: false
-
- entries_rate_duration:
- description:
- - Duration (sec) of the rate.
- required: false
-
- entries_rate_mode:
- description:
- - Rate limit mode.
- - choice | periodical | Allow configured number of packets every rate-duration.
- - choice | continuous | Block packets once the rate is reached.
- required: false
- choices: ["periodical", "continuous"]
-
- entries_rate_track:
- description:
- - Track the packet protocol field.
- - choice | none |
- - choice | src-ip | Source IP.
- - choice | dest-ip | Destination IP.
- - choice | dhcp-client-mac | DHCP client.
- - choice | dns-domain | DNS domain.
- required: false
- choices: ["none", "src-ip", "dest-ip", "dhcp-client-mac", "dns-domain"]
-
- entries_risk:
- description:
- - Risk, or impact, of allowing traffic from this application to occur 1 - 5;
- - (Low, Elevated, Medium, High, and Critical).
- required: false
-
- entries_session_ttl:
- description:
- - Session TTL (0 = default).
- required: false
-
- entries_shaper:
- description:
- - Traffic shaper.
- required: false
-
- entries_shaper_reverse:
- description:
- - Reverse traffic shaper.
- required: false
-
- entries_sub_category:
- description:
- - Application Sub-category ID list.
- required: false
-
- entries_technology:
- description:
- - Application technology filter.
- required: false
-
- entries_vendor:
- description:
- - Application vendor filter.
- required: false
-
- entries_parameters_value:
- description:
- - Parameter value.
- required: false
-
-
-'''
-
-EXAMPLES = '''
- - name: DELETE Profile
- fmgr_secprof_appctrl:
- name: "Ansible_Application_Control_Profile"
- comment: "Created by Ansible Module TEST"
- mode: "delete"
-
- - name: CREATE Profile
- fmgr_secprof_appctrl:
- name: "Ansible_Application_Control_Profile"
- comment: "Created by Ansible Module TEST"
- mode: "set"
- entries: [{
- action: "block",
- log: "enable",
- log-packet: "enable",
- protocols: ["1"],
- quarantine: "attacker",
- quarantine-log: "enable",
- },
- {action: "pass",
- category: ["2","3","4"]},
- ]
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-###############
-# START METHODS
-###############
-
-
-def fmgr_application_list_modify(fmgr, paramgram):
- """
- fmgr_application_list -- Modifies Application Control Profiles on FortiManager
-
- :param fmgr: The fmgr object instance from fmgr_utils.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
-
- :return: The response from the FortiManager
- :rtype: dict
- """
- # INIT A BASIC OBJECTS
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
-
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if paramgram["mode"] in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/obj/application/list'.format(adom=paramgram["adom"])
- datagram = scrub_dict(prepare_dict(paramgram))
-
- # EVAL THE MODE PARAMETER FOR DELETE
- elif paramgram["mode"] == "delete":
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/application/list/{name}'.format(adom=paramgram["adom"],
- name=paramgram["name"])
- datagram = {}
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-
-#############
-# END METHODS
-#############
-
-
-def main():
- argument_spec = dict(
- adom=dict(type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
-
- unknown_application_log=dict(required=False, type="str", choices=["disable", "enable"]),
- unknown_application_action=dict(required=False, type="str", choices=["pass", "block"]),
- replacemsg_group=dict(required=False, type="str"),
- p2p_black_list=dict(required=False, type="str", choices=["skype", "edonkey", "bittorrent"]),
- other_application_log=dict(required=False, type="str", choices=["disable", "enable"]),
- other_application_action=dict(required=False, type="str", choices=["pass", "block"]),
- options=dict(required=False, type="str",
- choices=["allow-dns", "allow-icmp", "allow-http", "allow-ssl", "allow-quic"]),
- name=dict(required=False, type="str"),
- extended_log=dict(required=False, type="str", choices=["disable", "enable"]),
- deep_app_inspection=dict(required=False, type="str", choices=["disable", "enable"]),
- comment=dict(required=False, type="str"),
- app_replacemsg=dict(required=False, type="str", choices=["disable", "enable"]),
- entries=dict(required=False, type="list"),
- entries_action=dict(required=False, type="str", choices=["pass", "block", "reset"]),
- entries_application=dict(required=False, type="str"),
- entries_behavior=dict(required=False, type="str"),
- entries_category=dict(required=False, type="str"),
- entries_log=dict(required=False, type="str", choices=["disable", "enable"]),
- entries_log_packet=dict(required=False, type="str", choices=["disable", "enable"]),
- entries_per_ip_shaper=dict(required=False, type="str"),
- entries_popularity=dict(required=False, type="str", choices=["1", "2", "3", "4", "5"]),
- entries_protocols=dict(required=False, type="str"),
- entries_quarantine=dict(required=False, type="str", choices=["none", "attacker"]),
- entries_quarantine_expiry=dict(required=False, type="str"),
- entries_quarantine_log=dict(required=False, type="str", choices=["disable", "enable"]),
- entries_rate_count=dict(required=False, type="int"),
- entries_rate_duration=dict(required=False, type="int"),
- entries_rate_mode=dict(required=False, type="str", choices=["periodical", "continuous"]),
- entries_rate_track=dict(required=False, type="str",
- choices=["none", "src-ip", "dest-ip", "dhcp-client-mac", "dns-domain"]),
- entries_risk=dict(required=False, type="str"),
- entries_session_ttl=dict(required=False, type="int"),
- entries_shaper=dict(required=False, type="str"),
- entries_shaper_reverse=dict(required=False, type="str"),
- entries_sub_category=dict(required=False, type="str"),
- entries_technology=dict(required=False, type="str"),
- entries_vendor=dict(required=False, type="str"),
-
- entries_parameters_value=dict(required=False, type="str"),
-
- )
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "unknown-application-log": module.params["unknown_application_log"],
- "unknown-application-action": module.params["unknown_application_action"],
- "replacemsg-group": module.params["replacemsg_group"],
- "p2p-black-list": module.params["p2p_black_list"],
- "other-application-log": module.params["other_application_log"],
- "other-application-action": module.params["other_application_action"],
- "options": module.params["options"],
- "name": module.params["name"],
- "extended-log": module.params["extended_log"],
- "deep-app-inspection": module.params["deep_app_inspection"],
- "comment": module.params["comment"],
- "app-replacemsg": module.params["app_replacemsg"],
- "entries": {
- "action": module.params["entries_action"],
- "application": module.params["entries_application"],
- "behavior": module.params["entries_behavior"],
- "category": module.params["entries_category"],
- "log": module.params["entries_log"],
- "log-packet": module.params["entries_log_packet"],
- "per-ip-shaper": module.params["entries_per_ip_shaper"],
- "popularity": module.params["entries_popularity"],
- "protocols": module.params["entries_protocols"],
- "quarantine": module.params["entries_quarantine"],
- "quarantine-expiry": module.params["entries_quarantine_expiry"],
- "quarantine-log": module.params["entries_quarantine_log"],
- "rate-count": module.params["entries_rate_count"],
- "rate-duration": module.params["entries_rate_duration"],
- "rate-mode": module.params["entries_rate_mode"],
- "rate-track": module.params["entries_rate_track"],
- "risk": module.params["entries_risk"],
- "session-ttl": module.params["entries_session_ttl"],
- "shaper": module.params["entries_shaper"],
- "shaper-reverse": module.params["entries_shaper_reverse"],
- "sub-category": module.params["entries_sub_category"],
- "technology": module.params["entries_technology"],
- "vendor": module.params["entries_vendor"],
- "parameters": {
- "value": module.params["entries_parameters_value"],
- }
- }
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- list_overrides = ['entries']
- paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides,
- paramgram=paramgram, module=module)
-
- results = DEFAULT_RESULT_OBJ
- try:
- results = fmgr_application_list_modify(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_secprof_av.py b/plugins/modules/network/fortimanager/fmgr_secprof_av.py
deleted file mode 100644
index ba8ea37051..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_secprof_av.py
+++ /dev/null
@@ -1,1390 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: fmgr_secprof_av
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Manage security profile
-description:
- - Manage security profile groups for FortiManager objects
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- scan_mode:
- description:
- - Choose between full scan mode and quick scan mode.
- required: false
- choices:
- - quick
- - full
-
- replacemsg_group:
- description:
- - Replacement message group customized for this profile.
- required: false
-
- name:
- description:
- - Profile name.
- required: false
-
- mobile_malware_db:
- description:
- - Enable/disable using the mobile malware signature database.
- required: false
- choices:
- - disable
- - enable
-
- inspection_mode:
- description:
- - Inspection mode.
- required: false
- choices:
- - proxy
- - flow-based
-
- ftgd_analytics:
- description:
- - Settings to control which files are uploaded to FortiSandbox.
- required: false
- choices:
- - disable
- - suspicious
- - everything
-
- extended_log:
- description:
- - Enable/disable extended logging for antivirus.
- required: false
- choices:
- - disable
- - enable
-
- comment:
- description:
- - Comment.
- required: false
-
- av_virus_log:
- description:
- - Enable/disable AntiVirus logging.
- required: false
- choices:
- - disable
- - enable
-
- av_block_log:
- description:
- - Enable/disable logging for AntiVirus file blocking.
- required: false
- choices:
- - disable
- - enable
-
- analytics_wl_filetype:
- description:
- - Do not submit files matching this DLP file-pattern to FortiSandbox.
- required: false
-
- analytics_max_upload:
- description:
- - Maximum size of files that can be uploaded to FortiSandbox (1 - 395 MBytes, default = 10).
- required: false
-
- analytics_db:
- description:
- - Enable/disable using the FortiSandbox signature database to supplement the AV signature databases.
- required: false
- choices:
- - disable
- - enable
-
- analytics_bl_filetype:
- description:
- - Only submit files matching this DLP file-pattern to FortiSandbox.
- required: false
-
- content_disarm:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- content_disarm_cover_page:
- description:
- - Enable/disable inserting a cover page into the disarmed document.
- required: false
- choices:
- - disable
- - enable
-
- content_disarm_detect_only:
- description:
- - Enable/disable only detect disarmable files, do not alter content.
- required: false
- choices:
- - disable
- - enable
-
- content_disarm_office_embed:
- description:
- - Enable/disable stripping of embedded objects in Microsoft Office documents.
- required: false
- choices:
- - disable
- - enable
-
- content_disarm_office_hylink:
- description:
- - Enable/disable stripping of hyperlinks in Microsoft Office documents.
- required: false
- choices:
- - disable
- - enable
-
- content_disarm_office_linked:
- description:
- - Enable/disable stripping of linked objects in Microsoft Office documents.
- required: false
- choices:
- - disable
- - enable
-
- content_disarm_office_macro:
- description:
- - Enable/disable stripping of macros in Microsoft Office documents.
- required: false
- choices:
- - disable
- - enable
-
- content_disarm_original_file_destination:
- description:
- - Destination to send original file if active content is removed.
- required: false
- choices:
- - fortisandbox
- - quarantine
- - discard
-
- content_disarm_pdf_act_form:
- description:
- - Enable/disable stripping of actions that submit data to other targets in PDF documents.
- required: false
- choices:
- - disable
- - enable
-
- content_disarm_pdf_act_gotor:
- description:
- - Enable/disable stripping of links to other PDFs in PDF documents.
- required: false
- choices:
- - disable
- - enable
-
- content_disarm_pdf_act_java:
- description:
- - Enable/disable stripping of actions that execute JavaScript code in PDF documents.
- required: false
- choices:
- - disable
- - enable
-
- content_disarm_pdf_act_launch:
- description:
- - Enable/disable stripping of links to external applications in PDF documents.
- required: false
- choices:
- - disable
- - enable
-
- content_disarm_pdf_act_movie:
- description:
- - Enable/disable stripping of embedded movies in PDF documents.
- required: false
- choices:
- - disable
- - enable
-
- content_disarm_pdf_act_sound:
- description:
- - Enable/disable stripping of embedded sound files in PDF documents.
- required: false
- choices:
- - disable
- - enable
-
- content_disarm_pdf_embedfile:
- description:
- - Enable/disable stripping of embedded files in PDF documents.
- required: false
- choices:
- - disable
- - enable
-
- content_disarm_pdf_hyperlink:
- description:
- - Enable/disable stripping of hyperlinks from PDF documents.
- required: false
- choices:
- - disable
- - enable
-
- content_disarm_pdf_javacode:
- description:
- - Enable/disable stripping of JavaScript code in PDF documents.
- required: false
- choices:
- - disable
- - enable
-
- ftp:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- ftp_archive_block:
- description:
- - Select the archive types to block.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- ftp_archive_log:
- description:
- - Select the archive types to log.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- ftp_emulator:
- description:
- - Enable/disable the virus emulator.
- required: false
- choices:
- - disable
- - enable
-
- ftp_options:
- description:
- - Enable/disable FTP AntiVirus scanning, monitoring, and quarantine.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - scan
- - quarantine
- - avmonitor
-
- ftp_outbreak_prevention:
- description:
- - Enable FortiGuard Virus Outbreak Prevention service.
- required: false
- choices:
- - disabled
- - files
- - full-archive
-
- http:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- http_archive_block:
- description:
- - Select the archive types to block.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- http_archive_log:
- description:
- - Select the archive types to log.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- http_content_disarm:
- description:
- - Enable Content Disarm and Reconstruction for this protocol.
- required: false
- choices:
- - disable
- - enable
-
- http_emulator:
- description:
- - Enable/disable the virus emulator.
- required: false
- choices:
- - disable
- - enable
-
- http_options:
- description:
- - Enable/disable HTTP AntiVirus scanning, monitoring, and quarantine.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - scan
- - quarantine
- - avmonitor
-
- http_outbreak_prevention:
- description:
- - Enable FortiGuard Virus Outbreak Prevention service.
- required: false
- choices:
- - disabled
- - files
- - full-archive
-
- imap:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- imap_archive_block:
- description:
- - Select the archive types to block.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- imap_archive_log:
- description:
- - Select the archive types to log.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- imap_content_disarm:
- description:
- - Enable Content Disarm and Reconstruction for this protocol.
- required: false
- choices:
- - disable
- - enable
-
- imap_emulator:
- description:
- - Enable/disable the virus emulator.
- required: false
- choices:
- - disable
- - enable
-
- imap_executables:
- description:
- - Treat Windows executable files as viruses for the purpose of blocking or monitoring.
- required: false
- choices:
- - default
- - virus
-
- imap_options:
- description:
- - Enable/disable IMAP AntiVirus scanning, monitoring, and quarantine.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - scan
- - quarantine
- - avmonitor
-
- imap_outbreak_prevention:
- description:
- - Enable FortiGuard Virus Outbreak Prevention service.
- required: false
- choices:
- - disabled
- - files
- - full-archive
-
- mapi:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- mapi_archive_block:
- description:
- - Select the archive types to block.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- mapi_archive_log:
- description:
- - Select the archive types to log.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- mapi_emulator:
- description:
- - Enable/disable the virus emulator.
- required: false
- choices:
- - disable
- - enable
-
- mapi_executables:
- description:
- - Treat Windows executable files as viruses for the purpose of blocking or monitoring.
- required: false
- choices:
- - default
- - virus
-
- mapi_options:
- description:
- - Enable/disable MAPI AntiVirus scanning, monitoring, and quarantine.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - scan
- - quarantine
- - avmonitor
-
- mapi_outbreak_prevention:
- description:
- - Enable FortiGuard Virus Outbreak Prevention service.
- required: false
- choices:
- - disabled
- - files
- - full-archive
-
- nac_quar:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- nac_quar_expiry:
- description:
- - Duration of quarantine.
- required: false
-
- nac_quar_infected:
- description:
- - Enable/Disable quarantining infected hosts to the banned user list.
- required: false
- choices:
- - none
- - quar-src-ip
-
- nac_quar_log:
- description:
- - Enable/disable AntiVirus quarantine logging.
- required: false
- choices:
- - disable
- - enable
-
- nntp:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- nntp_archive_block:
- description:
- - Select the archive types to block.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- nntp_archive_log:
- description:
- - Select the archive types to log.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- nntp_emulator:
- description:
- - Enable/disable the virus emulator.
- required: false
- choices:
- - disable
- - enable
-
- nntp_options:
- description:
- - Enable/disable NNTP AntiVirus scanning, monitoring, and quarantine.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - scan
- - quarantine
- - avmonitor
-
- nntp_outbreak_prevention:
- description:
- - Enable FortiGuard Virus Outbreak Prevention service.
- required: false
- choices:
- - disabled
- - files
- - full-archive
-
- pop3:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- pop3_archive_block:
- description:
- - Select the archive types to block.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- pop3_archive_log:
- description:
- - Select the archive types to log.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- pop3_content_disarm:
- description:
- - Enable Content Disarm and Reconstruction for this protocol.
- required: false
- choices:
- - disable
- - enable
-
- pop3_emulator:
- description:
- - Enable/disable the virus emulator.
- required: false
- choices:
- - disable
- - enable
-
- pop3_executables:
- description:
- - Treat Windows executable files as viruses for the purpose of blocking or monitoring.
- required: false
- choices:
- - default
- - virus
-
- pop3_options:
- description:
- - Enable/disable POP3 AntiVirus scanning, monitoring, and quarantine.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - scan
- - quarantine
- - avmonitor
-
- pop3_outbreak_prevention:
- description:
- - Enable FortiGuard Virus Outbreak Prevention service.
- required: false
- choices:
- - disabled
- - files
- - full-archive
-
- smb:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- smb_archive_block:
- description:
- - Select the archive types to block.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- smb_archive_log:
- description:
- - Select the archive types to log.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- smb_emulator:
- description:
- - Enable/disable the virus emulator.
- required: false
- choices:
- - disable
- - enable
-
- smb_options:
- description:
- - Enable/disable SMB AntiVirus scanning, monitoring, and quarantine.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - scan
- - quarantine
- - avmonitor
-
- smb_outbreak_prevention:
- description:
- - Enable FortiGuard Virus Outbreak Prevention service.
- required: false
- choices:
- - disabled
- - files
- - full-archive
-
- smtp:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- smtp_archive_block:
- description:
- - Select the archive types to block.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- smtp_archive_log:
- description:
- - Select the archive types to log.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - encrypted
- - corrupted
- - multipart
- - nested
- - mailbomb
- - unhandled
- - partiallycorrupted
- - fileslimit
- - timeout
-
- smtp_content_disarm:
- description:
- - Enable Content Disarm and Reconstruction for this protocol.
- required: false
- choices:
- - disable
- - enable
-
- smtp_emulator:
- description:
- - Enable/disable the virus emulator.
- required: false
- choices:
- - disable
- - enable
-
- smtp_executables:
- description:
- - Treat Windows executable files as viruses for the purpose of blocking or monitoring.
- required: false
- choices:
- - default
- - virus
-
- smtp_options:
- description:
- - Enable/disable SMTP AntiVirus scanning, monitoring, and quarantine.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - scan
- - quarantine
- - avmonitor
-
- smtp_outbreak_prevention:
- description:
- - Enable FortiGuard Virus Outbreak Prevention service.
- required: false
- choices:
- - disabled
- - files
- - full-archive
-'''
-
-EXAMPLES = '''
- - name: DELETE Profile
- fmgr_secprof_av:
- name: "Ansible_AV_Profile"
- mode: "delete"
-
- - name: CREATE Profile
- fmgr_secprof_av:
- name: "Ansible_AV_Profile"
- comment: "Created by Ansible Module TEST"
- mode: "set"
- inspection_mode: "proxy"
- ftgd_analytics: "everything"
- av_block_log: "enable"
- av_virus_log: "enable"
- scan_mode: "full"
- mobile_malware_db: "enable"
- ftp_archive_block: "encrypted"
- ftp_outbreak_prevention: "files"
- ftp_archive_log: "timeout"
- ftp_emulator: "disable"
- ftp_options: "scan"
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-###############
-# START METHODS
-###############
-
-
-def fmgr_antivirus_profile_modify(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- mode = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if mode in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/obj/antivirus/profile'.format(adom=adom)
- datagram = scrub_dict(prepare_dict(paramgram))
-
- # EVAL THE MODE PARAMETER FOR DELETE
- else:
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/antivirus/profile/{name}'.format(adom=adom, name=paramgram["name"])
- datagram = {}
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
- return response
-
-#############
-# END METHODS
-#############
-
-
-def main():
- argument_spec = dict(
- adom=dict(required=False, type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
-
- scan_mode=dict(required=False, type="str", choices=["quick", "full"]),
- replacemsg_group=dict(required=False, type="dict"),
- name=dict(required=False, type="str"),
- mobile_malware_db=dict(required=False, type="str", choices=["disable", "enable"]),
- inspection_mode=dict(required=False, type="str", choices=["proxy", "flow-based"]),
- ftgd_analytics=dict(required=False, type="str", choices=["disable", "suspicious", "everything"]),
- extended_log=dict(required=False, type="str", choices=["disable", "enable"]),
- comment=dict(required=False, type="str"),
- av_virus_log=dict(required=False, type="str", choices=["disable", "enable"]),
- av_block_log=dict(required=False, type="str", choices=["disable", "enable"]),
- analytics_wl_filetype=dict(required=False, type="dict"),
- analytics_max_upload=dict(required=False, type="int"),
- analytics_db=dict(required=False, type="str", choices=["disable", "enable"]),
- analytics_bl_filetype=dict(required=False, type="dict"),
- content_disarm=dict(required=False, type="list"),
- content_disarm_cover_page=dict(required=False, type="str", choices=["disable", "enable"]),
- content_disarm_detect_only=dict(required=False, type="str", choices=["disable", "enable"]),
- content_disarm_office_embed=dict(required=False, type="str", choices=["disable", "enable"]),
- content_disarm_office_hylink=dict(required=False, type="str", choices=["disable", "enable"]),
- content_disarm_office_linked=dict(required=False, type="str", choices=["disable", "enable"]),
- content_disarm_office_macro=dict(required=False, type="str", choices=["disable", "enable"]),
- content_disarm_original_file_destination=dict(required=False, type="str", choices=["fortisandbox",
- "quarantine",
- "discard"]),
- content_disarm_pdf_act_form=dict(required=False, type="str", choices=["disable", "enable"]),
- content_disarm_pdf_act_gotor=dict(required=False, type="str", choices=["disable", "enable"]),
- content_disarm_pdf_act_java=dict(required=False, type="str", choices=["disable", "enable"]),
- content_disarm_pdf_act_launch=dict(required=False, type="str", choices=["disable", "enable"]),
- content_disarm_pdf_act_movie=dict(required=False, type="str", choices=["disable", "enable"]),
- content_disarm_pdf_act_sound=dict(required=False, type="str", choices=["disable", "enable"]),
- content_disarm_pdf_embedfile=dict(required=False, type="str", choices=["disable", "enable"]),
- content_disarm_pdf_hyperlink=dict(required=False, type="str", choices=["disable", "enable"]),
- content_disarm_pdf_javacode=dict(required=False, type="str", choices=["disable", "enable"]),
- ftp=dict(required=False, type="list"),
- ftp_archive_block=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- ftp_archive_log=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- ftp_emulator=dict(required=False, type="str", choices=["disable", "enable"]),
- ftp_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]),
- ftp_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]),
- http=dict(required=False, type="list"),
- http_archive_block=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- http_archive_log=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- http_content_disarm=dict(required=False, type="str", choices=["disable", "enable"]),
- http_emulator=dict(required=False, type="str", choices=["disable", "enable"]),
- http_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]),
- http_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]),
- imap=dict(required=False, type="list"),
- imap_archive_block=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- imap_archive_log=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- imap_content_disarm=dict(required=False, type="str", choices=["disable", "enable"]),
- imap_emulator=dict(required=False, type="str", choices=["disable", "enable"]),
- imap_executables=dict(required=False, type="str", choices=["default", "virus"]),
- imap_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]),
- imap_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]),
- mapi=dict(required=False, type="list"),
- mapi_archive_block=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- mapi_archive_log=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- mapi_emulator=dict(required=False, type="str", choices=["disable", "enable"]),
- mapi_executables=dict(required=False, type="str", choices=["default", "virus"]),
- mapi_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]),
- mapi_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]),
- nac_quar=dict(required=False, type="list"),
- nac_quar_expiry=dict(required=False, type="str"),
- nac_quar_infected=dict(required=False, type="str", choices=["none", "quar-src-ip"]),
- nac_quar_log=dict(required=False, type="str", choices=["disable", "enable"]),
- nntp=dict(required=False, type="list"),
- nntp_archive_block=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- nntp_archive_log=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- nntp_emulator=dict(required=False, type="str", choices=["disable", "enable"]),
- nntp_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]),
- nntp_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]),
- pop3=dict(required=False, type="list"),
- pop3_archive_block=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- pop3_archive_log=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- pop3_content_disarm=dict(required=False, type="str", choices=["disable", "enable"]),
- pop3_emulator=dict(required=False, type="str", choices=["disable", "enable"]),
- pop3_executables=dict(required=False, type="str", choices=["default", "virus"]),
- pop3_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]),
- pop3_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]),
- smb=dict(required=False, type="list"),
- smb_archive_block=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- smb_archive_log=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- smb_emulator=dict(required=False, type="str", choices=["disable", "enable"]),
- smb_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]),
- smb_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]),
- smtp=dict(required=False, type="list"),
- smtp_archive_block=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- smtp_archive_log=dict(required=False, type="str", choices=["encrypted",
- "corrupted",
- "multipart",
- "nested",
- "mailbomb",
- "unhandled",
- "partiallycorrupted",
- "fileslimit",
- "timeout"]),
- smtp_content_disarm=dict(required=False, type="str", choices=["disable", "enable"]),
- smtp_emulator=dict(required=False, type="str", choices=["disable", "enable"]),
- smtp_executables=dict(required=False, type="str", choices=["default", "virus"]),
- smtp_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]),
- smtp_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "scan-mode": module.params["scan_mode"],
- "replacemsg-group": module.params["replacemsg_group"],
- "name": module.params["name"],
- "mobile-malware-db": module.params["mobile_malware_db"],
- "inspection-mode": module.params["inspection_mode"],
- "ftgd-analytics": module.params["ftgd_analytics"],
- "extended-log": module.params["extended_log"],
- "comment": module.params["comment"],
- "av-virus-log": module.params["av_virus_log"],
- "av-block-log": module.params["av_block_log"],
- "analytics-wl-filetype": module.params["analytics_wl_filetype"],
- "analytics-max-upload": module.params["analytics_max_upload"],
- "analytics-db": module.params["analytics_db"],
- "analytics-bl-filetype": module.params["analytics_bl_filetype"],
- "content-disarm": {
- "cover-page": module.params["content_disarm_cover_page"],
- "detect-only": module.params["content_disarm_detect_only"],
- "office-embed": module.params["content_disarm_office_embed"],
- "office-hylink": module.params["content_disarm_office_hylink"],
- "office-linked": module.params["content_disarm_office_linked"],
- "office-macro": module.params["content_disarm_office_macro"],
- "original-file-destination": module.params["content_disarm_original_file_destination"],
- "pdf-act-form": module.params["content_disarm_pdf_act_form"],
- "pdf-act-gotor": module.params["content_disarm_pdf_act_gotor"],
- "pdf-act-java": module.params["content_disarm_pdf_act_java"],
- "pdf-act-launch": module.params["content_disarm_pdf_act_launch"],
- "pdf-act-movie": module.params["content_disarm_pdf_act_movie"],
- "pdf-act-sound": module.params["content_disarm_pdf_act_sound"],
- "pdf-embedfile": module.params["content_disarm_pdf_embedfile"],
- "pdf-hyperlink": module.params["content_disarm_pdf_hyperlink"],
- "pdf-javacode": module.params["content_disarm_pdf_javacode"],
- },
- "ftp": {
- "archive-block": module.params["ftp_archive_block"],
- "archive-log": module.params["ftp_archive_log"],
- "emulator": module.params["ftp_emulator"],
- "options": module.params["ftp_options"],
- "outbreak-prevention": module.params["ftp_outbreak_prevention"],
- },
- "http": {
- "archive-block": module.params["http_archive_block"],
- "archive-log": module.params["http_archive_log"],
- "content-disarm": module.params["http_content_disarm"],
- "emulator": module.params["http_emulator"],
- "options": module.params["http_options"],
- "outbreak-prevention": module.params["http_outbreak_prevention"],
- },
- "imap": {
- "archive-block": module.params["imap_archive_block"],
- "archive-log": module.params["imap_archive_log"],
- "content-disarm": module.params["imap_content_disarm"],
- "emulator": module.params["imap_emulator"],
- "executables": module.params["imap_executables"],
- "options": module.params["imap_options"],
- "outbreak-prevention": module.params["imap_outbreak_prevention"],
- },
- "mapi": {
- "archive-block": module.params["mapi_archive_block"],
- "archive-log": module.params["mapi_archive_log"],
- "emulator": module.params["mapi_emulator"],
- "executables": module.params["mapi_executables"],
- "options": module.params["mapi_options"],
- "outbreak-prevention": module.params["mapi_outbreak_prevention"],
- },
- "nac-quar": {
- "expiry": module.params["nac_quar_expiry"],
- "infected": module.params["nac_quar_infected"],
- "log": module.params["nac_quar_log"],
- },
- "nntp": {
- "archive-block": module.params["nntp_archive_block"],
- "archive-log": module.params["nntp_archive_log"],
- "emulator": module.params["nntp_emulator"],
- "options": module.params["nntp_options"],
- "outbreak-prevention": module.params["nntp_outbreak_prevention"],
- },
- "pop3": {
- "archive-block": module.params["pop3_archive_block"],
- "archive-log": module.params["pop3_archive_log"],
- "content-disarm": module.params["pop3_content_disarm"],
- "emulator": module.params["pop3_emulator"],
- "executables": module.params["pop3_executables"],
- "options": module.params["pop3_options"],
- "outbreak-prevention": module.params["pop3_outbreak_prevention"],
- },
- "smb": {
- "archive-block": module.params["smb_archive_block"],
- "archive-log": module.params["smb_archive_log"],
- "emulator": module.params["smb_emulator"],
- "options": module.params["smb_options"],
- "outbreak-prevention": module.params["smb_outbreak_prevention"],
- },
- "smtp": {
- "archive-block": module.params["smtp_archive_block"],
- "archive-log": module.params["smtp_archive_log"],
- "content-disarm": module.params["smtp_content_disarm"],
- "emulator": module.params["smtp_emulator"],
- "executables": module.params["smtp_executables"],
- "options": module.params["smtp_options"],
- "outbreak-prevention": module.params["smtp_outbreak_prevention"],
- }
- }
-
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- list_overrides = ["content-disarm", "ftp", "http", "imap", "mapi", "nac-quar", "nntp", "pop3", "smb", "smtp"]
- paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides,
- paramgram=paramgram, module=module)
- module.paramgram = paramgram
-
- results = DEFAULT_RESULT_OBJ
-
- try:
- results = fmgr_antivirus_profile_modify(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_secprof_dns.py b/plugins/modules/network/fortimanager/fmgr_secprof_dns.py
deleted file mode 100644
index 62732df202..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_secprof_dns.py
+++ /dev/null
@@ -1,343 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_secprof_dns
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Manage DNS security profiles in FortiManager
-description:
- - Manage DNS security profiles in FortiManager
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values.
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- youtube_restrict:
- type: str
- description:
- - Set safe search for YouTube restriction level.
- - choice | strict | Enable strict safe seach for YouTube.
- - choice | moderate | Enable moderate safe search for YouTube.
- required: false
- choices: ["strict", "moderate"]
-
- sdns_ftgd_err_log:
- type: str
- description:
- - Enable/disable FortiGuard SDNS rating error logging.
- - choice | disable | Disable FortiGuard SDNS rating error logging.
- - choice | enable | Enable FortiGuard SDNS rating error logging.
- required: false
- choices: ["disable", "enable"]
-
- sdns_domain_log:
- type: str
- description:
- - Enable/disable domain filtering and botnet domain logging.
- - choice | disable | Disable domain filtering and botnet domain logging.
- - choice | enable | Enable domain filtering and botnet domain logging.
- required: false
- choices: ["disable", "enable"]
-
- safe_search:
- type: str
- description:
- - Enable/disable Google, Bing, and YouTube safe search.
- - choice | disable | Disable Google, Bing, and YouTube safe search.
- - choice | enable | Enable Google, Bing, and YouTube safe search.
- required: false
- choices: ["disable", "enable"]
-
- redirect_portal:
- type: str
- description:
- - IP address of the SDNS redirect portal.
- required: false
-
- name:
- type: str
- description:
- - Profile name.
- required: false
-
- log_all_domain:
- type: str
- description:
- - Enable/disable logging of all domains visited (detailed DNS logging).
- - choice | disable | Disable logging of all domains visited.
- - choice | enable | Enable logging of all domains visited.
- required: false
- choices: ["disable", "enable"]
-
- external_ip_blocklist:
- type: str
- description:
- - One or more external IP block lists.
- required: false
-
- comment:
- type: str
- description:
- - Comment for the security profile to show in the FortiManager GUI.
- required: false
-
- block_botnet:
- type: str
- description:
- - Enable/disable blocking botnet C&C; DNS lookups.
- - choice | disable | Disable blocking botnet C&C; DNS lookups.
- - choice | enable | Enable blocking botnet C&C; DNS lookups.
- required: false
- choices: ["disable", "enable"]
-
- block_action:
- type: str
- description:
- - Action to take for blocked domains.
- - choice | block | Return NXDOMAIN for blocked domains.
- - choice | redirect | Redirect blocked domains to SDNS portal.
- required: false
- choices: ["block", "redirect"]
-
- domain_filter_domain_filter_table:
- type: str
- description:
- - DNS domain filter table ID.
- required: false
-
- ftgd_dns_options:
- type: str
- description:
- - FortiGuard DNS filter options.
- - FLAG Based Options. Specify multiple in list form.
- - flag | error-allow | Allow all domains when FortiGuard DNS servers fail.
- - flag | ftgd-disable | Disable FortiGuard DNS domain rating.
- required: false
- choices: ["error-allow", "ftgd-disable"]
-
- ftgd_dns_filters_action:
- type: str
- description:
- - Action to take for DNS requests matching the category.
- - choice | monitor | Allow DNS requests matching the category and log the result.
- - choice | block | Block DNS requests matching the category.
- required: false
- choices: ["monitor", "block"]
-
- ftgd_dns_filters_category:
- type: str
- description:
- - Category number.
- required: false
-
- ftgd_dns_filters_log:
- type: str
- description:
- - Enable/disable DNS filter logging for this DNS profile.
- - choice | disable | Disable DNS filter logging.
- - choice | enable | Enable DNS filter logging.
- required: false
- choices: ["disable", "enable"]
-
-
-'''
-
-EXAMPLES = '''
- - name: DELETE Profile
- fmgr_secprof_dns:
- name: "Ansible_DNS_Profile"
- comment: "Created by Ansible Module TEST"
- mode: "delete"
-
- - name: CREATE Profile
- fmgr_secprof_dns:
- name: "Ansible_DNS_Profile"
- comment: "Created by Ansible Module TEST"
- mode: "set"
- block_action: "block"
-
-
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-
-###############
-# START METHODS
-###############
-
-
-def fmgr_dnsfilter_profile_modify(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- mode = paramgram["mode"]
- adom = paramgram["adom"]
- url = ""
- datagram = {}
-
- response = DEFAULT_RESULT_OBJ
-
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if mode in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/obj/dnsfilter/profile'.format(adom=adom)
- datagram = scrub_dict(prepare_dict(paramgram))
-
- # EVAL THE MODE PARAMETER FOR DELETE
- elif mode == "delete":
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/dnsfilter/profile/{name}'.format(adom=adom, name=paramgram["name"])
- datagram = {}
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
-
- return response
-
-
-#############
-# END METHODS
-#############
-
-
-def main():
- argument_spec = dict(
- adom=dict(type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
-
- youtube_restrict=dict(required=False, type="str", choices=["strict", "moderate"]),
- sdns_ftgd_err_log=dict(required=False, type="str", choices=["disable", "enable"]),
- sdns_domain_log=dict(required=False, type="str", choices=["disable", "enable"]),
- safe_search=dict(required=False, type="str", choices=["disable", "enable"]),
- redirect_portal=dict(required=False, type="str"),
- name=dict(required=False, type="str"),
- log_all_domain=dict(required=False, type="str", choices=["disable", "enable"]),
- external_ip_blocklist=dict(required=False, type="str"),
- comment=dict(required=False, type="str"),
- block_botnet=dict(required=False, type="str", choices=["disable", "enable"]),
- block_action=dict(required=False, type="str", choices=["block", "redirect"]),
-
- domain_filter_domain_filter_table=dict(required=False, type="str"),
-
- ftgd_dns_options=dict(required=False, type="str", choices=["error-allow", "ftgd-disable"]),
-
- ftgd_dns_filters_action=dict(required=False, type="str", choices=["monitor", "block"]),
- ftgd_dns_filters_category=dict(required=False, type="str"),
- ftgd_dns_filters_log=dict(required=False, type="str", choices=["disable", "enable"]),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "youtube-restrict": module.params["youtube_restrict"],
- "sdns-ftgd-err-log": module.params["sdns_ftgd_err_log"],
- "sdns-domain-log": module.params["sdns_domain_log"],
- "safe-search": module.params["safe_search"],
- "redirect-portal": module.params["redirect_portal"],
- "name": module.params["name"],
- "log-all-domain": module.params["log_all_domain"],
- "external-ip-blocklist": module.params["external_ip_blocklist"],
- "comment": module.params["comment"],
- "block-botnet": module.params["block_botnet"],
- "block-action": module.params["block_action"],
- "domain-filter": {
- "domain-filter-table": module.params["domain_filter_domain_filter_table"],
- },
- "ftgd-dns": {
- "options": module.params["ftgd_dns_options"],
- "filters": {
- "action": module.params["ftgd_dns_filters_action"],
- "category": module.params["ftgd_dns_filters_category"],
- "log": module.params["ftgd_dns_filters_log"],
- }
- }
- }
-
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- results = DEFAULT_RESULT_OBJ
-
- try:
- results = fmgr_dnsfilter_profile_modify(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_secprof_ips.py b/plugins/modules/network/fortimanager/fmgr_secprof_ips.py
deleted file mode 100644
index 525ab8cec3..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_secprof_ips.py
+++ /dev/null
@@ -1,668 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_secprof_ips
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Managing IPS security profiles in FortiManager
-description:
- - Managing IPS security profiles in FortiManager
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- replacemsg_group:
- description:
- - Replacement message group.
- required: false
-
- name:
- description:
- - Sensor name.
- required: false
-
- extended_log:
- description:
- - Enable/disable extended logging.
- required: false
- choices:
- - disable
- - enable
-
- comment:
- description:
- - Comment.
- required: false
-
- block_malicious_url:
- description:
- - Enable/disable malicious URL blocking.
- required: false
- choices:
- - disable
- - enable
-
- entries:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- entries_action:
- description:
- - Action taken with traffic in which signatures are detected.
- required: false
- choices:
- - pass
- - block
- - reset
- - default
-
- entries_application:
- description:
- - Applications to be protected. set application ? lists available applications. all includes
- all applications. other includes all unlisted applications.
- required: false
-
- entries_location:
- description:
- - Protect client or server traffic.
- required: false
-
- entries_log:
- description:
- - Enable/disable logging of signatures included in filter.
- required: false
- choices:
- - disable
- - enable
-
- entries_log_attack_context:
- description:
- - Enable/disable logging of attack context| URL buffer, header buffer, body buffer, packet buffer.
- required: false
- choices:
- - disable
- - enable
-
- entries_log_packet:
- description:
- - Enable/disable packet logging. Enable to save the packet that triggers the filter. You can
- download the packets in pcap format for diagnostic use.
- required: false
- choices:
- - disable
- - enable
-
- entries_os:
- description:
- - Operating systems to be protected. all includes all operating systems. other includes all
- unlisted operating systems.
- required: false
-
- entries_protocol:
- description:
- - Protocols to be examined. set protocol ? lists available protocols. all includes all protocols.
- other includes all unlisted protocols.
- required: false
-
- entries_quarantine:
- description:
- - Quarantine method.
- required: false
- choices:
- - none
- - attacker
-
- entries_quarantine_expiry:
- description:
- - Duration of quarantine.
- required: false
-
- entries_quarantine_log:
- description:
- - Enable/disable quarantine logging.
- required: false
- choices:
- - disable
- - enable
-
- entries_rate_count:
- description:
- - Count of the rate.
- required: false
-
- entries_rate_duration:
- description:
- - Duration (sec) of the rate.
- required: false
-
- entries_rate_mode:
- description:
- - Rate limit mode.
- required: false
- choices:
- - periodical
- - continuous
-
- entries_rate_track:
- description:
- - Track the packet protocol field.
- required: false
- choices:
- - none
- - src-ip
- - dest-ip
- - dhcp-client-mac
- - dns-domain
-
- entries_rule:
- description:
- - Identifies the predefined or custom IPS signatures to add to the sensor.
- required: false
-
- entries_severity:
- description:
- - Relative severity of the signature, from info to critical. Log messages generated by the signature
- include the severity.
- required: false
-
- entries_status:
- description:
- - Status of the signatures included in filter. default enables the filter and only use filters
- with default status of enable. Filters with default status of disable will not be used.
- required: false
- choices:
- - disable
- - enable
- - default
-
- entries_exempt_ip_dst_ip:
- description:
- - Destination IP address and netmask.
- required: false
-
- entries_exempt_ip_src_ip:
- description:
- - Source IP address and netmask.
- required: false
-
- filter:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- filter_action:
- description:
- - Action of selected rules.
- required: false
- choices:
- - pass
- - block
- - default
- - reset
-
- filter_application:
- description:
- - Vulnerable application filter.
- required: false
-
- filter_location:
- description:
- - Vulnerability location filter.
- required: false
-
- filter_log:
- description:
- - Enable/disable logging of selected rules.
- required: false
- choices:
- - disable
- - enable
-
- filter_log_packet:
- description:
- - Enable/disable packet logging of selected rules.
- required: false
- choices:
- - disable
- - enable
-
- filter_name:
- description:
- - Filter name.
- required: false
-
- filter_os:
- description:
- - Vulnerable OS filter.
- required: false
-
- filter_protocol:
- description:
- - Vulnerable protocol filter.
- required: false
-
- filter_quarantine:
- description:
- - Quarantine IP or interface.
- required: false
- choices:
- - none
- - attacker
-
- filter_quarantine_expiry:
- description:
- - Duration of quarantine in minute.
- required: false
-
- filter_quarantine_log:
- description:
- - Enable/disable logging of selected quarantine.
- required: false
- choices:
- - disable
- - enable
-
- filter_severity:
- description:
- - Vulnerability severity filter.
- required: false
-
- filter_status:
- description:
- - Selected rules status.
- required: false
- choices:
- - disable
- - enable
- - default
-
- override:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- override_action:
- description:
- - Action of override rule.
- required: false
- choices:
- - pass
- - block
- - reset
-
- override_log:
- description:
- - Enable/disable logging.
- required: false
- choices:
- - disable
- - enable
-
- override_log_packet:
- description:
- - Enable/disable packet logging.
- required: false
- choices:
- - disable
- - enable
-
- override_quarantine:
- description:
- - Quarantine IP or interface.
- required: false
- choices:
- - none
- - attacker
-
- override_quarantine_expiry:
- description:
- - Duration of quarantine in minute.
- required: false
-
- override_quarantine_log:
- description:
- - Enable/disable logging of selected quarantine.
- required: false
- choices:
- - disable
- - enable
-
- override_rule_id:
- description:
- - Override rule ID.
- required: false
-
- override_status:
- description:
- - Enable/disable status of override rule.
- required: false
- choices:
- - disable
- - enable
-
- override_exempt_ip_dst_ip:
- description:
- - Destination IP address and netmask.
- required: false
-
- override_exempt_ip_src_ip:
- description:
- - Source IP address and netmask.
- required: false
-'''
-
-EXAMPLES = '''
- - name: DELETE Profile
- fmgr_secprof_ips:
- name: "Ansible_IPS_Profile"
- comment: "Created by Ansible Module TEST"
- mode: "delete"
-
- - name: CREATE Profile
- fmgr_secprof_ips:
- name: "Ansible_IPS_Profile"
- comment: "Created by Ansible Module TEST"
- mode: "set"
- block_malicious_url: "enable"
- entries: [{severity: "high", action: "block", log-packet: "enable"}, {severity: "medium", action: "pass"}]
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-
-###############
-# START METHODS
-###############
-
-
-def fmgr_ips_sensor_modify(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- mode = paramgram["mode"]
- adom = paramgram["adom"]
- # INIT A BASIC OBJECTS
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
-
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if mode in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/obj/ips/sensor'.format(adom=adom)
- datagram = scrub_dict(prepare_dict(paramgram))
-
- # EVAL THE MODE PARAMETER FOR DELETE
- elif mode == "delete":
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/ips/sensor/{name}'.format(
- adom=adom, name=paramgram["name"])
- datagram = {}
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
-
- return response
-
-
-#############
-# END METHODS
-#############
-
-
-def main():
- argument_spec = dict(
- adom=dict(type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"],
- type="str", default="add"),
-
- replacemsg_group=dict(required=False, type="str"),
- name=dict(required=False, type="str"),
- extended_log=dict(required=False, type="str",
- choices=["disable", "enable"]),
- comment=dict(required=False, type="str"),
- block_malicious_url=dict(required=False, type="str", choices=[
- "disable", "enable"]),
- entries=dict(required=False, type="list"),
- entries_action=dict(required=False, type="str", choices=[
- "pass", "block", "reset", "default"]),
- entries_application=dict(required=False, type="str"),
- entries_location=dict(required=False, type="str"),
- entries_log=dict(required=False, type="str",
- choices=["disable", "enable"]),
- entries_log_attack_context=dict(
- required=False, type="str", choices=["disable", "enable"]),
- entries_log_packet=dict(required=False, type="str", choices=[
- "disable", "enable"]),
- entries_os=dict(required=False, type="str"),
- entries_protocol=dict(required=False, type="str"),
- entries_quarantine=dict(required=False, type="str", choices=[
- "none", "attacker"]),
- entries_quarantine_expiry=dict(required=False, type="str"),
- entries_quarantine_log=dict(
- required=False, type="str", choices=["disable", "enable"]),
- entries_rate_count=dict(required=False, type="int"),
- entries_rate_duration=dict(required=False, type="int"),
- entries_rate_mode=dict(required=False, type="str", choices=[
- "periodical", "continuous"]),
- entries_rate_track=dict(required=False, type="str",
- choices=["none", "src-ip", "dest-ip", "dhcp-client-mac", "dns-domain"]),
- entries_rule=dict(required=False, type="str"),
- entries_severity=dict(required=False, type="str"),
- entries_status=dict(required=False, type="str", choices=[
- "disable", "enable", "default"]),
-
- entries_exempt_ip_dst_ip=dict(required=False, type="str"),
- entries_exempt_ip_src_ip=dict(required=False, type="str"),
- filter=dict(required=False, type="list"),
- filter_action=dict(required=False, type="str", choices=[
- "pass", "block", "default", "reset"]),
- filter_application=dict(required=False, type="str"),
- filter_location=dict(required=False, type="str"),
- filter_log=dict(required=False, type="str",
- choices=["disable", "enable"]),
- filter_log_packet=dict(required=False, type="str",
- choices=["disable", "enable"]),
- filter_name=dict(required=False, type="str"),
- filter_os=dict(required=False, type="str"),
- filter_protocol=dict(required=False, type="str"),
- filter_quarantine=dict(required=False, type="str",
- choices=["none", "attacker"]),
- filter_quarantine_expiry=dict(required=False, type="int"),
- filter_quarantine_log=dict(required=False, type="str", choices=[
- "disable", "enable"]),
- filter_severity=dict(required=False, type="str"),
- filter_status=dict(required=False, type="str", choices=[
- "disable", "enable", "default"]),
- override=dict(required=False, type="list"),
- override_action=dict(required=False, type="str",
- choices=["pass", "block", "reset"]),
- override_log=dict(required=False, type="str",
- choices=["disable", "enable"]),
- override_log_packet=dict(required=False, type="str", choices=[
- "disable", "enable"]),
- override_quarantine=dict(required=False, type="str", choices=[
- "none", "attacker"]),
- override_quarantine_expiry=dict(required=False, type="int"),
- override_quarantine_log=dict(
- required=False, type="str", choices=["disable", "enable"]),
- override_rule_id=dict(required=False, type="str"),
- override_status=dict(required=False, type="str",
- choices=["disable", "enable"]),
-
- override_exempt_ip_dst_ip=dict(required=False, type="str"),
- override_exempt_ip_src_ip=dict(required=False, type="str"),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "replacemsg-group": module.params["replacemsg_group"],
- "name": module.params["name"],
- "extended-log": module.params["extended_log"],
- "comment": module.params["comment"],
- "block-malicious-url": module.params["block_malicious_url"],
- "entries": {
- "action": module.params["entries_action"],
- "application": module.params["entries_application"],
- "location": module.params["entries_location"],
- "log": module.params["entries_log"],
- "log-attack-context": module.params["entries_log_attack_context"],
- "log-packet": module.params["entries_log_packet"],
- "os": module.params["entries_os"],
- "protocol": module.params["entries_protocol"],
- "quarantine": module.params["entries_quarantine"],
- "quarantine-expiry": module.params["entries_quarantine_expiry"],
- "quarantine-log": module.params["entries_quarantine_log"],
- "rate-count": module.params["entries_rate_count"],
- "rate-duration": module.params["entries_rate_duration"],
- "rate-mode": module.params["entries_rate_mode"],
- "rate-track": module.params["entries_rate_track"],
- "rule": module.params["entries_rule"],
- "severity": module.params["entries_severity"],
- "status": module.params["entries_status"],
- "exempt-ip": {
- "dst-ip": module.params["entries_exempt_ip_dst_ip"],
- "src-ip": module.params["entries_exempt_ip_src_ip"],
- },
- },
- "filter": {
- "action": module.params["filter_action"],
- "application": module.params["filter_application"],
- "location": module.params["filter_location"],
- "log": module.params["filter_log"],
- "log-packet": module.params["filter_log_packet"],
- "name": module.params["filter_name"],
- "os": module.params["filter_os"],
- "protocol": module.params["filter_protocol"],
- "quarantine": module.params["filter_quarantine"],
- "quarantine-expiry": module.params["filter_quarantine_expiry"],
- "quarantine-log": module.params["filter_quarantine_log"],
- "severity": module.params["filter_severity"],
- "status": module.params["filter_status"],
- },
- "override": {
- "action": module.params["override_action"],
- "log": module.params["override_log"],
- "log-packet": module.params["override_log_packet"],
- "quarantine": module.params["override_quarantine"],
- "quarantine-expiry": module.params["override_quarantine_expiry"],
- "quarantine-log": module.params["override_quarantine_log"],
- "rule-id": module.params["override_rule_id"],
- "status": module.params["override_status"],
- "exempt-ip": {
- "dst-ip": module.params["override_exempt_ip_dst_ip"],
- "src-ip": module.params["override_exempt_ip_src_ip"],
- }
- }
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- list_overrides = ['entries', 'filter', 'override']
-
- paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides,
- paramgram=paramgram, module=module)
-
- results = DEFAULT_RESULT_OBJ
- try:
- results = fmgr_ips_sensor_modify(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_secprof_profile_group.py b/plugins/modules/network/fortimanager/fmgr_secprof_profile_group.py
deleted file mode 100644
index ac1fb88586..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_secprof_profile_group.py
+++ /dev/null
@@ -1,291 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_secprof_profile_group
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Manage security profiles within FortiManager
-description:
- - Manage security profile group which allows you to create a group of security profiles and apply that to a policy.
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values.
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- webfilter_profile:
- type: str
- description:
- - Name of an existing Web filter profile.
- required: false
-
- waf_profile:
- type: str
- description:
- - Name of an existing Web application firewall profile.
- required: false
-
- voip_profile:
- type: str
- description:
- - Name of an existing VoIP profile.
- required: false
-
- ssl_ssh_profile:
- type: str
- description:
- - Name of an existing SSL SSH profile.
- required: false
-
- ssh_filter_profile:
- type: str
- description:
- - Name of an existing SSH filter profile.
- required: false
-
- spamfilter_profile:
- type: str
- description:
- - Name of an existing Spam filter profile.
- required: false
-
- profile_protocol_options:
- type: str
- description:
- - Name of an existing Protocol options profile.
- required: false
-
- name:
- type: str
- description:
- - Profile group name.
- required: false
-
- mms_profile:
- type: str
- description:
- - Name of an existing MMS profile.
- required: false
-
- ips_sensor:
- type: str
- description:
- - Name of an existing IPS sensor.
- required: false
-
- icap_profile:
- type: str
- description:
- - Name of an existing ICAP profile.
- required: false
-
- dnsfilter_profile:
- type: str
- description:
- - Name of an existing DNS filter profile.
- required: false
-
- dlp_sensor:
- type: str
- description:
- - Name of an existing DLP sensor.
- required: false
-
- av_profile:
- type: str
- description:
- - Name of an existing Antivirus profile.
- required: false
-
- application_list:
- type: str
- description:
- - Name of an existing Application list.
- required: false
-
-
-'''
-
-EXAMPLES = '''
- - name: DELETE Profile
- fmgr_secprof_profile_group:
- name: "Ansible_TEST_Profile_Group"
- mode: "delete"
-
- - name: CREATE Profile
- fmgr_secprof_profile_group:
- name: "Ansible_TEST_Profile_Group"
- mode: "set"
- av_profile: "Ansible_AV_Profile"
- profile_protocol_options: "default"
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-
-###############
-# START METHODS
-###############
-
-
-def fmgr_firewall_profile_group_modify(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- mode = paramgram["mode"]
- adom = paramgram["adom"]
- url = ""
- datagram = {}
-
- response = DEFAULT_RESULT_OBJ
-
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if mode in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/obj/firewall/profile-group'.format(adom=adom)
- datagram = scrub_dict(prepare_dict(paramgram))
-
- # EVAL THE MODE PARAMETER FOR DELETE
- elif mode == "delete":
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/firewall/profile-group/{name}'.format(adom=adom, name=paramgram["name"])
- datagram = {}
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
-
- return response
-
-
-#############
-# END METHODS
-#############
-
-
-def main():
- argument_spec = dict(
- adom=dict(type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
-
- webfilter_profile=dict(required=False, type="str"),
- waf_profile=dict(required=False, type="str"),
- voip_profile=dict(required=False, type="str"),
- ssl_ssh_profile=dict(required=False, type="str"),
- ssh_filter_profile=dict(required=False, type="str"),
- spamfilter_profile=dict(required=False, type="str"),
- profile_protocol_options=dict(required=False, type="str"),
- name=dict(required=False, type="str"),
- mms_profile=dict(required=False, type="str"),
- ips_sensor=dict(required=False, type="str"),
- icap_profile=dict(required=False, type="str"),
- dnsfilter_profile=dict(required=False, type="str"),
- dlp_sensor=dict(required=False, type="str"),
- av_profile=dict(required=False, type="str"),
- application_list=dict(required=False, type="str"),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "webfilter-profile": module.params["webfilter_profile"],
- "waf-profile": module.params["waf_profile"],
- "voip-profile": module.params["voip_profile"],
- "ssl-ssh-profile": module.params["ssl_ssh_profile"],
- "ssh-filter-profile": module.params["ssh_filter_profile"],
- "spamfilter-profile": module.params["spamfilter_profile"],
- "profile-protocol-options": module.params["profile_protocol_options"],
- "name": module.params["name"],
- "mms-profile": module.params["mms_profile"],
- "ips-sensor": module.params["ips_sensor"],
- "icap-profile": module.params["icap_profile"],
- "dnsfilter-profile": module.params["dnsfilter_profile"],
- "dlp-sensor": module.params["dlp_sensor"],
- "av-profile": module.params["av_profile"],
- "application-list": module.params["application_list"],
-
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- results = DEFAULT_RESULT_OBJ
-
- try:
- results = fmgr_firewall_profile_group_modify(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_secprof_proxy.py b/plugins/modules/network/fortimanager/fmgr_secprof_proxy.py
deleted file mode 100644
index 7765ce0581..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_secprof_proxy.py
+++ /dev/null
@@ -1,336 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_secprof_proxy
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Manage proxy security profiles in FortiManager
-description:
- - Manage proxy security profiles for FortiGates via FortiManager using the FMG API with playbooks
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- strip_encoding:
- description:
- - Enable/disable stripping unsupported encoding from the request header.
- - choice | disable | Disable stripping of unsupported encoding from the request header.
- - choice | enable | Enable stripping of unsupported encoding from the request header.
- required: false
- choices: ["disable", "enable"]
-
- name:
- description:
- - Profile name.
- required: false
-
- log_header_change:
- description:
- - Enable/disable logging HTTP header changes.
- - choice | disable | Disable Enable/disable logging HTTP header changes.
- - choice | enable | Enable Enable/disable logging HTTP header changes.
- required: false
- choices: ["disable", "enable"]
-
- header_x_forwarded_for:
- description:
- - Action to take on the HTTP x-forwarded-for header in forwarded requests| forwards (pass), adds, or removes the
- - HTTP header.
- - choice | pass | Forward the same HTTP header.
- - choice | add | Add the HTTP header.
- - choice | remove | Remove the HTTP header.
- required: false
- choices: ["pass", "add", "remove"]
-
- header_x_authenticated_user:
- description:
- - Action to take on the HTTP x-authenticated-user header in forwarded requests| forwards (pass), adds, or remove
- - s the HTTP header.
- - choice | pass | Forward the same HTTP header.
- - choice | add | Add the HTTP header.
- - choice | remove | Remove the HTTP header.
- required: false
- choices: ["pass", "add", "remove"]
-
- header_x_authenticated_groups:
- description:
- - Action to take on the HTTP x-authenticated-groups header in forwarded requests| forwards (pass), adds, or remo
- - ves the HTTP header.
- - choice | pass | Forward the same HTTP header.
- - choice | add | Add the HTTP header.
- - choice | remove | Remove the HTTP header.
- required: false
- choices: ["pass", "add", "remove"]
-
- header_via_response:
- description:
- - Action to take on the HTTP via header in forwarded responses| forwards (pass), adds, or removes the HTTP heade
- - r.
- - choice | pass | Forward the same HTTP header.
- - choice | add | Add the HTTP header.
- - choice | remove | Remove the HTTP header.
- required: false
- choices: ["pass", "add", "remove"]
-
- header_via_request:
- description:
- - Action to take on the HTTP via header in forwarded requests| forwards (pass), adds, or removes the HTTP header
- - .
- - choice | pass | Forward the same HTTP header.
- - choice | add | Add the HTTP header.
- - choice | remove | Remove the HTTP header.
- required: false
- choices: ["pass", "add", "remove"]
-
- header_front_end_https:
- description:
- - Action to take on the HTTP front-end-HTTPS header in forwarded requests| forwards (pass), adds, or removes the
- - HTTP header.
- - choice | pass | Forward the same HTTP header.
- - choice | add | Add the HTTP header.
- - choice | remove | Remove the HTTP header.
- required: false
- choices: ["pass", "add", "remove"]
-
- header_client_ip:
- description:
- - Actions to take on the HTTP client-IP header in forwarded requests| forwards (pass), adds, or removes the HTTP
- - header.
- - choice | pass | Forward the same HTTP header.
- - choice | add | Add the HTTP header.
- - choice | remove | Remove the HTTP header.
- required: false
- choices: ["pass", "add", "remove"]
-
- headers:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- headers_action:
- description:
- - Action when HTTP the header forwarded.
- - choice | add-to-request | Add the HTTP header to request.
- - choice | add-to-response | Add the HTTP header to response.
- - choice | remove-from-request | Remove the HTTP header from request.
- - choice | remove-from-response | Remove the HTTP header from response.
- required: false
- choices: ["add-to-request", "add-to-response", "remove-from-request", "remove-from-response"]
-
- headers_content:
- description:
- - HTTP header's content.
- required: false
-
- headers_name:
- description:
- - HTTP forwarded header name.
- required: false
-
-
-'''
-
-EXAMPLES = '''
- - name: DELETE Profile
- fmgr_secprof_proxy:
- name: "Ansible_Web_Proxy_Profile"
- mode: "delete"
-
- - name: CREATE Profile
- fmgr_secprof_proxy:
- name: "Ansible_Web_Proxy_Profile"
- mode: "set"
- header_client_ip: "pass"
- header_front_end_https: "add"
- header_via_request: "remove"
- header_via_response: "pass"
- header_x_authenticated_groups: "add"
- header_x_authenticated_user: "remove"
- strip_encoding: "enable"
- log_header_change: "enable"
- header_x_forwarded_for: "pass"
- headers_action: "add-to-request"
- headers_content: "test"
- headers_name: "test_header"
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-
-###############
-# START METHODS
-###############
-
-
-def fmgr_web_proxy_profile_modify(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- mode = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
-
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if mode in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/obj/web-proxy/profile'.format(adom=adom)
- datagram = scrub_dict(prepare_dict(paramgram))
-
- # EVAL THE MODE PARAMETER FOR DELETE
- elif mode == "delete":
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/web-proxy/profile/{name}'.format(adom=adom, name=paramgram["name"])
- datagram = {}
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
-
- return response
-
-
-#############
-# END METHODS
-#############
-
-
-def main():
- argument_spec = dict(
- adom=dict(type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
-
- strip_encoding=dict(required=False, type="str", choices=["disable", "enable"]),
- name=dict(required=False, type="str"),
- log_header_change=dict(required=False, type="str", choices=["disable", "enable"]),
- header_x_forwarded_for=dict(required=False, type="str", choices=["pass", "add", "remove"]),
- header_x_authenticated_user=dict(required=False, type="str", choices=["pass", "add", "remove"]),
- header_x_authenticated_groups=dict(required=False, type="str", choices=["pass", "add", "remove"]),
- header_via_response=dict(required=False, type="str", choices=["pass", "add", "remove"]),
- header_via_request=dict(required=False, type="str", choices=["pass", "add", "remove"]),
- header_front_end_https=dict(required=False, type="str", choices=["pass", "add", "remove"]),
- header_client_ip=dict(required=False, type="str", choices=["pass", "add", "remove"]),
- headers=dict(required=False, type="list"),
- headers_action=dict(required=False, type="str", choices=["add-to-request", "add-to-response",
- "remove-from-request", "remove-from-response"]),
- headers_content=dict(required=False, type="str"),
- headers_name=dict(required=False, type="str"),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "strip-encoding": module.params["strip_encoding"],
- "name": module.params["name"],
- "log-header-change": module.params["log_header_change"],
- "header-x-forwarded-for": module.params["header_x_forwarded_for"],
- "header-x-authenticated-user": module.params["header_x_authenticated_user"],
- "header-x-authenticated-groups": module.params["header_x_authenticated_groups"],
- "header-via-response": module.params["header_via_response"],
- "header-via-request": module.params["header_via_request"],
- "header-front-end-https": module.params["header_front_end_https"],
- "header-client-ip": module.params["header_client_ip"],
- "headers": {
- "action": module.params["headers_action"],
- "content": module.params["headers_content"],
- "name": module.params["headers_name"],
- }
- }
-
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- list_overrides = ['headers']
- paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides,
- paramgram=paramgram, module=module)
- module.paramgram = paramgram
-
- results = DEFAULT_RESULT_OBJ
- try:
- results = fmgr_web_proxy_profile_modify(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_secprof_spam.py b/plugins/modules/network/fortimanager/fmgr_secprof_spam.py
deleted file mode 100644
index ebc374ce0d..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_secprof_spam.py
+++ /dev/null
@@ -1,611 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_secprof_spam
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: spam filter profile for FMG
-description:
- - Manage spam filter security profiles within FortiManager via API
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- spam_rbl_table:
- description:
- - Anti-spam DNSBL table ID.
- required: false
-
- spam_mheader_table:
- description:
- - Anti-spam MIME header table ID.
- required: false
-
- spam_log_fortiguard_response:
- description:
- - Enable/disable logging FortiGuard spam response.
- required: false
- choices:
- - disable
- - enable
-
- spam_log:
- description:
- - Enable/disable spam logging for email filtering.
- required: false
- choices:
- - disable
- - enable
-
- spam_iptrust_table:
- description:
- - Anti-spam IP trust table ID.
- required: false
-
- spam_filtering:
- description:
- - Enable/disable spam filtering.
- required: false
- choices:
- - disable
- - enable
-
- spam_bword_threshold:
- description:
- - Spam banned word threshold.
- required: false
-
- spam_bword_table:
- description:
- - Anti-spam banned word table ID.
- required: false
-
- spam_bwl_table:
- description:
- - Anti-spam black/white list table ID.
- required: false
-
- replacemsg_group:
- description:
- - Replacement message group.
- required: false
-
- options:
- description:
- - None
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - bannedword
- - spamfsip
- - spamfssubmit
- - spamfschksum
- - spamfsurl
- - spamhelodns
- - spamraddrdns
- - spamrbl
- - spamhdrcheck
- - spamfsphish
- - spambwl
-
- name:
- description:
- - Profile name.
- required: false
-
- flow_based:
- description:
- - Enable/disable flow-based spam filtering.
- required: false
- choices:
- - disable
- - enable
-
- external:
- description:
- - Enable/disable external Email inspection.
- required: false
- choices:
- - disable
- - enable
-
- comment:
- description:
- - Comment.
- required: false
-
- gmail:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- gmail_log:
- description:
- - Enable/disable logging.
- required: false
- choices:
- - disable
- - enable
-
- imap:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- imap_action:
- description:
- - Action for spam email.
- required: false
- choices:
- - pass
- - tag
-
- imap_log:
- description:
- - Enable/disable logging.
- required: false
- choices:
- - disable
- - enable
-
- imap_tag_msg:
- description:
- - Subject text or header added to spam email.
- required: false
-
- imap_tag_type:
- description:
- - Tag subject or header for spam email.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - subject
- - header
- - spaminfo
-
- mapi:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- mapi_action:
- description:
- - Action for spam email.
- required: false
- choices:
- - pass
- - discard
-
- mapi_log:
- description:
- - Enable/disable logging.
- required: false
- choices:
- - disable
- - enable
-
- msn_hotmail:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- msn_hotmail_log:
- description:
- - Enable/disable logging.
- required: false
- choices:
- - disable
- - enable
-
- pop3:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- pop3_action:
- description:
- - Action for spam email.
- required: false
- choices:
- - pass
- - tag
-
- pop3_log:
- description:
- - Enable/disable logging.
- required: false
- choices:
- - disable
- - enable
-
- pop3_tag_msg:
- description:
- - Subject text or header added to spam email.
- required: false
-
- pop3_tag_type:
- description:
- - Tag subject or header for spam email.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - subject
- - header
- - spaminfo
-
- smtp:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- smtp_action:
- description:
- - Action for spam email.
- required: false
- choices:
- - pass
- - tag
- - discard
-
- smtp_hdrip:
- description:
- - Enable/disable SMTP email header IP checks for spamfsip, spamrbl and spambwl filters.
- required: false
- choices:
- - disable
- - enable
-
- smtp_local_override:
- description:
- - Enable/disable local filter to override SMTP remote check result.
- required: false
- choices:
- - disable
- - enable
-
- smtp_log:
- description:
- - Enable/disable logging.
- required: false
- choices:
- - disable
- - enable
-
- smtp_tag_msg:
- description:
- - Subject text or header added to spam email.
- required: false
-
- smtp_tag_type:
- description:
- - Tag subject or header for spam email.
- - FLAG Based Options. Specify multiple in list form.
- required: false
- choices:
- - subject
- - header
- - spaminfo
-
- yahoo_mail:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- yahoo_mail_log:
- description:
- - Enable/disable logging.
- required: false
- choices:
- - disable
- - enable
-'''
-
-EXAMPLES = '''
- - name: DELETE Profile
- fmgr_secprof_spam:
- name: "Ansible_Spam_Filter_Profile"
- mode: "delete"
-
- - name: Create FMGR_SPAMFILTER_PROFILE
- fmgr_secprof_spam:
- host: "{{ inventory_hostname }}"
- username: "{{ username }}"
- password: "{{ password }}"
- mode: "set"
- adom: "root"
- spam_log_fortiguard_response: "enable"
- spam_iptrust_table:
- spam_filtering: "enable"
- spam_bword_threshold: 10
- options: ["bannedword", "spamfsip", "spamfsurl", "spamrbl", "spamfsphish", "spambwl"]
- name: "Ansible_Spam_Filter_Profile"
- flow_based: "enable"
- external: "enable"
- comment: "Created by Ansible"
- gmail_log: "enable"
- spam_log: "enable"
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-###############
-# START METHODS
-###############
-
-
-def fmgr_spamfilter_profile_modify(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- mode = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
-
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if mode in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/obj/spamfilter/profile'.format(adom=adom)
- datagram = scrub_dict(prepare_dict(paramgram))
-
- # EVAL THE MODE PARAMETER FOR DELETE
- elif mode == "delete":
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/spamfilter/profile/{name}'.format(adom=adom, name=paramgram["name"])
- datagram = {}
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
-
- return response
-
-
-#############
-# END METHODS
-#############
-
-
-def main():
- argument_spec = dict(
- adom=dict(type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
-
- spam_rbl_table=dict(required=False, type="str"),
- spam_mheader_table=dict(required=False, type="str"),
- spam_log_fortiguard_response=dict(required=False, type="str", choices=["disable", "enable"]),
- spam_log=dict(required=False, type="str", choices=["disable", "enable"]),
- spam_iptrust_table=dict(required=False, type="str"),
- spam_filtering=dict(required=False, type="str", choices=["disable", "enable"]),
- spam_bword_threshold=dict(required=False, type="int"),
- spam_bword_table=dict(required=False, type="str"),
- spam_bwl_table=dict(required=False, type="str"),
- replacemsg_group=dict(required=False, type="str"),
- options=dict(required=False, type="list", choices=["bannedword",
- "spamfsip",
- "spamfssubmit",
- "spamfschksum",
- "spamfsurl",
- "spamhelodns",
- "spamraddrdns",
- "spamrbl",
- "spamhdrcheck",
- "spamfsphish",
- "spambwl"]),
- name=dict(required=False, type="str"),
- flow_based=dict(required=False, type="str", choices=["disable", "enable"]),
- external=dict(required=False, type="str", choices=["disable", "enable"]),
- comment=dict(required=False, type="str"),
- gmail=dict(required=False, type="dict"),
- gmail_log=dict(required=False, type="str", choices=["disable", "enable"]),
- imap=dict(required=False, type="dict"),
- imap_action=dict(required=False, type="str", choices=["pass", "tag"]),
- imap_log=dict(required=False, type="str", choices=["disable", "enable"]),
- imap_tag_msg=dict(required=False, type="str"),
- imap_tag_type=dict(required=False, type="str", choices=["subject", "header", "spaminfo"]),
- mapi=dict(required=False, type="dict"),
- mapi_action=dict(required=False, type="str", choices=["pass", "discard"]),
- mapi_log=dict(required=False, type="str", choices=["disable", "enable"]),
- msn_hotmail=dict(required=False, type="dict"),
- msn_hotmail_log=dict(required=False, type="str", choices=["disable", "enable"]),
- pop3=dict(required=False, type="dict"),
- pop3_action=dict(required=False, type="str", choices=["pass", "tag"]),
- pop3_log=dict(required=False, type="str", choices=["disable", "enable"]),
- pop3_tag_msg=dict(required=False, type="str"),
- pop3_tag_type=dict(required=False, type="str", choices=["subject", "header", "spaminfo"]),
- smtp=dict(required=False, type="dict"),
- smtp_action=dict(required=False, type="str", choices=["pass", "tag", "discard"]),
- smtp_hdrip=dict(required=False, type="str", choices=["disable", "enable"]),
- smtp_local_override=dict(required=False, type="str", choices=["disable", "enable"]),
- smtp_log=dict(required=False, type="str", choices=["disable", "enable"]),
- smtp_tag_msg=dict(required=False, type="str"),
- smtp_tag_type=dict(required=False, type="str", choices=["subject", "header", "spaminfo"]),
- yahoo_mail=dict(required=False, type="dict"),
- yahoo_mail_log=dict(required=False, type="str", choices=["disable", "enable"]),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "spam-rbl-table": module.params["spam_rbl_table"],
- "spam-mheader-table": module.params["spam_mheader_table"],
- "spam-log-fortiguard-response": module.params["spam_log_fortiguard_response"],
- "spam-log": module.params["spam_log"],
- "spam-iptrust-table": module.params["spam_iptrust_table"],
- "spam-filtering": module.params["spam_filtering"],
- "spam-bword-threshold": module.params["spam_bword_threshold"],
- "spam-bword-table": module.params["spam_bword_table"],
- "spam-bwl-table": module.params["spam_bwl_table"],
- "replacemsg-group": module.params["replacemsg_group"],
- "options": module.params["options"],
- "name": module.params["name"],
- "flow-based": module.params["flow_based"],
- "external": module.params["external"],
- "comment": module.params["comment"],
- "gmail": {
- "log": module.params["gmail_log"],
- },
- "imap": {
- "action": module.params["imap_action"],
- "log": module.params["imap_log"],
- "tag-msg": module.params["imap_tag_msg"],
- "tag-type": module.params["imap_tag_type"],
- },
- "mapi": {
- "action": module.params["mapi_action"],
- "log": module.params["mapi_log"],
- },
- "msn-hotmail": {
- "log": module.params["msn_hotmail_log"],
- },
- "pop3": {
- "action": module.params["pop3_action"],
- "log": module.params["pop3_log"],
- "tag-msg": module.params["pop3_tag_msg"],
- "tag-type": module.params["pop3_tag_type"],
- },
- "smtp": {
- "action": module.params["smtp_action"],
- "hdrip": module.params["smtp_hdrip"],
- "local-override": module.params["smtp_local_override"],
- "log": module.params["smtp_log"],
- "tag-msg": module.params["smtp_tag_msg"],
- "tag-type": module.params["smtp_tag_type"],
- },
- "yahoo-mail": {
- "log": module.params["yahoo_mail_log"],
- }
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- list_overrides = ['gmail', 'imap', 'mapi', 'msn-hotmail', 'pop3', 'smtp', 'yahoo-mail']
- paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides,
- paramgram=paramgram, module=module)
-
- results = DEFAULT_RESULT_OBJ
- try:
-
- results = fmgr_spamfilter_profile_modify(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_secprof_ssl_ssh.py b/plugins/modules/network/fortimanager/fmgr_secprof_ssl_ssh.py
deleted file mode 100644
index e5c71c480d..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_secprof_ssl_ssh.py
+++ /dev/null
@@ -1,958 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_secprof_ssl_ssh
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Manage SSL and SSH security profiles in FortiManager
-description:
- - Manage SSL and SSH security profiles in FortiManager via the FMG API
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- whitelist:
- description:
- - Enable/disable exempting servers by FortiGuard whitelist.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- use_ssl_server:
- description:
- - Enable/disable the use of SSL server table for SSL offloading.
- - choice | disable | Don't use SSL server configuration.
- - choice | enable | Use SSL server configuration.
- required: false
- choices: ["disable", "enable"]
-
- untrusted_caname:
- description:
- - Untrusted CA certificate used by SSL Inspection.
- required: false
-
- ssl_exemptions_log:
- description:
- - Enable/disable logging SSL exemptions.
- - choice | disable | Disable logging SSL exemptions.
- - choice | enable | Enable logging SSL exemptions.
- required: false
- choices: ["disable", "enable"]
-
- ssl_anomalies_log:
- description:
- - Enable/disable logging SSL anomalies.
- - choice | disable | Disable logging SSL anomalies.
- - choice | enable | Enable logging SSL anomalies.
- required: false
- choices: ["disable", "enable"]
-
- server_cert_mode:
- description:
- - Re-sign or replace the server's certificate.
- - choice | re-sign | Multiple clients connecting to multiple servers.
- - choice | replace | Protect an SSL server.
- required: false
- choices: ["re-sign", "replace"]
-
- server_cert:
- description:
- - Certificate used by SSL Inspection to replace server certificate.
- required: false
-
- rpc_over_https:
- description:
- - Enable/disable inspection of RPC over HTTPS.
- - choice | disable | Disable inspection of RPC over HTTPS.
- - choice | enable | Enable inspection of RPC over HTTPS.
- required: false
- choices: ["disable", "enable"]
-
- name:
- description:
- - Name.
- required: false
-
- mapi_over_https:
- description:
- - Enable/disable inspection of MAPI over HTTPS.
- - choice | disable | Disable inspection of MAPI over HTTPS.
- - choice | enable | Enable inspection of MAPI over HTTPS.
- required: false
- choices: ["disable", "enable"]
-
- comment:
- description:
- - Optional comments.
- required: false
-
- caname:
- description:
- - CA certificate used by SSL Inspection.
- required: false
-
- ftps:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- ftps_allow_invalid_server_cert:
- description:
- - When enabled, allows SSL sessions whose server certificate validation failed.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- ftps_client_cert_request:
- description:
- - Action based on client certificate request failure.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- ftps_ports:
- description:
- - Ports to use for scanning (1 - 65535, default = 443).
- required: false
-
- ftps_status:
- description:
- - Configure protocol inspection status.
- - choice | disable | Disable.
- - choice | deep-inspection | Full SSL inspection.
- required: false
- choices: ["disable", "deep-inspection"]
-
- ftps_unsupported_ssl:
- description:
- - Action based on the SSL encryption used being unsupported.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- ftps_untrusted_cert:
- description:
- - Allow, ignore, or block the untrusted SSL session server certificate.
- - choice | allow | Allow the untrusted server certificate.
- - choice | block | Block the connection when an untrusted server certificate is detected.
- - choice | ignore | Always take the server certificate as trusted.
- required: false
- choices: ["allow", "block", "ignore"]
-
- https:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- https_allow_invalid_server_cert:
- description:
- - When enabled, allows SSL sessions whose server certificate validation failed.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- https_client_cert_request:
- description:
- - Action based on client certificate request failure.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- https_ports:
- description:
- - Ports to use for scanning (1 - 65535, default = 443).
- required: false
-
- https_status:
- description:
- - Configure protocol inspection status.
- - choice | disable | Disable.
- - choice | certificate-inspection | Inspect SSL handshake only.
- - choice | deep-inspection | Full SSL inspection.
- required: false
- choices: ["disable", "certificate-inspection", "deep-inspection"]
-
- https_unsupported_ssl:
- description:
- - Action based on the SSL encryption used being unsupported.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- https_untrusted_cert:
- description:
- - Allow, ignore, or block the untrusted SSL session server certificate.
- - choice | allow | Allow the untrusted server certificate.
- - choice | block | Block the connection when an untrusted server certificate is detected.
- - choice | ignore | Always take the server certificate as trusted.
- required: false
- choices: ["allow", "block", "ignore"]
-
- imaps:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- imaps_allow_invalid_server_cert:
- description:
- - When enabled, allows SSL sessions whose server certificate validation failed.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- imaps_client_cert_request:
- description:
- - Action based on client certificate request failure.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- imaps_ports:
- description:
- - Ports to use for scanning (1 - 65535, default = 443).
- required: false
-
- imaps_status:
- description:
- - Configure protocol inspection status.
- - choice | disable | Disable.
- - choice | deep-inspection | Full SSL inspection.
- required: false
- choices: ["disable", "deep-inspection"]
-
- imaps_unsupported_ssl:
- description:
- - Action based on the SSL encryption used being unsupported.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- imaps_untrusted_cert:
- description:
- - Allow, ignore, or block the untrusted SSL session server certificate.
- - choice | allow | Allow the untrusted server certificate.
- - choice | block | Block the connection when an untrusted server certificate is detected.
- - choice | ignore | Always take the server certificate as trusted.
- required: false
- choices: ["allow", "block", "ignore"]
-
- pop3s:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- pop3s_allow_invalid_server_cert:
- description:
- - When enabled, allows SSL sessions whose server certificate validation failed.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- pop3s_client_cert_request:
- description:
- - Action based on client certificate request failure.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- pop3s_ports:
- description:
- - Ports to use for scanning (1 - 65535, default = 443).
- required: false
-
- pop3s_status:
- description:
- - Configure protocol inspection status.
- - choice | disable | Disable.
- - choice | deep-inspection | Full SSL inspection.
- required: false
- choices: ["disable", "deep-inspection"]
-
- pop3s_unsupported_ssl:
- description:
- - Action based on the SSL encryption used being unsupported.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- pop3s_untrusted_cert:
- description:
- - Allow, ignore, or block the untrusted SSL session server certificate.
- - choice | allow | Allow the untrusted server certificate.
- - choice | block | Block the connection when an untrusted server certificate is detected.
- - choice | ignore | Always take the server certificate as trusted.
- required: false
- choices: ["allow", "block", "ignore"]
-
- smtps:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- smtps_allow_invalid_server_cert:
- description:
- - When enabled, allows SSL sessions whose server certificate validation failed.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- smtps_client_cert_request:
- description:
- - Action based on client certificate request failure.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- smtps_ports:
- description:
- - Ports to use for scanning (1 - 65535, default = 443).
- required: false
-
- smtps_status:
- description:
- - Configure protocol inspection status.
- - choice | disable | Disable.
- - choice | deep-inspection | Full SSL inspection.
- required: false
- choices: ["disable", "deep-inspection"]
-
- smtps_unsupported_ssl:
- description:
- - Action based on the SSL encryption used being unsupported.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- smtps_untrusted_cert:
- description:
- - Allow, ignore, or block the untrusted SSL session server certificate.
- - choice | allow | Allow the untrusted server certificate.
- - choice | block | Block the connection when an untrusted server certificate is detected.
- - choice | ignore | Always take the server certificate as trusted.
- required: false
- choices: ["allow", "block", "ignore"]
-
- ssh:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- ssh_inspect_all:
- description:
- - Level of SSL inspection.
- - choice | disable | Disable.
- - choice | deep-inspection | Full SSL inspection.
- required: false
- choices: ["disable", "deep-inspection"]
-
- ssh_ports:
- description:
- - Ports to use for scanning (1 - 65535, default = 443).
- required: false
-
- ssh_ssh_algorithm:
- description:
- - Relative strength of encryption algorithms accepted during negotiation.
- - choice | compatible | Allow a broader set of encryption algorithms for best compatibility.
- - choice | high-encryption | Allow only AES-CTR, AES-GCM ciphers and high encryption algorithms.
- required: false
- choices: ["compatible", "high-encryption"]
-
- ssh_ssh_policy_check:
- description:
- - Enable/disable SSH policy check.
- - choice | disable | Disable SSH policy check.
- - choice | enable | Enable SSH policy check.
- required: false
- choices: ["disable", "enable"]
-
- ssh_ssh_tun_policy_check:
- description:
- - Enable/disable SSH tunnel policy check.
- - choice | disable | Disable SSH tunnel policy check.
- - choice | enable | Enable SSH tunnel policy check.
- required: false
- choices: ["disable", "enable"]
-
- ssh_status:
- description:
- - Configure protocol inspection status.
- - choice | disable | Disable.
- - choice | deep-inspection | Full SSL inspection.
- required: false
- choices: ["disable", "deep-inspection"]
-
- ssh_unsupported_version:
- description:
- - Action based on SSH version being unsupported.
- - choice | block | Block.
- - choice | bypass | Bypass.
- required: false
- choices: ["block", "bypass"]
-
- ssl:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- ssl_allow_invalid_server_cert:
- description:
- - When enabled, allows SSL sessions whose server certificate validation failed.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- ssl_client_cert_request:
- description:
- - Action based on client certificate request failure.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- ssl_inspect_all:
- description:
- - Level of SSL inspection.
- - choice | disable | Disable.
- - choice | certificate-inspection | Inspect SSL handshake only.
- - choice | deep-inspection | Full SSL inspection.
- required: false
- choices: ["disable", "certificate-inspection", "deep-inspection"]
-
- ssl_unsupported_ssl:
- description:
- - Action based on the SSL encryption used being unsupported.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- ssl_untrusted_cert:
- description:
- - Allow, ignore, or block the untrusted SSL session server certificate.
- - choice | allow | Allow the untrusted server certificate.
- - choice | block | Block the connection when an untrusted server certificate is detected.
- - choice | ignore | Always take the server certificate as trusted.
- required: false
- choices: ["allow", "block", "ignore"]
-
- ssl_exempt:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- ssl_exempt_address:
- description:
- - IPv4 address object.
- required: false
-
- ssl_exempt_address6:
- description:
- - IPv6 address object.
- required: false
-
- ssl_exempt_fortiguard_category:
- description:
- - FortiGuard category ID.
- required: false
-
- ssl_exempt_regex:
- description:
- - Exempt servers by regular expression.
- required: false
-
- ssl_exempt_type:
- description:
- - Type of address object (IPv4 or IPv6) or FortiGuard category.
- - choice | fortiguard-category | FortiGuard category.
- - choice | address | Firewall IPv4 address.
- - choice | address6 | Firewall IPv6 address.
- - choice | wildcard-fqdn | Fully Qualified Domain Name with wildcard characters.
- - choice | regex | Regular expression FQDN.
- required: false
- choices: ["fortiguard-category", "address", "address6", "wildcard-fqdn", "regex"]
-
- ssl_exempt_wildcard_fqdn:
- description:
- - Exempt servers by wildcard FQDN.
- required: false
-
- ssl_server:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- ssl_server_ftps_client_cert_request:
- description:
- - Action based on client certificate request failure during the FTPS handshake.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- ssl_server_https_client_cert_request:
- description:
- - Action based on client certificate request failure during the HTTPS handshake.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- ssl_server_imaps_client_cert_request:
- description:
- - Action based on client certificate request failure during the IMAPS handshake.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- ssl_server_ip:
- description:
- - IPv4 address of the SSL server.
- required: false
-
- ssl_server_pop3s_client_cert_request:
- description:
- - Action based on client certificate request failure during the POP3S handshake.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- ssl_server_smtps_client_cert_request:
- description:
- - Action based on client certificate request failure during the SMTPS handshake.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
- ssl_server_ssl_other_client_cert_request:
- description:
- - Action based on client certificate request failure during an SSL protocol handshake.
- - choice | bypass | Bypass.
- - choice | inspect | Inspect.
- - choice | block | Block.
- required: false
- choices: ["bypass", "inspect", "block"]
-
-
-'''
-
-EXAMPLES = '''
- - name: DELETE Profile
- fmgr_secprof_ssl_ssh:
- name: Ansible_SSL_SSH_Profile
- mode: delete
-
- - name: CREATE Profile
- fmgr_secprof_ssl_ssh:
- name: Ansible_SSL_SSH_Profile
- comment: "Created by Ansible Module TEST"
- mode: set
- mapi_over_https: enable
- rpc_over_https: enable
- server_cert_mode: replace
- ssl_anomalies_log: enable
- ssl_exemptions_log: enable
- use_ssl_server: enable
- whitelist: enable
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-###############
-# START METHODS
-###############
-
-
-def fmgr_firewall_ssl_ssh_profile_modify(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- mode = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
-
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if mode in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/obj/firewall/ssl-ssh-profile'.format(adom=adom)
- datagram = scrub_dict(prepare_dict(paramgram))
-
- # EVAL THE MODE PARAMETER FOR DELETE
- elif mode == "delete":
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/firewall/ssl-ssh-profile/{name}'.format(adom=adom, name=paramgram["name"])
- datagram = {}
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
-
- return response
-
-
-#############
-# END METHODS
-#############
-
-
-def main():
- argument_spec = dict(
- adom=dict(type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
-
- whitelist=dict(required=False, type="str", choices=["disable", "enable"]),
- use_ssl_server=dict(required=False, type="str", choices=["disable", "enable"]),
- untrusted_caname=dict(required=False, type="str"),
- ssl_exemptions_log=dict(required=False, type="str", choices=["disable", "enable"]),
- ssl_anomalies_log=dict(required=False, type="str", choices=["disable", "enable"]),
- server_cert_mode=dict(required=False, type="str", choices=["re-sign", "replace"]),
- server_cert=dict(required=False, type="str"),
- rpc_over_https=dict(required=False, type="str", choices=["disable", "enable"]),
- name=dict(required=False, type="str"),
- mapi_over_https=dict(required=False, type="str", choices=["disable", "enable"]),
- comment=dict(required=False, type="str"),
- caname=dict(required=False, type="str"),
- ftps=dict(required=False, type="list"),
- ftps_allow_invalid_server_cert=dict(required=False, type="str", choices=["disable", "enable"]),
- ftps_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- ftps_ports=dict(required=False, type="str"),
- ftps_status=dict(required=False, type="str", choices=["disable", "deep-inspection"]),
- ftps_unsupported_ssl=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- ftps_untrusted_cert=dict(required=False, type="str", choices=["allow", "block", "ignore"]),
- https=dict(required=False, type="list"),
- https_allow_invalid_server_cert=dict(required=False, type="str", choices=["disable", "enable"]),
- https_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- https_ports=dict(required=False, type="str"),
- https_status=dict(required=False, type="str", choices=["disable", "certificate-inspection", "deep-inspection"]),
- https_unsupported_ssl=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- https_untrusted_cert=dict(required=False, type="str", choices=["allow", "block", "ignore"]),
- imaps=dict(required=False, type="list"),
- imaps_allow_invalid_server_cert=dict(required=False, type="str", choices=["disable", "enable"]),
- imaps_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- imaps_ports=dict(required=False, type="str"),
- imaps_status=dict(required=False, type="str", choices=["disable", "deep-inspection"]),
- imaps_unsupported_ssl=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- imaps_untrusted_cert=dict(required=False, type="str", choices=["allow", "block", "ignore"]),
- pop3s=dict(required=False, type="list"),
- pop3s_allow_invalid_server_cert=dict(required=False, type="str", choices=["disable", "enable"]),
- pop3s_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- pop3s_ports=dict(required=False, type="str"),
- pop3s_status=dict(required=False, type="str", choices=["disable", "deep-inspection"]),
- pop3s_unsupported_ssl=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- pop3s_untrusted_cert=dict(required=False, type="str", choices=["allow", "block", "ignore"]),
- smtps=dict(required=False, type="list"),
- smtps_allow_invalid_server_cert=dict(required=False, type="str", choices=["disable", "enable"]),
- smtps_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- smtps_ports=dict(required=False, type="str"),
- smtps_status=dict(required=False, type="str", choices=["disable", "deep-inspection"]),
- smtps_unsupported_ssl=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- smtps_untrusted_cert=dict(required=False, type="str", choices=["allow", "block", "ignore"]),
- ssh=dict(required=False, type="list"),
- ssh_inspect_all=dict(required=False, type="str", choices=["disable", "deep-inspection"]),
- ssh_ports=dict(required=False, type="str"),
- ssh_ssh_algorithm=dict(required=False, type="str", choices=["compatible", "high-encryption"]),
- ssh_ssh_policy_check=dict(required=False, type="str", choices=["disable", "enable"]),
- ssh_ssh_tun_policy_check=dict(required=False, type="str", choices=["disable", "enable"]),
- ssh_status=dict(required=False, type="str", choices=["disable", "deep-inspection"]),
- ssh_unsupported_version=dict(required=False, type="str", choices=["block", "bypass"]),
- ssl=dict(required=False, type="list"),
- ssl_allow_invalid_server_cert=dict(required=False, type="str", choices=["disable", "enable"]),
- ssl_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- ssl_inspect_all=dict(required=False, type="str", choices=["disable", "certificate-inspection",
- "deep-inspection"]),
- ssl_unsupported_ssl=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- ssl_untrusted_cert=dict(required=False, type="str", choices=["allow", "block", "ignore"]),
- ssl_exempt=dict(required=False, type="list"),
- ssl_exempt_address=dict(required=False, type="str"),
- ssl_exempt_address6=dict(required=False, type="str"),
- ssl_exempt_fortiguard_category=dict(required=False, type="str"),
- ssl_exempt_regex=dict(required=False, type="str"),
- ssl_exempt_type=dict(required=False, type="str", choices=["fortiguard-category", "address", "address6",
- "wildcard-fqdn", "regex"]),
- ssl_exempt_wildcard_fqdn=dict(required=False, type="str"),
- ssl_server=dict(required=False, type="list"),
- ssl_server_ftps_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- ssl_server_https_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- ssl_server_imaps_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- ssl_server_ip=dict(required=False, type="str"),
- ssl_server_pop3s_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- ssl_server_smtps_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]),
- ssl_server_ssl_other_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect",
- "block"]),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "whitelist": module.params["whitelist"],
- "use-ssl-server": module.params["use_ssl_server"],
- "untrusted-caname": module.params["untrusted_caname"],
- "ssl-exemptions-log": module.params["ssl_exemptions_log"],
- "ssl-anomalies-log": module.params["ssl_anomalies_log"],
- "server-cert-mode": module.params["server_cert_mode"],
- "server-cert": module.params["server_cert"],
- "rpc-over-https": module.params["rpc_over_https"],
- "name": module.params["name"],
- "mapi-over-https": module.params["mapi_over_https"],
- "comment": module.params["comment"],
- "caname": module.params["caname"],
- "ftps": {
- "allow-invalid-server-cert": module.params["ftps_allow_invalid_server_cert"],
- "client-cert-request": module.params["ftps_client_cert_request"],
- "ports": module.params["ftps_ports"],
- "status": module.params["ftps_status"],
- "unsupported-ssl": module.params["ftps_unsupported_ssl"],
- "untrusted-cert": module.params["ftps_untrusted_cert"],
- },
- "https": {
- "allow-invalid-server-cert": module.params["https_allow_invalid_server_cert"],
- "client-cert-request": module.params["https_client_cert_request"],
- "ports": module.params["https_ports"],
- "status": module.params["https_status"],
- "unsupported-ssl": module.params["https_unsupported_ssl"],
- "untrusted-cert": module.params["https_untrusted_cert"],
- },
- "imaps": {
- "allow-invalid-server-cert": module.params["imaps_allow_invalid_server_cert"],
- "client-cert-request": module.params["imaps_client_cert_request"],
- "ports": module.params["imaps_ports"],
- "status": module.params["imaps_status"],
- "unsupported-ssl": module.params["imaps_unsupported_ssl"],
- "untrusted-cert": module.params["imaps_untrusted_cert"],
- },
- "pop3s": {
- "allow-invalid-server-cert": module.params["pop3s_allow_invalid_server_cert"],
- "client-cert-request": module.params["pop3s_client_cert_request"],
- "ports": module.params["pop3s_ports"],
- "status": module.params["pop3s_status"],
- "unsupported-ssl": module.params["pop3s_unsupported_ssl"],
- "untrusted-cert": module.params["pop3s_untrusted_cert"],
- },
- "smtps": {
- "allow-invalid-server-cert": module.params["smtps_allow_invalid_server_cert"],
- "client-cert-request": module.params["smtps_client_cert_request"],
- "ports": module.params["smtps_ports"],
- "status": module.params["smtps_status"],
- "unsupported-ssl": module.params["smtps_unsupported_ssl"],
- "untrusted-cert": module.params["smtps_untrusted_cert"],
- },
- "ssh": {
- "inspect-all": module.params["ssh_inspect_all"],
- "ports": module.params["ssh_ports"],
- "ssh-algorithm": module.params["ssh_ssh_algorithm"],
- "ssh-policy-check": module.params["ssh_ssh_policy_check"],
- "ssh-tun-policy-check": module.params["ssh_ssh_tun_policy_check"],
- "status": module.params["ssh_status"],
- "unsupported-version": module.params["ssh_unsupported_version"],
- },
- "ssl": {
- "allow-invalid-server-cert": module.params["ssl_allow_invalid_server_cert"],
- "client-cert-request": module.params["ssl_client_cert_request"],
- "inspect-all": module.params["ssl_inspect_all"],
- "unsupported-ssl": module.params["ssl_unsupported_ssl"],
- "untrusted-cert": module.params["ssl_untrusted_cert"],
- },
- "ssl-exempt": {
- "address": module.params["ssl_exempt_address"],
- "address6": module.params["ssl_exempt_address6"],
- "fortiguard-category": module.params["ssl_exempt_fortiguard_category"],
- "regex": module.params["ssl_exempt_regex"],
- "type": module.params["ssl_exempt_type"],
- "wildcard-fqdn": module.params["ssl_exempt_wildcard_fqdn"],
- },
- "ssl-server": {
- "ftps-client-cert-request": module.params["ssl_server_ftps_client_cert_request"],
- "https-client-cert-request": module.params["ssl_server_https_client_cert_request"],
- "imaps-client-cert-request": module.params["ssl_server_imaps_client_cert_request"],
- "ip": module.params["ssl_server_ip"],
- "pop3s-client-cert-request": module.params["ssl_server_pop3s_client_cert_request"],
- "smtps-client-cert-request": module.params["ssl_server_smtps_client_cert_request"],
- "ssl-other-client-cert-request": module.params["ssl_server_ssl_other_client_cert_request"],
- }
- }
-
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- list_overrides = ['ftps', 'https', 'imaps', 'pop3s', 'smtps', 'ssh', 'ssl', 'ssl-exempt', 'ssl-server']
- paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides,
- paramgram=paramgram, module=module)
-
- results = DEFAULT_RESULT_OBJ
-
- try:
-
- results = fmgr_firewall_ssl_ssh_profile_modify(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_secprof_voip.py b/plugins/modules/network/fortimanager/fmgr_secprof_voip.py
deleted file mode 100644
index f35ebc8c1e..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_secprof_voip.py
+++ /dev/null
@@ -1,1202 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_secprof_voip
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: VOIP security profiles in FMG
-description:
- - Manage VOIP security profiles in FortiManager via API
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- name:
- description:
- - Profile name.
- required: false
-
- comment:
- description:
- - Comment.
- required: false
-
- sccp:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- sccp_block_mcast:
- description:
- - Enable/disable block multicast RTP connections.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sccp_log_call_summary:
- description:
- - Enable/disable log summary of SCCP calls.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sccp_log_violations:
- description:
- - Enable/disable logging of SCCP violations.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sccp_max_calls:
- description:
- - Maximum calls per minute per SCCP client (max 65535).
- required: false
-
- sccp_status:
- description:
- - Enable/disable SCCP.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sccp_verify_header:
- description:
- - Enable/disable verify SCCP header content.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- sip_ack_rate:
- description:
- - ACK request rate limit (per second, per policy).
- required: false
-
- sip_block_ack:
- description:
- - Enable/disable block ACK requests.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_bye:
- description:
- - Enable/disable block BYE requests.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_cancel:
- description:
- - Enable/disable block CANCEL requests.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_geo_red_options:
- description:
- - Enable/disable block OPTIONS requests, but OPTIONS requests still notify for redundancy.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_info:
- description:
- - Enable/disable block INFO requests.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_invite:
- description:
- - Enable/disable block INVITE requests.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_long_lines:
- description:
- - Enable/disable block requests with headers exceeding max-line-length.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_message:
- description:
- - Enable/disable block MESSAGE requests.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_notify:
- description:
- - Enable/disable block NOTIFY requests.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_options:
- description:
- - Enable/disable block OPTIONS requests and no OPTIONS as notifying message for redundancy either.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_prack:
- description:
- - Enable/disable block prack requests.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_publish:
- description:
- - Enable/disable block PUBLISH requests.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_refer:
- description:
- - Enable/disable block REFER requests.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_register:
- description:
- - Enable/disable block REGISTER requests.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_subscribe:
- description:
- - Enable/disable block SUBSCRIBE requests.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_unknown:
- description:
- - Block unrecognized SIP requests (enabled by default).
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_block_update:
- description:
- - Enable/disable block UPDATE requests.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_bye_rate:
- description:
- - BYE request rate limit (per second, per policy).
- required: false
-
- sip_call_keepalive:
- description:
- - Continue tracking calls with no RTP for this many minutes.
- required: false
-
- sip_cancel_rate:
- description:
- - CANCEL request rate limit (per second, per policy).
- required: false
-
- sip_contact_fixup:
- description:
- - Fixup contact anyway even if contact's IP|port doesn't match session's IP|port.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_hnt_restrict_source_ip:
- description:
- - Enable/disable restrict RTP source IP to be the same as SIP source IP when HNT is enabled.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_hosted_nat_traversal:
- description:
- - Hosted NAT Traversal (HNT).
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_info_rate:
- description:
- - INFO request rate limit (per second, per policy).
- required: false
-
- sip_invite_rate:
- description:
- - INVITE request rate limit (per second, per policy).
- required: false
-
- sip_ips_rtp:
- description:
- - Enable/disable allow IPS on RTP.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_log_call_summary:
- description:
- - Enable/disable logging of SIP call summary.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_log_violations:
- description:
- - Enable/disable logging of SIP violations.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_malformed_header_allow:
- description:
- - Action for malformed Allow header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_call_id:
- description:
- - Action for malformed Call-ID header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_contact:
- description:
- - Action for malformed Contact header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_content_length:
- description:
- - Action for malformed Content-Length header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_content_type:
- description:
- - Action for malformed Content-Type header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_cseq:
- description:
- - Action for malformed CSeq header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_expires:
- description:
- - Action for malformed Expires header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_from:
- description:
- - Action for malformed From header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_max_forwards:
- description:
- - Action for malformed Max-Forwards header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_p_asserted_identity:
- description:
- - Action for malformed P-Asserted-Identity header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_rack:
- description:
- - Action for malformed RAck header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_record_route:
- description:
- - Action for malformed Record-Route header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_route:
- description:
- - Action for malformed Route header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_rseq:
- description:
- - Action for malformed RSeq header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_sdp_a:
- description:
- - Action for malformed SDP a line.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_sdp_b:
- description:
- - Action for malformed SDP b line.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_sdp_c:
- description:
- - Action for malformed SDP c line.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_sdp_i:
- description:
- - Action for malformed SDP i line.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_sdp_k:
- description:
- - Action for malformed SDP k line.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_sdp_m:
- description:
- - Action for malformed SDP m line.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_sdp_o:
- description:
- - Action for malformed SDP o line.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_sdp_r:
- description:
- - Action for malformed SDP r line.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_sdp_s:
- description:
- - Action for malformed SDP s line.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_sdp_t:
- description:
- - Action for malformed SDP t line.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_sdp_v:
- description:
- - Action for malformed SDP v line.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_sdp_z:
- description:
- - Action for malformed SDP z line.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_to:
- description:
- - Action for malformed To header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_header_via:
- description:
- - Action for malformed VIA header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_malformed_request_line:
- description:
- - Action for malformed request line.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_max_body_length:
- description:
- - Maximum SIP message body length (0 meaning no limit).
- required: false
-
- sip_max_dialogs:
- description:
- - Maximum number of concurrent calls/dialogs (per policy).
- required: false
-
- sip_max_idle_dialogs:
- description:
- - Maximum number established but idle dialogs to retain (per policy).
- required: false
-
- sip_max_line_length:
- description:
- - Maximum SIP header line length (78-4096).
- required: false
-
- sip_message_rate:
- description:
- - MESSAGE request rate limit (per second, per policy).
- required: false
-
- sip_nat_trace:
- description:
- - Enable/disable preservation of original IP in SDP i line.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_no_sdp_fixup:
- description:
- - Enable/disable no SDP fix-up.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_notify_rate:
- description:
- - NOTIFY request rate limit (per second, per policy).
- required: false
-
- sip_open_contact_pinhole:
- description:
- - Enable/disable open pinhole for non-REGISTER Contact port.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_open_record_route_pinhole:
- description:
- - Enable/disable open pinhole for Record-Route port.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_open_register_pinhole:
- description:
- - Enable/disable open pinhole for REGISTER Contact port.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_open_via_pinhole:
- description:
- - Enable/disable open pinhole for Via port.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_options_rate:
- description:
- - OPTIONS request rate limit (per second, per policy).
- required: false
-
- sip_prack_rate:
- description:
- - PRACK request rate limit (per second, per policy).
- required: false
-
- sip_preserve_override:
- description:
- - Override i line to preserve original IPS (default| append).
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_provisional_invite_expiry_time:
- description:
- - Expiry time for provisional INVITE (10 - 3600 sec).
- required: false
-
- sip_publish_rate:
- description:
- - PUBLISH request rate limit (per second, per policy).
- required: false
-
- sip_refer_rate:
- description:
- - REFER request rate limit (per second, per policy).
- required: false
-
- sip_register_contact_trace:
- description:
- - Enable/disable trace original IP/port within the contact header of REGISTER requests.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_register_rate:
- description:
- - REGISTER request rate limit (per second, per policy).
- required: false
-
- sip_rfc2543_branch:
- description:
- - Enable/disable support via branch compliant with RFC 2543.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_rtp:
- description:
- - Enable/disable create pinholes for RTP traffic to traverse firewall.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_ssl_algorithm:
- description:
- - Relative strength of encryption algorithms accepted in negotiation.
- - choice | high | High encryption. Allow only AES and ChaCha.
- - choice | medium | Medium encryption. Allow AES, ChaCha, 3DES, and RC4.
- - choice | low | Low encryption. Allow AES, ChaCha, 3DES, RC4, and DES.
- required: false
- choices: ["high", "medium", "low"]
-
- sip_ssl_auth_client:
- description:
- - Require a client certificate and authenticate it with the peer/peergrp.
- required: false
-
- sip_ssl_auth_server:
- description:
- - Authenticate the server's certificate with the peer/peergrp.
- required: false
-
- sip_ssl_client_certificate:
- description:
- - Name of Certificate to offer to server if requested.
- required: false
-
- sip_ssl_client_renegotiation:
- description:
- - Allow/block client renegotiation by server.
- - choice | allow | Allow a SSL client to renegotiate.
- - choice | deny | Abort any SSL connection that attempts to renegotiate.
- - choice | secure | Reject any SSL connection that does not offer a RFC 5746 Secure Renegotiation Indication.
- required: false
- choices: ["allow", "deny", "secure"]
-
- sip_ssl_max_version:
- description:
- - Highest SSL/TLS version to negotiate.
- - choice | ssl-3.0 | SSL 3.0.
- - choice | tls-1.0 | TLS 1.0.
- - choice | tls-1.1 | TLS 1.1.
- - choice | tls-1.2 | TLS 1.2.
- required: false
- choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]
-
- sip_ssl_min_version:
- description:
- - Lowest SSL/TLS version to negotiate.
- - choice | ssl-3.0 | SSL 3.0.
- - choice | tls-1.0 | TLS 1.0.
- - choice | tls-1.1 | TLS 1.1.
- - choice | tls-1.2 | TLS 1.2.
- required: false
- choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]
-
- sip_ssl_mode:
- description:
- - SSL/TLS mode for encryption & decryption of traffic.
- - choice | off | No SSL.
- - choice | full | Client to FortiGate and FortiGate to Server SSL.
- required: false
- choices: ["off", "full"]
-
- sip_ssl_pfs:
- description:
- - SSL Perfect Forward Secrecy.
- - choice | require | PFS mandatory.
- - choice | deny | PFS rejected.
- - choice | allow | PFS allowed.
- required: false
- choices: ["require", "deny", "allow"]
-
- sip_ssl_send_empty_frags:
- description:
- - Send empty fragments to avoid attack on CBC IV (SSL 3.0 & TLS 1.0 only).
- - choice | disable | Do not send empty fragments.
- - choice | enable | Send empty fragments.
- required: false
- choices: ["disable", "enable"]
-
- sip_ssl_server_certificate:
- description:
- - Name of Certificate return to the client in every SSL connection.
- required: false
-
- sip_status:
- description:
- - Enable/disable SIP.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_strict_register:
- description:
- - Enable/disable only allow the registrar to connect.
- - choice | disable | Disable status.
- - choice | enable | Enable status.
- required: false
- choices: ["disable", "enable"]
-
- sip_subscribe_rate:
- description:
- - SUBSCRIBE request rate limit (per second, per policy).
- required: false
-
- sip_unknown_header:
- description:
- - Action for unknown SIP header.
- - choice | pass | Bypass malformed messages.
- - choice | discard | Discard malformed messages.
- - choice | respond | Respond with error code.
- required: false
- choices: ["pass", "discard", "respond"]
-
- sip_update_rate:
- description:
- - UPDATE request rate limit (per second, per policy).
- required: false
-
-
-'''
-
-EXAMPLES = '''
- - name: DELETE Profile
- fmgr_secprof_voip:
- name: "Ansible_VOIP_Profile"
- mode: "delete"
-
- - name: Create FMGR_VOIP_PROFILE
- fmgr_secprof_voip:
- mode: "set"
- adom: "root"
- name: "Ansible_VOIP_Profile"
- comment: "Created by Ansible"
- sccp: {block-mcast: "enable", log-call-summary: "enable", log-violations: "enable", status: "enable"}
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-
-###############
-# START METHODS
-###############
-
-
-def fmgr_voip_profile_modify(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- mode = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
-
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if mode in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/obj/voip/profile'.format(adom=adom)
- datagram = scrub_dict(prepare_dict(paramgram))
-
- # EVAL THE MODE PARAMETER FOR DELETE
- elif mode == "delete":
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/voip/profile/{name}'.format(adom=adom, name=paramgram["name"])
- datagram = {}
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
-
- return response
-
-
-#############
-# END METHODS
-#############
-
-
-def main():
- argument_spec = dict(
- adom=dict(type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
-
- name=dict(required=False, type="str"),
- comment=dict(required=False, type="str"),
- sccp=dict(required=False, type="dict"),
- sccp_block_mcast=dict(required=False, type="str", choices=["disable", "enable"]),
- sccp_log_call_summary=dict(required=False, type="str", choices=["disable", "enable"]),
- sccp_log_violations=dict(required=False, type="str", choices=["disable", "enable"]),
- sccp_max_calls=dict(required=False, type="int"),
- sccp_status=dict(required=False, type="str", choices=["disable", "enable"]),
- sccp_verify_header=dict(required=False, type="str", choices=["disable", "enable"]),
- sip=dict(required=False, type="dict"),
- sip_ack_rate=dict(required=False, type="int"),
- sip_block_ack=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_bye=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_cancel=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_geo_red_options=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_info=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_invite=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_long_lines=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_message=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_notify=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_options=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_prack=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_publish=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_refer=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_register=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_subscribe=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_unknown=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_block_update=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_bye_rate=dict(required=False, type="int"),
- sip_call_keepalive=dict(required=False, type="int"),
- sip_cancel_rate=dict(required=False, type="int"),
- sip_contact_fixup=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_hnt_restrict_source_ip=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_hosted_nat_traversal=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_info_rate=dict(required=False, type="int"),
- sip_invite_rate=dict(required=False, type="int"),
- sip_ips_rtp=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_log_call_summary=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_log_violations=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_malformed_header_allow=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_call_id=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_contact=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_content_length=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_content_type=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_cseq=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_expires=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_from=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_max_forwards=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_p_asserted_identity=dict(required=False, type="str", choices=["pass",
- "discard",
- "respond"]),
- sip_malformed_header_rack=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_record_route=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_route=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_rseq=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_sdp_a=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_sdp_b=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_sdp_c=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_sdp_i=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_sdp_k=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_sdp_m=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_sdp_o=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_sdp_r=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_sdp_s=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_sdp_t=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_sdp_v=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_sdp_z=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_to=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_header_via=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_malformed_request_line=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_max_body_length=dict(required=False, type="int"),
- sip_max_dialogs=dict(required=False, type="int"),
- sip_max_idle_dialogs=dict(required=False, type="int"),
- sip_max_line_length=dict(required=False, type="int"),
- sip_message_rate=dict(required=False, type="int"),
- sip_nat_trace=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_no_sdp_fixup=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_notify_rate=dict(required=False, type="int"),
- sip_open_contact_pinhole=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_open_record_route_pinhole=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_open_register_pinhole=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_open_via_pinhole=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_options_rate=dict(required=False, type="int"),
- sip_prack_rate=dict(required=False, type="int"),
- sip_preserve_override=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_provisional_invite_expiry_time=dict(required=False, type="int"),
- sip_publish_rate=dict(required=False, type="int"),
- sip_refer_rate=dict(required=False, type="int"),
- sip_register_contact_trace=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_register_rate=dict(required=False, type="int"),
- sip_rfc2543_branch=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_rtp=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_ssl_algorithm=dict(required=False, type="str", choices=["high", "medium", "low"]),
- sip_ssl_auth_client=dict(required=False, type="str"),
- sip_ssl_auth_server=dict(required=False, type="str"),
- sip_ssl_client_certificate=dict(required=False, type="str"),
- sip_ssl_client_renegotiation=dict(required=False, type="str", choices=["allow", "deny", "secure"]),
- sip_ssl_max_version=dict(required=False, type="str", choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]),
- sip_ssl_min_version=dict(required=False, type="str", choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]),
- sip_ssl_mode=dict(required=False, type="str", choices=["off", "full"]),
- sip_ssl_pfs=dict(required=False, type="str", choices=["require", "deny", "allow"]),
- sip_ssl_send_empty_frags=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_ssl_server_certificate=dict(required=False, type="str"),
- sip_status=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_strict_register=dict(required=False, type="str", choices=["disable", "enable"]),
- sip_subscribe_rate=dict(required=False, type="int"),
- sip_unknown_header=dict(required=False, type="str", choices=["pass", "discard", "respond"]),
- sip_update_rate=dict(required=False, type="int"),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "name": module.params["name"],
- "comment": module.params["comment"],
- "sccp": {
- "block-mcast": module.params["sccp_block_mcast"],
- "log-call-summary": module.params["sccp_log_call_summary"],
- "log-violations": module.params["sccp_log_violations"],
- "max-calls": module.params["sccp_max_calls"],
- "status": module.params["sccp_status"],
- "verify-header": module.params["sccp_verify_header"],
- },
- "sip": {
- "ack-rate": module.params["sip_ack_rate"],
- "block-ack": module.params["sip_block_ack"],
- "block-bye": module.params["sip_block_bye"],
- "block-cancel": module.params["sip_block_cancel"],
- "block-geo-red-options": module.params["sip_block_geo_red_options"],
- "block-info": module.params["sip_block_info"],
- "block-invite": module.params["sip_block_invite"],
- "block-long-lines": module.params["sip_block_long_lines"],
- "block-message": module.params["sip_block_message"],
- "block-notify": module.params["sip_block_notify"],
- "block-options": module.params["sip_block_options"],
- "block-prack": module.params["sip_block_prack"],
- "block-publish": module.params["sip_block_publish"],
- "block-refer": module.params["sip_block_refer"],
- "block-register": module.params["sip_block_register"],
- "block-subscribe": module.params["sip_block_subscribe"],
- "block-unknown": module.params["sip_block_unknown"],
- "block-update": module.params["sip_block_update"],
- "bye-rate": module.params["sip_bye_rate"],
- "call-keepalive": module.params["sip_call_keepalive"],
- "cancel-rate": module.params["sip_cancel_rate"],
- "contact-fixup": module.params["sip_contact_fixup"],
- "hnt-restrict-source-ip": module.params["sip_hnt_restrict_source_ip"],
- "hosted-nat-traversal": module.params["sip_hosted_nat_traversal"],
- "info-rate": module.params["sip_info_rate"],
- "invite-rate": module.params["sip_invite_rate"],
- "ips-rtp": module.params["sip_ips_rtp"],
- "log-call-summary": module.params["sip_log_call_summary"],
- "log-violations": module.params["sip_log_violations"],
- "malformed-header-allow": module.params["sip_malformed_header_allow"],
- "malformed-header-call-id": module.params["sip_malformed_header_call_id"],
- "malformed-header-contact": module.params["sip_malformed_header_contact"],
- "malformed-header-content-length": module.params["sip_malformed_header_content_length"],
- "malformed-header-content-type": module.params["sip_malformed_header_content_type"],
- "malformed-header-cseq": module.params["sip_malformed_header_cseq"],
- "malformed-header-expires": module.params["sip_malformed_header_expires"],
- "malformed-header-from": module.params["sip_malformed_header_from"],
- "malformed-header-max-forwards": module.params["sip_malformed_header_max_forwards"],
- "malformed-header-p-asserted-identity": module.params["sip_malformed_header_p_asserted_identity"],
- "malformed-header-rack": module.params["sip_malformed_header_rack"],
- "malformed-header-record-route": module.params["sip_malformed_header_record_route"],
- "malformed-header-route": module.params["sip_malformed_header_route"],
- "malformed-header-rseq": module.params["sip_malformed_header_rseq"],
- "malformed-header-sdp-a": module.params["sip_malformed_header_sdp_a"],
- "malformed-header-sdp-b": module.params["sip_malformed_header_sdp_b"],
- "malformed-header-sdp-c": module.params["sip_malformed_header_sdp_c"],
- "malformed-header-sdp-i": module.params["sip_malformed_header_sdp_i"],
- "malformed-header-sdp-k": module.params["sip_malformed_header_sdp_k"],
- "malformed-header-sdp-m": module.params["sip_malformed_header_sdp_m"],
- "malformed-header-sdp-o": module.params["sip_malformed_header_sdp_o"],
- "malformed-header-sdp-r": module.params["sip_malformed_header_sdp_r"],
- "malformed-header-sdp-s": module.params["sip_malformed_header_sdp_s"],
- "malformed-header-sdp-t": module.params["sip_malformed_header_sdp_t"],
- "malformed-header-sdp-v": module.params["sip_malformed_header_sdp_v"],
- "malformed-header-sdp-z": module.params["sip_malformed_header_sdp_z"],
- "malformed-header-to": module.params["sip_malformed_header_to"],
- "malformed-header-via": module.params["sip_malformed_header_via"],
- "malformed-request-line": module.params["sip_malformed_request_line"],
- "max-body-length": module.params["sip_max_body_length"],
- "max-dialogs": module.params["sip_max_dialogs"],
- "max-idle-dialogs": module.params["sip_max_idle_dialogs"],
- "max-line-length": module.params["sip_max_line_length"],
- "message-rate": module.params["sip_message_rate"],
- "nat-trace": module.params["sip_nat_trace"],
- "no-sdp-fixup": module.params["sip_no_sdp_fixup"],
- "notify-rate": module.params["sip_notify_rate"],
- "open-contact-pinhole": module.params["sip_open_contact_pinhole"],
- "open-record-route-pinhole": module.params["sip_open_record_route_pinhole"],
- "open-register-pinhole": module.params["sip_open_register_pinhole"],
- "open-via-pinhole": module.params["sip_open_via_pinhole"],
- "options-rate": module.params["sip_options_rate"],
- "prack-rate": module.params["sip_prack_rate"],
- "preserve-override": module.params["sip_preserve_override"],
- "provisional-invite-expiry-time": module.params["sip_provisional_invite_expiry_time"],
- "publish-rate": module.params["sip_publish_rate"],
- "refer-rate": module.params["sip_refer_rate"],
- "register-contact-trace": module.params["sip_register_contact_trace"],
- "register-rate": module.params["sip_register_rate"],
- "rfc2543-branch": module.params["sip_rfc2543_branch"],
- "rtp": module.params["sip_rtp"],
- "ssl-algorithm": module.params["sip_ssl_algorithm"],
- "ssl-auth-client": module.params["sip_ssl_auth_client"],
- "ssl-auth-server": module.params["sip_ssl_auth_server"],
- "ssl-client-certificate": module.params["sip_ssl_client_certificate"],
- "ssl-client-renegotiation": module.params["sip_ssl_client_renegotiation"],
- "ssl-max-version": module.params["sip_ssl_max_version"],
- "ssl-min-version": module.params["sip_ssl_min_version"],
- "ssl-mode": module.params["sip_ssl_mode"],
- "ssl-pfs": module.params["sip_ssl_pfs"],
- "ssl-send-empty-frags": module.params["sip_ssl_send_empty_frags"],
- "ssl-server-certificate": module.params["sip_ssl_server_certificate"],
- "status": module.params["sip_status"],
- "strict-register": module.params["sip_strict_register"],
- "subscribe-rate": module.params["sip_subscribe_rate"],
- "unknown-header": module.params["sip_unknown_header"],
- "update-rate": module.params["sip_update_rate"],
- }
- }
-
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- list_overrides = ['sccp', 'sip']
- paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides,
- paramgram=paramgram, module=module)
- module.paramgram = paramgram
-
- results = DEFAULT_RESULT_OBJ
- try:
-
- results = fmgr_voip_profile_modify(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_secprof_waf.py b/plugins/modules/network/fortimanager/fmgr_secprof_waf.py
deleted file mode 100644
index 275176959f..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_secprof_waf.py
+++ /dev/null
@@ -1,1481 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of`
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_secprof_waf
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: FortiManager web application firewall security profile
-description:
- - Manage web application firewall security profiles for FGTs via FMG
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- name:
- description:
- - WAF Profile name.
- required: false
-
- external:
- description:
- - Disable/Enable external HTTP Inspection.
- - choice | disable | Disable external inspection.
- - choice | enable | Enable external inspection.
- required: false
- choices: ["disable", "enable"]
-
- extended_log:
- description:
- - Enable/disable extended logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- comment:
- description:
- - Comment.
- required: false
-
- address_list:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- address_list_blocked_address:
- description:
- - Blocked address.
- required: false
-
- address_list_blocked_log:
- description:
- - Enable/disable logging on blocked addresses.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- address_list_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- address_list_status:
- description:
- - Status.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- address_list_trusted_address:
- description:
- - Trusted address.
- required: false
-
- constraint:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- constraint_content_length_action:
- description:
- - Action.
- - choice | allow | Allow.
- - choice | block | Block.
- required: false
- choices: ["allow", "block"]
-
- constraint_content_length_length:
- description:
- - Length of HTTP content in bytes (0 to 2147483647).
- required: false
-
- constraint_content_length_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_content_length_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- constraint_content_length_status:
- description:
- - Enable/disable the constraint.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_exception_address:
- description:
- - Host address.
- required: false
-
- constraint_exception_content_length:
- description:
- - HTTP content length in request.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_exception_header_length:
- description:
- - HTTP header length in request.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_exception_hostname:
- description:
- - Enable/disable hostname check.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_exception_line_length:
- description:
- - HTTP line length in request.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_exception_malformed:
- description:
- - Enable/disable malformed HTTP request check.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_exception_max_cookie:
- description:
- - Maximum number of cookies in HTTP request.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_exception_max_header_line:
- description:
- - Maximum number of HTTP header line.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_exception_max_range_segment:
- description:
- - Maximum number of range segments in HTTP range line.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_exception_max_url_param:
- description:
- - Maximum number of parameters in URL.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_exception_method:
- description:
- - Enable/disable HTTP method check.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_exception_param_length:
- description:
- - Maximum length of parameter in URL, HTTP POST request or HTTP body.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_exception_pattern:
- description:
- - URL pattern.
- required: false
-
- constraint_exception_regex:
- description:
- - Enable/disable regular expression based pattern match.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_exception_url_param_length:
- description:
- - Maximum length of parameter in URL.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_exception_version:
- description:
- - Enable/disable HTTP version check.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_header_length_action:
- description:
- - Action.
- - choice | allow | Allow.
- - choice | block | Block.
- required: false
- choices: ["allow", "block"]
-
- constraint_header_length_length:
- description:
- - Length of HTTP header in bytes (0 to 2147483647).
- required: false
-
- constraint_header_length_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_header_length_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- constraint_header_length_status:
- description:
- - Enable/disable the constraint.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_hostname_action:
- description:
- - Action for a hostname constraint.
- - choice | allow | Allow.
- - choice | block | Block.
- required: false
- choices: ["allow", "block"]
-
- constraint_hostname_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_hostname_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- constraint_hostname_status:
- description:
- - Enable/disable the constraint.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_line_length_action:
- description:
- - Action.
- - choice | allow | Allow.
- - choice | block | Block.
- required: false
- choices: ["allow", "block"]
-
- constraint_line_length_length:
- description:
- - Length of HTTP line in bytes (0 to 2147483647).
- required: false
-
- constraint_line_length_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_line_length_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- constraint_line_length_status:
- description:
- - Enable/disable the constraint.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_malformed_action:
- description:
- - Action.
- - choice | allow | Allow.
- - choice | block | Block.
- required: false
- choices: ["allow", "block"]
-
- constraint_malformed_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_malformed_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- constraint_malformed_status:
- description:
- - Enable/disable the constraint.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_max_cookie_action:
- description:
- - Action.
- - choice | allow | Allow.
- - choice | block | Block.
- required: false
- choices: ["allow", "block"]
-
- constraint_max_cookie_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_max_cookie_max_cookie:
- description:
- - Maximum number of cookies in HTTP request (0 to 2147483647).
- required: false
-
- constraint_max_cookie_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- constraint_max_cookie_status:
- description:
- - Enable/disable the constraint.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_max_header_line_action:
- description:
- - Action.
- - choice | allow | Allow.
- - choice | block | Block.
- required: false
- choices: ["allow", "block"]
-
- constraint_max_header_line_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_max_header_line_max_header_line:
- description:
- - Maximum number HTTP header lines (0 to 2147483647).
- required: false
-
- constraint_max_header_line_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- constraint_max_header_line_status:
- description:
- - Enable/disable the constraint.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_max_range_segment_action:
- description:
- - Action.
- - choice | allow | Allow.
- - choice | block | Block.
- required: false
- choices: ["allow", "block"]
-
- constraint_max_range_segment_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_max_range_segment_max_range_segment:
- description:
- - Maximum number of range segments in HTTP range line (0 to 2147483647).
- required: false
-
- constraint_max_range_segment_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- constraint_max_range_segment_status:
- description:
- - Enable/disable the constraint.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_max_url_param_action:
- description:
- - Action.
- - choice | allow | Allow.
- - choice | block | Block.
- required: false
- choices: ["allow", "block"]
-
- constraint_max_url_param_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_max_url_param_max_url_param:
- description:
- - Maximum number of parameters in URL (0 to 2147483647).
- required: false
-
- constraint_max_url_param_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- constraint_max_url_param_status:
- description:
- - Enable/disable the constraint.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_method_action:
- description:
- - Action.
- - choice | allow | Allow.
- - choice | block | Block.
- required: false
- choices: ["allow", "block"]
-
- constraint_method_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_method_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- constraint_method_status:
- description:
- - Enable/disable the constraint.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_param_length_action:
- description:
- - Action.
- - choice | allow | Allow.
- - choice | block | Block.
- required: false
- choices: ["allow", "block"]
-
- constraint_param_length_length:
- description:
- - Maximum length of parameter in URL, HTTP POST request or HTTP body in bytes (0 to 2147483647).
- required: false
-
- constraint_param_length_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_param_length_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- constraint_param_length_status:
- description:
- - Enable/disable the constraint.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_url_param_length_action:
- description:
- - Action.
- - choice | allow | Allow.
- - choice | block | Block.
- required: false
- choices: ["allow", "block"]
-
- constraint_url_param_length_length:
- description:
- - Maximum length of URL parameter in bytes (0 to 2147483647).
- required: false
-
- constraint_url_param_length_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_url_param_length_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- constraint_url_param_length_status:
- description:
- - Enable/disable the constraint.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_version_action:
- description:
- - Action.
- - choice | allow | Allow.
- - choice | block | Block.
- required: false
- choices: ["allow", "block"]
-
- constraint_version_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- constraint_version_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- constraint_version_status:
- description:
- - Enable/disable the constraint.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- method:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- method_default_allowed_methods:
- description:
- - Methods.
- - FLAG Based Options. Specify multiple in list form.
- - flag | delete | HTTP DELETE method.
- - flag | get | HTTP GET method.
- - flag | head | HTTP HEAD method.
- - flag | options | HTTP OPTIONS method.
- - flag | post | HTTP POST method.
- - flag | put | HTTP PUT method.
- - flag | trace | HTTP TRACE method.
- - flag | others | Other HTTP methods.
- - flag | connect | HTTP CONNECT method.
- required: false
- choices: ["delete", "get", "head", "options", "post", "put", "trace", "others", "connect"]
-
- method_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- method_severity:
- description:
- - Severity.
- - choice | low | low severity
- - choice | medium | medium severity
- - choice | high | High severity
- required: false
- choices: ["low", "medium", "high"]
-
- method_status:
- description:
- - Status.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- method_method_policy_address:
- description:
- - Host address.
- required: false
-
- method_method_policy_allowed_methods:
- description:
- - Allowed Methods.
- - FLAG Based Options. Specify multiple in list form.
- - flag | delete | HTTP DELETE method.
- - flag | get | HTTP GET method.
- - flag | head | HTTP HEAD method.
- - flag | options | HTTP OPTIONS method.
- - flag | post | HTTP POST method.
- - flag | put | HTTP PUT method.
- - flag | trace | HTTP TRACE method.
- - flag | others | Other HTTP methods.
- - flag | connect | HTTP CONNECT method.
- required: false
- choices: ["delete", "get", "head", "options", "post", "put", "trace", "others", "connect"]
-
- method_method_policy_pattern:
- description:
- - URL pattern.
- required: false
-
- method_method_policy_regex:
- description:
- - Enable/disable regular expression based pattern match.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- signature:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- signature_credit_card_detection_threshold:
- description:
- - The minimum number of Credit cards to detect violation.
- required: false
-
- signature_disabled_signature:
- description:
- - Disabled signatures
- required: false
-
- signature_disabled_sub_class:
- description:
- - Disabled signature subclasses.
- required: false
-
- signature_custom_signature_action:
- description:
- - Action.
- - choice | allow | Allow.
- - choice | block | Block.
- - choice | erase | Erase credit card numbers.
- required: false
- choices: ["allow", "block", "erase"]
-
- signature_custom_signature_case_sensitivity:
- description:
- - Case sensitivity in pattern.
- - choice | disable | Case insensitive in pattern.
- - choice | enable | Case sensitive in pattern.
- required: false
- choices: ["disable", "enable"]
-
- signature_custom_signature_direction:
- description:
- - Traffic direction.
- - choice | request | Match HTTP request.
- - choice | response | Match HTTP response.
- required: false
- choices: ["request", "response"]
-
- signature_custom_signature_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- signature_custom_signature_name:
- description:
- - Signature name.
- required: false
-
- signature_custom_signature_pattern:
- description:
- - Match pattern.
- required: false
-
- signature_custom_signature_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- signature_custom_signature_status:
- description:
- - Status.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- signature_custom_signature_target:
- description:
- - Match HTTP target.
- - FLAG Based Options. Specify multiple in list form.
- - flag | arg | HTTP arguments.
- - flag | arg-name | Names of HTTP arguments.
- - flag | req-body | HTTP request body.
- - flag | req-cookie | HTTP request cookies.
- - flag | req-cookie-name | HTTP request cookie names.
- - flag | req-filename | HTTP request file name.
- - flag | req-header | HTTP request headers.
- - flag | req-header-name | HTTP request header names.
- - flag | req-raw-uri | Raw URI of HTTP request.
- - flag | req-uri | URI of HTTP request.
- - flag | resp-body | HTTP response body.
- - flag | resp-hdr | HTTP response headers.
- - flag | resp-status | HTTP response status.
- required: false
- choices: ["arg","arg-name","req-body","req-cookie","req-cookie-name","req-filename","req-header","req-header-name",
- "req-raw-uri","req-uri","resp-body","resp-hdr","resp-status"]
-
- signature_main_class_action:
- description:
- - Action.
- - choice | allow | Allow.
- - choice | block | Block.
- - choice | erase | Erase credit card numbers.
- required: false
- choices: ["allow", "block", "erase"]
-
- signature_main_class_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- signature_main_class_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- signature_main_class_status:
- description:
- - Status.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- url_access:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- url_access_action:
- description:
- - Action.
- - choice | bypass | Allow the HTTP request, also bypass further WAF scanning.
- - choice | permit | Allow the HTTP request, and continue further WAF scanning.
- - choice | block | Block HTTP request.
- required: false
- choices: ["bypass", "permit", "block"]
-
- url_access_address:
- description:
- - Host address.
- required: false
-
- url_access_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- url_access_severity:
- description:
- - Severity.
- - choice | low | Low severity.
- - choice | medium | Medium severity.
- - choice | high | High severity.
- required: false
- choices: ["low", "medium", "high"]
-
- url_access_access_pattern_negate:
- description:
- - Enable/disable match negation.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- url_access_access_pattern_pattern:
- description:
- - URL pattern.
- required: false
-
- url_access_access_pattern_regex:
- description:
- - Enable/disable regular expression based pattern match.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- url_access_access_pattern_srcaddr:
- description:
- - Source address.
- required: false
-
-'''
-
-EXAMPLES = '''
- - name: DELETE Profile
- fmgr_secprof_waf:
- name: "Ansible_WAF_Profile"
- comment: "Created by Ansible Module TEST"
- mode: "delete"
-
- - name: CREATE Profile
- fmgr_secprof_waf:
- name: "Ansible_WAF_Profile"
- comment: "Created by Ansible Module TEST"
- mode: "set"
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-
-###############
-# START METHODS
-###############
-
-
-def fmgr_waf_profile_modify(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
- mode = paramgram["mode"]
- adom = paramgram["adom"]
- # INIT A BASIC OBJECTS
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
-
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if mode in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/obj/waf/profile'.format(adom=adom)
- datagram = scrub_dict(prepare_dict(paramgram))
-
- # EVAL THE MODE PARAMETER FOR DELETE
- elif mode == "delete":
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/waf/profile/{name}'.format(adom=adom, name=paramgram["name"])
- datagram = {}
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
-
- return response
-
-
-#############
-# END METHODS
-#############
-
-
-def main():
- argument_spec = dict(
- adom=dict(type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
-
- name=dict(required=False, type="str"),
- external=dict(required=False, type="str", choices=["disable", "enable"]),
- extended_log=dict(required=False, type="str", choices=["disable", "enable"]),
- comment=dict(required=False, type="str"),
- address_list=dict(required=False, type="list"),
- address_list_blocked_address=dict(required=False, type="str"),
- address_list_blocked_log=dict(required=False, type="str", choices=["disable", "enable"]),
- address_list_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- address_list_status=dict(required=False, type="str", choices=["disable", "enable"]),
- address_list_trusted_address=dict(required=False, type="str"),
- constraint=dict(required=False, type="list"),
-
- constraint_content_length_action=dict(required=False, type="str", choices=["allow", "block"]),
- constraint_content_length_length=dict(required=False, type="int"),
- constraint_content_length_log=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_content_length_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- constraint_content_length_status=dict(required=False, type="str", choices=["disable", "enable"]),
-
- constraint_exception_address=dict(required=False, type="str"),
- constraint_exception_content_length=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_exception_header_length=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_exception_hostname=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_exception_line_length=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_exception_malformed=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_exception_max_cookie=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_exception_max_header_line=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_exception_max_range_segment=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_exception_max_url_param=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_exception_method=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_exception_param_length=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_exception_pattern=dict(required=False, type="str"),
- constraint_exception_regex=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_exception_url_param_length=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_exception_version=dict(required=False, type="str", choices=["disable", "enable"]),
-
- constraint_header_length_action=dict(required=False, type="str", choices=["allow", "block"]),
- constraint_header_length_length=dict(required=False, type="int"),
- constraint_header_length_log=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_header_length_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- constraint_header_length_status=dict(required=False, type="str", choices=["disable", "enable"]),
-
- constraint_hostname_action=dict(required=False, type="str", choices=["allow", "block"]),
- constraint_hostname_log=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_hostname_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- constraint_hostname_status=dict(required=False, type="str", choices=["disable", "enable"]),
-
- constraint_line_length_action=dict(required=False, type="str", choices=["allow", "block"]),
- constraint_line_length_length=dict(required=False, type="int"),
- constraint_line_length_log=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_line_length_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- constraint_line_length_status=dict(required=False, type="str", choices=["disable", "enable"]),
-
- constraint_malformed_action=dict(required=False, type="str", choices=["allow", "block"]),
- constraint_malformed_log=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_malformed_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- constraint_malformed_status=dict(required=False, type="str", choices=["disable", "enable"]),
-
- constraint_max_cookie_action=dict(required=False, type="str", choices=["allow", "block"]),
- constraint_max_cookie_log=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_max_cookie_max_cookie=dict(required=False, type="int"),
- constraint_max_cookie_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- constraint_max_cookie_status=dict(required=False, type="str", choices=["disable", "enable"]),
-
- constraint_max_header_line_action=dict(required=False, type="str", choices=["allow", "block"]),
- constraint_max_header_line_log=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_max_header_line_max_header_line=dict(required=False, type="int"),
- constraint_max_header_line_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- constraint_max_header_line_status=dict(required=False, type="str", choices=["disable", "enable"]),
-
- constraint_max_range_segment_action=dict(required=False, type="str", choices=["allow", "block"]),
- constraint_max_range_segment_log=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_max_range_segment_max_range_segment=dict(required=False, type="int"),
- constraint_max_range_segment_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- constraint_max_range_segment_status=dict(required=False, type="str", choices=["disable", "enable"]),
-
- constraint_max_url_param_action=dict(required=False, type="str", choices=["allow", "block"]),
- constraint_max_url_param_log=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_max_url_param_max_url_param=dict(required=False, type="int"),
- constraint_max_url_param_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- constraint_max_url_param_status=dict(required=False, type="str", choices=["disable", "enable"]),
-
- constraint_method_action=dict(required=False, type="str", choices=["allow", "block"]),
- constraint_method_log=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_method_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- constraint_method_status=dict(required=False, type="str", choices=["disable", "enable"]),
-
- constraint_param_length_action=dict(required=False, type="str", choices=["allow", "block"]),
- constraint_param_length_length=dict(required=False, type="int"),
- constraint_param_length_log=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_param_length_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- constraint_param_length_status=dict(required=False, type="str", choices=["disable", "enable"]),
-
- constraint_url_param_length_action=dict(required=False, type="str", choices=["allow", "block"]),
- constraint_url_param_length_length=dict(required=False, type="int"),
- constraint_url_param_length_log=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_url_param_length_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- constraint_url_param_length_status=dict(required=False, type="str", choices=["disable", "enable"]),
-
- constraint_version_action=dict(required=False, type="str", choices=["allow", "block"]),
- constraint_version_log=dict(required=False, type="str", choices=["disable", "enable"]),
- constraint_version_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- constraint_version_status=dict(required=False, type="str", choices=["disable", "enable"]),
- method=dict(required=False, type="list"),
- method_default_allowed_methods=dict(required=False, type="str", choices=["delete",
- "get",
- "head",
- "options",
- "post",
- "put",
- "trace",
- "others",
- "connect"]),
- method_log=dict(required=False, type="str", choices=["disable", "enable"]),
- method_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- method_status=dict(required=False, type="str", choices=["disable", "enable"]),
-
- method_method_policy_address=dict(required=False, type="str"),
- method_method_policy_allowed_methods=dict(required=False, type="str", choices=["delete",
- "get",
- "head",
- "options",
- "post",
- "put",
- "trace",
- "others",
- "connect"]),
- method_method_policy_pattern=dict(required=False, type="str"),
- method_method_policy_regex=dict(required=False, type="str", choices=["disable", "enable"]),
- signature=dict(required=False, type="list"),
- signature_credit_card_detection_threshold=dict(required=False, type="int"),
- signature_disabled_signature=dict(required=False, type="str"),
- signature_disabled_sub_class=dict(required=False, type="str"),
-
- signature_custom_signature_action=dict(required=False, type="str", choices=["allow", "block", "erase"]),
- signature_custom_signature_case_sensitivity=dict(required=False, type="str", choices=["disable", "enable"]),
- signature_custom_signature_direction=dict(required=False, type="str", choices=["request", "response"]),
- signature_custom_signature_log=dict(required=False, type="str", choices=["disable", "enable"]),
- signature_custom_signature_name=dict(required=False, type="str"),
- signature_custom_signature_pattern=dict(required=False, type="str"),
- signature_custom_signature_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- signature_custom_signature_status=dict(required=False, type="str", choices=["disable", "enable"]),
- signature_custom_signature_target=dict(required=False, type="str", choices=["arg",
- "arg-name",
- "req-body",
- "req-cookie",
- "req-cookie-name",
- "req-filename",
- "req-header",
- "req-header-name",
- "req-raw-uri",
- "req-uri",
- "resp-body",
- "resp-hdr",
- "resp-status"]),
-
- signature_main_class_action=dict(required=False, type="str", choices=["allow", "block", "erase"]),
- signature_main_class_log=dict(required=False, type="str", choices=["disable", "enable"]),
- signature_main_class_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
- signature_main_class_status=dict(required=False, type="str", choices=["disable", "enable"]),
- url_access=dict(required=False, type="list"),
- url_access_action=dict(required=False, type="str", choices=["bypass", "permit", "block"]),
- url_access_address=dict(required=False, type="str"),
- url_access_log=dict(required=False, type="str", choices=["disable", "enable"]),
- url_access_severity=dict(required=False, type="str", choices=["low", "medium", "high"]),
-
- url_access_access_pattern_negate=dict(required=False, type="str", choices=["disable", "enable"]),
- url_access_access_pattern_pattern=dict(required=False, type="str"),
- url_access_access_pattern_regex=dict(required=False, type="str", choices=["disable", "enable"]),
- url_access_access_pattern_srcaddr=dict(required=False, type="str"),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "name": module.params["name"],
- "external": module.params["external"],
- "extended-log": module.params["extended_log"],
- "comment": module.params["comment"],
- "address-list": {
- "blocked-address": module.params["address_list_blocked_address"],
- "blocked-log": module.params["address_list_blocked_log"],
- "severity": module.params["address_list_severity"],
- "status": module.params["address_list_status"],
- "trusted-address": module.params["address_list_trusted_address"],
- },
- "constraint": {
- "content-length": {
- "action": module.params["constraint_content_length_action"],
- "length": module.params["constraint_content_length_length"],
- "log": module.params["constraint_content_length_log"],
- "severity": module.params["constraint_content_length_severity"],
- "status": module.params["constraint_content_length_status"],
- },
- "exception": {
- "address": module.params["constraint_exception_address"],
- "content-length": module.params["constraint_exception_content_length"],
- "header-length": module.params["constraint_exception_header_length"],
- "hostname": module.params["constraint_exception_hostname"],
- "line-length": module.params["constraint_exception_line_length"],
- "malformed": module.params["constraint_exception_malformed"],
- "max-cookie": module.params["constraint_exception_max_cookie"],
- "max-header-line": module.params["constraint_exception_max_header_line"],
- "max-range-segment": module.params["constraint_exception_max_range_segment"],
- "max-url-param": module.params["constraint_exception_max_url_param"],
- "method": module.params["constraint_exception_method"],
- "param-length": module.params["constraint_exception_param_length"],
- "pattern": module.params["constraint_exception_pattern"],
- "regex": module.params["constraint_exception_regex"],
- "url-param-length": module.params["constraint_exception_url_param_length"],
- "version": module.params["constraint_exception_version"],
- },
- "header-length": {
- "action": module.params["constraint_header_length_action"],
- "length": module.params["constraint_header_length_length"],
- "log": module.params["constraint_header_length_log"],
- "severity": module.params["constraint_header_length_severity"],
- "status": module.params["constraint_header_length_status"],
- },
- "hostname": {
- "action": module.params["constraint_hostname_action"],
- "log": module.params["constraint_hostname_log"],
- "severity": module.params["constraint_hostname_severity"],
- "status": module.params["constraint_hostname_status"],
- },
- "line-length": {
- "action": module.params["constraint_line_length_action"],
- "length": module.params["constraint_line_length_length"],
- "log": module.params["constraint_line_length_log"],
- "severity": module.params["constraint_line_length_severity"],
- "status": module.params["constraint_line_length_status"],
- },
- "malformed": {
- "action": module.params["constraint_malformed_action"],
- "log": module.params["constraint_malformed_log"],
- "severity": module.params["constraint_malformed_severity"],
- "status": module.params["constraint_malformed_status"],
- },
- "max-cookie": {
- "action": module.params["constraint_max_cookie_action"],
- "log": module.params["constraint_max_cookie_log"],
- "max-cookie": module.params["constraint_max_cookie_max_cookie"],
- "severity": module.params["constraint_max_cookie_severity"],
- "status": module.params["constraint_max_cookie_status"],
- },
- "max-header-line": {
- "action": module.params["constraint_max_header_line_action"],
- "log": module.params["constraint_max_header_line_log"],
- "max-header-line": module.params["constraint_max_header_line_max_header_line"],
- "severity": module.params["constraint_max_header_line_severity"],
- "status": module.params["constraint_max_header_line_status"],
- },
- "max-range-segment": {
- "action": module.params["constraint_max_range_segment_action"],
- "log": module.params["constraint_max_range_segment_log"],
- "max-range-segment": module.params["constraint_max_range_segment_max_range_segment"],
- "severity": module.params["constraint_max_range_segment_severity"],
- "status": module.params["constraint_max_range_segment_status"],
- },
- "max-url-param": {
- "action": module.params["constraint_max_url_param_action"],
- "log": module.params["constraint_max_url_param_log"],
- "max-url-param": module.params["constraint_max_url_param_max_url_param"],
- "severity": module.params["constraint_max_url_param_severity"],
- "status": module.params["constraint_max_url_param_status"],
- },
- "method": {
- "action": module.params["constraint_method_action"],
- "log": module.params["constraint_method_log"],
- "severity": module.params["constraint_method_severity"],
- "status": module.params["constraint_method_status"],
- },
- "param-length": {
- "action": module.params["constraint_param_length_action"],
- "length": module.params["constraint_param_length_length"],
- "log": module.params["constraint_param_length_log"],
- "severity": module.params["constraint_param_length_severity"],
- "status": module.params["constraint_param_length_status"],
- },
- "url-param-length": {
- "action": module.params["constraint_url_param_length_action"],
- "length": module.params["constraint_url_param_length_length"],
- "log": module.params["constraint_url_param_length_log"],
- "severity": module.params["constraint_url_param_length_severity"],
- "status": module.params["constraint_url_param_length_status"],
- },
- "version": {
- "action": module.params["constraint_version_action"],
- "log": module.params["constraint_version_log"],
- "severity": module.params["constraint_version_severity"],
- "status": module.params["constraint_version_status"],
- },
- },
- "method": {
- "default-allowed-methods": module.params["method_default_allowed_methods"],
- "log": module.params["method_log"],
- "severity": module.params["method_severity"],
- "status": module.params["method_status"],
- "method-policy": {
- "address": module.params["method_method_policy_address"],
- "allowed-methods": module.params["method_method_policy_allowed_methods"],
- "pattern": module.params["method_method_policy_pattern"],
- "regex": module.params["method_method_policy_regex"],
- },
- },
- "signature": {
- "credit-card-detection-threshold": module.params["signature_credit_card_detection_threshold"],
- "disabled-signature": module.params["signature_disabled_signature"],
- "disabled-sub-class": module.params["signature_disabled_sub_class"],
- "custom-signature": {
- "action": module.params["signature_custom_signature_action"],
- "case-sensitivity": module.params["signature_custom_signature_case_sensitivity"],
- "direction": module.params["signature_custom_signature_direction"],
- "log": module.params["signature_custom_signature_log"],
- "name": module.params["signature_custom_signature_name"],
- "pattern": module.params["signature_custom_signature_pattern"],
- "severity": module.params["signature_custom_signature_severity"],
- "status": module.params["signature_custom_signature_status"],
- "target": module.params["signature_custom_signature_target"],
- },
- "main-class": {
- "action": module.params["signature_main_class_action"],
- "log": module.params["signature_main_class_log"],
- "severity": module.params["signature_main_class_severity"],
- "status": module.params["signature_main_class_status"],
- },
- },
- "url-access": {
- "action": module.params["url_access_action"],
- "address": module.params["url_access_address"],
- "log": module.params["url_access_log"],
- "severity": module.params["url_access_severity"],
- "access-pattern": {
- "negate": module.params["url_access_access_pattern_negate"],
- "pattern": module.params["url_access_access_pattern_pattern"],
- "regex": module.params["url_access_access_pattern_regex"],
- "srcaddr": module.params["url_access_access_pattern_srcaddr"],
- }
- }
- }
-
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- list_overrides = ['address-list', 'constraint', 'method', 'signature', 'url-access']
- paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides,
- paramgram=paramgram, module=module)
-
- results = DEFAULT_RESULT_OBJ
-
- try:
- results = fmgr_waf_profile_modify(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_secprof_wanopt.py b/plugins/modules/network/fortimanager/fmgr_secprof_wanopt.py
deleted file mode 100644
index 0b03e06a6c..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_secprof_wanopt.py
+++ /dev/null
@@ -1,689 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_secprof_wanopt
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: WAN optimization
-description:
- - Manage WanOpt security profiles in FortiManager via API
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- transparent:
- description:
- - Enable/disable transparent mode.
- required: false
- choices:
- - disable
- - enable
-
- name:
- description:
- - Profile name.
- required: false
-
- comments:
- description:
- - Comment.
- required: false
-
- auth_group:
- description:
- - Optionally add an authentication group to restrict access to the WAN Optimization tunnel to
- peers in the authentication group.
- required: false
-
- cifs:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- cifs_byte_caching:
- description:
- - Enable/disable byte-caching for HTTP. Byte caching reduces the amount of traffic by caching
- file data sent across the WAN and in future serving if from the cache.
- required: false
- choices:
- - disable
- - enable
-
- cifs_log_traffic:
- description:
- - Enable/disable logging.
- required: false
- choices:
- - disable
- - enable
-
- cifs_port:
- description:
- - Single port number or port number range for CIFS. Only packets with a destination port number
- that matches this port number or range are accepted by this profile.
- required: false
-
- cifs_prefer_chunking:
- description:
- - Select dynamic or fixed-size data chunking for HTTP WAN Optimization.
- required: false
- choices:
- - dynamic
- - fix
-
- cifs_secure_tunnel:
- description:
- - Enable/disable securing the WAN Opt tunnel using SSL. Secure and non-secure tunnels use the
- same TCP port (7810).
- required: false
- choices:
- - disable
- - enable
-
- cifs_status:
- description:
- - Enable/disable HTTP WAN Optimization.
- required: false
- choices:
- - disable
- - enable
-
- cifs_tunnel_sharing:
- description:
- - Tunnel sharing mode for aggressive/non-aggressive and/or interactive/non-interactive protocols.
- required: false
- choices:
- - private
- - shared
- - express-shared
-
- ftp:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- ftp_byte_caching:
- description:
- - Enable/disable byte-caching for HTTP. Byte caching reduces the amount of traffic by caching
- file data sent across the WAN and in future serving if from the cache.
- required: false
- choices:
- - disable
- - enable
-
- ftp_log_traffic:
- description:
- - Enable/disable logging.
- required: false
- choices:
- - disable
- - enable
-
- ftp_port:
- description:
- - Single port number or port number range for FTP. Only packets with a destination port number
- that matches this port number or range are accepted by this profile.
- required: false
-
- ftp_prefer_chunking:
- description:
- - Select dynamic or fixed-size data chunking for HTTP WAN Optimization.
- required: false
- choices:
- - dynamic
- - fix
-
- ftp_secure_tunnel:
- description:
- - Enable/disable securing the WAN Opt tunnel using SSL. Secure and non-secure tunnels use the
- same TCP port (7810).
- required: false
- choices:
- - disable
- - enable
-
- ftp_status:
- description:
- - Enable/disable HTTP WAN Optimization.
- required: false
- choices:
- - disable
- - enable
-
- ftp_tunnel_sharing:
- description:
- - Tunnel sharing mode for aggressive/non-aggressive and/or interactive/non-interactive protocols.
- required: false
- choices:
- - private
- - shared
- - express-shared
-
- http:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- http_byte_caching:
- description:
- - Enable/disable byte-caching for HTTP. Byte caching reduces the amount of traffic by caching
- file data sent across the WAN and in future serving if from the cache.
- required: false
- choices:
- - disable
- - enable
-
- http_log_traffic:
- description:
- - Enable/disable logging.
- required: false
- choices:
- - disable
- - enable
-
- http_port:
- description:
- - Single port number or port number range for HTTP. Only packets with a destination port number
- that matches this port number or range are accepted by this profile.
- required: false
-
- http_prefer_chunking:
- description:
- - Select dynamic or fixed-size data chunking for HTTP WAN Optimization.
- required: false
- choices:
- - dynamic
- - fix
-
- http_secure_tunnel:
- description:
- - Enable/disable securing the WAN Opt tunnel using SSL. Secure and non-secure tunnels use the
- same TCP port (7810).
- required: false
- choices:
- - disable
- - enable
-
- http_ssl:
- description:
- - Enable/disable SSL/TLS offloading (hardware acceleration) for HTTPS traffic in this tunnel.
- required: false
- choices:
- - disable
- - enable
-
- http_ssl_port:
- description:
- - Port on which to expect HTTPS traffic for SSL/TLS offloading.
- required: false
-
- http_status:
- description:
- - Enable/disable HTTP WAN Optimization.
- required: false
- choices:
- - disable
- - enable
-
- http_tunnel_non_http:
- description:
- - Configure how to process non-HTTP traffic when a profile configured for HTTP traffic accepts
- a non-HTTP session. Can occur if an application sends non-HTTP traffic using an HTTP destination port.
- required: false
- choices:
- - disable
- - enable
-
- http_tunnel_sharing:
- description:
- - Tunnel sharing mode for aggressive/non-aggressive and/or interactive/non-interactive protocols.
- required: false
- choices:
- - private
- - shared
- - express-shared
-
- http_unknown_http_version:
- description:
- - How to handle HTTP sessions that do not comply with HTTP 0.9, 1.0, or 1.1.
- required: false
- choices:
- - best-effort
- - reject
- - tunnel
-
- mapi:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- mapi_byte_caching:
- description:
- - Enable/disable byte-caching for HTTP. Byte caching reduces the amount of traffic by caching
- file data sent across the WAN and in future serving if from the cache.
- required: false
- choices:
- - disable
- - enable
-
- mapi_log_traffic:
- description:
- - Enable/disable logging.
- required: false
- choices:
- - disable
- - enable
-
- mapi_port:
- description:
- - Single port number or port number range for MAPI. Only packets with a destination port number
- that matches this port number or range are accepted by this profile.
- required: false
-
- mapi_secure_tunnel:
- description:
- - Enable/disable securing the WAN Opt tunnel using SSL. Secure and non-secure tunnels use the
- same TCP port (7810).
- required: false
- choices:
- - disable
- - enable
-
- mapi_status:
- description:
- - Enable/disable HTTP WAN Optimization.
- required: false
- choices:
- - disable
- - enable
-
- mapi_tunnel_sharing:
- description:
- - Tunnel sharing mode for aggressive/non-aggressive and/or interactive/non-interactive protocols.
- required: false
- choices:
- - private
- - shared
- - express-shared
-
- tcp:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- tcp_byte_caching:
- description:
- - Enable/disable byte-caching for HTTP. Byte caching reduces the amount of traffic by caching
- file data sent across the WAN and in future serving if from the cache.
- required: false
- choices:
- - disable
- - enable
-
- tcp_byte_caching_opt:
- description:
- - Select whether TCP byte-caching uses system memory only or both memory and disk space.
- required: false
- choices:
- - mem-only
- - mem-disk
-
- tcp_log_traffic:
- description:
- - Enable/disable logging.
- required: false
- choices:
- - disable
- - enable
-
- tcp_port:
- description:
- - Single port number or port number range for TCP. Only packets with a destination port number
- that matches this port number or range are accepted by this profile.
- required: false
-
- tcp_secure_tunnel:
- description:
- - Enable/disable securing the WAN Opt tunnel using SSL. Secure and non-secure tunnels use the
- same TCP port (7810).
- required: false
- choices:
- - disable
- - enable
-
- tcp_ssl:
- description:
- - Enable/disable SSL/TLS offloading.
- required: false
- choices:
- - disable
- - enable
-
- tcp_ssl_port:
- description:
- - Port on which to expect HTTPS traffic for SSL/TLS offloading.
- required: false
-
- tcp_status:
- description:
- - Enable/disable HTTP WAN Optimization.
- required: false
- choices:
- - disable
- - enable
-
- tcp_tunnel_sharing:
- description:
- - Tunnel sharing mode for aggressive/non-aggressive and/or interactive/non-interactive protocols.
- required: false
- choices:
- - private
- - shared
- - express-shared
-
-'''
-
-EXAMPLES = '''
- - name: DELETE Profile
- fmgr_secprof_wanopt:
- name: "Ansible_WanOpt_Profile"
- mode: "delete"
-
- - name: Create FMGR_WANOPT_PROFILE
- fmgr_secprof_wanopt:
- mode: "set"
- adom: "root"
- transparent: "enable"
- name: "Ansible_WanOpt_Profile"
- comments: "Created by Ansible"
- cifs: {byte-caching: "enable",
- log-traffic: "enable",
- port: 80,
- prefer-chunking: "dynamic",
- status: "enable",
- tunnel-sharing: "private"}
- ftp: {byte-caching: "enable",
- log-traffic: "enable",
- port: 80,
- prefer-chunking: "dynamic",
- secure-tunnel: "disable",
- status: "enable",
- tunnel-sharing: "private"}
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-
-###############
-# START METHODS
-###############
-
-
-def fmgr_wanopt_profile_modify(fmgr, paramgram):
- """
- :param fmgr: The fmgr object instance from fortimanager.py
- :type fmgr: class object
- :param paramgram: The formatted dictionary of options to process
- :type paramgram: dict
- :return: The response from the FortiManager
- :rtype: dict
- """
-
- mode = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
-
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if mode in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/obj/wanopt/profile'.format(adom=adom)
- datagram = scrub_dict(prepare_dict(paramgram))
-
- # EVAL THE MODE PARAMETER FOR DELETE
- elif mode == "delete":
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/wanopt/profile/{name}'.format(adom=adom, name=paramgram["name"])
- datagram = {}
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
-
- return response
-
-
-#############
-# END METHODS
-#############
-
-
-def main():
- argument_spec = dict(
- adom=dict(type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
-
- transparent=dict(required=False, type="str", choices=["disable", "enable"]),
- name=dict(required=False, type="str"),
- comments=dict(required=False, type="str"),
- auth_group=dict(required=False, type="str"),
- cifs=dict(required=False, type="dict"),
- cifs_byte_caching=dict(required=False, type="str", choices=["disable", "enable"]),
- cifs_log_traffic=dict(required=False, type="str", choices=["disable", "enable"]),
- cifs_port=dict(required=False, type="str"),
- cifs_prefer_chunking=dict(required=False, type="str", choices=["dynamic", "fix"]),
- cifs_secure_tunnel=dict(required=False, type="str", choices=["disable", "enable"]),
- cifs_status=dict(required=False, type="str", choices=["disable", "enable"]),
- cifs_tunnel_sharing=dict(required=False, type="str", choices=["private", "shared", "express-shared"]),
- ftp=dict(required=False, type="dict"),
- ftp_byte_caching=dict(required=False, type="str", choices=["disable", "enable"]),
- ftp_log_traffic=dict(required=False, type="str", choices=["disable", "enable"]),
- ftp_port=dict(required=False, type="str"),
- ftp_prefer_chunking=dict(required=False, type="str", choices=["dynamic", "fix"]),
- ftp_secure_tunnel=dict(required=False, type="str", choices=["disable", "enable"]),
- ftp_status=dict(required=False, type="str", choices=["disable", "enable"]),
- ftp_tunnel_sharing=dict(required=False, type="str", choices=["private", "shared", "express-shared"]),
- http=dict(required=False, type="dict"),
- http_byte_caching=dict(required=False, type="str", choices=["disable", "enable"]),
- http_log_traffic=dict(required=False, type="str", choices=["disable", "enable"]),
- http_port=dict(required=False, type="str"),
- http_prefer_chunking=dict(required=False, type="str", choices=["dynamic", "fix"]),
- http_secure_tunnel=dict(required=False, type="str", choices=["disable", "enable"]),
- http_ssl=dict(required=False, type="str", choices=["disable", "enable"]),
- http_ssl_port=dict(required=False, type="str"),
- http_status=dict(required=False, type="str", choices=["disable", "enable"]),
- http_tunnel_non_http=dict(required=False, type="str", choices=["disable", "enable"]),
- http_tunnel_sharing=dict(required=False, type="str", choices=["private", "shared", "express-shared"]),
- http_unknown_http_version=dict(required=False, type="str", choices=["best-effort", "reject", "tunnel"]),
- mapi=dict(required=False, type="dict"),
- mapi_byte_caching=dict(required=False, type="str", choices=["disable", "enable"]),
- mapi_log_traffic=dict(required=False, type="str", choices=["disable", "enable"]),
- mapi_port=dict(required=False, type="str"),
- mapi_secure_tunnel=dict(required=False, type="str", choices=["disable", "enable"]),
- mapi_status=dict(required=False, type="str", choices=["disable", "enable"]),
- mapi_tunnel_sharing=dict(required=False, type="str", choices=["private", "shared", "express-shared"]),
- tcp=dict(required=False, type="dict"),
- tcp_byte_caching=dict(required=False, type="str", choices=["disable", "enable"]),
- tcp_byte_caching_opt=dict(required=False, type="str", choices=["mem-only", "mem-disk"]),
- tcp_log_traffic=dict(required=False, type="str", choices=["disable", "enable"]),
- tcp_port=dict(required=False, type="str"),
- tcp_secure_tunnel=dict(required=False, type="str", choices=["disable", "enable"]),
- tcp_ssl=dict(required=False, type="str", choices=["disable", "enable"]),
- tcp_ssl_port=dict(required=False, type="str"),
- tcp_status=dict(required=False, type="str", choices=["disable", "enable"]),
- tcp_tunnel_sharing=dict(required=False, type="str", choices=["private", "shared", "express-shared"]),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "transparent": module.params["transparent"],
- "name": module.params["name"],
- "comments": module.params["comments"],
- "auth-group": module.params["auth_group"],
- "cifs": {
- "byte-caching": module.params["cifs_byte_caching"],
- "log-traffic": module.params["cifs_log_traffic"],
- "port": module.params["cifs_port"],
- "prefer-chunking": module.params["cifs_prefer_chunking"],
- "secure-tunnel": module.params["cifs_secure_tunnel"],
- "status": module.params["cifs_status"],
- "tunnel-sharing": module.params["cifs_tunnel_sharing"],
- },
- "ftp": {
- "byte-caching": module.params["ftp_byte_caching"],
- "log-traffic": module.params["ftp_log_traffic"],
- "port": module.params["ftp_port"],
- "prefer-chunking": module.params["ftp_prefer_chunking"],
- "secure-tunnel": module.params["ftp_secure_tunnel"],
- "status": module.params["ftp_status"],
- "tunnel-sharing": module.params["ftp_tunnel_sharing"],
- },
- "http": {
- "byte-caching": module.params["http_byte_caching"],
- "log-traffic": module.params["http_log_traffic"],
- "port": module.params["http_port"],
- "prefer-chunking": module.params["http_prefer_chunking"],
- "secure-tunnel": module.params["http_secure_tunnel"],
- "ssl": module.params["http_ssl"],
- "ssl-port": module.params["http_ssl_port"],
- "status": module.params["http_status"],
- "tunnel-non-http": module.params["http_tunnel_non_http"],
- "tunnel-sharing": module.params["http_tunnel_sharing"],
- "unknown-http-version": module.params["http_unknown_http_version"],
- },
- "mapi": {
- "byte-caching": module.params["mapi_byte_caching"],
- "log-traffic": module.params["mapi_log_traffic"],
- "port": module.params["mapi_port"],
- "secure-tunnel": module.params["mapi_secure_tunnel"],
- "status": module.params["mapi_status"],
- "tunnel-sharing": module.params["mapi_tunnel_sharing"],
- },
- "tcp": {
- "byte-caching": module.params["tcp_byte_caching"],
- "byte-caching-opt": module.params["tcp_byte_caching_opt"],
- "log-traffic": module.params["tcp_log_traffic"],
- "port": module.params["tcp_port"],
- "secure-tunnel": module.params["tcp_secure_tunnel"],
- "ssl": module.params["tcp_ssl"],
- "ssl-port": module.params["tcp_ssl_port"],
- "status": module.params["tcp_status"],
- "tunnel-sharing": module.params["tcp_tunnel_sharing"],
- }
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- list_overrides = ['cifs', 'ftp', 'http', 'mapi', 'tcp']
- paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides,
- paramgram=paramgram, module=module)
-
- results = DEFAULT_RESULT_OBJ
-
- try:
- results = fmgr_wanopt_profile_modify(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/fortimanager/fmgr_secprof_web.py b/plugins/modules/network/fortimanager/fmgr_secprof_web.py
deleted file mode 100644
index 7a3da4ff17..0000000000
--- a/plugins/modules/network/fortimanager/fmgr_secprof_web.py
+++ /dev/null
@@ -1,1085 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: fmgr_secprof_web
-notes:
- - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
-author:
- - Luke Weighall (@lweighall)
- - Andrew Welsh (@Ghilli3)
- - Jim Huber (@p4r4n0y1ng)
-short_description: Manage web filter security profiles in FortiManager
-description:
- - Manage web filter security profiles in FortiManager through playbooks using the FMG API
-
-options:
- adom:
- description:
- - The ADOM the configuration should belong to.
- required: false
- default: root
-
- mode:
- description:
- - Sets one of three modes for managing the object.
- - Allows use of soft-adds instead of overwriting existing values
- choices: ['add', 'set', 'delete', 'update']
- required: false
- default: add
-
- youtube_channel_status:
- description:
- - YouTube channel filter status.
- - choice | disable | Disable YouTube channel filter.
- - choice | blacklist | Block matches.
- - choice | whitelist | Allow matches.
- required: false
- choices: ["disable", "blacklist", "whitelist"]
-
- wisp_servers:
- description:
- - WISP servers.
- required: false
-
- wisp_algorithm:
- description:
- - WISP server selection algorithm.
- - choice | auto-learning | Select the lightest loading healthy server.
- - choice | primary-secondary | Select the first healthy server in order.
- - choice | round-robin | Select the next healthy server.
- required: false
- choices: ["auto-learning", "primary-secondary", "round-robin"]
-
- wisp:
- description:
- - Enable/disable web proxy WISP.
- - choice | disable | Disable web proxy WISP.
- - choice | enable | Enable web proxy WISP.
- required: false
- choices: ["disable", "enable"]
-
- web_url_log:
- description:
- - Enable/disable logging URL filtering.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_invalid_domain_log:
- description:
- - Enable/disable logging invalid domain names.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_ftgd_quota_usage:
- description:
- - Enable/disable logging daily quota usage.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_ftgd_err_log:
- description:
- - Enable/disable logging rating errors.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_filter_vbs_log:
- description:
- - Enable/disable logging VBS scripts.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_filter_unknown_log:
- description:
- - Enable/disable logging unknown scripts.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_filter_referer_log:
- description:
- - Enable/disable logging referrers.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_filter_jscript_log:
- description:
- - Enable/disable logging JScripts.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_filter_js_log:
- description:
- - Enable/disable logging Java scripts.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_filter_cookie_removal_log:
- description:
- - Enable/disable logging blocked cookies.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_filter_cookie_log:
- description:
- - Enable/disable logging cookie filtering.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_filter_command_block_log:
- description:
- - Enable/disable logging blocked commands.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_filter_applet_log:
- description:
- - Enable/disable logging Java applets.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_filter_activex_log:
- description:
- - Enable/disable logging ActiveX.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_extended_all_action_log:
- description:
- - Enable/disable extended any filter action logging for web filtering.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_content_log:
- description:
- - Enable/disable logging logging blocked web content.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- replacemsg_group:
- description:
- - Replacement message group.
- required: false
-
- post_action:
- description:
- - Action taken for HTTP POST traffic.
- - choice | normal | Normal, POST requests are allowed.
- - choice | block | POST requests are blocked.
- required: false
- choices: ["normal", "block"]
-
- ovrd_perm:
- description:
- - FLAG Based Options. Specify multiple in list form.
- - flag | bannedword-override | Banned word override.
- - flag | urlfilter-override | URL filter override.
- - flag | fortiguard-wf-override | FortiGuard Web Filter override.
- - flag | contenttype-check-override | Content-type header override.
- required: false
- choices:
- - bannedword-override
- - urlfilter-override
- - fortiguard-wf-override
- - contenttype-check-override
-
- options:
- description:
- - FLAG Based Options. Specify multiple in list form.
- - flag | block-invalid-url | Block sessions contained an invalid domain name.
- - flag | jscript | Javascript block.
- - flag | js | JS block.
- - flag | vbs | VB script block.
- - flag | unknown | Unknown script block.
- - flag | wf-referer | Referring block.
- - flag | intrinsic | Intrinsic script block.
- - flag | wf-cookie | Cookie block.
- - flag | per-user-bwl | Per-user black/white list filter
- - flag | activexfilter | ActiveX filter.
- - flag | cookiefilter | Cookie filter.
- - flag | javafilter | Java applet filter.
- required: false
- choices:
- - block-invalid-url
- - jscript
- - js
- - vbs
- - unknown
- - wf-referer
- - intrinsic
- - wf-cookie
- - per-user-bwl
- - activexfilter
- - cookiefilter
- - javafilter
-
- name:
- description:
- - Profile name.
- required: false
-
- log_all_url:
- description:
- - Enable/disable logging all URLs visited.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- inspection_mode:
- description:
- - Web filtering inspection mode.
- - choice | proxy | Proxy.
- - choice | flow-based | Flow based.
- required: false
- choices: ["proxy", "flow-based"]
-
- https_replacemsg:
- description:
- - Enable replacement messages for HTTPS.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- extended_log:
- description:
- - Enable/disable extended logging for web filtering.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- comment:
- description:
- - Optional comments.
- required: false
-
- ftgd_wf:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- ftgd_wf_exempt_quota:
- description:
- - Do not stop quota for these categories.
- required: false
-
- ftgd_wf_max_quota_timeout:
- description:
- - Maximum FortiGuard quota used by single page view in seconds (excludes streams).
- required: false
-
- ftgd_wf_options:
- description:
- - Options for FortiGuard Web Filter.
- - FLAG Based Options. Specify multiple in list form.
- - flag | error-allow | Allow web pages with a rating error to pass through.
- - flag | rate-server-ip | Rate the server IP in addition to the domain name.
- - flag | connect-request-bypass | Bypass connection which has CONNECT request.
- - flag | ftgd-disable | Disable FortiGuard scanning.
- required: false
- choices: ["error-allow", "rate-server-ip", "connect-request-bypass", "ftgd-disable"]
-
- ftgd_wf_ovrd:
- description:
- - Allow web filter profile overrides.
- required: false
-
- ftgd_wf_rate_crl_urls:
- description:
- - Enable/disable rating CRL by URL.
- - choice | disable | Disable rating CRL by URL.
- - choice | enable | Enable rating CRL by URL.
- required: false
- choices: ["disable", "enable"]
-
- ftgd_wf_rate_css_urls:
- description:
- - Enable/disable rating CSS by URL.
- - choice | disable | Disable rating CSS by URL.
- - choice | enable | Enable rating CSS by URL.
- required: false
- choices: ["disable", "enable"]
-
- ftgd_wf_rate_image_urls:
- description:
- - Enable/disable rating images by URL.
- - choice | disable | Disable rating images by URL (blocked images are replaced with blanks).
- - choice | enable | Enable rating images by URL (blocked images are replaced with blanks).
- required: false
- choices: ["disable", "enable"]
-
- ftgd_wf_rate_javascript_urls:
- description:
- - Enable/disable rating JavaScript by URL.
- - choice | disable | Disable rating JavaScript by URL.
- - choice | enable | Enable rating JavaScript by URL.
- required: false
- choices: ["disable", "enable"]
-
- ftgd_wf_filters_action:
- description:
- - Action to take for matches.
- - choice | block | Block access.
- - choice | monitor | Allow access while logging the action.
- - choice | warning | Allow access after warning the user.
- - choice | authenticate | Authenticate user before allowing access.
- required: false
- choices: ["block", "monitor", "warning", "authenticate"]
-
- ftgd_wf_filters_auth_usr_grp:
- description:
- - Groups with permission to authenticate.
- required: false
-
- ftgd_wf_filters_category:
- description:
- - Categories and groups the filter examines.
- required: false
-
- ftgd_wf_filters_log:
- description:
- - Enable/disable logging.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- ftgd_wf_filters_override_replacemsg:
- description:
- - Override replacement message.
- required: false
-
- ftgd_wf_filters_warn_duration:
- description:
- - Duration of warnings.
- required: false
-
- ftgd_wf_filters_warning_duration_type:
- description:
- - Re-display warning after closing browser or after a timeout.
- - choice | session | After session ends.
- - choice | timeout | After timeout occurs.
- required: false
- choices: ["session", "timeout"]
-
- ftgd_wf_filters_warning_prompt:
- description:
- - Warning prompts in each category or each domain.
- - choice | per-domain | Per-domain warnings.
- - choice | per-category | Per-category warnings.
- required: false
- choices: ["per-domain", "per-category"]
-
- ftgd_wf_quota_category:
- description:
- - FortiGuard categories to apply quota to (category action must be set to monitor).
- required: false
-
- ftgd_wf_quota_duration:
- description:
- - Duration of quota.
- required: false
-
- ftgd_wf_quota_override_replacemsg:
- description:
- - Override replacement message.
- required: false
-
- ftgd_wf_quota_type:
- description:
- - Quota type.
- - choice | time | Use a time-based quota.
- - choice | traffic | Use a traffic-based quota.
- required: false
- choices: ["time", "traffic"]
-
- ftgd_wf_quota_unit:
- description:
- - Traffic quota unit of measurement.
- - choice | B | Quota in bytes.
- - choice | KB | Quota in kilobytes.
- - choice | MB | Quota in megabytes.
- - choice | GB | Quota in gigabytes.
- required: false
- choices: ["B", "KB", "MB", "GB"]
-
- ftgd_wf_quota_value:
- description:
- - Traffic quota value.
- required: false
-
- override:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- override_ovrd_cookie:
- description:
- - Allow/deny browser-based (cookie) overrides.
- - choice | deny | Deny browser-based (cookie) override.
- - choice | allow | Allow browser-based (cookie) override.
- required: false
- choices: ["deny", "allow"]
-
- override_ovrd_dur:
- description:
- - Override duration.
- required: false
-
- override_ovrd_dur_mode:
- description:
- - Override duration mode.
- - choice | constant | Constant mode.
- - choice | ask | Prompt for duration when initiating an override.
- required: false
- choices: ["constant", "ask"]
-
- override_ovrd_scope:
- description:
- - Override scope.
- - choice | user | Override for the user.
- - choice | user-group | Override for the user's group.
- - choice | ip | Override for the initiating IP.
- - choice | ask | Prompt for scope when initiating an override.
- - choice | browser | Create browser-based (cookie) override.
- required: false
- choices: ["user", "user-group", "ip", "ask", "browser"]
-
- override_ovrd_user_group:
- description:
- - User groups with permission to use the override.
- required: false
-
- override_profile:
- description:
- - Web filter profile with permission to create overrides.
- required: false
-
- override_profile_attribute:
- description:
- - Profile attribute to retrieve from the RADIUS server.
- - choice | User-Name | Use this attribute.
- - choice | NAS-IP-Address | Use this attribute.
- - choice | Framed-IP-Address | Use this attribute.
- - choice | Framed-IP-Netmask | Use this attribute.
- - choice | Filter-Id | Use this attribute.
- - choice | Login-IP-Host | Use this attribute.
- - choice | Reply-Message | Use this attribute.
- - choice | Callback-Number | Use this attribute.
- - choice | Callback-Id | Use this attribute.
- - choice | Framed-Route | Use this attribute.
- - choice | Framed-IPX-Network | Use this attribute.
- - choice | Class | Use this attribute.
- - choice | Called-Station-Id | Use this attribute.
- - choice | Calling-Station-Id | Use this attribute.
- - choice | NAS-Identifier | Use this attribute.
- - choice | Proxy-State | Use this attribute.
- - choice | Login-LAT-Service | Use this attribute.
- - choice | Login-LAT-Node | Use this attribute.
- - choice | Login-LAT-Group | Use this attribute.
- - choice | Framed-AppleTalk-Zone | Use this attribute.
- - choice | Acct-Session-Id | Use this attribute.
- - choice | Acct-Multi-Session-Id | Use this attribute.
- required: false
- choices:
- - User-Name
- - NAS-IP-Address
- - Framed-IP-Address
- - Framed-IP-Netmask
- - Filter-Id
- - Login-IP-Host
- - Reply-Message
- - Callback-Number
- - Callback-Id
- - Framed-Route
- - Framed-IPX-Network
- - Class
- - Called-Station-Id
- - Calling-Station-Id
- - NAS-Identifier
- - Proxy-State
- - Login-LAT-Service
- - Login-LAT-Node
- - Login-LAT-Group
- - Framed-AppleTalk-Zone
- - Acct-Session-Id
- - Acct-Multi-Session-Id
-
- override_profile_type:
- description:
- - Override profile type.
- - choice | list | Profile chosen from list.
- - choice | radius | Profile determined by RADIUS server.
- required: false
- choices: ["list", "radius"]
-
- url_extraction:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- url_extraction_redirect_header:
- description:
- - HTTP header name to use for client redirect on blocked requests
- required: false
-
- url_extraction_redirect_no_content:
- description:
- - Enable / Disable empty message-body entity in HTTP response
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- url_extraction_redirect_url:
- description:
- - HTTP header value to use for client redirect on blocked requests
- required: false
-
- url_extraction_server_fqdn:
- description:
- - URL extraction server FQDN (fully qualified domain name)
- required: false
-
- url_extraction_status:
- description:
- - Enable URL Extraction
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- web_blacklist:
- description:
- - Enable/disable automatic addition of URLs detected by FortiSandbox to blacklist.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_bword_table:
- description:
- - Banned word table ID.
- required: false
-
- web_bword_threshold:
- description:
- - Banned word score threshold.
- required: false
-
- web_content_header_list:
- description:
- - Content header list.
- required: false
-
- web_keyword_match:
- description:
- - Search keywords to log when match is found.
- required: false
-
- web_log_search:
- description:
- - Enable/disable logging all search phrases.
- - choice | disable | Disable setting.
- - choice | enable | Enable setting.
- required: false
- choices: ["disable", "enable"]
-
- web_safe_search:
- description:
- - Safe search type.
- - FLAG Based Options. Specify multiple in list form.
- - flag | url | Insert safe search string into URL.
- - flag | header | Insert safe search header.
- required: false
- choices: ["url", "header"]
-
- web_urlfilter_table:
- description:
- - URL filter table ID.
- required: false
-
- web_whitelist:
- description:
- - FortiGuard whitelist settings.
- - FLAG Based Options. Specify multiple in list form.
- - flag | exempt-av | Exempt antivirus.
- - flag | exempt-webcontent | Exempt web content.
- - flag | exempt-activex-java-cookie | Exempt ActiveX-JAVA-Cookie.
- - flag | exempt-dlp | Exempt DLP.
- - flag | exempt-rangeblock | Exempt RangeBlock.
- - flag | extended-log-others | Support extended log.
- required: false
- choices:
- - exempt-av
- - exempt-webcontent
- - exempt-activex-java-cookie
- - exempt-dlp
- - exempt-rangeblock
- - extended-log-others
-
- web_youtube_restrict:
- description:
- - YouTube EDU filter level.
- - choice | strict | Strict access for YouTube.
- - choice | none | Full access for YouTube.
- - choice | moderate | Moderate access for YouTube.
- required: false
- choices: ["strict", "none", "moderate"]
-
- youtube_channel_filter:
- description:
- - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED!
- - List of multiple child objects to be added. Expects a list of dictionaries.
- - Dictionaries must use FortiManager API parameters, not the ansible ones listed below.
- - If submitted, all other prefixed sub-parameters ARE IGNORED.
- - This object is MUTUALLY EXCLUSIVE with its options.
- - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide.
- - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS
- required: false
-
- youtube_channel_filter_channel_id:
- description:
- - YouTube channel ID to be filtered.
- required: false
-
- youtube_channel_filter_comment:
- description:
- - Comment.
- required: false
-
-
-'''
-
-EXAMPLES = '''
- - name: DELETE Profile
- fmgr_secprof_web:
- name: "Ansible_Web_Filter_Profile"
- mode: "delete"
-
- - name: CREATE Profile
- fmgr_secprof_web:
- name: "Ansible_Web_Filter_Profile"
- comment: "Created by Ansible Module TEST"
- mode: "set"
- extended_log: "enable"
- inspection_mode: "proxy"
- log_all_url: "enable"
- options: "js"
- ovrd_perm: "bannedword-override"
- post_action: "block"
- web_content_log: "enable"
- web_extended_all_action_log: "enable"
- web_filter_activex_log: "enable"
- web_filter_applet_log: "enable"
- web_filter_command_block_log: "enable"
- web_filter_cookie_log: "enable"
- web_filter_cookie_removal_log: "enable"
- web_filter_js_log: "enable"
- web_filter_jscript_log: "enable"
- web_filter_referer_log: "enable"
- web_filter_unknown_log: "enable"
- web_filter_vbs_log: "enable"
- web_ftgd_err_log: "enable"
- web_ftgd_quota_usage: "enable"
- web_invalid_domain_log: "enable"
- web_url_log: "enable"
- wisp: "enable"
- wisp_algorithm: "auto-learning"
- youtube_channel_status: "blacklist"
-'''
-
-RETURN = """
-api_result:
- description: full API response, includes status code and message
- returned: always
- type: str
-"""
-
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import Connection
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict
-from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict
-
-
-def fmgr_webfilter_profile_modify(fmgr, paramgram):
-
- mode = paramgram["mode"]
- adom = paramgram["adom"]
-
- response = DEFAULT_RESULT_OBJ
- url = ""
- datagram = {}
-
- # EVAL THE MODE PARAMETER FOR SET OR ADD
- if mode in ['set', 'add', 'update']:
- url = '/pm/config/adom/{adom}/obj/webfilter/profile'.format(adom=adom)
- datagram = scrub_dict(prepare_dict(paramgram))
-
- # EVAL THE MODE PARAMETER FOR DELETE
- elif mode == "delete":
- # SET THE CORRECT URL FOR DELETE
- url = '/pm/config/adom/{adom}/obj/webfilter/profile/{name}'.format(adom=adom, name=paramgram["name"])
- datagram = {}
-
- response = fmgr.process_request(url, datagram, paramgram["mode"])
-
- return response
-
-
-#############
-# END METHODS
-#############
-
-
-def main():
- argument_spec = dict(
- adom=dict(type="str", default="root"),
- mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"),
-
- youtube_channel_status=dict(required=False, type="str", choices=["disable", "blacklist", "whitelist"]),
- wisp_servers=dict(required=False, type="str"),
- wisp_algorithm=dict(required=False, type="str", choices=["auto-learning", "primary-secondary", "round-robin"]),
- wisp=dict(required=False, type="str", choices=["disable", "enable"]),
- web_url_log=dict(required=False, type="str", choices=["disable", "enable"]),
- web_invalid_domain_log=dict(required=False, type="str", choices=["disable", "enable"]),
- web_ftgd_quota_usage=dict(required=False, type="str", choices=["disable", "enable"]),
- web_ftgd_err_log=dict(required=False, type="str", choices=["disable", "enable"]),
- web_filter_vbs_log=dict(required=False, type="str", choices=["disable", "enable"]),
- web_filter_unknown_log=dict(required=False, type="str", choices=["disable", "enable"]),
- web_filter_referer_log=dict(required=False, type="str", choices=["disable", "enable"]),
- web_filter_jscript_log=dict(required=False, type="str", choices=["disable", "enable"]),
- web_filter_js_log=dict(required=False, type="str", choices=["disable", "enable"]),
- web_filter_cookie_removal_log=dict(required=False, type="str", choices=["disable", "enable"]),
- web_filter_cookie_log=dict(required=False, type="str", choices=["disable", "enable"]),
- web_filter_command_block_log=dict(required=False, type="str", choices=["disable", "enable"]),
- web_filter_applet_log=dict(required=False, type="str", choices=["disable", "enable"]),
- web_filter_activex_log=dict(required=False, type="str", choices=["disable", "enable"]),
- web_extended_all_action_log=dict(required=False, type="str", choices=["disable", "enable"]),
- web_content_log=dict(required=False, type="str", choices=["disable", "enable"]),
- replacemsg_group=dict(required=False, type="str"),
- post_action=dict(required=False, type="str", choices=["normal", "block"]),
- ovrd_perm=dict(required=False, type="list", choices=["bannedword-override",
- "urlfilter-override",
- "fortiguard-wf-override",
- "contenttype-check-override"]),
- options=dict(required=False, type="list", choices=["block-invalid-url",
- "jscript",
- "js",
- "vbs",
- "unknown",
- "wf-referer",
- "intrinsic",
- "wf-cookie",
- "per-user-bwl",
- "activexfilter",
- "cookiefilter",
- "javafilter"]),
- name=dict(required=False, type="str"),
- log_all_url=dict(required=False, type="str", choices=["disable", "enable"]),
- inspection_mode=dict(required=False, type="str", choices=["proxy", "flow-based"]),
- https_replacemsg=dict(required=False, type="str", choices=["disable", "enable"]),
- extended_log=dict(required=False, type="str", choices=["disable", "enable"]),
- comment=dict(required=False, type="str"),
- ftgd_wf=dict(required=False, type="list"),
- ftgd_wf_exempt_quota=dict(required=False, type="str"),
- ftgd_wf_max_quota_timeout=dict(required=False, type="int"),
- ftgd_wf_options=dict(required=False, type="str", choices=["error-allow", "rate-server-ip",
- "connect-request-bypass", "ftgd-disable"]),
- ftgd_wf_ovrd=dict(required=False, type="str"),
- ftgd_wf_rate_crl_urls=dict(required=False, type="str", choices=["disable", "enable"]),
- ftgd_wf_rate_css_urls=dict(required=False, type="str", choices=["disable", "enable"]),
- ftgd_wf_rate_image_urls=dict(required=False, type="str", choices=["disable", "enable"]),
- ftgd_wf_rate_javascript_urls=dict(required=False, type="str", choices=["disable", "enable"]),
-
- ftgd_wf_filters_action=dict(required=False, type="str", choices=["block", "monitor",
- "warning", "authenticate"]),
- ftgd_wf_filters_auth_usr_grp=dict(required=False, type="str"),
- ftgd_wf_filters_category=dict(required=False, type="str"),
- ftgd_wf_filters_log=dict(required=False, type="str", choices=["disable", "enable"]),
- ftgd_wf_filters_override_replacemsg=dict(required=False, type="str"),
- ftgd_wf_filters_warn_duration=dict(required=False, type="str"),
- ftgd_wf_filters_warning_duration_type=dict(required=False, type="str", choices=["session", "timeout"]),
- ftgd_wf_filters_warning_prompt=dict(required=False, type="str", choices=["per-domain", "per-category"]),
-
- ftgd_wf_quota_category=dict(required=False, type="str"),
- ftgd_wf_quota_duration=dict(required=False, type="str"),
- ftgd_wf_quota_override_replacemsg=dict(required=False, type="str"),
- ftgd_wf_quota_type=dict(required=False, type="str", choices=["time", "traffic"]),
- ftgd_wf_quota_unit=dict(required=False, type="str", choices=["B", "KB", "MB", "GB"]),
- ftgd_wf_quota_value=dict(required=False, type="int"),
- override=dict(required=False, type="list"),
- override_ovrd_cookie=dict(required=False, type="str", choices=["deny", "allow"]),
- override_ovrd_dur=dict(required=False, type="str"),
- override_ovrd_dur_mode=dict(required=False, type="str", choices=["constant", "ask"]),
- override_ovrd_scope=dict(required=False, type="str", choices=["user", "user-group", "ip", "ask", "browser"]),
- override_ovrd_user_group=dict(required=False, type="str"),
- override_profile=dict(required=False, type="str"),
- override_profile_attribute=dict(required=False, type="list", choices=["User-Name",
- "NAS-IP-Address",
- "Framed-IP-Address",
- "Framed-IP-Netmask",
- "Filter-Id",
- "Login-IP-Host",
- "Reply-Message",
- "Callback-Number",
- "Callback-Id",
- "Framed-Route",
- "Framed-IPX-Network",
- "Class",
- "Called-Station-Id",
- "Calling-Station-Id",
- "NAS-Identifier",
- "Proxy-State",
- "Login-LAT-Service",
- "Login-LAT-Node",
- "Login-LAT-Group",
- "Framed-AppleTalk-Zone",
- "Acct-Session-Id",
- "Acct-Multi-Session-Id"]),
- override_profile_type=dict(required=False, type="str", choices=["list", "radius"]),
- url_extraction=dict(required=False, type="list"),
- url_extraction_redirect_header=dict(required=False, type="str"),
- url_extraction_redirect_no_content=dict(required=False, type="str", choices=["disable", "enable"]),
- url_extraction_redirect_url=dict(required=False, type="str"),
- url_extraction_server_fqdn=dict(required=False, type="str"),
- url_extraction_status=dict(required=False, type="str", choices=["disable", "enable"]),
- web=dict(required=False, type="list"),
- web_blacklist=dict(required=False, type="str", choices=["disable", "enable"]),
- web_bword_table=dict(required=False, type="str"),
- web_bword_threshold=dict(required=False, type="int"),
- web_content_header_list=dict(required=False, type="str"),
- web_keyword_match=dict(required=False, type="str"),
- web_log_search=dict(required=False, type="str", choices=["disable", "enable"]),
- web_safe_search=dict(required=False, type="str", choices=["url", "header"]),
- web_urlfilter_table=dict(required=False, type="str"),
- web_whitelist=dict(required=False, type="list", choices=["exempt-av",
- "exempt-webcontent",
- "exempt-activex-java-cookie",
- "exempt-dlp",
- "exempt-rangeblock",
- "extended-log-others"]),
- web_youtube_restrict=dict(required=False, type="str", choices=["strict", "none", "moderate"]),
- youtube_channel_filter=dict(required=False, type="list"),
- youtube_channel_filter_channel_id=dict(required=False, type="str"),
- youtube_channel_filter_comment=dict(required=False, type="str"),
-
- )
-
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
- # MODULE PARAMGRAM
- paramgram = {
- "mode": module.params["mode"],
- "adom": module.params["adom"],
- "youtube-channel-status": module.params["youtube_channel_status"],
- "wisp-servers": module.params["wisp_servers"],
- "wisp-algorithm": module.params["wisp_algorithm"],
- "wisp": module.params["wisp"],
- "web-url-log": module.params["web_url_log"],
- "web-invalid-domain-log": module.params["web_invalid_domain_log"],
- "web-ftgd-quota-usage": module.params["web_ftgd_quota_usage"],
- "web-ftgd-err-log": module.params["web_ftgd_err_log"],
- "web-filter-vbs-log": module.params["web_filter_vbs_log"],
- "web-filter-unknown-log": module.params["web_filter_unknown_log"],
- "web-filter-referer-log": module.params["web_filter_referer_log"],
- "web-filter-jscript-log": module.params["web_filter_jscript_log"],
- "web-filter-js-log": module.params["web_filter_js_log"],
- "web-filter-cookie-removal-log": module.params["web_filter_cookie_removal_log"],
- "web-filter-cookie-log": module.params["web_filter_cookie_log"],
- "web-filter-command-block-log": module.params["web_filter_command_block_log"],
- "web-filter-applet-log": module.params["web_filter_applet_log"],
- "web-filter-activex-log": module.params["web_filter_activex_log"],
- "web-extended-all-action-log": module.params["web_extended_all_action_log"],
- "web-content-log": module.params["web_content_log"],
- "replacemsg-group": module.params["replacemsg_group"],
- "post-action": module.params["post_action"],
- "ovrd-perm": module.params["ovrd_perm"],
- "options": module.params["options"],
- "name": module.params["name"],
- "log-all-url": module.params["log_all_url"],
- "inspection-mode": module.params["inspection_mode"],
- "https-replacemsg": module.params["https_replacemsg"],
- "extended-log": module.params["extended_log"],
- "comment": module.params["comment"],
- "ftgd-wf": {
- "exempt-quota": module.params["ftgd_wf_exempt_quota"],
- "max-quota-timeout": module.params["ftgd_wf_max_quota_timeout"],
- "options": module.params["ftgd_wf_options"],
- "ovrd": module.params["ftgd_wf_ovrd"],
- "rate-crl-urls": module.params["ftgd_wf_rate_crl_urls"],
- "rate-css-urls": module.params["ftgd_wf_rate_css_urls"],
- "rate-image-urls": module.params["ftgd_wf_rate_image_urls"],
- "rate-javascript-urls": module.params["ftgd_wf_rate_javascript_urls"],
- "filters": {
- "action": module.params["ftgd_wf_filters_action"],
- "auth-usr-grp": module.params["ftgd_wf_filters_auth_usr_grp"],
- "category": module.params["ftgd_wf_filters_category"],
- "log": module.params["ftgd_wf_filters_log"],
- "override-replacemsg": module.params["ftgd_wf_filters_override_replacemsg"],
- "warn-duration": module.params["ftgd_wf_filters_warn_duration"],
- "warning-duration-type": module.params["ftgd_wf_filters_warning_duration_type"],
- "warning-prompt": module.params["ftgd_wf_filters_warning_prompt"],
- },
- "quota": {
- "category": module.params["ftgd_wf_quota_category"],
- "duration": module.params["ftgd_wf_quota_duration"],
- "override-replacemsg": module.params["ftgd_wf_quota_override_replacemsg"],
- "type": module.params["ftgd_wf_quota_type"],
- "unit": module.params["ftgd_wf_quota_unit"],
- "value": module.params["ftgd_wf_quota_value"],
- },
- },
- "override": {
- "ovrd-cookie": module.params["override_ovrd_cookie"],
- "ovrd-dur": module.params["override_ovrd_dur"],
- "ovrd-dur-mode": module.params["override_ovrd_dur_mode"],
- "ovrd-scope": module.params["override_ovrd_scope"],
- "ovrd-user-group": module.params["override_ovrd_user_group"],
- "profile": module.params["override_profile"],
- "profile-attribute": module.params["override_profile_attribute"],
- "profile-type": module.params["override_profile_type"],
- },
- "url-extraction": {
- "redirect-header": module.params["url_extraction_redirect_header"],
- "redirect-no-content": module.params["url_extraction_redirect_no_content"],
- "redirect-url": module.params["url_extraction_redirect_url"],
- "server-fqdn": module.params["url_extraction_server_fqdn"],
- "status": module.params["url_extraction_status"],
- },
- "web": {
- "blacklist": module.params["web_blacklist"],
- "bword-table": module.params["web_bword_table"],
- "bword-threshold": module.params["web_bword_threshold"],
- "content-header-list": module.params["web_content_header_list"],
- "keyword-match": module.params["web_keyword_match"],
- "log-search": module.params["web_log_search"],
- "safe-search": module.params["web_safe_search"],
- "urlfilter-table": module.params["web_urlfilter_table"],
- "whitelist": module.params["web_whitelist"],
- "youtube-restrict": module.params["web_youtube_restrict"],
- },
- "youtube-channel-filter": {
- "channel-id": module.params["youtube_channel_filter_channel_id"],
- "comment": module.params["youtube_channel_filter_comment"],
- }
- }
- module.paramgram = paramgram
- fmgr = None
- if module._socket_path:
- connection = Connection(module._socket_path)
- fmgr = FortiManagerHandler(connection, module)
- fmgr.tools = FMGRCommon()
- else:
- module.fail_json(**FAIL_SOCKET_MSG)
-
- list_overrides = ['ftgd-wf', 'override', 'url-extraction', 'web', 'youtube-channel-filter']
- paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides,
- paramgram=paramgram, module=module)
-
- results = DEFAULT_RESULT_OBJ
-
- try:
-
- results = fmgr_webfilter_profile_modify(fmgr, paramgram)
- fmgr.govern_response(module=module, results=results,
- ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
-
- except Exception as err:
- raise FMGBaseException(err)
-
- return module.exit_json(**results[1])
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/ftd/ftd_configuration.py b/plugins/modules/network/ftd/ftd_configuration.py
deleted file mode 100644
index 41cded30d8..0000000000
--- a/plugins/modules/network/ftd/ftd_configuration.py
+++ /dev/null
@@ -1,139 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2018 Cisco and/or its affiliates.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ftd_configuration
-short_description: Manages configuration on Cisco FTD devices over REST API
-description:
- - Manages configuration on Cisco FTD devices including creating, updating, removing configuration objects,
- scheduling and staring jobs, deploying pending changes, etc. All operations are performed over REST API.
-author: "Cisco Systems, Inc. (@annikulin)"
-options:
- operation:
- description:
- - The name of the operation to execute. Commonly, the operation starts with 'add', 'edit', 'get', 'upsert'
- or 'delete' verbs, but can have an arbitrary name too.
- required: true
- type: str
- data:
- description:
- - Key-value pairs that should be sent as body parameters in a REST API call
- type: dict
- query_params:
- description:
- - Key-value pairs that should be sent as query parameters in a REST API call.
- type: dict
- path_params:
- description:
- - Key-value pairs that should be sent as path parameters in a REST API call.
- type: dict
- register_as:
- description:
- - Specifies Ansible fact name that is used to register received response from the FTD device.
- type: str
- filters:
- description:
- - Key-value dict that represents equality filters. Every key is a property name and value is its desired value.
- If multiple filters are present, they are combined with logical operator AND.
- type: dict
-'''
-
-EXAMPLES = """
-- name: Create a network object
- ftd_configuration:
- operation: "addNetworkObject"
- data:
- name: "Ansible-network-host"
- description: "From Ansible with love"
- subType: "HOST"
- value: "192.168.2.0"
- dnsResolution: "IPV4_AND_IPV6"
- type: "networkobject"
- isSystemDefined: false
- register_as: "hostNetwork"
-
-- name: Delete the network object
- ftd_configuration:
- operation: "deleteNetworkObject"
- path_params:
- objId: "{{ hostNetwork['id'] }}"
-"""
-
-RETURN = """
-response:
- description: HTTP response returned from the API call.
- returned: success
- type: dict
-"""
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.community.general.plugins.module_utils.network.ftd.configuration import BaseConfigurationResource, CheckModeException, \
- FtdInvalidOperationNameError
-from ansible_collections.community.general.plugins.module_utils.network.ftd.fdm_swagger_client import ValidationError
-from ansible_collections.community.general.plugins.module_utils.network.ftd.common import construct_ansible_facts, FtdConfigurationError, \
- FtdServerError, FtdUnexpectedResponse
-
-
-def main():
- fields = dict(
- operation=dict(type='str', required=True),
- data=dict(type='dict'),
- query_params=dict(type='dict'),
- path_params=dict(type='dict'),
- register_as=dict(type='str'),
- filters=dict(type='dict')
- )
- module = AnsibleModule(argument_spec=fields,
- supports_check_mode=True)
- params = module.params
-
- connection = Connection(module._socket_path)
- resource = BaseConfigurationResource(connection, module.check_mode)
- op_name = params['operation']
- try:
- resp = resource.execute_operation(op_name, params)
- module.exit_json(changed=resource.config_changed, response=resp,
- ansible_facts=construct_ansible_facts(resp, module.params))
- except FtdInvalidOperationNameError as e:
- module.fail_json(msg='Invalid operation name provided: %s' % e.operation_name)
- except FtdConfigurationError as e:
- module.fail_json(msg='Failed to execute %s operation because of the configuration error: %s' % (op_name, e.msg))
- except FtdServerError as e:
- module.fail_json(msg='Server returned an error trying to execute %s operation. Status code: %s. '
- 'Server response: %s' % (op_name, e.code, e.response))
- except FtdUnexpectedResponse as e:
- module.fail_json(msg=e.args[0])
- except ValidationError as e:
- module.fail_json(msg=e.args[0])
- except CheckModeException:
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/ftd/ftd_file_download.py b/plugins/modules/network/ftd/ftd_file_download.py
deleted file mode 100644
index 18c8b15633..0000000000
--- a/plugins/modules/network/ftd/ftd_file_download.py
+++ /dev/null
@@ -1,131 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2018 Cisco and/or its affiliates.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ftd_file_download
-short_description: Downloads files from Cisco FTD devices over HTTP(S)
-description:
- - Downloads files from Cisco FTD devices including pending changes, disk files, certificates,
- troubleshoot reports, and backups.
-author: "Cisco Systems, Inc. (@annikulin)"
-options:
- operation:
- description:
- - The name of the operation to execute.
- - Only operations that return a file can be used in this module.
- required: true
- type: str
- path_params:
- description:
- - Key-value pairs that should be sent as path parameters in a REST API call.
- type: dict
- destination:
- description:
- - Absolute path of where to download the file to.
- - If destination is a directory, the module uses a filename from 'Content-Disposition' header specified by
- the server.
- required: true
- type: path
-'''
-
-EXAMPLES = """
-- name: Download pending changes
- ftd_file_download:
- operation: 'getdownload'
- path_params:
- objId: 'default'
- destination: /tmp/
-"""
-
-RETURN = """
-msg:
- description: The error message describing why the module failed.
- returned: error
- type: str
-"""
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.community.general.plugins.module_utils.network.ftd.common import FtdServerError, HTTPMethod
-from ansible_collections.community.general.plugins.module_utils.network.ftd.fdm_swagger_client import OperationField, ValidationError, FILE_MODEL_NAME
-
-
-def is_download_operation(op_spec):
- return op_spec[OperationField.METHOD] == HTTPMethod.GET and op_spec[OperationField.MODEL_NAME] == FILE_MODEL_NAME
-
-
-def validate_params(connection, op_name, path_params):
- field_name = 'Invalid path_params provided'
- try:
- is_valid, validation_report = connection.validate_path_params(op_name, path_params)
- if not is_valid:
- raise ValidationError({
- field_name: validation_report
- })
- except Exception as e:
- raise ValidationError({
- field_name: str(e)
- })
-
-
-def main():
- fields = dict(
- operation=dict(type='str', required=True),
- path_params=dict(type='dict'),
- destination=dict(type='path', required=True)
- )
- module = AnsibleModule(argument_spec=fields,
- supports_check_mode=True)
- params = module.params
- connection = Connection(module._socket_path)
-
- op_name = params['operation']
- op_spec = connection.get_operation_spec(op_name)
- if op_spec is None:
- module.fail_json(msg='Operation with specified name is not found: %s' % op_name)
- if not is_download_operation(op_spec):
- module.fail_json(
- msg='Invalid download operation: %s. The operation must make GET request and return a file.' %
- op_name)
-
- try:
- path_params = params['path_params']
- validate_params(connection, op_name, path_params)
- if module.check_mode:
- module.exit_json(changed=False)
- connection.download_file(op_spec[OperationField.URL], params['destination'], path_params)
- module.exit_json(changed=False)
- except FtdServerError as e:
- module.fail_json(msg='Download request for %s operation failed. Status code: %s. '
- 'Server response: %s' % (op_name, e.code, e.response))
- except ValidationError as e:
- module.fail_json(msg=e.args[0])
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/ftd/ftd_file_upload.py b/plugins/modules/network/ftd/ftd_file_upload.py
deleted file mode 100644
index 50062d8c1f..0000000000
--- a/plugins/modules/network/ftd/ftd_file_upload.py
+++ /dev/null
@@ -1,107 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2018 Cisco and/or its affiliates.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ftd_file_upload
-short_description: Uploads files to Cisco FTD devices over HTTP(S)
-description:
- - Uploads files to Cisco FTD devices including disk files, backups, and upgrades.
-author: "Cisco Systems, Inc. (@annikulin)"
-options:
- operation:
- description:
- - The name of the operation to execute.
- - Only operations that upload file can be used in this module.
- required: true
- type: str
- file_to_upload:
- description:
- - Absolute path to the file that should be uploaded.
- required: true
- type: path
- register_as:
- description:
- - Specifies Ansible fact name that is used to register received response from the FTD device.
- type: str
-'''
-
-EXAMPLES = """
-- name: Upload disk file
- ftd_file_upload:
- operation: 'postuploaddiskfile'
- file_to_upload: /tmp/test1.txt
-"""
-
-RETURN = """
-msg:
- description: The error message describing why the module failed.
- returned: error
- type: str
-"""
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible_collections.community.general.plugins.module_utils.network.ftd.common import construct_ansible_facts, FtdServerError, HTTPMethod
-from ansible_collections.community.general.plugins.module_utils.network.ftd.fdm_swagger_client import OperationField
-
-
-def is_upload_operation(op_spec):
- return op_spec[OperationField.METHOD] == HTTPMethod.POST or 'UploadStatus' in op_spec[OperationField.MODEL_NAME]
-
-
-def main():
- fields = dict(
- operation=dict(type='str', required=True),
- file_to_upload=dict(type='path', required=True),
- register_as=dict(type='str'),
- )
- module = AnsibleModule(argument_spec=fields,
- supports_check_mode=True)
- params = module.params
- connection = Connection(module._socket_path)
-
- op_spec = connection.get_operation_spec(params['operation'])
- if op_spec is None:
- module.fail_json(msg='Operation with specified name is not found: %s' % params['operation'])
- if not is_upload_operation(op_spec):
- module.fail_json(
- msg='Invalid upload operation: %s. The operation must make POST request and return UploadStatus model.' %
- params['operation'])
-
- try:
- if module.check_mode:
- module.exit_json()
- resp = connection.upload_file(params['file_to_upload'], op_spec[OperationField.URL])
- module.exit_json(changed=True, response=resp, ansible_facts=construct_ansible_facts(resp, module.params))
- except FtdServerError as e:
- module.fail_json(msg='Upload request for %s operation failed. Status code: %s. '
- 'Server response: %s' % (params['operation'], e.code, e.response))
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/ftd/ftd_install.py b/plugins/modules/network/ftd/ftd_install.py
deleted file mode 100644
index 025bac5e3b..0000000000
--- a/plugins/modules/network/ftd/ftd_install.py
+++ /dev/null
@@ -1,294 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2019 Cisco and/or its affiliates.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-#
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: ftd_install
-short_description: Installs FTD pkg image on the firewall
-description:
- - Provisioning module for FTD devices that installs ROMMON image (if needed) and
- FTD pkg image on the firewall.
- - Can be used with `httpapi` and `local` connection types. The `httpapi` is preferred,
- the `local` connection should be used only when the device cannot be accessed via
- REST API.
-requirements: [ "python >= 3.5", "firepower-kickstart" ]
-notes:
- - Requires `firepower-kickstart` library that should be installed separately and requires Python >= 3.5.
- - On localhost, Ansible can be still run with Python >= 2.7, but the interpreter for this particular module must be
- Python >= 3.5.
- - Python interpreter for the module can overwritten in `ansible_python_interpreter` variable.
-author: "Cisco Systems, Inc. (@annikulin)"
-options:
- device_hostname:
- description:
- - Hostname of the device as appears in the prompt (e.g., 'firepower-5516').
- required: true
- type: str
- device_username:
- description:
- - Username to login on the device.
- - Defaulted to 'admin' if not specified.
- required: false
- type: str
- default: admin
- device_password:
- description:
- - Password to login on the device.
- required: true
- type: str
- device_sudo_password:
- description:
- - Root password for the device. If not specified, `device_password` is used.
- required: false
- type: str
- device_new_password:
- description:
- - New device password to set after image installation.
- - If not specified, current password from `device_password` property is reused.
- - Not applicable for ASA5500-X series devices.
- required: false
- type: str
- device_ip:
- description:
- - Device IP address of management interface.
- - If not specified and connection is 'httpapi`, the module tries to fetch the existing value via REST API.
- - For 'local' connection type, this parameter is mandatory.
- required: false
- type: str
- device_gateway:
- description:
- - Device gateway of management interface.
- - If not specified and connection is 'httpapi`, the module tries to fetch the existing value via REST API.
- - For 'local' connection type, this parameter is mandatory.
- required: false
- type: str
- device_netmask:
- description:
- - Device netmask of management interface.
- - If not specified and connection is 'httpapi`, the module tries to fetch the existing value via REST API.
- - For 'local' connection type, this parameter is mandatory.
- required: false
- type: str
- device_model:
- description:
- - Platform model of the device (e.g., 'Cisco ASA5506-X Threat Defense').
- - If not specified and connection is 'httpapi`, the module tries to fetch the device model via REST API.
- - For 'local' connection type, this parameter is mandatory.
- required: false
- type: str
- choices:
- - Cisco ASA5506-X Threat Defense
- - Cisco ASA5508-X Threat Defense
- - Cisco ASA5516-X Threat Defense
- - Cisco Firepower 2110 Threat Defense
- - Cisco Firepower 2120 Threat Defense
- - Cisco Firepower 2130 Threat Defense
- - Cisco Firepower 2140 Threat Defense
- dns_server:
- description:
- - DNS IP address of management interface.
- - If not specified and connection is 'httpapi`, the module tries to fetch the existing value via REST API.
- - For 'local' connection type, this parameter is mandatory.
- required: false
- type: str
- console_ip:
- description:
- - IP address of a terminal server.
- - Used to set up an SSH connection with device's console port through the terminal server.
- required: true
- type: str
- console_port:
- description:
- - Device's port on a terminal server.
- required: true
- type: str
- console_username:
- description:
- - Username to login on a terminal server.
- required: true
- type: str
- console_password:
- description:
- - Password to login on a terminal server.
- required: true
- type: str
- rommon_file_location:
- description:
- - Path to the boot (ROMMON) image on TFTP server.
- - Only TFTP is supported.
- required: true
- type: str
- image_file_location:
- description:
- - Path to the FTD pkg image on the server to be downloaded.
- - FTP, SCP, SFTP, TFTP, or HTTP protocols are usually supported, but may depend on the device model.
- required: true
- type: str
- image_version:
- description:
- - Version of FTD image to be installed.
- - Helps to compare target and current FTD versions to prevent unnecessary reinstalls.
- required: true
- type: str
- force_install:
- description:
- - Forces the FTD image to be installed even when the same version is already installed on the firewall.
- - By default, the module stops execution when the target version is installed in the device.
- required: false
- type: bool
- default: false
- search_domains:
- description:
- - Search domains delimited by comma.
- - Defaulted to 'cisco.com' if not specified.
- required: false
- type: str
- default: cisco.com
-'''
-
-EXAMPLES = """
- - name: Install image v6.3.0 on FTD 5516
- ftd_install:
- device_hostname: firepower
- device_password: pass
- device_ip: 192.168.0.1
- device_netmask: 255.255.255.0
- device_gateway: 192.168.0.254
- dns_server: 8.8.8.8
-
- console_ip: 10.89.0.0
- console_port: 2004
- console_username: console_user
- console_password: console_pass
-
- rommon_file_location: 'tftp://10.89.0.11/installers/ftd-boot-9.10.1.3.lfbff'
- image_file_location: 'https://10.89.0.11/installers/ftd-6.3.0-83.pkg'
- image_version: 6.3.0-83
-"""
-
-RETURN = """
-msg:
- description: The message saying whether the image was installed or explaining why the installation failed.
- returned: always
- type: str
-"""
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible.module_utils.six import iteritems
-
-from ansible_collections.community.general.plugins.module_utils.network.ftd.configuration import BaseConfigurationResource, ParamName
-from ansible_collections.community.general.plugins.module_utils.network.ftd.device import assert_kick_is_installed, FtdPlatformFactory, FtdModel
-from ansible_collections.community.general.plugins.module_utils.network.ftd.operation import FtdOperations, get_system_info
-
-REQUIRED_PARAMS_FOR_LOCAL_CONNECTION = ['device_ip', 'device_netmask', 'device_gateway', 'device_model', 'dns_server']
-
-
-def main():
- fields = dict(
- device_hostname=dict(type='str', required=True),
- device_username=dict(type='str', required=False, default='admin'),
- device_password=dict(type='str', required=True, no_log=True),
- device_sudo_password=dict(type='str', required=False, no_log=True),
- device_new_password=dict(type='str', required=False, no_log=True),
- device_ip=dict(type='str', required=False),
- device_netmask=dict(type='str', required=False),
- device_gateway=dict(type='str', required=False),
- device_model=dict(type='str', required=False, choices=FtdModel.supported_models()),
- dns_server=dict(type='str', required=False),
- search_domains=dict(type='str', required=False, default='cisco.com'),
-
- console_ip=dict(type='str', required=True),
- console_port=dict(type='str', required=True),
- console_username=dict(type='str', required=True),
- console_password=dict(type='str', required=True, no_log=True),
-
- rommon_file_location=dict(type='str', required=True),
- image_file_location=dict(type='str', required=True),
- image_version=dict(type='str', required=True),
- force_install=dict(type='bool', required=False, default=False)
- )
- module = AnsibleModule(argument_spec=fields)
- assert_kick_is_installed(module)
-
- use_local_connection = module._socket_path is None
- if use_local_connection:
- check_required_params_for_local_connection(module, module.params)
- platform_model = module.params['device_model']
- check_that_model_is_supported(module, platform_model)
- else:
- connection = Connection(module._socket_path)
- resource = BaseConfigurationResource(connection, module.check_mode)
- system_info = get_system_info(resource)
-
- platform_model = module.params['device_model'] or system_info['platformModel']
- check_that_model_is_supported(module, platform_model)
- check_that_update_is_needed(module, system_info)
- check_management_and_dns_params(resource, module.params)
-
- ftd_platform = FtdPlatformFactory.create(platform_model, module.params)
- ftd_platform.install_ftd_image(module.params)
-
- module.exit_json(changed=True,
- msg='Successfully installed FTD image %s on the firewall device.' % module.params["image_version"])
-
-
-def check_required_params_for_local_connection(module, params):
- missing_params = [k for k, v in iteritems(params) if k in REQUIRED_PARAMS_FOR_LOCAL_CONNECTION and v is None]
- if missing_params:
- message = "The following parameters are mandatory when the module is used with 'local' connection: %s." % \
- ', '.join(sorted(missing_params))
- module.fail_json(msg=message)
-
-
-def check_that_model_is_supported(module, platform_model):
- if platform_model not in FtdModel.supported_models():
- module.fail_json(msg="Platform model '%s' is not supported by this module." % platform_model)
-
-
-def check_that_update_is_needed(module, system_info):
- target_ftd_version = module.params["image_version"]
- if not module.params["force_install"] and target_ftd_version == system_info['softwareVersion']:
- module.exit_json(changed=False, msg="FTD already has %s version of software installed." % target_ftd_version)
-
-
-def check_management_and_dns_params(resource, params):
- if not all([params['device_ip'], params['device_netmask'], params['device_gateway']]):
- management_ip = resource.execute_operation(FtdOperations.GET_MANAGEMENT_IP_LIST, {})['items'][0]
- params['device_ip'] = params['device_ip'] or management_ip['ipv4Address']
- params['device_netmask'] = params['device_netmask'] or management_ip['ipv4NetMask']
- params['device_gateway'] = params['device_gateway'] or management_ip['ipv4Gateway']
- if not params['dns_server']:
- dns_setting = resource.execute_operation(FtdOperations.GET_DNS_SETTING_LIST, {})['items'][0]
- dns_server_group_id = dns_setting['dnsServerGroup']['id']
- dns_server_group = resource.execute_operation(FtdOperations.GET_DNS_SERVER_GROUP,
- {ParamName.PATH_PARAMS: {'objId': dns_server_group_id}})
- params['dns_server'] = dns_server_group['dnsServers'][0]['ipAddress']
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/icx/icx_banner.py b/plugins/modules/network/icx/icx_banner.py
deleted file mode 100644
index 7faadbe997..0000000000
--- a/plugins/modules/network/icx/icx_banner.py
+++ /dev/null
@@ -1,215 +0,0 @@
-#!/usr/bin/python
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: icx_banner
-author: "Ruckus Wireless (@Commscope)"
-short_description: Manage multiline banners on Ruckus ICX 7000 series switches
-description:
- - This will configure both login and motd banners on remote
- ruckus ICX 7000 series switches. It allows playbooks to add or remove
- banner text from the active running configuration.
-notes:
- - Tested against ICX 10.1
-options:
- banner:
- description:
- - Specifies which banner should be configured on the remote device.
- type: str
- required: true
- choices: ['motd', 'exec', 'incoming']
- text:
- description:
- - The banner text that should be
- present in the remote device running configuration.
- This argument accepts a multiline string, with no empty lines.
- type: str
- state:
- description:
- - Specifies whether or not the configuration is
- present in the current devices active running configuration.
- type: str
- default: present
- choices: ['present', 'absent']
- enterkey:
- description:
- - Specifies whether or not the motd configuration should accept
- the require-enter-key
- type: bool
- default: no
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- Module will use environment variable value(default:True), unless it is overridden,
- by specifying it as module parameter.
- type: bool
- default: yes
-
-'''
-
-EXAMPLES = """
-- name: configure the motd banner
- icx_banner:
- banner: motd
- text: |
- this is my motd banner
- that contains a multiline
- string
- state: present
-
-- name: remove the motd banner
- icx_banner:
- banner: motd
- state: absent
-
-- name: configure require-enter-key for motd
- icx_banner:
- banner: motd
- enterkey: True
-
-- name: remove require-enter-key for motd
- icx_banner:
- banner: motd
- enterkey: False
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always
- type: list
- sample:
- - banner motd
- - this is my motd banner
- - that contains a multiline
- - string
-"""
-
-import re
-from ansible.module_utils._text import to_text
-from ansible.module_utils.connection import exec_command
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import load_config, get_config
-from ansible.module_utils.connection import Connection, ConnectionError
-
-
-def map_obj_to_commands(updates, module):
- commands = list()
- state = module.params['state']
- want, have = updates
-
- if module.params['banner'] != 'motd' and module.params['enterkey']:
- module.fail_json(msg=module.params['banner'] + " banner can have text only, got enterkey")
-
- if state == 'absent':
- if 'text' in have.keys() and have['text']:
- commands.append('no banner %s' % module.params['banner'])
- if(module.params['enterkey'] is False):
- commands.append('no banner %s require-enter-key' % module.params['banner'])
-
- elif state == 'present':
- if module.params['text'] is None and module.params['enterkey'] is None:
- module.fail_json(msg=module.params['banner'] + " one of the following is required: text, enterkey:only if motd")
-
- if module.params["banner"] == "motd" and want['enterkey'] != have['enterkey']:
- if(module.params['enterkey']):
- commands.append('banner %s require-enter-key' % module.params['banner'])
-
- if want['text'] and (want['text'] != have.get('text')):
- module.params["enterkey"] = None
- banner_cmd = 'banner %s' % module.params['banner']
- banner_cmd += ' $\n'
- banner_cmd += module.params['text'].strip()
- banner_cmd += '\n$'
- commands.append(banner_cmd)
- return commands
-
-
-def map_config_to_obj(module):
- compare = module.params.get('check_running_config')
- obj = {'banner': module.params['banner'], 'state': 'absent', 'enterkey': False}
- exec_command(module, 'skip')
- output_text = ''
- output_re = ''
- out = get_config(module, flags=['| begin banner %s'
- % module.params['banner']], compare=module.params['check_running_config'])
- if out:
- try:
- output_re = re.search(r'banner %s( require-enter-key)' % module.params['banner'], out, re.S).group(0)
- obj['enterkey'] = True
- except BaseException:
- pass
- try:
- output_text = re.search(r'banner %s (\$([^\$])+\$){1}' % module.params['banner'], out, re.S).group(1).strip('$\n')
- except BaseException:
- pass
-
- else:
- output_text = None
- if output_text:
- obj['text'] = output_text
- obj['state'] = 'present'
- if module.params['check_running_config'] is False:
- obj = {'banner': module.params['banner'], 'state': 'absent', 'enterkey': False, 'text': 'JUNK'}
- return obj
-
-
-def map_params_to_obj(module):
- text = module.params['text']
- if text:
- text = str(text).strip()
-
- return {
- 'banner': module.params['banner'],
- 'text': text,
- 'state': module.params['state'],
- 'enterkey': module.params['enterkey']
- }
-
-
-def main():
- """entry point for module execution
- """
- argument_spec = dict(
- banner=dict(required=True, choices=['motd', 'exec', 'incoming']),
- text=dict(),
- enterkey=dict(type='bool'),
- state=dict(default='present', choices=['present', 'absent']),
- check_running_config=dict(default=True, type='bool', fallback=(env_fallback, ['ANSIBLE_CHECK_ICX_RUNNING_CONFIG']))
- )
-
- required_one_of = [['text', 'enterkey', 'state']]
- module = AnsibleModule(argument_spec=argument_spec,
- required_one_of=required_one_of,
- supports_check_mode=True)
-
- warnings = list()
- results = {'changed': False}
-
- want = map_params_to_obj(module)
- have = map_config_to_obj(module)
- commands = map_obj_to_commands((want, have), module)
- results['commands'] = commands
-
- if commands:
- if not module.check_mode:
- response = load_config(module, commands)
-
- results['changed'] = True
-
- module.exit_json(**results)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/icx/icx_command.py b/plugins/modules/network/icx/icx_command.py
deleted file mode 100644
index 871991743f..0000000000
--- a/plugins/modules/network/icx/icx_command.py
+++ /dev/null
@@ -1,232 +0,0 @@
-#!/usr/bin/python
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = """
----
-module: icx_command
-author: "Ruckus Wireless (@Commscope)"
-short_description: Run arbitrary commands on remote Ruckus ICX 7000 series switches
-description:
- - Sends arbitrary commands to an ICX node and returns the results
- read from the device. This module includes an
- argument that will cause the module to wait for a specific condition
- before returning or timing out if the condition is not met.
-notes:
- - Tested against ICX 10.1
-options:
- commands:
- description:
- - List of commands to send to the remote ICX device over the
- configured provider. The resulting output from the command
- is returned. If the I(wait_for) argument is provided, the
- module is not returned until the condition is satisfied or
- the number of retries has expired. If a command sent to the
- device requires answering a prompt, checkall and newline if
- multiple prompts, it is possible to pass
- a dict containing I(command), I(answer), I(prompt), I(check_all)
- and I(newline).Common answers are 'y' or "\\r" (carriage return,
- must be double quotes). See examples.
- type: list
- required: true
- wait_for:
- description:
- - List of conditions to evaluate against the output of the
- command. The task will wait for each condition to be true
- before moving forward. If the conditional is not true
- within the configured number of retries, the task fails.
- See examples.
- type: list
- aliases: ['waitfor']
- match:
- description:
- - The I(match) argument is used in conjunction with the
- I(wait_for) argument to specify the match policy. Valid
- values are C(all) or C(any). If the value is set to C(all)
- then all conditionals in the wait_for must be satisfied. If
- the value is set to C(any) then only one of the values must be
- satisfied.
- type: str
- default: all
- choices: ['any', 'all']
- retries:
- description:
- - Specifies the number of times a command should by tried
- before it is considered failed. The command is run on the
- target device every retry and evaluated against the
- I(wait_for) conditions.
- type: int
- default: 10
- interval:
- description:
- - Configures the interval in seconds to wait between retries
- of the command. If the command does not pass the specified
- conditions, the interval indicates how long to wait before
- trying the command again.
- type: int
- default: 1
-"""
-
-EXAMPLES = """
-tasks:
- - name: run show version on remote devices
- icx_command:
- commands: show version
-
- - name: run show version and check to see if output contains ICX
- icx_command:
- commands: show version
- wait_for: result[0] contains ICX
-
- - name: run multiple commands on remote nodes
- icx_command:
- commands:
- - show version
- - show interfaces
-
- - name: run multiple commands and evaluate the output
- icx_command:
- commands:
- - show version
- - show interfaces
- wait_for:
- - result[0] contains ICX
- - result[1] contains GigabitEthernet1/1/1
- - name: run commands that require answering a prompt
- icx_command:
- commands:
- - command: 'service password-encryption sha1'
- prompt: 'Warning: Moving to higher password-encryption type,.*'
- answer: 'y'
- - name: run commands that require answering multiple prompt
- icx_command:
- commands:
- - command: 'username qqq password qqq'
- prompt:
- - 'User already exists. Do you want to modify:.*'
- - 'To modify or remove user, enter current password:'
- answer:
- - 'y'
- - 'qqq\\\r'
- check_all: True
- newline: False
-"""
-
-RETURN = """
-stdout:
- description: The set of responses from the commands
- returned: always apart from low level errors
- type: list
- sample: ['...', '...']
-stdout_lines:
- description: The value of stdout split into a list
- returned: always apart from low level errors
- type: list
- sample: [['...', '...'], ['...'], ['...']]
-failed_conditions:
- description: The list of conditionals that have failed
- returned: failed
- type: list
- sample: ['...', '...']
-"""
-
-
-import re
-import time
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import run_commands
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ComplexList, to_lines
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import Conditional
-from ansible.module_utils.six import string_types
-
-
-def parse_commands(module, warnings):
- command = ComplexList(dict(
- command=dict(key=True),
- prompt=dict(),
- answer=dict(),
- check_all=dict(type='bool', default='False'),
- newline=dict(type='bool', default='True')
- ), module)
- commands = command(module.params['commands'])
- for item in list(commands):
- if module.check_mode:
- if not item['command'].startswith('show'):
- warnings.append(
- 'Only show commands are supported when using check mode, not executing configure terminal')
- commands.remove(item)
- return commands
-
-
-def main():
- """main entry point for module execution
- """
- argument_spec = dict(
- commands=dict(type='list', required=True),
-
- wait_for=dict(type='list', aliases=['waitfor']),
- match=dict(default='all', choices=['all', 'any']),
-
- retries=dict(default=10, type='int'),
- interval=dict(default=1, type='int')
- )
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- result = {'changed': False}
-
- warnings = list()
- run_commands(module, ['skip'])
- commands = parse_commands(module, warnings)
- result['warnings'] = warnings
-
- wait_for = module.params['wait_for'] or list()
- conditionals = [Conditional(c) for c in wait_for]
- retries = module.params['retries']
- interval = module.params['interval']
- match = module.params['match']
-
- while retries > 0:
-
- responses = run_commands(module, commands)
-
- for item in list(conditionals):
-
- if item(responses):
- if match == 'any':
- conditionals = list()
- break
- conditionals.remove(item)
-
- if not conditionals:
- break
-
- time.sleep(interval)
- retries -= 1
-
- if conditionals:
- failed_conditions = [item.raw for item in conditionals]
- msg = 'One or more conditional statements have not been satisfied'
- module.fail_json(msg=msg, failed_conditions=failed_conditions)
-
- result.update({
- 'changed': False,
- 'stdout': responses,
- 'stdout_lines': list(to_lines(responses))
- })
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/icx/icx_config.py b/plugins/modules/network/icx/icx_config.py
deleted file mode 100644
index 920a56d38a..0000000000
--- a/plugins/modules/network/icx/icx_config.py
+++ /dev/null
@@ -1,483 +0,0 @@
-#!/usr/bin/python
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: icx_config
-author: "Ruckus Wireless (@Commscope)"
-short_description: Manage configuration sections of Ruckus ICX 7000 series switches
-description:
- - Ruckus ICX configurations use a simple block indent file syntax
- for segmenting configuration into sections. This module provides
- an implementation for working with ICX configuration sections in
- a deterministic way.
-notes:
- - Tested against ICX 10.1.
- - For information on using ICX platform, see L(the ICX OS Platform Options guide,../network/user_guide/platform_icx.html).
-options:
- lines:
- description:
- - The ordered set of commands that should be configured in the
- section. The commands must be the exact same commands as found
- in the device running-config. Be sure to note the configuration
- command syntax as some commands are automatically modified by the
- device config parser.
- type: list
- aliases: ['commands']
- parents:
- description:
- - The ordered set of parents that uniquely identify the section or hierarchy
- the commands should be checked against. If the parents argument
- is omitted, the commands are checked against the set of top
- level or global commands.
- type: list
- src:
- description:
- - Specifies the source path to the file that contains the configuration
- or configuration template to load. The path to the source file can
- either be the full path on the Ansible control host or a relative
- path from the playbook or role root directory. This argument is mutually
- exclusive with I(lines), I(parents).
- type: str
- before:
- description:
- - The ordered set of commands to push on to the command stack if
- a change needs to be made. This allows the playbook designer
- the opportunity to perform configuration commands prior to pushing
- any changes without affecting how the set of commands are matched
- against the system.
- type: list
- after:
- description:
- - The ordered set of commands to append to the end of the command
- stack if a change needs to be made. Just like with I(before) this
- allows the playbook designer to append a set of commands to be
- executed after the command set.
- type: list
- match:
- description:
- - Instructs the module on the way to perform the matching of
- the set of commands against the current device config. If
- match is set to I(line), commands are matched line by line. If
- match is set to I(strict), command lines are matched with respect
- to position. If match is set to I(exact), command lines
- must be an equal match. Finally, if match is set to I(none), the
- module will not attempt to compare the source configuration with
- the running configuration on the remote device.
- type: str
- choices: ['line', 'strict', 'exact', 'none']
- default: line
- replace:
- description:
- - Instructs the module on the way to perform the configuration
- on the device. If the replace argument is set to I(line) then
- the modified lines are pushed to the device in configuration
- mode. If the replace argument is set to I(block) then the entire
- command block is pushed to the device in configuration mode if any
- line is not correct.
- type: str
- default: line
- choices: ['line', 'block']
- multiline_delimiter:
- description:
- - This argument is used when pushing a multiline configuration
- element to the ICX device. It specifies the character to use
- as the delimiting character. This only applies to the
- configuration action.
- type: str
- default: "@"
- backup:
- description:
- - This argument will cause the module to create a full backup of
- the current C(running-config) from the remote device before any
- changes are made. The backup file is written to the C(backup)
- folder in the playbook root directory or role root directory, if
- playbook is part of an ansible role. If the directory does not exist,
- it is created.
- type: bool
- default: 'no'
- defaults:
- description:
- - This argument specifies whether or not to collect all defaults
- when getting the remote device running config. When enabled,
- the module will get the current config by issuing the command
- C(show running-config all).
- type: bool
- default: 'no'
- running_config:
- description:
- - The module, by default, will connect to the remote device and
- retrieve the current running-config to use as a base for comparing
- against the contents of source. There are times when it is not
- desirable to have the task get the current running-config for
- every task in a playbook. The I(running_config) argument allows the
- implementer to pass in the configuration to use as the base
- config for comparison.
- type: str
- aliases: ['config']
- save_when:
- description:
- - When changes are made to the device running-configuration, the
- changes are not copied to non-volatile storage by default. Using
- this argument will change that before. If the argument is set to
- I(always), then the running-config will always be copied to the
- start-up configuration and the I(modified) flag will always be set to
- True. If the argument is set to I(modified), then the running-config
- will only be copied to the start-up configuration if it has changed since
- the last save to configuration. If the argument is set to
- I(never), the running-config will never be copied to the
- configuration. If the argument is set to I(changed), then the running-config
- will only be copied to the configuration if the task has made a change.
- type: str
- default: never
- choices: ['always', 'never', 'modified', 'changed']
- diff_against:
- description:
- - When using the C(ansible-playbook --diff) command line argument
- the module can generate diffs against different sources.
- - When this option is configure as I(startup), the module will return
- the diff of the running-config against the configuration.
- - When this option is configured as I(intended), the module will
- return the diff of the running-config against the configuration
- provided in the C(intended_config) argument.
- - When this option is configured as I(running), the module will
- return the before and after diff of the running-config with respect
- to any changes made to the device configuration.
- type: str
- choices: ['running', 'startup', 'intended']
- diff_ignore_lines:
- description:
- - Use this argument to specify one or more lines that should be
- ignored during the diff. This is used for lines in the configuration
- that are automatically updated by the system. This argument takes
- a list of regular expressions or exact line matches.
- type: list
- intended_config:
- description:
- - The C(intended_config) provides the master configuration that
- the node should conform to and is used to check the final
- running-config against. This argument will not modify any settings
- on the remote device and is strictly used to check the compliance
- of the current device's configuration against. When specifying this
- argument, the task should also modify the C(diff_against) value and
- set it to I(intended).
- type: str
-'''
-
-EXAMPLES = """
-- name: configure top level configuration
- icx_config:
- lines: hostname {{ inventory_hostname }}
-
-- name: configure interface settings
- icx_config:
- lines:
- - port-name test string
- - ip address 172.31.1.1 255.255.255.0
- parents: interface ethernet 1/1/2
-
-- name: configure ip helpers on multiple interfaces
- icx_config:
- lines:
- - ip helper-address 172.26.1.10
- - ip helper-address 172.26.3.8
- parents: "{{ item }}"
- with_items:
- - interface ethernet 1/1/2
- - interface ethernet 1/1/3
-
-- name: load new acl into device
- icx_config:
- lines:
- - permit ip host 192.0.2.1 any log
- - permit ip host 192.0.2.2 any log
- - permit ip host 192.0.2.3 any log
- - permit ip host 192.0.2.4 any log
- parents: ip access-list extended test
- before: no ip access-list extended test
- match: exact
-
-- name: check the running-config against master config
- icx_config:
- diff_against: intended
- intended_config: "{{ lookup('file', 'master.cfg') }}"
-
-- name: check the configuration against the running-config
- icx_config:
- diff_against: startup
- diff_ignore_lines:
- - ntp clock .*
-
-- name: for idempotency, use full-form commands
- icx_config:
- lines:
- # - en
- - enable
- # parents: int eth1/0/11
- parents: interface ethernet 1/1/2
-
-# Set boot image based on comparison to a group_var (version) and the version
-# that is returned from the `icx_facts` module
-- name: SETTING BOOT IMAGE
- icx_config:
- lines:
- - no boot system
- - boot system flash bootflash:{{new_image}}
- host: "{{ inventory_hostname }}"
- when: ansible_net_version != version
-
-- name: render template onto an ICX device
- icx_config:
- backup: yes
- src: "{{ lookup('file', 'config.j2') }}"
-"""
-
-RETURN = """
-updates:
- description: The set of commands that will be pushed to the remote device
- returned: always
- type: list
- sample: ['hostname foo', 'router ospf 1', 'router-id 192.0.2.1']
-commands:
- description: The set of commands that will be pushed to the remote device
- returned: always
- type: list
- sample: ['hostname foo', 'router ospf 1', 'router-id 192.0.2.1']
-backup_path:
- description: The full path to the backup file
- returned: when backup is yes
- type: str
- sample: /playbooks/ansible/backup/icx_config.2016-07-16@22:28:34
-"""
-
-import json
-from ansible.module_utils._text import to_text
-from ansible.module_utils.connection import ConnectionError
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import run_commands, get_config
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import get_defaults_flag, get_connection
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import check_args as icx_check_args
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, dumps
-
-
-def check_args(module, warnings):
- icx_check_args(module, warnings)
- if module.params['multiline_delimiter']:
- if len(module.params['multiline_delimiter']) != 1:
- module.fail_json(msg='multiline_delimiter value can only be a '
- 'single character')
-
-
-def edit_config_or_macro(connection, commands):
- if "macro name" in commands[0]:
- connection.edit_macro(candidate=commands)
- else:
- if commands[0] != '':
- connection.edit_config(candidate=commands)
-
-
-def get_candidate_config(module):
- candidate = ''
- if module.params['src']:
- candidate = module.params['src']
-
- elif module.params['lines']:
- candidate_obj = NetworkConfig(indent=1)
- parents = module.params['parents'] or list()
- candidate_obj.add(module.params['lines'], parents=parents)
- candidate = dumps(candidate_obj, 'raw')
-
- return candidate
-
-
-def get_running_config(module, current_config=None, flags=None):
- running = module.params['running_config']
- if not running:
- if not module.params['defaults'] and current_config:
- running = current_config
- else:
- running = get_config(module, flags=flags)
-
- return running
-
-
-def save_config(module, result):
- result['changed'] = True
- if not module.check_mode:
- run_commands(module, 'write memory')
- else:
- module.warn('Skipping command `copy running-config start-up configuration` '
- 'due to check_mode. Configuration not copied to '
- 'non-volatile storage')
-
-
-def main():
- """ main entry point for module execution
- """
- argument_spec = dict(
- src=dict(),
- lines=dict(aliases=['commands'], type='list'),
- parents=dict(type='list'),
-
- before=dict(type='list'),
- after=dict(type='list'),
-
- match=dict(default='line', choices=['line', 'strict', 'exact', 'none']),
- replace=dict(default='line', choices=['line', 'block']),
- multiline_delimiter=dict(default='@'),
-
- running_config=dict(aliases=['config']),
- intended_config=dict(),
-
- defaults=dict(type='bool', default=False),
- backup=dict(type='bool', default=False),
-
- save_when=dict(choices=['always', 'never', 'modified', 'changed'], default='never'),
-
- diff_against=dict(choices=['startup', 'intended', 'running']),
- diff_ignore_lines=dict(type='list'),
-
- )
-
- mutually_exclusive = [('lines', 'src'),
- ('parents', 'src')]
-
- required_if = [('match', 'strict', ['lines']),
- ('match', 'exact', ['lines']),
- ('replace', 'block', ['lines']),
- ('diff_against', 'intended', ['intended_config'])]
-
- module = AnsibleModule(argument_spec=argument_spec,
- mutually_exclusive=mutually_exclusive,
- required_if=required_if,
- supports_check_mode=True)
-
- result = {'changed': False}
-
- warnings = list()
- check_args(module, warnings)
- result['warnings'] = warnings
- run_commands(module, 'skip')
- diff_ignore_lines = module.params['diff_ignore_lines']
- config = None
- contents = None
- flags = None if module.params['defaults'] else []
- connection = get_connection(module)
-
- if module.params['backup'] or (module._diff and module.params['diff_against'] == 'running'):
- contents = get_config(module, flags=flags)
- config = NetworkConfig(indent=1, contents=contents)
- if module.params['backup']:
- result['__backup__'] = contents
-
- if any((module.params['lines'], module.params['src'])):
- match = module.params['match']
- replace = module.params['replace']
- path = module.params['parents']
-
- candidate = get_candidate_config(module)
- running = get_running_config(module, contents, flags=flags)
- try:
- response = connection.get_diff(candidate=candidate, running=running, diff_match=match, diff_ignore_lines=diff_ignore_lines, path=path,
- diff_replace=replace)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
-
- config_diff = response['config_diff']
- banner_diff = response['banner_diff']
-
- if config_diff or banner_diff:
- commands = config_diff.split('\n')
-
- if module.params['before']:
- commands[:0] = module.params['before']
-
- if module.params['after']:
- commands.extend(module.params['after'])
-
- result['commands'] = commands
- result['updates'] = commands
- result['banners'] = banner_diff
-
- # send the configuration commands to the device and merge
- # them with the current running config
- if not module.check_mode:
- if commands:
- edit_config_or_macro(connection, commands)
- if banner_diff:
- connection.edit_banner(candidate=json.dumps(banner_diff), multiline_delimiter=module.params['multiline_delimiter'])
-
- result['changed'] = True
-
- running_config = module.params['running_config']
- startup_config = None
-
- if module.params['save_when'] == 'always':
- save_config(module, result)
- elif module.params['save_when'] == 'modified':
- output = run_commands(module, ['show running-config', 'show configuration'])
-
- running_config = NetworkConfig(indent=1, contents=output[0], ignore_lines=diff_ignore_lines)
- startup_config = NetworkConfig(indent=1, contents=output[1], ignore_lines=diff_ignore_lines)
-
- if running_config.sha1 != startup_config.sha1:
- save_config(module, result)
- elif module.params['save_when'] == 'changed' and result['changed']:
- save_config(module, result)
-
- if module._diff:
- if not running_config:
- output = run_commands(module, 'show running-config')
- contents = output[0]
- else:
- contents = running_config
-
- # recreate the object in order to process diff_ignore_lines
- running_config = NetworkConfig(indent=1, contents=contents, ignore_lines=diff_ignore_lines)
-
- if module.params['diff_against'] == 'running':
- if module.check_mode:
- module.warn("unable to perform diff against running-config due to check mode")
- contents = None
- else:
- contents = config.config_text
-
- elif module.params['diff_against'] == 'startup':
- if not startup_config:
- output = run_commands(module, 'show configuration')
- contents = output[0]
- else:
- contents = startup_config.config_text
-
- elif module.params['diff_against'] == 'intended':
- contents = module.params['intended_config']
-
- if contents is not None:
- base_config = NetworkConfig(indent=1, contents=contents, ignore_lines=diff_ignore_lines)
-
- if running_config.sha1 != base_config.sha1:
- if module.params['diff_against'] == 'intended':
- before = running_config
- after = base_config
- elif module.params['diff_against'] in ('startup', 'running'):
- before = base_config
- after = running_config
-
- result.update({
- 'changed': True,
- 'diff': {'before': str(before), 'after': str(after)}
- })
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/icx/icx_copy.py b/plugins/modules/network/icx/icx_copy.py
deleted file mode 100644
index 2512870b04..0000000000
--- a/plugins/modules/network/icx/icx_copy.py
+++ /dev/null
@@ -1,372 +0,0 @@
-#!/usr/bin/python
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: icx_copy
-author: "Ruckus Wireless (@Commscope)"
-short_description: Transfer files from or to remote Ruckus ICX 7000 series switches
-description:
- - This module transfers files from or to remote devices running ICX.
-notes:
- - Tested against ICX 10.1.
- - For information on using ICX platform, see L(the ICX OS Platform Options guide,../network/user_guide/platform_icx.html).
-options:
- upload:
- description:
- - Name of the resource to be uploaded. Mutually exclusive with download.
- type: str
- choices: ['running-config', 'startup-config', 'flash_primary', 'flash_secondary']
- download:
- description:
- - Name of the resource to be downloaded. Mutually exclusive with upload.
- type: str
- choices: ['running-config', 'startup-config', 'flash_primary', 'flash_secondary', 'bootrom', 'fips-primary-sig', 'fips-secondary-sig', 'fips-bootrom-sig']
- protocol:
- description:
- - Data transfer protocol to be used
- type: str
- choices: ['scp', 'https']
- required: true
- remote_server:
- description:
- - IP address of the remote server
- type: str
- required: true
- remote_port:
- description:
- - The port number of the remote host. Default values will be selected based on protocol type.
- Default scp:22, http:443
- type: str
- remote_filename:
- description:
- - The name or path of the remote file/resource to be uploaded or downloaded.
- type: str
- required: true
- remote_user:
- description:
- - remote username to be used for scp login.
- type: str
- remote_pass:
- description:
- - remote password to be used for scp login.
- type: str
- public_key:
- description:
- - public key type to be used to login to scp server
- type: str
- choices: ['rsa', 'dsa']
-
-'''
-
-EXAMPLES = """
-- name: upload running-config to the remote scp server
- icx_copy:
- upload: running-config
- protocol: scp
- remote_server: 172.16.10.49
- remote_filename: running.conf
- remote_user: user1
- remote_pass: pass123
-
-- name: download running-config from the remote scp server
- icx_copy:
- download: running-config
- protocol: scp
- remote_server: 172.16.10.49
- remote_filename: running.conf
- remote_user: user1
- remote_pass: pass123
-
-- name: download running-config from the remote scp server using rsa public key
- icx_copy:
- download: running-config
- protocol: scp
- remote_server: 172.16.10.49
- remote_filename: running.conf
- remote_user: user1
- remote_pass: pass123
- public_key: rsa
-
-- name: upload startup-config to the remote https server
- icx_copy:
- upload: startup-config
- protocol: https
- remote_server: 172.16.10.49
- remote_filename: config/running.conf
- remote_user: user1
- remote_pass: pass123
-
-- name: upload startup-config to the remote https server
- icx_copy:
- upload: startup-config
- protocol: https
- remote_server: 172.16.10.49
- remote_filename: config/running.conf
- remote_user: user1
- remote_pass: pass123
-
-- name: Download OS image into the flash from remote scp ipv6 server
- icx_copy:
- download: startup-config
- protocol: scp
- remote_server: ipv6 FE80:CD00:0000:0CDE:1257:0000:211E:729C
- remote_filename: img.bin
- remote_user: user1
- remote_pass: pass123
-
-- name: Download OS image into the secondary flash from remote scp ipv6 server
- icx_copy:
- Download: flash_secondary
- protocol: scp
- remote_server: ipv6 FE80:CD00:0000:0CDE:1257:0000:211E:729C
- remote_filename: img.bin
- remote_user: user1
- remote_pass: pass123
-
-- name: Download OS image into the secondary flash from remote scp ipv6 server on port 5000
- icx_copy:
- Download: flash_secondary
- protocol: scp
- remote_server: ipv6 FE80:CD00:0000:0CDE:1257:0000:211E:729C
- remote_port: 5000
- remote_filename: img.bin
- remote_user: user1
- remote_pass: pass123
-
-- name: Download OS image into the primary flash from remote https ipv6 server
- icx_copy:
- Download: flash_primary
- protocol: https
- remote_server: ipv6 FE80:CD00:0000:0CDE:1257:0000:211E:729C
- remote_filename: images/img.bin
- remote_user: user1
- remote_pass: pass123
-
-- name: Download OS image into the primary flash from remote https ipv6 server on port 8080
- icx_copy:
- Download: flash_primary
- protocol: https
- remote_server: ipv6 FE80:CD00:0000:0CDE:1257:0000:211E:729C
- remote_port: 8080
- remote_filename: images/img.bin
- remote_user: user1
- remote_pass: pass123
-"""
-
-RETURN = """
-changed:
- description: true when downloaded any configuration or flash. false otherwise.
- returned: always
- type: bool
-"""
-
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import ConnectionError, exec_command
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import exec_scp, run_commands
-
-
-def map_params_to_obj(module):
- command = dict()
-
- if(module.params['protocol'] == 'scp'):
- if(module.params['upload'] is not None):
- module.params["upload"] = module.params["upload"].replace("flash_primary", "primary")
- module.params["upload"] = module.params["upload"].replace("flash_secondary", "secondary")
- if(module.params["upload"] == 'running-config' or module.params["upload"] == 'startup-config'):
- command["command"] = "copy %s scp %s%s %s%s" % (module.params['upload'],
- module.params["remote_server"],
- " " + module.params["remote_port"] if module.params["remote_port"] else "",
- module.params["remote_filename"],
- "public-key " + module.params["public_key"] if module.params["public_key"] else "")
- else:
- command["command"] = "copy flash scp %s%s %s%s %s" % (module.params["remote_server"],
- " " + module.params["remote_port"] if module.params["remote_port"] else "",
- module.params["remote_filename"],
- "public-key " + module.params["public_key"] if module.params["public_key"] else "",
- module.params["upload"])
- command["scp_user"] = module.params["remote_user"]
- command["scp_pass"] = module.params["remote_pass"]
- if(module.params['download'] is not None):
- module.params["download"] = module.params["download"].replace("flash_primary", "primary")
- module.params["download"] = module.params["download"].replace("flash_secondary", "secondary")
- if(module.params["download"] == 'running-config' or module.params["download"] == 'startup-config'):
- command["command"] = "copy scp %s %s%s %s%s" % (module.params['download'],
- module.params["remote_server"],
- " " + module.params["remote_port"] if module.params["remote_port"] else "",
- module.params["remote_filename"],
- "public-key " + module.params["public_key"] if module.params["public_key"] else "")
- else:
- command["command"] = "copy scp flash %s%s %s%s %s" % (module.params["remote_server"],
- " " + module.params["remote_port"] if module.params["remote_port"] else "",
- module.params["remote_filename"],
- "public-key " + module.params["public_key"] if module.params["public_key"] else "",
- module.params["download"])
- command["scp_user"] = module.params["remote_user"]
- command["scp_pass"] = module.params["remote_pass"]
- if(module.params['protocol'] == 'https'):
- if(module.params['upload'] is not None):
- module.params["upload"] = module.params["upload"].replace("flash_primary", "primary")
- module.params["upload"] = module.params["upload"].replace("flash_secondary", "secondary")
- if(module.params["upload"] == 'running-config' or module.params["upload"] == 'startup-config'):
- command["command"] = "copy %s https %s %s%s" % (module.params['upload'],
- module.params["remote_server"],
- module.params["remote_filename"],
- " port " + module.params["remote_port"] if module.params["remote_port"] else "")
- else:
- command["command"] = "copy https flash %s %s %s%s" % (module.params["remote_server"],
- module.params["remote_filename"],
- module.params['upload'],
- " port " + module.params["remote_port"] if module.params["remote_port"] else "")
- if(module.params['download'] is not None):
- module.params["download"] = module.params["download"].replace("flash_primary", "primary")
- module.params["download"] = module.params["download"].replace("flash_secondary", "secondary")
- if(module.params["download"] == 'running-config' or module.params["download"] == 'startup-config'):
- command["command"] = "copy https %s %s %s%s" % (module.params['download'],
- module.params["remote_server"],
- module.params["remote_filename"],
- " port " + module.params["remote_port"] if module.params["remote_port"] else "")
- else:
- command["command"] = "copy https flash %s %s %s%s" % (module.params["remote_server"],
- module.params["remote_filename"],
- module.params['download'],
- " port " + module.params["remote_port"] if module.params["remote_port"] else "")
- return command
-
-
-def checkValidations(module):
- validation = dict(
- scp=dict(
- upload=[
- 'running-config',
- 'startup-config',
- 'flash_primary',
- 'flash_secondary'],
- download=[
- 'running-config',
- 'startup-config',
- 'flash_primary',
- 'flash_secondary',
- 'bootrom',
- 'fips-primary-sig',
- 'fips-secondary-sig',
- 'fips-bootrom-sig']),
- https=dict(
- upload=[
- 'running-config',
- 'startup-config'],
- download=[
- 'flash_primary',
- 'flash_secondary',
- 'startup-config']))
- protocol = module.params['protocol']
- upload = module.params['upload']
- download = module.params['download']
-
- if(protocol == 'scp' and module.params['remote_user'] is None):
- module.fail_json(msg="While using scp remote_user argument is required")
- if(upload is None and download is None):
- module.fail_json(msg="Upload or download params are required.")
- if(upload is not None and download is not None):
- module.fail_json(msg="Only upload or download can be used at a time.")
- if(upload):
- if(not (upload in validation.get(protocol).get("upload"))):
- module.fail_json(msg="Specified resource '" + upload + "' can't be uploaded to '" + protocol + "'")
- if(download):
- if(not (download in validation.get(protocol).get("download"))):
- module.fail_json(msg="Specified resource '" + download + "' can't be downloaded from '" + protocol + "'")
-
-
-def main():
- """entry point for module execution
- """
- argument_spec = dict(
- upload=dict(
- type='str',
- required=False,
- choices=[
- 'running-config',
- 'flash_primary',
- 'flash_secondary',
- 'startup-config']),
- download=dict(
- type='str',
- required=False,
- choices=[
- 'running-config',
- 'startup-config',
- 'flash_primary',
- 'flash_secondary',
- 'bootrom',
- 'fips-primary-sig',
- 'fips-secondary-sig',
- 'fips-bootrom-sig']),
- protocol=dict(
- type='str',
- required=True,
- choices=[
- 'https',
- 'scp']),
- remote_server=dict(
- type='str',
- required=True),
- remote_port=dict(
- type='str',
- required=False),
- remote_filename=dict(
- type='str',
- required=True),
- remote_user=dict(
- type='str',
- required=False),
- remote_pass=dict(
- type='str',
- required=False,
- no_log=True),
- public_key=dict(
- type='str',
- required=False,
- choices=[
- 'rsa',
- 'dsa']))
- mutually_exclusive = [['upload', 'download']]
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, mutually_exclusive=mutually_exclusive)
-
- checkValidations(module)
- warnings = list()
- result = {'changed': False, 'warnings': warnings}
- exec_command(module, 'skip')
-
- response = ''
- try:
- command = map_params_to_obj(module)
- result['commands'] = [command["command"]]
-
- if(module.params['protocol'] == 'scp'):
- response = exec_scp(module, command)
- else:
- response = run_commands(module, command)
- if('Response Code: 404' in response):
- module.fail_json(msg=response)
- else:
- result['response'] = "in progress..."
- if(module.params["download"] is not None):
- result['changed'] = True
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/icx/icx_facts.py b/plugins/modules/network/icx/icx_facts.py
deleted file mode 100644
index af45d0d14c..0000000000
--- a/plugins/modules/network/icx/icx_facts.py
+++ /dev/null
@@ -1,548 +0,0 @@
-#!/usr/bin/python
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: icx_facts
-author: "Ruckus Wireless (@Commscope)"
-short_description: Collect facts from remote Ruckus ICX 7000 series switches
-description:
- - Collects a base set of device facts from a remote device that
- is running ICX. This module prepends all of the
- base network fact keys with C(ansible_net_). The facts
- module will always collect a base set of facts from the device
- and can enable or disable collection of additional facts.
-notes:
- - Tested against ICX 10.1.
- - For information on using ICX platform, see L(the ICX OS Platform Options guide,../network/user_guide/platform_icx.html).
-options:
- gather_subset:
- description:
- - When supplied, this argument will restrict the facts collected
- to a given subset. Possible values for this argument include
- all, hardware, config, and interfaces. Can specify a list of
- values to include a larger subset. Values can also be used
- with an initial C(M(!)) to specify that a specific subset should
- not be collected.
- required: false
- type: list
- default: '!config'
-'''
-
-EXAMPLES = """
-# Collect all facts from the device
-- icx_facts:
- gather_subset: all
-
-# Collect only the config and default facts
-- icx_facts:
- gather_subset:
- - config
-
-# Do not collect hardware facts
-- icx_facts:
- gather_subset:
- - "!hardware"
-"""
-
-RETURN = """
-ansible_net_gather_subset:
- description: The list of fact subsets collected from the device
- returned: always
- type: list
-
-# default
-ansible_net_model:
- description: The model name returned from the device
- returned: always
- type: str
-ansible_net_serialnum:
- description: The serial number of the remote device
- returned: always
- type: str
-ansible_net_version:
- description: The operating system version running on the remote device
- returned: always
- type: str
-ansible_net_hostname:
- description: The configured hostname of the device
- returned: always
- type: str
-ansible_net_image:
- description: The image file the device is running
- returned: always
- type: str
-ansible_net_stacked_models:
- description: The model names of each device in the stack
- returned: when multiple devices are configured in a stack
- type: list
-ansible_net_stacked_serialnums:
- description: The serial numbers of each device in the stack
- returned: when multiple devices are configured in a stack
- type: list
-
-# hardware
-ansible_net_filesystems:
- description: All file system names available on the device
- returned: when hardware is configured
- type: list
-ansible_net_filesystems_info:
- description: A hash of all file systems containing info about each file system (e.g. free and total space)
- returned: when hardware is configured
- type: dict
-ansible_net_memfree_mb:
- description: The available free memory on the remote device in Mb
- returned: when hardware is configured
- type: int
-ansible_net_memtotal_mb:
- description: The total memory on the remote device in Mb
- returned: when hardware is configured
- type: int
-
-# config
-ansible_net_config:
- description: The current active config from the device
- returned: when config is configured
- type: str
-
-# interfaces
-ansible_net_all_ipv4_addresses:
- description: All IPv4 addresses configured on the device
- returned: when interfaces is configured
- type: list
-ansible_net_all_ipv6_addresses:
- description: All IPv6 addresses configured on the device
- returned: when interfaces is configured
- type: list
-ansible_net_interfaces:
- description: A hash of all interfaces running on the system
- returned: when interfaces is configured
- type: dict
-ansible_net_neighbors:
- description: The list of LLDP neighbors from the remote device
- returned: when interfaces is configured
- type: dict
-"""
-
-
-import re
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import run_commands
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.six import iteritems
-from ansible.module_utils.six.moves import zip
-
-
-class FactsBase(object):
-
- COMMANDS = list()
-
- def __init__(self, module):
- self.module = module
- self.facts = dict()
- self.responses = None
-
- def populate(self):
- self.responses = run_commands(self.module, commands=self.COMMANDS, check_rc=False)
-
- def run(self, cmd):
- return run_commands(self.module, commands=cmd, check_rc=False)
-
-
-class Default(FactsBase):
-
- COMMANDS = ['show version', 'show running-config | include hostname']
-
- def populate(self):
- super(Default, self).run(['skip'])
- super(Default, self).populate()
- data = self.responses[0]
- if data:
- self.facts['version'] = self.parse_version(data)
- self.facts['serialnum'] = self.parse_serialnum(data)
- self.facts['model'] = self.parse_model(data)
- self.facts['image'] = self.parse_image(data)
- self.facts['hostname'] = self.parse_hostname(self.responses[1])
- self.parse_stacks(data)
-
- def parse_version(self, data):
- match = re.search(r'SW: Version ([0-9]+.[0-9]+.[0-9a-zA-Z]+)', data)
- if match:
- return match.group(1)
-
- def parse_hostname(self, data):
- match = re.search(r'^hostname (\S+)', data, re.M)
- if match:
- return match.group(1)
-
- def parse_model(self, data):
- match = re.search(r'HW: (\S+ \S+)', data, re.M)
- if match:
- return match.group(1)
-
- def parse_image(self, data):
- match = re.search(r'\([0-9]+ bytes\) from \S+ (\S+)', data)
- if match:
- return match.group(1)
-
- def parse_serialnum(self, data):
- match = re.search(r'Serial #:(\S+)', data)
- if match:
- return match.group(1)
-
- def parse_stacks(self, data):
- match = re.findall(r'UNIT [1-9]+: SL [1-9]+: (\S+)', data, re.M)
- if match:
- self.facts['stacked_models'] = match
-
- match = re.findall(r'^System [Ss]erial [Nn]umber\s+: (\S+)', data, re.M)
- if match:
- self.facts['stacked_serialnums'] = match
-
-
-class Hardware(FactsBase):
-
- COMMANDS = [
- 'show memory',
- 'show flash'
- ]
-
- def populate(self):
- super(Hardware, self).populate()
- data = self.responses[0]
- if data:
- self.facts['filesystems'] = self.parse_filesystems(data)
- self.facts['filesystems_info'] = self.parse_filesystems_info(self.responses[1])
-
- if data:
- if 'Invalid input detected' in data:
- warnings.append('Unable to gather memory statistics')
- else:
- match = re.search(r'Dynamic memory: ([0-9]+) bytes total, ([0-9]+) bytes free, ([0-9]+%) used', data)
- if match:
- self.facts['memtotal_mb'] = int(match.group(1)) / 1024
- self.facts['memfree_mb'] = int(match.group(2)) / 1024
-
- def parse_filesystems(self, data):
- return "flash"
-
- def parse_filesystems_info(self, data):
- facts = dict()
- fs = ''
- for line in data.split('\n'):
- match = re.match(r'^(Stack unit \S+):', line)
- if match:
- fs = match.group(1)
- facts[fs] = dict()
- continue
- match = re.match(r'\W+NAND Type: Micron NAND (\S+)', line)
- if match:
- facts[fs]['spacetotal'] = match.group(1)
- match = re.match(r'\W+Code Flash Free Space = (\S+)', line)
- if match:
- facts[fs]['spacefree'] = int(int(match.group(1)) / 1024)
- facts[fs]['spacefree'] = str(facts[fs]['spacefree']) + "Kb"
- return {"flash": facts}
-
-
-class Config(FactsBase):
-
- COMMANDS = ['skip', 'show running-config']
-
- def populate(self):
- super(Config, self).populate()
- data = self.responses[1]
- if data:
- self.facts['config'] = data
-
-
-class Interfaces(FactsBase):
-
- COMMANDS = [
- 'skip',
- 'show interfaces',
- 'show running-config',
- 'show lldp',
- 'show media'
- ]
-
- def populate(self):
- super(Interfaces, self).populate()
-
- self.facts['all_ipv4_addresses'] = list()
- self.facts['all_ipv6_addresses'] = list()
- data = self.responses[1]
- if data:
- interfaces = self.parse_interfaces(data)
- self.facts['interfaces'] = self.populate_interfaces(interfaces)
-
- data = self.responses[1]
- if data:
- data = self.parse_interfaces(data)
- self.populate_ipv4_interfaces(data)
-
- data = self.responses[2]
- if data:
- self.populate_ipv6_interfaces(data)
-
- data = self.responses[3]
- lldp_errs = ['Invalid input', 'LLDP is not enabled']
-
- if data and not any(err in data for err in lldp_errs):
- neighbors = self.run(['show lldp neighbors detail'])
- if neighbors:
- self.facts['neighbors'] = self.parse_neighbors(neighbors[0])
-
- data = self.responses[4]
- self.populate_mediatype(data)
-
- interfaceList = {}
- for iface in self.facts['interfaces']:
- if 'type' in self.facts['interfaces'][iface]:
- newName = self.facts['interfaces'][iface]['type'] + iface
- else:
- newName = iface
- interfaceList[newName] = self.facts['interfaces'][iface]
- self.facts['interfaces'] = interfaceList
-
- def populate_mediatype(self, data):
- lines = data.split("\n")
- for line in lines:
- match = re.match(r'Port (\S+):\W+Type\W+:\W+(.*)', line)
- if match:
- self.facts['interfaces'][match.group(1)]["mediatype"] = match.group(2)
-
- def populate_interfaces(self, interfaces):
- facts = dict()
- for key, value in iteritems(interfaces):
- intf = dict()
- intf['description'] = self.parse_description(value)
- intf['macaddress'] = self.parse_macaddress(value)
- intf['mtu'] = self.parse_mtu(value)
- intf['bandwidth'] = self.parse_bandwidth(value)
- intf['duplex'] = self.parse_duplex(value)
- intf['lineprotocol'] = self.parse_lineprotocol(value)
- intf['operstatus'] = self.parse_operstatus(value)
- intf['type'] = self.parse_type(value)
- facts[key] = intf
- return facts
-
- def populate_ipv4_interfaces(self, data):
- for key, value in data.items():
- self.facts['interfaces'][key]['ipv4'] = dict()
- primary_address = addresses = []
- primary_address = re.findall(r'Internet address is (\S+/\S+), .*$', value, re.M)
- addresses = re.findall(r'Secondary address (.+)$', value, re.M)
- if len(primary_address) == 0:
- continue
- addresses.append(primary_address[0])
- for address in addresses:
- addr, subnet = address.split("/")
- ipv4 = dict(address=addr.strip(), subnet=subnet.strip())
- self.add_ip_address(addr.strip(), 'ipv4')
- self.facts['interfaces'][key]['ipv4'] = ipv4
-
- def populate_ipv6_interfaces(self, data):
- parts = data.split("\n")
- for line in parts:
- match = re.match(r'\W*interface \S+ (\S+)', line)
- if match:
- key = match.group(1)
- try:
- self.facts['interfaces'][key]['ipv6'] = list()
- except KeyError:
- self.facts['interfaces'][key] = dict()
- self.facts['interfaces'][key]['ipv6'] = list()
- self.facts['interfaces'][key]['ipv6'] = {}
- continue
- match = re.match(r'\W+ipv6 address (\S+)/(\S+)', line)
- if match:
- self.add_ip_address(match.group(1), "ipv6")
- self.facts['interfaces'][key]['ipv6']["address"] = match.group(1)
- self.facts['interfaces'][key]['ipv6']["subnet"] = match.group(2)
-
- def add_ip_address(self, address, family):
- if family == 'ipv4':
- self.facts['all_ipv4_addresses'].append(address)
- else:
- self.facts['all_ipv6_addresses'].append(address)
-
- def parse_neighbors(self, neighbors):
- facts = dict()
- for entry in neighbors.split('------------------------------------------------'):
- if entry == '':
- continue
- intf = self.parse_lldp_intf(entry)
- if intf not in facts:
- facts[intf] = list()
- fact = dict()
- fact['host'] = self.parse_lldp_host(entry)
- fact['port'] = self.parse_lldp_port(entry)
- facts[intf].append(fact)
- return facts
-
- def parse_interfaces(self, data):
- parsed = dict()
- key = ''
- for line in data.split('\n'):
- if len(line) == 0:
- continue
- elif line[0] == ' ':
- parsed[key] += '\n%s' % line
- else:
- match = re.match(r'\S+Ethernet(\S+)', line)
- if match:
- key = match.group(1)
- parsed[key] = line
- return parsed
-
- def parse_description(self, data):
- match = re.search(r'Port name is ([ \S]+)', data, re.M)
- if match:
- return match.group(1)
-
- def parse_macaddress(self, data):
- match = re.search(r'Hardware is \S+, address is (\S+)', data)
- if match:
- return match.group(1)
-
- def parse_ipv4(self, data):
- match = re.search(r'Internet address is (\S+)', data)
- if match:
- addr, masklen = match.group(1).split('/')
- return dict(address=addr, masklen=int(masklen))
-
- def parse_mtu(self, data):
- match = re.search(r'MTU (\d+)', data)
- if match:
- return int(match.group(1))
-
- def parse_bandwidth(self, data):
- match = re.search(r'Configured speed (\S+), actual (\S+)', data)
- if match:
- return match.group(1)
-
- def parse_duplex(self, data):
- match = re.search(r'configured duplex (\S+), actual (\S+)', data, re.M)
- if match:
- return match.group(2)
-
- def parse_mediatype(self, data):
- match = re.search(r'media type is (.+)$', data, re.M)
- if match:
- return match.group(1)
-
- def parse_type(self, data):
- match = re.search(r'Hardware is (.+),', data, re.M)
- if match:
- return match.group(1)
-
- def parse_lineprotocol(self, data):
- match = re.search(r'line protocol is (.+)$', data, re.M)
- if match:
- return match.group(1)
-
- def parse_operstatus(self, data):
- match = re.search(r'^(?:.+) is (.+),', data, re.M)
- if match:
- return match.group(1)
-
- def parse_lldp_intf(self, data):
- match = re.search(r'^Local Intf: (.+)$', data, re.M)
- if match:
- return match.group(1)
-
- def parse_lldp_host(self, data):
- match = re.search(r'System Name: (.+)$', data, re.M)
- if match:
- return match.group(1)
-
- def parse_lldp_port(self, data):
- match = re.search(r'Port id: (.+)$', data, re.M)
- if match:
- return match.group(1)
-
-
-FACT_SUBSETS = dict(
- default=Default,
- hardware=Hardware,
- interfaces=Interfaces,
- config=Config,
-)
-
-VALID_SUBSETS = frozenset(FACT_SUBSETS.keys())
-
-warnings = list()
-
-
-def main():
- """main entry point for module execution
- """
- argument_spec = dict(
- gather_subset=dict(default=['!config'], type='list')
- )
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- gather_subset = module.params['gather_subset']
-
- runable_subsets = set()
- exclude_subsets = set()
-
- for subset in gather_subset:
- if subset == 'all':
- runable_subsets.update(VALID_SUBSETS)
- continue
-
- if subset.startswith('!'):
- subset = subset[1:]
- if subset == 'all':
- exclude_subsets.update(VALID_SUBSETS)
- continue
- exclude = True
- else:
- exclude = False
-
- if subset not in VALID_SUBSETS:
- module.fail_json(msg='Bad subset')
-
- if exclude:
- exclude_subsets.add(subset)
- else:
- runable_subsets.add(subset)
-
- if not runable_subsets:
- runable_subsets.update(VALID_SUBSETS)
-
- runable_subsets.difference_update(exclude_subsets)
- runable_subsets.add('default')
-
- facts = dict()
- facts['gather_subset'] = list(runable_subsets)
-
- instances = list()
- for key in runable_subsets:
- instances.append(FACT_SUBSETS[key](module))
-
- for inst in instances:
- inst.populate()
- facts.update(inst.facts)
-
- ansible_facts = dict()
- for key, value in iteritems(facts):
- key = 'ansible_net_%s' % key
- ansible_facts[key] = value
-
- module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/icx/icx_interface.py b/plugins/modules/network/icx/icx_interface.py
deleted file mode 100644
index 1dbce9dde3..0000000000
--- a/plugins/modules/network/icx/icx_interface.py
+++ /dev/null
@@ -1,693 +0,0 @@
-#!/usr/bin/python
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: icx_interface
-author: "Ruckus Wireless (@Commscope)"
-short_description: Manage Interface on Ruckus ICX 7000 series switches
-description:
- - This module provides declarative management of Interfaces
- on ruckus icx devices.
-notes:
- - Tested against ICX 10.1.
- - For information on using ICX platform, see L(the ICX OS Platform Options guide,../network/user_guide/platform_icx.html).
-options:
- name:
- description:
- - Name of the Interface.
- type: str
- description:
- description:
- - Name of the description.
- type: str
- enabled:
- description:
- - Interface link status
- default: yes
- type: bool
- speed:
- description:
- - Interface link speed/duplex
- choices: ['10-full', '10-half', '100-full', '100-half', '1000-full', '1000-full-master',
- '1000-full-slave', '10g-full', '10g-full-master', '10g-full-slave', '2500-full', '2500-full-master',
- '2500-full-slave', '5g-full', '5g-full-master', '5g-full-slave', 'auto']
- type: str
- stp:
- description:
- - enable/disable stp for the interface
- type: bool
- tx_rate:
- description:
- - Transmit rate in bits per second (bps).
- - This is state check parameter only.
- - Supports conditionals, see L(Conditionals in Networking Modules,../network/user_guide/network_working_with_command_output.html)
- type: str
- rx_rate:
- description:
- - Receiver rate in bits per second (bps).
- - This is state check parameter only.
- - Supports conditionals, see L(Conditionals in Networking Modules,../network/user_guide/network_working_with_command_output.html)
- type: str
- neighbors:
- description:
- - Check the operational state of given interface C(name) for CDP/LLDP neighbor.
- - The following suboptions are available.
- type: list
- suboptions:
- host:
- description:
- - "CDP/LLDP neighbor host for given interface C(name)."
- type: str
- port:
- description:
- - "CDP/LLDP neighbor port to which given interface C(name) is connected."
- type: str
- delay:
- description:
- - Time in seconds to wait before checking for the operational state on remote
- device. This wait is applicable for operational state argument which are
- I(state) with values C(up)/C(down), I(tx_rate) and I(rx_rate).
- type: int
- default: 10
- state:
- description:
- - State of the Interface configuration, C(up) means present and
- operationally up and C(down) means present and operationally C(down)
- default: present
- type: str
- choices: ['present', 'absent', 'up', 'down']
- power:
- description:
- - Inline power on Power over Ethernet (PoE) ports.
- type: dict
- suboptions:
- by_class:
- description:
- - "The range is 0-4"
- - "The power limit based on class value for given interface C(name)"
- choices: ['0', '1', '2', '3', '4']
- type: str
- limit:
- description:
- - "The range is 1000-15400|30000mW. For PoH ports the range is 1000-95000mW"
- - "The power limit based on actual power value for given interface C(name)"
- type: str
- priority:
- description:
- - "The range is 1 (highest) to 3 (lowest)"
- - "The priority for power management or given interface C(name)"
- choices: ['1', '2', '3']
- type: str
- enabled:
- description:
- - "enable/disable the poe of the given interface C(name)"
- default: no
- type: bool
- aggregate:
- description:
- - List of Interfaces definitions.
- type: list
- suboptions:
- name:
- description:
- - Name of the Interface.
- type: str
- description:
- description:
- - Name of the description.
- type: str
- enabled:
- description:
- - Interface link status
- type: bool
- speed:
- description:
- - Interface link speed/duplex
- choices: ['10-full', '10-half', '100-full', '100-half', '1000-full', '1000-full-master',
- '1000-full-slave', '10g-full', '10g-full-master', '10g-full-slave', '2500-full', '2500-full-master',
- '2500-full-slave', '5g-full', '5g-full-master', '5g-full-slave', 'auto']
- type: str
- stp:
- description:
- - enable/disable stp for the interface
- type: bool
- tx_rate:
- description:
- - Transmit rate in bits per second (bps).
- - This is state check parameter only.
- - Supports conditionals, see L(Conditionals in Networking Modules,../network/user_guide/network_working_with_command_output.html)
- type: str
- rx_rate:
- description:
- - Receiver rate in bits per second (bps).
- - This is state check parameter only.
- - Supports conditionals, see L(Conditionals in Networking Modules,../network/user_guide/network_working_with_command_output.html)
- type: str
- neighbors:
- description:
- - Check the operational state of given interface C(name) for CDP/LLDP neighbor.
- - The following suboptions are available.
- type: list
- suboptions:
- host:
- description:
- - "CDP/LLDP neighbor host for given interface C(name)."
- type: str
- port:
- description:
- - "CDP/LLDP neighbor port to which given interface C(name) is connected."
- type: str
- delay:
- description:
- - Time in seconds to wait before checking for the operational state on remote
- device. This wait is applicable for operational state argument which are
- I(state) with values C(up)/C(down), I(tx_rate) and I(rx_rate).
- type: int
- state:
- description:
- - State of the Interface configuration, C(up) means present and
- operationally up and C(down) means present and operationally C(down)
- type: str
- choices: ['present', 'absent', 'up', 'down']
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- - Module will use environment variable value(default:True), unless it is overridden, by specifying it as module parameter.
- type: bool
- power:
- description:
- - Inline power on Power over Ethernet (PoE) ports.
- type: dict
- suboptions:
- by_class:
- description:
- - "The range is 0-4"
- - "The power limit based on class value for given interface C(name)"
- choices: ['0', '1', '2', '3', '4']
- type: str
- limit:
- description:
- - "The range is 1000-15400|30000mW. For PoH ports the range is 1000-95000mW"
- - "The power limit based on actual power value for given interface C(name)"
- type: str
- priority:
- description:
- - "The range is 1 (highest) to 3 (lowest)"
- - "The priority for power management or given interface C(name)"
- choices: ['1', '2', '3']
- type: str
- enabled:
- description:
- - "enable/disable the poe of the given interface C(name)"
- type: bool
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- - Module will use environment variable value(default:True), unless it is overridden,
- by specifying it as module parameter.
- default: yes
- type: bool
-'''
-
-EXAMPLES = """
-- name: enable ethernet port and set name
- icx_interface:
- name: ethernet 1/1/1
- description: interface-1
- stp: true
- enabled: true
-
-- name: disable ethernet port 1/1/1
- icx_interface:
- name: ethernet 1/1/1
- enabled: false
-
-- name: enable ethernet port range, set name and speed.
- icx_interface:
- name: ethernet 1/1/1 to 1/1/10
- description: interface-1
- speed: 100-full
- enabled: true
-
-- name: enable poe. Set class.
- icx_interface:
- name: ethernet 1/1/1
- power:
- by_class: 2
-
-- name: configure poe limit of interface
- icx_interface:
- name: ethernet 1/1/1
- power:
- limit: 10000
-
-- name: disable poe of interface
- icx_interface:
- name: ethernet 1/1/1
- power:
- enabled: false
-
-- name: set lag name for a range of lags
- icx_interface:
- name: lag 1 to 10
- description: test lags
-
-- name: Disable lag
- icx_interface:
- name: lag 1
- enabled: false
-
-- name: enable management interface
- icx_interface:
- name: management 1
- enabled: true
-
-- name: enable loopback interface
- icx_interface:
- name: loopback 10
- enabled: true
-
-- name: Add interface using aggregate
- icx_interface:
- aggregate:
- - { name: ethernet 1/1/1, description: test-interface-1, power: { by_class: 2 } }
- - { name: ethernet 1/1/3, description: test-interface-3}
- speed: 10-full
- enabled: true
-
-- name: Check tx_rate, rx_rate intent arguments
- icx_interface:
- name: ethernet 1/1/10
- state: up
- tx_rate: ge(0)
- rx_rate: le(0)
-
-- name: Check neighbors intent arguments
- icx_interface:
- name: ethernet 1/1/10
- neighbors:
- - port: 1/1/5
- host: netdev
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device.
- returned: always
- type: list
- sample:
- - interface ethernet 1/1/1
- - port-name interface-1
- - state present
- - speed-duplex 100-full
- - inline power priority 1
-"""
-
-import re
-from copy import deepcopy
-from time import sleep
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import load_config, get_config
-from ansible.module_utils.connection import Connection, ConnectionError, exec_command
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import conditional, remove_default_spec
-
-
-def parse_enable(configobj, name):
- cfg = configobj['interface %s' % name]
- cfg = '\n'.join(cfg.children)
- match = re.search(r'^disable', cfg, re.M)
- if match:
- return True
- else:
- return False
-
-
-def parse_power_argument(configobj, name):
- cfg = configobj['interface %s' % name]
- cfg = '\n'.join(cfg.children)
- match = re.search(r'(^inline power|^inline power(.*))+$', cfg, re.M)
- if match:
- return match.group(1)
-
-
-def parse_config_argument(configobj, name, arg=None):
- cfg = configobj['interface %s' % name]
- cfg = '\n'.join(cfg.children)
- match = re.search(r'%s (.+)$' % arg, cfg, re.M)
- if match:
- return match.group(1)
-
-
-def parse_stp_arguments(module, item):
- rc, out, err = exec_command(module, 'show interfaces ' + item)
- match = re.search(r'STP configured to (\S+),', out, re.S)
- if match:
- return True if match.group(1) == "ON" else False
-
-
-def search_obj_in_list(name, lst):
- for o in lst:
- if o['name'] == name:
- return o
-
- return None
-
-
-def validate_power(module, power):
- count = 0
- for item in power:
- if power.get(item) is not None:
- count += 1
- if count > 1:
- module.fail_json(msg='power parameters are mutually exclusive: class,limit,priority,enabled')
-
-
-def add_command_to_interface(interface, cmd, commands):
- if interface not in commands:
- commands.append(interface)
- commands.append(cmd)
-
-
-def map_config_to_obj(module):
- compare = module.params['check_running_config']
- config = get_config(module, None, compare)
- configobj = NetworkConfig(indent=1, contents=config)
- match = re.findall(r'^interface (.+)$', config, re.M)
-
- if not match:
- return list()
-
- instances = list()
-
- for item in set(match):
- obj = {
- 'name': item,
- 'port-name': parse_config_argument(configobj, item, 'port-name'),
- 'speed-duplex': parse_config_argument(configobj, item, 'speed-duplex'),
- 'stp': parse_stp_arguments(module, item),
- 'disable': True if parse_enable(configobj, item) else False,
- 'power': parse_power_argument(configobj, item),
- 'state': 'present'
- }
- instances.append(obj)
- return instances
-
-
-def parse_poe_config(poe, power):
- if poe.get('by_class') is not None:
- power += 'power-by-class %s' % poe.get('by_class')
- elif poe.get('limit') is not None:
- power += 'power-limit %s' % poe.get('limit')
- elif poe.get('priority') is not None:
- power += 'priority %s' % poe.get('priority')
- elif poe.get('enabled'):
- power = 'inline power'
- elif poe.get('enabled') is False:
- power = 'no inline power'
- return power
-
-
-def map_params_to_obj(module):
- obj = []
- aggregate = module.params.get('aggregate')
- if aggregate:
- for item in aggregate:
- for key in item:
- if item.get(key) is None:
- item[key] = module.params[key]
-
- item['port-name'] = item.pop('description')
- item['speed-duplex'] = item.pop('speed')
- poe = item.get('power')
- if poe:
-
- validate_power(module, poe)
- power = 'inline power' + ' '
- power_arg = parse_poe_config(poe, power)
- item.update({'power': power_arg})
-
- d = item.copy()
-
- if d['enabled']:
- d['disable'] = False
- else:
- d['disable'] = True
-
- obj.append(d)
-
- else:
- params = {
- 'name': module.params['name'],
- 'port-name': module.params['description'],
- 'speed-duplex': module.params['speed'],
- 'stp': module.params['stp'],
- 'delay': module.params['delay'],
- 'state': module.params['state'],
- 'tx_rate': module.params['tx_rate'],
- 'rx_rate': module.params['rx_rate'],
- 'neighbors': module.params['neighbors']
- }
- poe = module.params.get('power')
- if poe:
- validate_power(module, poe)
- power = 'inline power' + ' '
- power_arg = parse_poe_config(poe, power)
- params.update({'power': power_arg})
-
- if module.params['enabled']:
- params.update({'disable': False})
- else:
- params.update({'disable': True})
-
- obj.append(params)
- return obj
-
-
-def map_obj_to_commands(updates):
- commands = list()
- want, have = updates
-
- args = ('speed-duplex', 'port-name', 'power', 'stp')
- for w in want:
- name = w['name']
- disable = w['disable']
- state = w['state']
-
- obj_in_have = search_obj_in_list(name, have)
- interface = 'interface ' + name
-
- if state == 'absent' and have == []:
- commands.append('no ' + interface)
-
- elif state == 'absent' and obj_in_have:
- commands.append('no ' + interface)
-
- elif state in ('present', 'up', 'down'):
- if obj_in_have:
- for item in args:
- candidate = w.get(item)
- running = obj_in_have.get(item)
- if candidate == 'no inline power' and running is None:
- candidate = None
- if candidate != running:
- if candidate:
- if item == 'power':
- cmd = str(candidate)
- elif item == 'stp':
- cmd = 'spanning-tree' if candidate else 'no spanning-tree'
- else:
- cmd = item + ' ' + str(candidate)
- add_command_to_interface(interface, cmd, commands)
-
- if disable and not obj_in_have.get('disable', False):
- add_command_to_interface(interface, 'disable', commands)
- elif not disable and obj_in_have.get('disable', False):
- add_command_to_interface(interface, 'enable', commands)
- else:
- commands.append(interface)
- for item in args:
- value = w.get(item)
- if value:
- if item == 'power':
- commands.append(str(value))
- elif item == 'stp':
- cmd = 'spanning-tree' if item else 'no spanning-tree'
- else:
- commands.append(item + ' ' + str(value))
-
- if disable:
- commands.append('disable')
- if disable is False:
- commands.append('enable')
-
- return commands
-
-
-def check_declarative_intent_params(module, want, result):
- failed_conditions = []
- have_neighbors_lldp = None
- have_neighbors_cdp = None
- for w in want:
- want_state = w.get('state')
- want_tx_rate = w.get('tx_rate')
- want_rx_rate = w.get('rx_rate')
- want_neighbors = w.get('neighbors')
-
- if want_state not in ('up', 'down') and not want_tx_rate and not want_rx_rate and not want_neighbors:
- continue
-
- if result['changed']:
- sleep(w['delay'])
-
- command = 'show interfaces %s' % w['name']
- rc, out, err = exec_command(module, command)
-
- if rc != 0:
- module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc)
-
- if want_state in ('up', 'down'):
- match = re.search(r'%s (\w+)' % 'line protocol is', out, re.M)
- have_state = None
- if match:
- have_state = match.group(1)
- if have_state is None or not conditional(want_state, have_state.strip()):
- failed_conditions.append('state ' + 'eq(%s)' % want_state)
-
- if want_tx_rate:
- match = re.search(r'%s (\d+)' % 'output rate:', out, re.M)
- have_tx_rate = None
- if match:
- have_tx_rate = match.group(1)
-
- if have_tx_rate is None or not conditional(want_tx_rate, have_tx_rate.strip(), cast=int):
- failed_conditions.append('tx_rate ' + want_tx_rate)
-
- if want_rx_rate:
- match = re.search(r'%s (\d+)' % 'input rate:', out, re.M)
- have_rx_rate = None
- if match:
- have_rx_rate = match.group(1)
-
- if have_rx_rate is None or not conditional(want_rx_rate, have_rx_rate.strip(), cast=int):
- failed_conditions.append('rx_rate ' + want_rx_rate)
-
- if want_neighbors:
- have_host = []
- have_port = []
-
- if have_neighbors_lldp is None:
- rc, have_neighbors_lldp, err = exec_command(module, 'show lldp neighbors detail')
- if rc != 0:
- module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc)
- if have_neighbors_lldp:
- lines = have_neighbors_lldp.strip().split('Local port: ')
-
- for line in lines:
- field = line.split('\n')
- if field[0].strip() == w['name'].split(' ')[1]:
- for item in field:
- match = re.search(r'\s*\+\s+System name\s+:\s+"(.*)"', item, re.M)
- if match:
- have_host.append(match.group(1))
-
- match = re.search(r'\s*\+\s+Port description\s+:\s+"(.*)"', item, re.M)
- if match:
- have_port.append(match.group(1))
-
- for item in want_neighbors:
- host = item.get('host')
- port = item.get('port')
- if host and host not in have_host:
- failed_conditions.append('host ' + host)
- if port and port not in have_port:
- failed_conditions.append('port ' + port)
- return failed_conditions
-
-
-def main():
- """ main entry point for module execution
- """
- power_spec = dict(
- by_class=dict(choices=['0', '1', '2', '3', '4']),
- limit=dict(type='str'),
- priority=dict(choices=['1', '2', '3']),
- enabled=dict(type='bool')
- )
- neighbors_spec = dict(
- host=dict(),
- port=dict()
- )
- element_spec = dict(
- name=dict(),
- description=dict(),
- enabled=dict(default=True, type='bool'),
- speed=dict(type='str', choices=['10-full', '10-half', '100-full', '100-half', '1000-full', '1000-full-master',
- '1000-full-slave', '10g-full', '10g-full-master', '10g-full-slave', '2500-full', '2500-full-master',
- '2500-full-slave', '5g-full', '5g-full-master', '5g-full-slave', 'auto']),
- stp=dict(type='bool'),
- tx_rate=dict(),
- rx_rate=dict(),
- neighbors=dict(type='list', elements='dict', options=neighbors_spec),
- delay=dict(default=10, type='int'),
- state=dict(default='present',
- choices=['present', 'absent', 'up', 'down']),
- power=dict(type='dict', options=power_spec),
- check_running_config=dict(default=True, type='bool', fallback=(env_fallback, ['ANSIBLE_CHECK_ICX_RUNNING_CONFIG']))
- )
- aggregate_spec = deepcopy(element_spec)
- aggregate_spec['name'] = dict(required=True)
-
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec),
- )
- argument_spec.update(element_spec)
-
- required_one_of = [['name', 'aggregate']]
- mutually_exclusive = [['name', 'aggregate']]
-
- module = AnsibleModule(argument_spec=argument_spec,
- required_one_of=required_one_of,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
- warnings = list()
- result = {}
- result['changed'] = False
- if warnings:
- result['warnings'] = warnings
- exec_command(module, 'skip')
- want = map_params_to_obj(module)
- have = map_config_to_obj(module)
- commands = map_obj_to_commands((want, have))
- result['commands'] = commands
-
- if commands:
- if not module.check_mode:
- load_config(module, commands)
- result['changed'] = True
-
- failed_conditions = check_declarative_intent_params(module, want, result)
-
- if failed_conditions:
- msg = 'One or more conditional statements have not been satisfied'
- module.fail_json(msg=msg, failed_conditions=failed_conditions)
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/icx/icx_l3_interface.py b/plugins/modules/network/icx/icx_l3_interface.py
deleted file mode 100644
index cd382c3610..0000000000
--- a/plugins/modules/network/icx/icx_l3_interface.py
+++ /dev/null
@@ -1,438 +0,0 @@
-#!/usr/bin/python
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: icx_l3_interface
-author: "Ruckus Wireless (@Commscope)"
-short_description: Manage Layer-3 interfaces on Ruckus ICX 7000 series switches
-description:
- - This module provides declarative management of Layer-3 interfaces
- on ICX network devices.
-notes:
- - Tested against ICX 10.1.
- - For information on using ICX platform, see L(the ICX OS Platform Options guide,../network/user_guide/platform_icx.html).
-options:
- name:
- description:
- - Name of the Layer-3 interface to be configured eg. GigabitEthernet0/2, ve 10, ethernet 1/1/1
- type: str
- ipv4:
- description:
- - IPv4 address to be set for the Layer-3 interface mentioned in I(name) option.
- The address format is /, the mask is number
- in range 0-32 eg. 192.168.0.1/24
- type: str
- ipv6:
- description:
- - IPv6 address to be set for the Layer-3 interface mentioned in I(name) option.
- The address format is /, the mask is number
- in range 0-128 eg. fd5d:12c9:2201:1::1/64.
- type: str
- mode:
- description:
- - Specifies if ipv4 address should be dynamic/advertise to ospf/not advertise to ospf.
- This should be specified only if ipv4 address is configured and if it is not secondary IP address.
- choices: ['dynamic', 'ospf-ignore', 'ospf-passive']
- type: str
- replace:
- description:
- - Replaces the configured primary IP address on the interface.
- choices: ['yes', 'no']
- type: str
- secondary:
- description:
- - Specifies that the configured address is a secondary IP address.
- If this keyword is omitted, the configured address is the primary IP address.
- choices: ['yes', 'no']
- type: str
- aggregate:
- description:
- - List of Layer-3 interfaces definitions. Each of the entry in aggregate list should
- define name of interface C(name) and a optional C(ipv4) or C(ipv6) address.
- type: list
- suboptions:
- name:
- description:
- - Name of the Layer-3 interface to be configured eg. GigabitEthernet0/2, ve 10, ethernet 1/1/1
- type: str
- ipv4:
- description:
- - IPv4 address to be set for the Layer-3 interface mentioned in I(name) option.
- The address format is /, the mask is number
- in range 0-32 eg. 192.168.0.1/24
- type: str
- ipv6:
- description:
- - IPv6 address to be set for the Layer-3 interface mentioned in I(name) option.
- The address format is /, the mask is number
- in range 0-128 eg. fd5d:12c9:2201:1::1/64.
- type: str
- mode:
- description:
- - Specifies if ipv4 address should be dynamic/advertise to ospf/not advertise to ospf.
- This should be specified only if ipv4 address is configured and if it is not secondary IP address.
- choices: ['dynamic', 'ospf-ignore', 'ospf-passive']
- type: str
- replace:
- description:
- - Replaces the configured primary IP address on the interface.
- choices: ['yes', 'no']
- type: str
- secondary:
- description:
- - Specifies that the configured address is a secondary IP address.
- If this keyword is omitted, the configured address is the primary IP address.
- choices: ['yes', 'no']
- type: str
- state:
- description:
- - State of the Layer-3 interface configuration. It indicates if the configuration should
- be present or absent on remote device.
- choices: ['present', 'absent']
- type: str
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- Module will use environment variable value(default:True), unless it is overridden, by specifying it as module parameter.
- type: bool
- state:
- description:
- - State of the Layer-3 interface configuration. It indicates if the configuration should
- be present or absent on remote device.
- default: present
- choices: ['present', 'absent']
- type: str
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- Module will use environment variable value(default:True), unless it is overridden, by specifying it as module parameter.
- type: bool
- default: yes
-'''
-
-EXAMPLES = """
-- name: Remove ethernet 1/1/1 IPv4 and IPv6 address
- icx_l3_interface:
- name: ethernet 1/1/1
- ipv4: 192.168.0.1/24
- ipv6: "fd5d:12c9:2201:1::1/64"
- state: absent
-
-- name: Replace ethernet 1/1/1 primary IPv4 address
- icx_l3_interface:
- name: ethernet 1/1/1
- ipv4: 192.168.0.1/24
- replace: yes
- state: absent
-
-- name: Replace ethernet 1/1/1 dynamic IPv4 address
- icx_l3_interface:
- name: ethernet 1/1/1
- ipv4: 192.168.0.1/24
- mode: dynamic
- state: absent
-
-- name: Set ethernet 1/1/1 secondary IPv4 address
- icx_l3_interface:
- name: ethernet 1/1/1
- ipv4: 192.168.0.1/24
- secondary: yes
- state: absent
-
-- name: Set ethernet 1/1/1 IPv4 address
- icx_l3_interface:
- name: ethernet 1/1/1
- ipv4: 192.168.0.1/24
-
-- name: Set ethernet 1/1/1 IPv6 address
- icx_l3_interface:
- name: ethernet 1/1/1
- ipv6: "fd5d:12c9:2201:1::1/64"
-
-- name: Set IP addresses on aggregate
- icx_l3_interface:
- aggregate:
- - { name: GigabitEthernet0/3, ipv4: 192.168.2.10/24 }
- - { name: GigabitEthernet0/3, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" }
-
-- name: Remove IP addresses on aggregate
- icx_l3_interface:
- aggregate:
- - { name: GigabitEthernet0/3, ipv4: 192.168.2.10/24 }
- - { name: GigabitEthernet0/3, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" }
- state: absent
-
-
-- name: Set the ipv4 and ipv6 of a virtual ethernet(ve)
- icx_l3_interface:
- name: ve 100
- ipv4: 192.168.0.1
- ipv6: "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always, except for the platforms that use Netconf transport to manage the device.
- type: list
- sample:
- - interface ethernet 1/1/1
- - ip address 192.168.0.1 255.255.255.0
- - ipv6 address fd5d:12c9:2201:1::1/64
-"""
-
-
-import re
-from copy import deepcopy
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import exec_command
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import get_config, load_config
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import is_netmask, is_masklen, to_netmask, to_masklen
-
-
-def validate_ipv4(value, module):
- if value:
- address = value.split('/')
- if len(address) != 2:
- module.fail_json(msg='address format is /, got invalid format %s' % value)
- else:
- if not is_masklen(address[1]):
- module.fail_json(msg='invalid value for mask: %s, mask should be in range 0-32' % address[1])
-
-
-def validate_ipv6(value, module):
- if value:
- address = value.split('/')
- if len(address) != 2:
- module.fail_json(msg='address format is /, got invalid format %s' % value)
- else:
- if not 0 <= int(address[1]) <= 128:
- module.fail_json(msg='invalid value for mask: %s, mask should be in range 0-128' % address[1])
-
-
-def validate_param_values(module, obj, param=None):
- if param is None:
- param = module.params
- for key in obj:
- validator = globals().get('validate_%s' % key)
- if callable(validator):
- validator(param.get(key), module)
-
-
-def map_params_to_obj(module):
- obj = []
-
- aggregate = module.params.get('aggregate')
- if aggregate:
- for item in aggregate:
- for key in item:
- if item.get(key) is None:
- item[key] = module.params[key]
-
- validate_param_values(module, item, item)
- obj.append(item.copy())
- else:
- obj.append({
- 'name': module.params['name'],
- 'ipv4': module.params['ipv4'],
- 'ipv6': module.params['ipv6'],
- 'state': module.params['state'],
- 'replace': module.params['replace'],
- 'mode': module.params['mode'],
- 'secondary': module.params['secondary'],
- })
-
- validate_param_values(module, obj)
-
- return obj
-
-
-def parse_config_argument(configobj, name, arg=None):
- cfg = configobj['interface %s' % name]
- cfg = '\n'.join(cfg.children)
-
- values = []
- matches = re.finditer(r'%s (.+)$' % arg, cfg, re.M)
- for match in matches:
- match_str = match.group(1).strip()
- if arg == 'ipv6 address':
- values.append(match_str)
- else:
- values = match_str
- break
-
- return values or None
-
-
-def search_obj_in_list(name, lst):
- for o in lst:
- if o['name'] == name:
- return o
-
- return None
-
-
-def map_config_to_obj(module):
- compare = module.params['check_running_config']
- config = get_config(module, flags=['| begin interface'], compare=compare)
- configobj = NetworkConfig(indent=1, contents=config)
-
- match = re.findall(r'^interface (\S+ \S+)', config, re.M)
- if not match:
- return list()
-
- instances = list()
-
- for item in set(match):
- ipv4 = parse_config_argument(configobj, item, 'ip address')
- if ipv4:
- address = ipv4.strip().split(' ')
- if len(address) == 2 and is_netmask(address[1]):
- ipv4 = '{0}/{1}'.format(address[0], to_text(to_masklen(address[1])))
- obj = {
- 'name': item,
- 'ipv4': ipv4,
- 'ipv6': parse_config_argument(configobj, item, 'ipv6 address'),
- 'state': 'present'
- }
- instances.append(obj)
-
- return instances
-
-
-def map_obj_to_commands(updates, module):
- commands = list()
- want, have = updates
- for w in want:
- name = w['name']
- ipv4 = w['ipv4']
- ipv6 = w['ipv6']
- state = w['state']
- if 'replace' in w:
- replace = w['replace'] == 'yes'
- else:
- replace = False
- if w['mode'] is not None:
- mode = ' ' + w['mode']
- else:
- mode = ''
- if w['secondary'] is not None:
- secondary = w['secondary'] == 'yes'
- else:
- secondary = False
-
- interface = 'interface ' + name
- commands.append(interface)
-
- obj_in_have = search_obj_in_list(name, have)
- if state == 'absent' and have == []:
- if ipv4:
- address = ipv4.split('/')
- if len(address) == 2:
- ipv4 = '{addr} {mask}'.format(addr=address[0], mask=to_netmask(address[1]))
- commands.append('no ip address {ip}'.format(ip=ipv4))
- if ipv6:
- commands.append('no ipv6 address {ip}'.format(ip=ipv6))
-
- elif state == 'absent' and obj_in_have:
- if obj_in_have['ipv4']:
- if ipv4:
- address = ipv4.split('/')
- if len(address) == 2:
- ipv4 = '{addr} {mask}'.format(addr=address[0], mask=to_netmask(address[1]))
- commands.append('no ip address {ip}'.format(ip=ipv4))
- if obj_in_have['ipv6']:
- if ipv6:
- commands.append('no ipv6 address {ip}'.format(ip=ipv6))
-
- elif state == 'present':
- if ipv4:
- if obj_in_have is None or obj_in_have.get('ipv4') is None or ipv4 != obj_in_have['ipv4']:
- address = ipv4.split('/')
- if len(address) == 2:
- ipv4 = '{0} {1}'.format(address[0], to_netmask(address[1]))
- commands.append('ip address %s%s%s%s' % (format(ipv4), mode, ' replace' if (replace) else '', ' secondary' if (secondary) else ''))
-
- if ipv6:
- if obj_in_have is None or obj_in_have.get('ipv6') is None or ipv6.lower() not in [addr.lower() for addr in obj_in_have['ipv6']]:
- commands.append('ipv6 address {ip}'.format(ip=ipv6))
-
- if commands[-1] == interface:
- commands.pop(-1)
- else:
- commands.append("exit")
-
- return commands
-
-
-def main():
- """ main entry point for module execution
- """
- element_spec = dict(
- name=dict(),
- ipv4=dict(),
- ipv6=dict(),
- replace=dict(choices=['yes', 'no']),
- mode=dict(choices=['dynamic', 'ospf-ignore', 'ospf-passive']),
- secondary=dict(choices=['yes', 'no']),
- check_running_config=dict(default=True, type='bool', fallback=(env_fallback, ['ANSIBLE_CHECK_ICX_RUNNING_CONFIG'])),
- state=dict(default='present',
- choices=['present', 'absent']),
- )
-
- aggregate_spec = deepcopy(element_spec)
- aggregate_spec['name'] = dict(required=True)
-
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec)
- )
-
- argument_spec.update(element_spec)
-
- required_one_of = [['name', 'aggregate']]
- mutually_exclusive = [['name', 'aggregate'], ['secondary', 'replace'], ['secondary', 'mode']]
- module = AnsibleModule(argument_spec=argument_spec,
- required_one_of=required_one_of,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
-
- warnings = list()
-
- result = {'changed': False}
- exec_command(module, 'skip')
- want = map_params_to_obj(module)
- have = map_config_to_obj(module)
- commands = map_obj_to_commands((want, have), module)
-
- if commands:
- if not module.check_mode:
- resp = load_config(module, commands)
- warnings.extend((out for out in resp if out))
-
- result['changed'] = True
-
- if warnings:
- result['warnings'] = warnings
-
- result['commands'] = commands
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/icx/icx_linkagg.py b/plugins/modules/network/icx/icx_linkagg.py
deleted file mode 100644
index 82d2b952be..0000000000
--- a/plugins/modules/network/icx/icx_linkagg.py
+++ /dev/null
@@ -1,327 +0,0 @@
-#!/usr/bin/python
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: icx_linkagg
-author: "Ruckus Wireless (@Commscope)"
-short_description: Manage link aggregation groups on Ruckus ICX 7000 series switches
-description:
- - This module provides declarative management of link aggregation groups
- on Ruckus ICX network devices.
-notes:
- - Tested against ICX 10.1.
- - For information on using ICX platform, see L(the ICX OS Platform Options guide,../network/user_guide/platform_icx.html).
-options:
- group:
- description:
- - Channel-group number for the port-channel
- Link aggregation group. Range 1-255 or set to 'auto' to auto-generates a LAG ID
- type: int
- name:
- description:
- - Name of the LAG
- type: str
- mode:
- description:
- - Mode of the link aggregation group.
- type: str
- choices: ['dynamic', 'static']
- members:
- description:
- - List of port members or ranges of the link aggregation group.
- type: list
- state:
- description:
- - State of the link aggregation group.
- type: str
- default: present
- choices: ['present', 'absent']
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- Module will use environment variable value(default:True), unless it is overridden, by specifying it as module parameter.
- type: bool
- default: yes
- aggregate:
- description:
- - List of link aggregation definitions.
- type: list
- suboptions:
- group:
- description:
- - Channel-group number for the port-channel
- Link aggregation group. Range 1-255 or set to 'auto' to auto-generates a LAG ID
- type: int
- name:
- description:
- - Name of the LAG
- type: str
- mode:
- description:
- - Mode of the link aggregation group.
- type: str
- choices: ['dynamic', 'static']
- members:
- description:
- - List of port members or ranges of the link aggregation group.
- type: list
- state:
- description:
- - State of the link aggregation group.
- type: str
- choices: ['present', 'absent']
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- Module will use environment variable value(default:True), unless it is overridden, by specifying it as module parameter.
- type: bool
- purge:
- description:
- - Purge links not defined in the I(aggregate) parameter.
- type: bool
- default: no
-
-'''
-
-EXAMPLES = """
-- name: create static link aggregation group
- icx_linkagg:
- group: 10
- mode: static
- name: LAG1
-
-- name: create link aggregation group with auto id
- icx_linkagg:
- group: auto
- mode: dynamic
- name: LAG2
-
-- name: delete link aggregation group
- icx_linkagg:
- group: 10
- state: absent
-
-- name: Set members to LAG
- icx_linkagg:
- group: 200
- mode: static
- members:
- - ethernet 1/1/1 to 1/1/6
- - ethernet 1/1/10
-
-- name: Remove links other then LAG id 100 and 3 using purge
- icx_linkagg:
- aggregate:
- - { group: 3}
- - { group: 100}
- purge: true
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always, except for the platforms that use Netconf transport to manage the device.
- type: list
- sample:
- - lag LAG1 dynamic id 11
- - ports ethernet 1/1/1 to 1/1/6
- - no ports ethernet 1/1/10
- - no lag LAG1 dynamic id 12
-"""
-
-
-import re
-from copy import deepcopy
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import ConnectionError, exec_command
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import run_commands, get_config, load_config
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import CustomNetworkConfig
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec
-
-
-def range_to_members(ranges, prefix=""):
- match = re.findall(r'(ethe[a-z]* [0-9]/[0-9]/[0-9]+)( to [0-9]/[0-9]/[0-9]+)?', ranges)
- members = list()
- for m in match:
- start, end = m
- if(end == ''):
- start = start.replace("ethe ", "ethernet ")
- members.append("%s%s" % (prefix, start))
- else:
- start_tmp = re.search(r'[0-9]/[0-9]/([0-9]+)', start)
- end_tmp = re.search(r'[0-9]/[0-9]/([0-9]+)', end)
- start = int(start_tmp.group(1))
- end = int(end_tmp.group(1)) + 1
- for num in range(start, end):
- members.append("%sethernet 1/1/%s" % (prefix, num))
- return members
-
-
-def map_config_to_obj(module):
- objs = dict()
- compare = module.params['check_running_config']
- config = get_config(module, None, compare=compare)
- obj = None
- for line in config.split('\n'):
- l = line.strip()
- match1 = re.search(r'lag (\S+) (\S+) id (\S+)', l, re.M)
- if match1:
- obj = dict()
- obj['name'] = match1.group(1)
- obj['mode'] = match1.group(2)
- obj['group'] = match1.group(3)
- obj['state'] = 'present'
- obj['members'] = list()
- else:
- match2 = re.search(r'ports .*', l, re.M)
- if match2 and obj is not None:
- obj['members'].extend(range_to_members(match2.group(0)))
- elif obj is not None:
- objs[obj['group']] = obj
- obj = None
- return objs
-
-
-def map_params_to_obj(module):
- obj = []
-
- aggregate = module.params.get('aggregate')
- if aggregate:
- for item in aggregate:
- for key in item:
- if item.get(key) is None:
- item[key] = module.params[key]
- d = item.copy()
- d['group'] = str(d['group'])
- obj.append(d)
- else:
- obj.append({
- 'group': str(module.params['group']),
- 'mode': module.params['mode'],
- 'members': module.params['members'],
- 'state': module.params['state'],
- 'name': module.params['name']
- })
-
- return obj
-
-
-def search_obj_in_list(group, lst):
- for o in lst:
- if o['group'] == group:
- return o
- return None
-
-
-def is_member(member, lst):
- for li in lst:
- ml = range_to_members(li)
- if member in ml:
- return True
- return False
-
-
-def map_obj_to_commands(updates, module):
- commands = list()
- want, have = updates
- purge = module.params['purge']
-
- for w in want:
- if have == {} and w['state'] == 'absent':
- commands.append("%slag %s %s id %s" % ('no ' if w['state'] == 'absent' else '', w['name'], w['mode'], w['group']))
- elif have.get(w['group']) is None:
- commands.append("%slag %s %s id %s" % ('no ' if w['state'] == 'absent' else '', w['name'], w['mode'], w['group']))
- if(w.get('members') is not None and w['state'] == 'present'):
- for m in w['members']:
- commands.append("ports %s" % (m))
- if w['state'] == 'present':
- commands.append("exit")
- else:
- commands.append("%slag %s %s id %s" % ('no ' if w['state'] == 'absent' else '', w['name'], w['mode'], w['group']))
- if(w.get('members') is not None and w['state'] == 'present'):
- for m in have[w['group']]['members']:
- if not is_member(m, w['members']):
- commands.append("no ports %s" % (m))
- for m in w['members']:
- sm = range_to_members(ranges=m)
- for smm in sm:
- if smm not in have[w['group']]['members']:
- commands.append("ports %s" % (smm))
-
- if w['state'] == 'present':
- commands.append("exit")
- if purge:
- for h in have:
- if search_obj_in_list(have[h]['group'], want) is None:
- commands.append("no lag %s %s id %s" % (have[h]['name'], have[h]['mode'], have[h]['group']))
- return commands
-
-
-def main():
- element_spec = dict(
- group=dict(type='int'),
- name=dict(type='str'),
- mode=dict(choices=['dynamic', 'static']),
- members=dict(type='list'),
- state=dict(default='present',
- choices=['present', 'absent']),
- check_running_config=dict(default=True, type='bool', fallback=(env_fallback, ['ANSIBLE_CHECK_ICX_RUNNING_CONFIG']))
- )
-
- aggregate_spec = deepcopy(element_spec)
- aggregate_spec['group'] = dict(required=True, type='int')
-
- required_one_of = [['group', 'aggregate']]
- required_together = [['name', 'group']]
- mutually_exclusive = [['group', 'aggregate']]
-
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec, required_together=required_together),
- purge=dict(default=False, type='bool')
- )
-
- argument_spec.update(element_spec)
-
- module = AnsibleModule(argument_spec=argument_spec,
- required_one_of=required_one_of,
- required_together=required_together,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
-
- warnings = list()
- result = {'changed': False}
- exec_command(module, 'skip')
- if warnings:
- result['warnings'] = warnings
-
- want = map_params_to_obj(module)
- have = map_config_to_obj(module)
- commands = map_obj_to_commands((want, have), module)
-
- result["commands"] = commands
-
- if commands:
- if not module.check_mode:
- load_config(module, commands)
- result['changed'] = True
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/icx/icx_lldp.py b/plugins/modules/network/icx/icx_lldp.py
deleted file mode 100644
index 955ebc4553..0000000000
--- a/plugins/modules/network/icx/icx_lldp.py
+++ /dev/null
@@ -1,183 +0,0 @@
-#!/usr/bin/python
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: icx_lldp
-author: "Ruckus Wireless (@Commscope)"
-short_description: Manage LLDP configuration on Ruckus ICX 7000 series switches
-description:
- - This module provides declarative management of LLDP service on ICX network devices.
-notes:
- - Tested against ICX 10.1.
- - For information on using ICX platform, see L(the ICX OS Platform Options guide,../network/user_guide/platform_icx.html).
-options:
- interfaces:
- description:
- - specify interfaces
- suboptions:
- name:
- description:
- - List of ethernet ports to enable lldp. To add a range of ports use 'to' keyword. See the example.
- type: list
- state:
- description:
- - State of lldp configuration for interfaces
- type: str
- choices: ['present', 'absent', 'enabled', 'disabled']
- type: list
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- Module will use environment variable value(default:True), unless it is overridden, by specifying it as module parameter.
- type: bool
- default: yes
- state:
- description:
- - Enables the receipt and transmission of Link Layer Discovery Protocol (LLDP) globally.
- type: str
- choices: ['present', 'absent', 'enabled', 'disabled']
-'''
-
-EXAMPLES = """
-- name: Disable LLDP
- icx_lldp:
- state: absent
-
-- name: Enable LLDP
- icx_lldp:
- state: present
-
-- name: Disable LLDP on ports 1/1/1 - 1/1/10, 1/1/20
- icx_lldp:
- interfaces:
- - name:
- - ethernet 1/1/1 to 1/1/10
- - ethernet 1/1/20
- state: absent
- state: present
-
-- name: Enable LLDP on ports 1/1/5 - 1/1/10
- icx_lldp:
- interfaces:
- - name:
- - ethernet 1/1/1 to 1/1/10
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always, except for the platforms that use Netconf transport to manage the device.
- type: list
- sample:
- - lldp run
- - no lldp run
-"""
-
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import load_config, run_commands
-
-
-def has_lldp(module):
- run_commands(module, ['skip'])
- output = run_commands(module, ['show lldp'])
- is_lldp_enable = False
- if len(output) > 0 and "LLDP is not running" not in output[0]:
- is_lldp_enable = True
-
- return is_lldp_enable
-
-
-def map_obj_to_commands(module, commands):
- interfaces = module.params.get('interfaces')
- for item in interfaces:
- state = item.get('state')
- if state == 'present':
- for port in item.get('name'):
- if 'all' in port:
- module.fail_json(msg='cannot enable on all the ports')
- else:
- commands.append('lldp enable ports {0}'.format(str(port)))
- elif state == 'absent':
- for port in item.get('name'):
- if 'all' in port:
- module.fail_json(msg='cannot enable on all the ports')
- else:
- commands.append('no lldp enable ports {0}'.format(str(port)))
-
-
-def main():
- """ main entry point for module execution
- """
- interfaces_spec = dict(
- name=dict(type='list'),
- state=dict(choices=['present', 'absent',
- 'enabled', 'disabled'])
- )
-
- argument_spec = dict(
- interfaces=dict(type='list', elements='dict', options=interfaces_spec),
- state=dict(choices=['present', 'absent',
- 'enabled', 'disabled']),
- check_running_config=dict(default=True, type='bool', fallback=(env_fallback, ['ANSIBLE_CHECK_ICX_RUNNING_CONFIG']))
- )
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- warnings = list()
-
- result = {'changed': False}
-
- if warnings:
- result['warnings'] = warnings
-
- if module.params['check_running_config'] is False:
- HAS_LLDP = None
- else:
- HAS_LLDP = has_lldp(module)
-
- commands = []
- state = module.params['state']
-
- if state is None:
- if HAS_LLDP:
- map_obj_to_commands(module, commands)
- else:
- module.fail_json(msg='LLDP is not running')
- else:
- if state == 'absent' and HAS_LLDP is None:
- commands.append('no lldp run')
-
- if state == 'absent' and HAS_LLDP:
- commands.append('no lldp run')
-
- elif state == 'present':
- if not HAS_LLDP:
- commands.append('lldp run')
- if module.params.get('interfaces'):
- map_obj_to_commands(module, commands)
-
- result['commands'] = commands
-
- if commands:
- if not module.check_mode:
- load_config(module, commands)
-
- result['changed'] = True
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/icx/icx_logging.py b/plugins/modules/network/icx/icx_logging.py
deleted file mode 100644
index 847aef6711..0000000000
--- a/plugins/modules/network/icx/icx_logging.py
+++ /dev/null
@@ -1,581 +0,0 @@
-#!/usr/bin/python
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: icx_logging
-author: "Ruckus Wireless (@Commscope)"
-short_description: Manage logging on Ruckus ICX 7000 series switches
-description:
- - This module provides declarative management of logging
- on Ruckus ICX 7000 series switches.
-notes:
- - Tested against ICX 10.1.
- - For information on using ICX platform, see L(the ICX OS Platform Options guide,../network/user_guide/platform_icx.html).
-options:
- dest:
- description:
- - Destination of the logs.
- choices: ['on', 'host', 'console', 'buffered', 'persistence', 'rfc5424']
- type: str
- name:
- description:
- - ipv4 address/ipv6 address/name of syslog server.
- type: str
- udp_port:
- description:
- - UDP port of destination host(syslog server).
- type: str
- facility:
- description:
- - Specifies log facility to log messages from the device.
- choices: ['auth','cron','daemon','kern','local0', 'local1', 'local2', 'local3', 'local4', 'local5', 'local6', 'local7', 'user',
- 'lpr','mail','news','syslog','sys9','sys10','sys11','sys12','sys13','sys14','user','uucp']
- type: str
- level:
- description:
- - Specifies the message level.
- type: list
- choices: ['alerts', 'critical', 'debugging', 'emergencies', 'errors', 'informational',
- 'notifications', 'warnings']
- aggregate:
- description:
- - List of logging definitions.
- type: list
- suboptions:
- dest:
- description:
- - Destination of the logs.
- choices: ['on', 'host', 'console', 'buffered', 'persistence', 'rfc5424']
- type: str
- name:
- description:
- - ipv4 address/ipv6 address/name of syslog server.
- type: str
- udp_port:
- description:
- - UDP port of destination host(syslog server).
- type: str
- facility:
- description:
- - Specifies log facility to log messages from the device.
- choices: ['auth','cron','daemon','kern','local0', 'local1', 'local2', 'local3', 'local4', 'local5', 'local6', 'local7', 'user',
- 'lpr','mail','news','syslog','sys9','sys10','sys11','sys12','sys13','sys14','user','uucp']
- type: str
- level:
- description:
- - Specifies the message level.
- type: list
- choices: ['alerts', 'critical', 'debugging', 'emergencies', 'errors', 'informational',
- 'notifications', 'warnings']
- state:
- description:
- - State of the logging configuration.
- choices: ['present', 'absent']
- type: str
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- Module will use environment variable value(default:True), unless it is overridden, by specifying it as module parameter.
- type: bool
- state:
- description:
- - State of the logging configuration.
- default: present
- choices: ['present', 'absent']
- type: str
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- Module will use environment variable value(default:True), unless it is overridden, by specifying it as module parameter.
- type: bool
- default: yes
-'''
-
-EXAMPLES = """
-- name: Configure host logging.
- icx_logging:
- dest: host
- name: 172.16.0.1
- udp_port: 5555
-- name: Remove host logging configuration.
- icx_logging:
- dest: host
- name: 172.16.0.1
- udp_port: 5555
- state: absent
-- name: Disables the real-time display of syslog messages.
- icx_logging:
- dest: console
- state: absent
-- name: Enables local syslog logging.
- icx_logging:
- dest : on
- state: present
-- name: configure buffer level.
- icx_logging:
- dest: buffered
- level: critical
-- name: Configure logging using aggregate
- icx_logging:
- aggregate:
- - { dest: buffered, level: ['notifications','errors'] }
-- name: remove logging using aggregate
- icx_logging:
- aggregate:
- - { dest: console }
- - { dest: host, name: 172.16.0.1, udp_port: 5555 }
- state: absent
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always
- type: list
- sample:
- - logging host 172.16.0.1
- - logging console
-"""
-
-import re
-from copy import deepcopy
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import Connection, ConnectionError, exec_command
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec, validate_ip_v6_address
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import get_config, load_config
-
-
-def search_obj_in_list(name, lst):
- for o in lst:
- if o['name'] == name:
- return o
-
-
-def diff_in_list(want, have):
- adds = set()
- removes = set()
- for w in want:
- if w['dest'] == 'buffered':
- for h in have:
- if h['dest'] == 'buffered':
- adds = w['level'] - h['level']
- removes = h['level'] - w['level']
- return adds, removes
- return adds, removes
-
-
-def map_obj_to_commands(updates):
- dest_group = ('host', 'console', 'persistence', 'enable')
- commands = list()
- want, have = updates
-
- for w in want:
- dest = w['dest']
- name = w['name']
- level = w['level']
- state = w['state']
- udp_port = w['udp_port']
- facility = w['facility']
- del w['state']
- del w['facility']
-
- facility_name = ''
- facility_level = ''
- if name is not None and validate_ip_v6_address(name):
- name = 'ipv6 ' + name
-
- if facility:
- for item in have:
- if item['dest'] == 'facility':
- facility_name = item['dest']
- facility_level = item['facility']
-
- if state == 'absent':
- if have == []:
- if facility:
- commands.append('no logging facility')
-
- if dest == 'buffered':
- for item in have:
- if item['dest'] == 'buffered':
- want_level = level
- have_level = item['level']
- for item in want_level:
- commands.append('no logging buffered {0}'.format(item))
-
- if dest == 'host':
- if name and udp_port:
- commands.append('no logging host {0} udp-port {1}'.format(name, udp_port))
- elif name:
- commands.append('no logging host {0}'.format(name))
- else:
- if dest == 'rfc5424':
- commands.append('no logging enable {0}'.format(dest))
- else:
- if dest != 'buffered':
- commands.append('no logging {0}'.format(dest))
-
- if facility:
- if facility_name == 'facility' and facility_level != 'user':
- commands.append('no logging facility')
-
- if dest == 'buffered':
- for item in have:
- if item['dest'] == 'buffered':
- want_level = level
- have_level = item['level']
- for item in want_level:
- if item in have_level:
- commands.append('no logging buffered {0}'.format(item))
-
- if w in have:
- if dest == 'host':
- if name and udp_port:
- commands.append('no logging host {0} udp-port {1}'.format(name, udp_port))
- elif name:
- commands.append('no logging host {0}'.format(name))
- else:
- if dest == 'rfc5424':
- commands.append('no logging enable {0}'.format(dest))
- else:
- if dest != 'buffered':
- commands.append('no logging {0}'.format(dest))
-
- if state == 'present':
- if facility:
- if facility != facility_level:
- commands.append('logging facility {0}'.format(facility))
- if w not in have:
- if dest == 'host':
- if name and udp_port:
- commands.append('logging host {0} udp-port {1}'.format(name, udp_port))
- elif name:
- commands.append('logging host {0}'.format(name))
- elif dest == 'buffered':
- adds, removes = diff_in_list(want, have)
- for item in adds:
- commands.append('logging buffered {0}'.format(item))
- for item in removes:
- commands.append('no logging buffered {0}'.format(item))
- elif dest == 'rfc5424':
- commands.append('logging enable {0}'.format(dest))
- else:
- commands.append('logging {0}'.format(dest))
-
- return commands
-
-
-def parse_port(line, dest):
- port = None
- if dest == 'host':
- match = re.search(r'logging host \S+\s+udp-port\s+(\d+)', line, re.M)
- if match:
- port = match.group(1)
- else:
- match_port = re.search(r'logging host ipv6 \S+\s+udp-port\s+(\d+)', line, re.M)
- if match_port:
- port = match_port.group(1)
- return port
-
-
-def parse_name(line, dest):
- name = None
- if dest == 'host':
- match = re.search(r'logging host (\S+)', line, re.M)
- if match:
- if match.group(1) == 'ipv6':
- ipv6_add = re.search(r'logging host ipv6 (\S+)', line, re.M)
- name = ipv6_add.group(1)
- else:
- name = match.group(1)
-
- return name
-
-
-def parse_address(line, dest):
- if dest == 'host':
- match = re.search(r'^logging host ipv6 (\S+)', line.strip(), re.M)
- if match:
- return True
- return False
-
-
-def map_config_to_obj(module):
- obj = []
- facility = ''
- addr6 = False
- dest_group = ('host', 'console', 'buffered', 'persistence', 'enable')
- dest_level = ('alerts', 'critical', 'debugging', 'emergencies', 'errors', 'informational', 'notifications', 'warnings')
- buff_level = list()
- if module.params['check_running_config'] is False:
- return []
- data = get_config(module, flags=['| include logging'])
- facility_match = re.search(r'^logging facility (\S+)', data, re.M)
- if facility_match:
- facility = facility_match.group(1)
- obj.append({
- 'dest': 'facility',
- 'facility': facility
- })
- else:
- obj.append({
- 'dest': 'facility',
- 'facility': 'user'
- })
- for line in data.split('\n'):
- match = re.search(r'^logging (\S+)', line.strip(), re.M)
- if match:
-
- if match.group(1) in dest_group:
- dest = match.group(1)
- if dest == 'host':
- obj.append({
- 'dest': dest,
- 'name': parse_name(line.strip(), dest),
- 'udp_port': parse_port(line, dest),
- 'level': None,
- 'addr6': parse_address(line, dest)
-
- })
- elif dest == 'buffered':
- obj.append({
- 'dest': dest,
- 'level': None,
- 'name': None,
- 'udp_port': None,
- 'addr6': False
- })
- else:
- if dest == 'enable':
- dest = 'rfc5424'
- obj.append({
- 'dest': dest,
- 'level': None,
- 'name': None,
- 'udp_port': None,
- 'addr6': False
- })
- else:
-
- ip_match = re.search(r'^no logging buffered (\S+)', line, re.M)
- if ip_match:
- dest = 'buffered'
- buff_level.append(ip_match.group(1))
- if 'no logging on' not in data:
- obj.append({
- 'dest': 'on',
- 'level': None,
- 'name': None,
- 'udp_port': None,
- 'addr6': False
-
- })
- levels = set()
- for items in dest_level:
- if items not in buff_level:
- levels.add(items)
- obj.append({
- 'dest': 'buffered',
- 'level': levels,
- 'name': None,
- 'udp_port': None,
- 'addr6': False
-
- })
- return obj
-
-
-def count_terms(check, param=None):
- count = 0
- for term in check:
- if param[term] is not None:
- count += 1
- return count
-
-
-def check_required_if(module, spec, param):
- for sp in spec:
- missing = []
- max_missing_count = 0
- is_one_of = False
- if len(sp) == 4:
- key, val, requirements, is_one_of = sp
- else:
- key, val, requirements = sp
-
- if is_one_of:
- max_missing_count = len(requirements)
- term = 'any'
- else:
- term = 'all'
-
- if key in param and param[key] == val:
- for check in requirements:
- count = count_terms((check,), param)
- if count == 0:
- missing.append(check)
- if len(missing) and len(missing) >= max_missing_count:
- msg = "%s is %s but %s of the following are missing: %s" % (key, val, term, ', '.join(missing))
- module.fail_json(msg=msg)
-
-
-def map_params_to_obj(module, required_if=None):
- obj = []
- addr6 = False
- aggregate = module.params.get('aggregate')
-
- if aggregate:
- for item in aggregate:
- if item['name'] is not None and validate_ip_v6_address(item['name']):
- addr6 = True
- for key in item:
- if item.get(key) is None:
- item[key] = module.params[key]
-
- check_required_if(module, required_if, item)
- item.update({'addr6': addr6})
-
- d = item.copy()
- d['level'] = set(d['level']) if d['level'] is not None else None
- if d['dest'] != 'host':
- d['name'] = None
- d['udp_port'] = None
-
- if d['dest'] != 'buffered':
- d['level'] = None
- del d['check_running_config']
- obj.append(d)
-
- else:
- if module.params['name'] is not None and validate_ip_v6_address(module.params['name']):
- addr6 = True
- if module.params['dest'] != 'host':
- module.params['name'] = None
- module.params['udp_port'] = None
-
- if module.params['dest'] != 'buffered':
- module.params['level'] = None
-
- obj.append({
- 'dest': module.params['dest'],
- 'name': module.params['name'],
- 'udp_port': module.params['udp_port'],
- 'level': set(module.params['level']) if module.params['level'] else None,
- 'facility': module.params['facility'],
- 'state': module.params['state'],
- 'addr6': addr6
- })
- return obj
-
-
-def main():
- """ main entry point for module execution
- """
- element_spec = dict(
- dest=dict(
- type='str',
- choices=[
- 'on',
- 'host',
- 'console',
- 'buffered',
- 'persistence',
- 'rfc5424']),
- name=dict(
- type='str'),
- udp_port=dict(),
- level=dict(
- type='list',
- choices=[
- 'alerts',
- 'critical',
- 'debugging',
- 'emergencies',
- 'errors',
- 'informational',
- 'notifications',
- 'warnings']),
- facility=dict(
- type='str',
- choices=[
- 'auth',
- 'cron',
- 'daemon',
- 'kern',
- 'local0',
- 'local1',
- 'local2',
- 'local3',
- 'local4',
- 'local5',
- 'local6',
- 'local7',
- 'user',
- 'lpr',
- 'mail',
- 'news',
- 'syslog',
- 'sys9',
- 'sys10',
- 'sys11',
- 'sys12',
- 'sys13',
- 'sys14',
- 'user',
- 'uucp']),
- state=dict(
- default='present',
- choices=[
- 'present',
- 'absent']),
- check_running_config=dict(default=True, type='bool', fallback=(env_fallback, ['ANSIBLE_CHECK_ICX_RUNNING_CONFIG'])))
-
- aggregate_spec = deepcopy(element_spec)
-
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec),
- )
-
- argument_spec.update(element_spec)
- required_if = [('dest', 'host', ['name']),
- ('dest', 'buffered', ['level'])]
- module = AnsibleModule(argument_spec=argument_spec,
- required_if=required_if,
- supports_check_mode=True)
-
- result = {'changed': False}
- warnings = list()
-
- exec_command(module, 'skip')
- if warnings:
- result['warnings'] = warnings
-
- want = map_params_to_obj(module, required_if=required_if)
- have = map_config_to_obj(module)
- result['want'] = want
- result['have'] = have
-
- commands = map_obj_to_commands((want, have))
- result['commands'] = commands
- if commands:
- if not module.check_mode:
- load_config(module, commands)
- result['changed'] = True
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/icx/icx_ping.py b/plugins/modules/network/icx/icx_ping.py
deleted file mode 100644
index 828570e6f6..0000000000
--- a/plugins/modules/network/icx/icx_ping.py
+++ /dev/null
@@ -1,269 +0,0 @@
-#!/usr/bin/python
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: icx_ping
-author: "Ruckus Wireless (@Commscope)"
-short_description: Tests reachability using ping from Ruckus ICX 7000 series switches
-description:
- - Tests reachability using ping from switch to a remote destination.
-notes:
- - Tested against ICX 10.1
-options:
- count:
- description:
- - Number of packets to send. Default is 1.
- type: int
- dest:
- description:
- - ip-addr | host-name | vrf vrf-name | ipv6 [ ipv6-addr | host-name | vrf vrf-name] (resolvable by switch) of the remote node.
- required: true
- type: str
- timeout:
- description:
- - Specifies the time, in milliseconds for which the device waits for a reply from the pinged device.
- The value can range from 1 to 4294967296. The default is 5000 (5 seconds).
- type: int
- ttl:
- description:
- - Specifies the time to live as a maximum number of hops. The value can range from 1 to 255. The default is 64.
- type: int
- size:
- description:
- - Specifies the size of the ICMP data portion of the packet, in bytes. This is the payload and does not include the header.
- The value can range from 0 to 10000. The default is 16..
- type: int
- source:
- description:
- - IP address to be used as the origin of the ping packets.
- type: str
- vrf:
- description:
- - Specifies the Virtual Routing and Forwarding (VRF) instance of the device to be pinged.
- type: str
- state:
- description:
- - Determines if the expected result is success or fail.
- type: str
- choices: [ absent, present ]
- default: present
-'''
-
-EXAMPLES = r'''
-- name: Test reachability to 10.10.10.10
- icx_ping:
- dest: 10.10.10.10
-
-- name: Test reachability to ipv6 address from source with timeout
- icx_ping:
- dest: ipv6 2001:cdba:0000:0000:0000:0000:3257:9652
- source: 10.1.1.1
- timeout: 100000
-
-- name: Test reachability to 10.1.1.1 through vrf using 5 packets
- icx_ping:
- dest: 10.1.1.1
- vrf: x.x.x.x
- count: 5
-
-- name: Test unreachability to 10.30.30.30
- icx_ping:
- dest: 10.40.40.40
- state: absent
-
-- name: Test reachability to ipv4 with ttl and packet size
- icx_ping:
- dest: 10.10.10.10
- ttl: 20
- size: 500
-'''
-
-RETURN = '''
-commands:
- description: Show the command sent.
- returned: always
- type: list
- sample: ["ping 10.40.40.40 count 20 source loopback0", "ping 10.40.40.40"]
-packet_loss:
- description: Percentage of packets lost.
- returned: always
- type: str
- sample: "0%"
-packets_rx:
- description: Packets successfully received.
- returned: always
- type: int
- sample: 20
-packets_tx:
- description: Packets successfully transmitted.
- returned: always
- type: int
- sample: 20
-rtt:
- description: Show RTT stats.
- returned: always
- type: dict
- sample: {"avg": 2, "max": 8, "min": 1}
-'''
-
-from ansible.module_utils._text import to_text
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import run_commands
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection, ConnectionError
-import re
-
-
-def build_ping(dest, count=None, source=None, timeout=None, ttl=None, size=None, vrf=None):
- """
- Function to build the command to send to the terminal for the switch
- to execute. All args come from the module's unique params.
- """
-
- if vrf is not None:
- cmd = "ping vrf {0} {1}".format(vrf, dest)
- else:
- cmd = "ping {0}".format(dest)
-
- if count is not None:
- cmd += " count {0}".format(str(count))
-
- if timeout is not None:
- cmd += " timeout {0}".format(str(timeout))
-
- if ttl is not None:
- cmd += " ttl {0}".format(str(ttl))
-
- if size is not None:
- cmd += " size {0}".format(str(size))
-
- if source is not None:
- cmd += " source {0}".format(source)
-
- return cmd
-
-
-def parse_ping(ping_stats):
- """
- Function used to parse the statistical information from the ping response.
- Example: "Success rate is 100 percent (5/5), round-trip min/avg/max=40/51/55 ms."
- Returns the percent of packet loss, received packets, transmitted packets, and RTT dict.
- """
- if ping_stats.startswith('Success'):
- rate_re = re.compile(r"^\w+\s+\w+\s+\w+\s+(?P\d+)\s+\w+\s+\((?P\d+)/(?P\d+)\)")
- rtt_re = re.compile(r".*,\s+\S+\s+\S+=(?P\d+)/(?P\d+)/(?P\d+)\s+\w+\.+\s*$|.*\s*$")
-
- rate = rate_re.match(ping_stats)
- rtt = rtt_re.match(ping_stats)
- return rate.group("pct"), rate.group("rx"), rate.group("tx"), rtt.groupdict()
- else:
- rate_re = re.compile(r"^Sending+\s+(?P\d+),")
- rate = rate_re.match(ping_stats)
- rtt = {'avg': 0, 'max': 0, 'min': 0}
- return 0, 0, rate.group('tx'), rtt
-
-
-def validate_results(module, loss, results):
- """
- This function is used to validate whether the ping results were unexpected per "state" param.
- """
- state = module.params["state"]
- if state == "present" and loss == 100:
- module.fail_json(msg="Ping failed unexpectedly", **results)
- elif state == "absent" and loss < 100:
- module.fail_json(msg="Ping succeeded unexpectedly", **results)
-
-
-def validate_fail(module, responses):
- if ("Success" in responses or "No reply" in responses) is False:
- module.fail_json(msg=responses)
-
-
-def validate_parameters(module, timeout, count):
- if timeout and not 1 <= int(timeout) <= 4294967294:
- module.fail_json(msg="bad value for timeout - valid range (1-4294967294)")
- if count and not 1 <= int(count) <= 4294967294:
- module.fail_json(msg="bad value for count - valid range (1-4294967294)")
-
-
-def main():
- """ main entry point for module execution
- """
- argument_spec = dict(
- count=dict(type="int"),
- dest=dict(type="str", required=True),
- timeout=dict(type="int"),
- ttl=dict(type="int"),
- size=dict(type="int"),
- source=dict(type="str"),
- state=dict(type="str", choices=["absent", "present"], default="present"),
- vrf=dict(type="str")
- )
-
- module = AnsibleModule(argument_spec=argument_spec)
-
- count = module.params["count"]
- dest = module.params["dest"]
- source = module.params["source"]
- timeout = module.params["timeout"]
- ttl = module.params["ttl"]
- size = module.params["size"]
- vrf = module.params["vrf"]
- results = {}
- warnings = list()
-
- if warnings:
- results["warnings"] = warnings
-
- response = ''
- try:
- validate_parameters(module, timeout, count)
- results["commands"] = [build_ping(dest, count, source, timeout, ttl, size, vrf)]
- ping_results = run_commands(module, commands=results["commands"])
- ping_results_list = ping_results[0].split("\n")
-
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
-
- validate_fail(module, ping_results[0])
-
- stats = ""
- statserror = ''
- for line in ping_results_list:
- if line.startswith('Sending'):
- statserror = line
- if line.startswith('Success'):
- stats = line
- elif line.startswith('No reply'):
- stats = statserror
-
- success, rx, tx, rtt = parse_ping(stats)
- loss = abs(100 - int(success))
- results["packet_loss"] = str(loss) + "%"
- results["packets_rx"] = int(rx)
- results["packets_tx"] = int(tx)
-
- # Convert rtt values to int
- for k, v in rtt.items():
- if rtt[k] is not None:
- rtt[k] = int(v)
-
- results["rtt"] = rtt
-
- validate_results(module, loss, results)
-
- module.exit_json(**results)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/icx/icx_static_route.py b/plugins/modules/network/icx/icx_static_route.py
deleted file mode 100644
index 51b6855bfa..0000000000
--- a/plugins/modules/network/icx/icx_static_route.py
+++ /dev/null
@@ -1,314 +0,0 @@
-#!/usr/bin/python
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: icx_static_route
-author: "Ruckus Wireless (@Commscope)"
-short_description: Manage static IP routes on Ruckus ICX 7000 series switches
-description:
- - This module provides declarative management of static
- IP routes on Ruckus ICX network devices.
-notes:
- - Tested against ICX 10.1.
- - For information on using ICX platform, see L(the ICX OS Platform Options guide,../network/user_guide/platform_icx.html).
-options:
- prefix:
- description:
- - Network prefix of the static route.
- type: str
- mask:
- description:
- - Network prefix mask of the static route.
- type: str
- next_hop:
- description:
- - Next hop IP of the static route.
- type: str
- admin_distance:
- description:
- - Admin distance of the static route. Range is 1 to 255.
- type: int
- aggregate:
- description: List of static route definitions.
- type: list
- suboptions:
- prefix:
- description:
- - Network prefix of the static route.
- type: str
- mask:
- description:
- - Network prefix mask of the static route.
- type: str
- next_hop:
- description:
- - Next hop IP of the static route.
- type: str
- admin_distance:
- description:
- - Admin distance of the static route. Range is 1 to 255.
- type: int
- state:
- description:
- - State of the static route configuration.
- type: str
- choices: ['present', 'absent']
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- Module will use environment variable value(default:True), unless it is overridden, by specifying it as module parameter.
- type: bool
- purge:
- description:
- - Purge routes not defined in the I(aggregate) parameter.
- default: no
- type: bool
- state:
- description:
- - State of the static route configuration.
- type: str
- default: present
- choices: ['present', 'absent']
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- Module will use environment variable value(default:True), unless it is overridden, by specifying it as module parameter.
- type: bool
- default: yes
-'''
-
-EXAMPLES = """
-- name: configure static route
- icx_static_route:
- prefix: 192.168.2.0/24
- next_hop: 10.0.0.1
-
-- name: remove configuration
- icx_static_route:
- prefix: 192.168.2.0
- mask: 255.255.255.0
- next_hop: 10.0.0.1
- state: absent
-
-- name: Add static route aggregates
- icx_static_route:
- aggregate:
- - { prefix: 172.16.32.0, mask: 255.255.255.0, next_hop: 10.0.0.8 }
- - { prefix: 172.16.33.0, mask: 255.255.255.0, next_hop: 10.0.0.8 }
-
-- name: remove static route aggregates
- icx_static_route:
- aggregate:
- - { prefix: 172.16.32.0, mask: 255.255.255.0, next_hop: 10.0.0.8 }
- - { prefix: 172.16.33.0, mask: 255.255.255.0, next_hop: 10.0.0.8 }
- state: absent
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always
- type: list
- sample:
- - ip route 192.168.2.0 255.255.255.0 10.0.0.1
-"""
-
-
-from copy import deepcopy
-import re
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible.module_utils.connection import ConnectionError
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import get_config, load_config
-
-try:
- from ipaddress import ip_network
- HAS_IPADDRESS = True
-except ImportError:
- HAS_IPADDRESS = False
-
-
-def map_obj_to_commands(want, have, module):
- commands = list()
- purge = module.params['purge']
- for w in want:
- for h in have:
- for key in ['prefix', 'mask', 'next_hop']:
- if w[key] != h[key]:
- break
- else:
- break
- else:
- h = None
-
- prefix = w['prefix']
- mask = w['mask']
- next_hop = w['next_hop']
- admin_distance = w.get('admin_distance')
- if not admin_distance and h:
- w['admin_distance'] = admin_distance = h['admin_distance']
- state = w['state']
- del w['state']
-
- if state == 'absent' and have == []:
- commands.append('no ip route %s %s %s' % (prefix, mask, next_hop))
-
- if state == 'absent' and w in have:
- commands.append('no ip route %s %s %s' % (prefix, mask, next_hop))
- elif state == 'present' and w not in have:
- if admin_distance:
- commands.append('ip route %s %s %s distance %s' % (prefix, mask, next_hop, admin_distance))
- else:
- commands.append('ip route %s %s %s' % (prefix, mask, next_hop))
- if purge:
- commands = []
- for h in have:
- if h not in want:
- commands.append('no ip route %s %s %s' % (prefix, mask, next_hop))
- return commands
-
-
-def map_config_to_obj(module):
- obj = []
- compare = module.params['check_running_config']
- out = get_config(module, flags='| include ip route', compare=compare)
-
- for line in out.splitlines():
- splitted_line = line.split()
- if len(splitted_line) not in (4, 5, 6):
- continue
- cidr = ip_network(to_text(splitted_line[2]))
- prefix = str(cidr.network_address)
- mask = str(cidr.netmask)
- next_hop = splitted_line[3]
- if len(splitted_line) == 6:
- admin_distance = splitted_line[5]
- else:
- admin_distance = '1'
-
- obj.append({
- 'prefix': prefix, 'mask': mask, 'next_hop': next_hop,
- 'admin_distance': admin_distance
- })
-
- return obj
-
-
-def prefix_length_parser(prefix, mask, module):
- if '/' in prefix and mask is not None:
- module.fail_json(msg='Ambigous, specifed both length and mask')
- if '/' in prefix:
- cidr = ip_network(to_text(prefix))
- prefix = str(cidr.network_address)
- mask = str(cidr.netmask)
- return prefix, mask
-
-
-def map_params_to_obj(module, required_together=None):
- keys = ['prefix', 'mask', 'next_hop', 'admin_distance', 'state']
- obj = []
-
- aggregate = module.params.get('aggregate')
- if aggregate:
- for item in aggregate:
- route = item.copy()
- for key in keys:
- if route.get(key) is None:
- route[key] = module.params.get(key)
-
- module._check_required_together(required_together, route)
-
- prefix, mask = prefix_length_parser(route['prefix'], route['mask'], module)
- route.update({'prefix': prefix, 'mask': mask})
-
- obj.append(route)
- else:
- module._check_required_together(required_together, module.params)
- prefix, mask = prefix_length_parser(module.params['prefix'], module.params['mask'], module)
-
- obj.append({
- 'prefix': prefix,
- 'mask': mask,
- 'next_hop': module.params['next_hop'].strip(),
- 'admin_distance': module.params.get('admin_distance'),
- 'state': module.params['state'],
- })
-
- for route in obj:
- if route['admin_distance']:
- route['admin_distance'] = str(route['admin_distance'])
-
- return obj
-
-
-def main():
- """ main entry point for module execution
- """
- element_spec = dict(
- prefix=dict(type='str'),
- mask=dict(type='str'),
- next_hop=dict(type='str'),
- admin_distance=dict(type='int'),
- state=dict(default='present', choices=['present', 'absent']),
- check_running_config=dict(default=True, type='bool', fallback=(env_fallback, ['ANSIBLE_CHECK_ICX_RUNNING_CONFIG']))
- )
-
- aggregate_spec = deepcopy(element_spec)
- aggregate_spec['prefix'] = dict(required=True)
-
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec),
- purge=dict(default=False, type='bool')
- )
-
- argument_spec.update(element_spec)
-
- required_one_of = [['aggregate', 'prefix']]
- required_together = [['prefix', 'next_hop']]
- mutually_exclusive = [['aggregate', 'prefix']]
-
- module = AnsibleModule(argument_spec=argument_spec,
- required_one_of=required_one_of,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
-
- if not HAS_IPADDRESS:
- module.fail_json(msg="ipaddress python package is required")
-
- warnings = list()
-
- result = {'changed': False}
- if warnings:
- result['warnings'] = warnings
-
- want = map_params_to_obj(module, required_together=required_together)
- have = map_config_to_obj(module)
-
- commands = map_obj_to_commands(want, have, module)
- result['commands'] = commands
-
- if commands:
- if not module.check_mode:
- load_config(module, commands)
-
- result['changed'] = True
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/icx/icx_system.py b/plugins/modules/network/icx/icx_system.py
deleted file mode 100644
index ffda03fece..0000000000
--- a/plugins/modules/network/icx/icx_system.py
+++ /dev/null
@@ -1,470 +0,0 @@
-#!/usr/bin/python
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: icx_system
-author: "Ruckus Wireless (@Commscope)"
-short_description: Manage the system attributes on Ruckus ICX 7000 series switches
-description:
- - This module provides declarative management of node system attributes
- on Ruckus ICX 7000 series switches. It provides an option to configure host system
- parameters or remove those parameters from the device active
- configuration.
-notes:
- - Tested against ICX 10.1.
- - For information on using ICX platform, see L(the ICX OS Platform Options guide,../network/user_guide/platform_icx.html).
-options:
- hostname:
- description:
- - Configure the device hostname parameter. This option takes an ASCII string value.
- type: str
- domain_name:
- description:
- - Configure the IP domain name on the remote device to the provided value.
- Value should be in the dotted name form and
- will be appended to the hostname to create a fully-qualified domain name.
- type: list
- domain_search:
- description:
- - Provides the list of domain names to
- append to the hostname for the purpose of doing name resolution.
- This argument accepts a list of names and will be reconciled
- with the current active configuration on the running node.
- type: list
- name_servers:
- description:
- - List of DNS name servers by IP address to use to perform name resolution
- lookups.
- type: list
- aaa_servers:
- description:
- - Configures radius/tacacs server
- type: list
- suboptions:
- type:
- description:
- - specify the type of the server
- type: str
- choices: ['radius','tacacs']
- hostname:
- description:
- - Configures the host name of the RADIUS server
- type: str
- auth_port_type:
- description:
- - specifies the type of the authentication port
- type: str
- choices: ['auth-port']
- auth_port_num:
- description:
- - Configures the authentication UDP port. The default value is 1812.
- type: str
- acct_port_num:
- description:
- - Configures the accounting UDP port. The default value is 1813.
- type: str
- acct_type:
- description:
- - Usage of the accounting port.
- type: str
- choices: ['accounting-only', 'authentication-only','authorization-only', default]
- auth_key:
- description:
- - Configure the key for the server
- type: str
- auth_key_type:
- description:
- - List of authentication level specified in the choices
- type: list
- choices: ['dot1x','mac-auth','web-auth']
- state:
- description:
- - State of the configuration
- values in the device's current active configuration. When set
- to I(present), the values should be configured in the device active
- configuration and when set to I(absent) the values should not be
- in the device active configuration
- type: str
- default: present
- choices: ['present', 'absent']
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- Module will use environment variable value(default:True), unless it is overridden, by specifying it as module parameter.
- type: bool
- default: yes
-'''
-
-EXAMPLES = """
-- name: configure hostname and domain name
- icx_system:
- hostname: icx
- domain_search:
- - ansible.com
- - redhat.com
- - ruckus.com
-
-- name: configure radius server of type auth-port
- icx_system:
- aaa_servers:
- - type: radius
- hostname: radius-server
- auth_port_type: auth-port
- auth_port_num: 1821
- acct_port_num: 1321
- acct_type: accounting-only
- auth_key: abc
- auth_key_type:
- - dot1x
- - mac-auth
-
-- name: configure tacacs server
- icx_system:
- aaa_servers:
- - type: tacacs
- hostname: tacacs-server
- auth_port_type: auth-port
- auth_port_num: 1821
- acct_port_num: 1321
- acct_type: accounting-only
- auth_key: xyz
-
-- name: configure name servers
- icx_system:
- name_servers:
- - 8.8.8.8
- - 8.8.4.4
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always
- type: list
- sample:
- - hostname icx
- - ip domain name test.example.com
- - radius-server host 172.16.10.12 auth-port 2083 acct-port 1850 default key abc dot1x mac-auth
- - tacacs-server host 10.2.3.4 auth-port 4058 authorization-only key xyz
-
-"""
-
-
-import re
-from copy import deepcopy
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import get_config, load_config
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ComplexList, validate_ip_v6_address
-from ansible.module_utils.connection import Connection, ConnectionError, exec_command
-
-
-def diff_list(want, have):
- adds = [w for w in want if w not in have]
- removes = [h for h in have if h not in want]
- return (adds, removes)
-
-
-def map_obj_to_commands(want, have, module):
- commands = list()
- state = module.params['state']
-
- def needs_update(x):
- return want.get(x) is not None and (want.get(x) != have.get(x))
-
- if state == 'absent':
- if have['name_servers'] == [] and have['aaa_servers'] == [] and have['domain_search'] == [] and have['hostname'] is None:
- if want['hostname']:
- commands.append('no hostname')
-
- if want['domain_search']:
- for item in want['domain_search']:
- commands.append('no ip dns domain-list %s' % item)
-
- if want['name_servers']:
- for item in want['name_servers']:
- commands.append('no ip dns server-address %s' % item)
-
- if want['aaa_servers']:
- want_servers = []
- want_server = want['aaa_servers']
- if want_server:
- want_list = deepcopy(want_server)
- for items in want_list:
- items['auth_key'] = None
- want_servers.append(items)
- for item in want_servers:
- ipv6addr = validate_ip_v6_address(item['hostname'])
- if ipv6addr:
- commands.append('no ' + item['type'] + '-server host ipv6 ' + item['hostname'])
- else:
- commands.append('no ' + item['type'] + '-server host ' + item['hostname'])
-
- if want['hostname']:
- if have['hostname'] == want['hostname']:
- commands.append('no hostname')
-
- if want['domain_search']:
- for item in want['domain_search']:
- if item in have['domain_search']:
- commands.append('no ip dns domain-list %s' % item)
-
- if want['name_servers']:
- for item in want['name_servers']:
- if item in have['name_servers']:
- commands.append('no ip dns server-address %s' % item)
-
- if want['aaa_servers']:
- want_servers = []
- want_server = want['aaa_servers']
- have_server = have['aaa_servers']
- if want_server:
- want_list = deepcopy(want_server)
- for items in want_list:
- items['auth_key'] = None
- want_servers.append(items)
- for item in want_servers:
- if item in have_server:
- ipv6addr = validate_ip_v6_address(item['hostname'])
- if ipv6addr:
- commands.append('no ' + item['type'] + '-server host ipv6 ' + item['hostname'])
- else:
- commands.append('no ' + item['type'] + '-server host ' + item['hostname'])
-
- elif state == 'present':
- if needs_update('hostname'):
- commands.append('hostname %s' % want['hostname'])
-
- if want['domain_search']:
- adds, removes = diff_list(want['domain_search'], have['domain_search'])
- for item in removes:
- commands.append('no ip dns domain-list %s' % item)
- for item in adds:
- commands.append('ip dns domain-list %s' % item)
-
- if want['name_servers']:
- adds, removes = diff_list(want['name_servers'], have['name_servers'])
- for item in removes:
- commands.append('no ip dns server-address %s' % item)
- for item in adds:
- commands.append('ip dns server-address %s' % item)
-
- if want['aaa_servers']:
- want_servers = []
- want_server = want['aaa_servers']
- have_server = have['aaa_servers']
- want_list = deepcopy(want_server)
- for items in want_list:
- items['auth_key'] = None
- want_servers.append(items)
-
- adds, removes = diff_list(want_servers, have_server)
-
- for item in removes:
- ip6addr = validate_ip_v6_address(item['hostname'])
- if ip6addr:
- cmd = 'no ' + item['type'] + '-server host ipv6 ' + item['hostname']
- else:
- cmd = 'no ' + item['type'] + '-server host ' + item['hostname']
- commands.append(cmd)
-
- for w_item in adds:
- for item in want_server:
- if item['hostname'] == w_item['hostname'] and item['type'] == w_item['type']:
- auth_key = item['auth_key']
-
- ip6addr = validate_ip_v6_address(w_item['hostname'])
- if ip6addr:
- cmd = w_item['type'] + '-server host ipv6 ' + w_item['hostname']
- else:
- cmd = w_item['type'] + '-server host ' + w_item['hostname']
- if w_item['auth_port_type']:
- cmd += ' ' + w_item['auth_port_type'] + ' ' + w_item['auth_port_num']
- if w_item['acct_port_num'] and w_item['type'] == 'radius':
- cmd += ' acct-port ' + w_item['acct_port_num']
- if w_item['type'] == 'tacacs':
- if any((w_item['acct_port_num'], w_item['auth_key_type'])):
- module.fail_json(msg='acct_port and auth_key_type is not applicable for tacacs server')
- if w_item['acct_type']:
- cmd += ' ' + w_item['acct_type']
- if auth_key is not None:
- cmd += ' key ' + auth_key
- if w_item['auth_key_type'] and w_item['type'] == 'radius':
- val = ''
- for y in w_item['auth_key_type']:
- val = val + ' ' + y
- cmd += val
- commands.append(cmd)
-
- return commands
-
-
-def parse_hostname(config):
- match = re.search(r'^hostname (\S+)', config, re.M)
- if match:
- return match.group(1)
-
-
-def parse_domain_search(config):
- match = re.findall(r'^ip dns domain[- ]list (\S+)', config, re.M)
- matches = list()
- for name in match:
- matches.append(name)
- return matches
-
-
-def parse_name_servers(config):
- matches = list()
- values = list()
- lines = config.split('\n')
- for line in lines:
- if 'ip dns server-address' in line:
- values = line.split(' ')
- for val in values:
- match = re.search(r'([0-9.]+)', val)
- if match:
- matches.append(match.group())
-
- return matches
-
-
-def parse_aaa_servers(config):
- configlines = config.split('\n')
- obj = []
- for line in configlines:
- auth_key_type = []
- if 'radius-server' in line or 'tacacs-server' in line:
- aaa_type = 'radius' if 'radius-server' in line else 'tacacs'
- match = re.search(r'(host ipv6 (\S+))|(host (\S+))', line)
- if match:
- hostname = match.group(2) if match.group(2) is not None else match.group(4)
- match = re.search(r'auth-port ([0-9]+)', line)
- if match:
- auth_port_num = match.group(1)
- else:
- auth_port_num = None
- match = re.search(r'acct-port ([0-9]+)', line)
- if match:
- acct_port_num = match.group(1)
- else:
- acct_port_num = None
- match = re.search(r'acct-port [0-9]+ (\S+)', line)
- if match:
- acct_type = match.group(1)
- else:
- acct_type = None
- if aaa_type == 'tacacs':
- match = re.search(r'auth-port [0-9]+ (\S+)', line)
- if match:
- acct_type = match.group(1)
- else:
- acct_type = None
- match = re.search(r'(dot1x)', line)
- if match:
- auth_key_type.append('dot1x')
- match = re.search(r'(mac-auth)', line)
- if match:
- auth_key_type.append('mac-auth')
- match = re.search(r'(web-auth)', line)
- if match:
- auth_key_type.append('web-auth')
-
- obj.append({
- 'type': aaa_type,
- 'hostname': hostname,
- 'auth_port_type': 'auth-port',
- 'auth_port_num': auth_port_num,
- 'acct_port_num': acct_port_num,
- 'acct_type': acct_type,
- 'auth_key': None,
- 'auth_key_type': set(auth_key_type) if len(auth_key_type) > 0 else None
- })
-
- return obj
-
-
-def map_config_to_obj(module):
- compare = module.params['check_running_config']
- config = get_config(module, None, compare=compare)
- return {
- 'hostname': parse_hostname(config),
- 'domain_search': parse_domain_search(config),
- 'name_servers': parse_name_servers(config),
- 'aaa_servers': parse_aaa_servers(config)
- }
-
-
-def map_params_to_obj(module):
- if module.params['aaa_servers']:
- for item in module.params['aaa_servers']:
- if item['auth_key_type']:
- item['auth_key_type'] = set(item['auth_key_type'])
- obj = {
- 'hostname': module.params['hostname'],
- 'domain_name': module.params['domain_name'],
- 'domain_search': module.params['domain_search'],
- 'name_servers': module.params['name_servers'],
- 'state': module.params['state'],
- 'aaa_servers': module.params['aaa_servers']
- }
- return obj
-
-
-def main():
- """ Main entry point for Ansible module execution
- """
- server_spec = dict(
- type=dict(choices=['radius', 'tacacs']),
- hostname=dict(),
- auth_port_type=dict(choices=['auth-port']),
- auth_port_num=dict(),
- acct_port_num=dict(),
- acct_type=dict(choices=['accounting-only', 'authentication-only', 'authorization-only', 'default']),
- auth_key=dict(),
- auth_key_type=dict(type='list', choices=['dot1x', 'mac-auth', 'web-auth'])
- )
- argument_spec = dict(
- hostname=dict(),
-
- domain_name=dict(type='list'),
- domain_search=dict(type='list'),
- name_servers=dict(type='list'),
-
- aaa_servers=dict(type='list', elements='dict', options=server_spec),
- state=dict(choices=['present', 'absent'], default='present'),
- check_running_config=dict(default=True, type='bool', fallback=(env_fallback, ['ANSIBLE_CHECK_ICX_RUNNING_CONFIG']))
- )
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- result = {'changed': False}
-
- warnings = list()
-
- result['warnings'] = warnings
- exec_command(module, 'skip')
- want = map_params_to_obj(module)
- have = map_config_to_obj(module)
- commands = map_obj_to_commands(want, have, module)
- result['commands'] = commands
-
- if commands:
- if not module.check_mode:
- load_config(module, commands)
- result['changed'] = True
-
- module.exit_json(**result)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/icx/icx_user.py b/plugins/modules/network/icx/icx_user.py
deleted file mode 100644
index e26f9dc849..0000000000
--- a/plugins/modules/network/icx/icx_user.py
+++ /dev/null
@@ -1,390 +0,0 @@
-#!/usr/bin/python
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: icx_user
-author: "Ruckus Wireless (@Commscope)"
-short_description: Manage the user accounts on Ruckus ICX 7000 series switches.
-description:
- - This module creates or updates user account on network devices. It allows playbooks to manage
- either individual usernames or the aggregate of usernames in the
- current running config. It also supports purging usernames from the
- configuration that are not explicitly defined.
-notes:
- - Tested against ICX 10.1.
- - For information on using ICX platform, see L(the ICX OS Platform Options guide,../network/user_guide/platform_icx.html).
-options:
- aggregate:
- description:
- - The set of username objects to be configured on the remote
- ICX device. The list entries can either be the username
- or a hash of username and properties. This argument is mutually
- exclusive with the C(name) argument.
- aliases: ['users', 'collection']
- type: list
- suboptions:
- name:
- description:
- - The username to be configured on the ICX device.
- required: true
- type: str
- configured_password:
- description: The password to be configured on the ICX device.
- type: str
- update_password:
- description:
- - This argument will instruct the module when to change the password. When
- set to C(always), the password will always be updated in the device
- and when set to C(on_create) the password will be updated only if
- the username is created.
- choices: ['on_create', 'always']
- type: str
- privilege:
- description:
- - The privilege level to be granted to the user
- choices: ['0', '4', '5']
- type: str
- nopassword:
- description:
- - Defines the username without assigning
- a password. This will allow the user to login to the system
- without being authenticated by a password.
- type: bool
- state:
- description:
- - Configures the state of the username definition
- as it relates to the device operational configuration. When set
- to I(present), the username(s) should be configured in the device active
- configuration and when set to I(absent) the username(s) should not be
- in the device active configuration
- choices: ['present', 'absent']
- type: str
- access_time:
- description:
- - This parameter indicates the time the file's access time should be set to.
- Should be preserve when no modification is required, YYYYMMDDHHMM.SS when using default time format, or now.
- Default is None meaning that preserve is the default for state=[file,directory,link,hard] and now is default for state=touch
- type: str
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- Module will use environment variable value(default:True), unless it is overridden, by specifying it as module parameter.
- type: bool
- name:
- description:
- - The username to be configured on the ICX device.
- required: true
- type: str
- configured_password:
- description: The password to be configured on the ICX device.
- type: str
- update_password:
- description:
- - This argument will instruct the module when to change the password. When
- set to C(always), the password will always be updated in the device
- and when set to C(on_create) the password will be updated only if
- the username is created.
- default: always
- choices: ['on_create', 'always']
- type: str
- privilege:
- description:
- - The privilege level to be granted to the user
- default: 0
- choices: ['0', '4', '5']
- type: str
- nopassword:
- description:
- - Defines the username without assigning
- a password. This will allow the user to login to the system
- without being authenticated by a password.
- type: bool
- purge:
- description:
- - If set to true module will remove any previously
- configured usernames on the device except the current defined set of users.
- type: bool
- default: false
- state:
- description:
- - Configures the state of the username definition
- as it relates to the device operational configuration. When set
- to I(present), the username(s) should be configured in the device active
- configuration and when set to I(absent) the username(s) should not be
- in the device active configuration
- default: present
- choices: ['present', 'absent']
- type: str
- access_time:
- description:
- - This parameter indicates the time the file's access time should be set to.
- Should be preserve when no modification is required, YYYYMMDDHHMM.SS when using default time format, or now.
- Default is None meaning that preserve is the default for state=[file,directory,link,hard] and now is default for state=touch
- type: str
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- Module will use environment variable value(default:True), unless it is overridden, by specifying it as module parameter.
- type: bool
- default: yes
-'''
-
-EXAMPLES = """
-- name: create a new user without password
- icx_user:
- name: user1
- nopassword: true
-
-- name: create a new user with password
- icx_user:
- name: user1
- configured_password: 'newpassword'
-
-- name: remove users
- icx_user:
- name: user1
- state: absent
-
-- name: set user privilege level to 5
- icx_user:
- name: user1
- privilege: 5
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always
- type: list
- sample:
- - username ansible nopassword
- - username ansible password-string alethea123
- - no username ansible
- - username ansible privilege 5
- - username ansible enable
-"""
-
-from copy import deepcopy
-
-import re
-import base64
-import hashlib
-
-from functools import partial
-
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec
-from ansible.module_utils.connection import exec_command
-from ansible.module_utils.six import iteritems
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import get_config, load_config
-
-
-def get_param_value(key, item, module):
- if not item.get(key):
- value = module.params[key]
-
- else:
- value_type = module.argument_spec[key].get('type', 'str')
- type_checker = module._CHECK_ARGUMENT_TYPES_DISPATCHER[value_type]
- type_checker(item[key])
- value = item[key]
-
- validator = globals().get('validate_%s' % key)
- if all((value, validator)):
- validator(value, module)
-
- return value
-
-
-def map_params_to_obj(module):
- users = module.params['aggregate']
- if not users:
- if not module.params['name'] and module.params['purge']:
- return list()
- elif not module.params['name']:
- module.fail_json(msg='username is required')
- else:
- aggregate = [{'name': module.params['name']}]
- else:
- aggregate = list()
- for item in users:
- if not isinstance(item, dict):
- aggregate.append({'name': item})
- elif 'name' not in item:
- module.fail_json(msg='name is required')
- else:
- aggregate.append(item)
-
- objects = list()
-
- for item in aggregate:
- get_value = partial(get_param_value, item=item, module=module)
- item['configured_password'] = get_value('configured_password')
- item['nopassword'] = get_value('nopassword')
- item['privilege'] = get_value('privilege')
- item['state'] = get_value('state')
- objects.append(item)
-
- return objects
-
-
-def parse_privilege(data):
- match = re.search(r'privilege (\S)', data, re.M)
- if match:
- return match.group(1)
-
-
-def map_config_to_obj(module):
- compare = module.params['check_running_config']
- data = get_config(module, flags=['| include username'], compare=compare)
-
- match = re.findall(r'(?:^(?:u|\s{2}u))sername (\S+)', data, re.M)
- if not match:
- return list()
-
- instances = list()
-
- for user in set(match):
- regex = r'username %s .+$' % user
- cfg = re.findall(regex, data, re.M)
- cfg = '\n'.join(cfg)
- obj = {
- 'name': user,
- 'state': 'present',
- 'nopassword': 'nopassword' in cfg,
- 'configured_password': None,
- 'privilege': parse_privilege(cfg)
- }
- instances.append(obj)
-
- return instances
-
-
-def map_obj_to_commands(updates, module):
- commands = list()
- state = module.params['state']
- update_password = module.params['update_password']
-
- def needs_update(want, have, x):
- return want.get(x) and (want.get(x) != have.get(x))
-
- def add(command, want, x):
- command.append('username %s %s' % (want['name'], x))
- for update in updates:
- want, have = update
- if want['state'] == 'absent':
- commands.append(user_del_cmd(want['name']))
-
- if needs_update(want, have, 'privilege'):
- add(commands, want, 'privilege %s password %s' % (want['privilege'], want['configured_password']))
- else:
- if needs_update(want, have, 'configured_password'):
- if update_password == 'always' or not have:
- add(commands, want, '%spassword %s' % ('privilege ' + str(have.get('privilege')) +
- " " if have.get('privilege') is not None else '', want['configured_password']))
-
- if needs_update(want, have, 'nopassword'):
- if want['nopassword']:
- add(commands, want, 'nopassword')
-
- if needs_update(want, have, 'access_time'):
- add(commands, want, 'access-time %s' % want['access_time'])
-
- if needs_update(want, have, 'expiry_days'):
- add(commands, want, 'expires %s' % want['expiry_days'])
-
- return commands
-
-
-def update_objects(want, have):
- updates = list()
- for entry in want:
- item = next((i for i in have if i['name'] == entry['name']), None)
-
- if all((item is None, entry['state'] == 'present')):
- updates.append((entry, {}))
-
- elif all((have == [], entry['state'] == 'absent')):
- for key, value in iteritems(entry):
- if key not in ['update_password']:
- updates.append((entry, item))
- break
- elif item:
- for key, value in iteritems(entry):
- if key not in ['update_password']:
- if value is not None and value != item.get(key):
- updates.append((entry, item))
- break
- return updates
-
-
-def user_del_cmd(username):
- return 'no username %s' % username
-
-
-def main():
- """entry point for module execution
- """
- element_spec = dict(
- name=dict(),
-
- configured_password=dict(no_log=True),
- nopassword=dict(type='bool', default=False),
- update_password=dict(default='always', choices=['on_create', 'always']),
- privilege=dict(type='str', choices=['0', '4', '5']),
- access_time=dict(type='str'),
- state=dict(default='present', choices=['present', 'absent']),
- check_running_config=dict(default=True, type='bool', fallback=(env_fallback, ['ANSIBLE_CHECK_ICX_RUNNING_CONFIG']))
- )
- aggregate_spec = deepcopy(element_spec)
- aggregate_spec['name'] = dict(required=True)
-
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec, aliases=['users', 'collection']),
- purge=dict(type='bool', default=False)
- )
-
- argument_spec.update(element_spec)
-
- mutually_exclusive = [('name', 'aggregate')]
-
- module = AnsibleModule(argument_spec=argument_spec,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
-
- result = {'changed': False}
- exec_command(module, 'skip')
- want = map_params_to_obj(module)
- have = map_config_to_obj(module)
- commands = map_obj_to_commands(update_objects(want, have), module)
-
- if module.params['purge']:
- want_users = [x['name'] for x in want]
- have_users = [x['name'] for x in have]
- for item in set(have_users).difference(want_users):
- if item != 'admin':
- commands.append(user_del_cmd(item))
-
- result["commands"] = commands
-
- if commands:
- if not module.check_mode:
- load_config(module, commands)
- result['changed'] = True
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/icx/icx_vlan.py b/plugins/modules/network/icx/icx_vlan.py
deleted file mode 100644
index 468a7d0988..0000000000
--- a/plugins/modules/network/icx/icx_vlan.py
+++ /dev/null
@@ -1,783 +0,0 @@
-#!/usr/bin/python
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: icx_vlan
-author: "Ruckus Wireless (@Commscope)"
-short_description: Manage VLANs on Ruckus ICX 7000 series switches
-description:
- - This module provides declarative management of VLANs
- on ICX network devices.
-notes:
- - Tested against ICX 10.1.
- - For information on using ICX platform, see L(the ICX OS Platform Options guide,../network/user_guide/platform_icx.html).
-options:
- name:
- description:
- - Name of the VLAN.
- type: str
- vlan_id:
- description:
- - ID of the VLAN. Range 1-4094.
- required: true
- type: int
- interfaces:
- description:
- - List of ethernet ports or LAGS to be added as access(untagged) ports to the vlan.
- To add a range of ports use 'to' keyword. See the example.
- suboptions:
- name:
- description:
- - Name of the interface or lag
- type: list
- purge:
- description:
- - Purge interfaces not defined in the I(name)
- type: bool
- type: dict
- tagged:
- description:
- - List of ethernet ports or LAGS to be added as trunk(tagged) ports to the vlan.
- To add a range of ports use 'to' keyword. See the example.
- suboptions:
- name:
- description:
- - Name of the interface or lag
- type: list
- purge:
- description:
- - Purge interfaces not defined in the I(name)
- type: bool
- type: dict
- ip_dhcp_snooping:
- description:
- - Enables DHCP snooping on a VLAN.
- type: bool
- ip_arp_inspection:
- description:
- - Enables dynamic ARP inspection on a VLAN.
- type: bool
- associated_interfaces:
- description:
- - This is a intent option and checks the operational state of the for given vlan C(name)
- for associated interfaces. If the value in the C(associated_interfaces) does not match with
- the operational state of vlan interfaces on device it will result in failure.
- type: list
- associated_tagged:
- description:
- - This is a intent option and checks the operational state of given vlan C(name)
- for associated tagged ports and lags. If the value in the C(associated_tagged) does not match with
- the operational state of vlan interfaces on device it will result in failure.
- type: list
- delay:
- description:
- - Delay the play should wait to check for declarative intent params values.
- default: 10
- type: int
- stp:
- description:
- - Enable spanning-tree 802-1w/rstp for this vlan.
- suboptions:
- type:
- description:
- - Specify the type of spanning-tree
- type: str
- default: 802-1w
- choices: ['802-1w','rstp']
- priority:
- description:
- - Configures the priority of the bridge. The value ranges from
- 0 through 65535. A lower numerical value means the bridge has
- a higher priority. Thus, the highest priority is 0. The default is 32768.
- type: str
- enabled:
- description:
- - Manage the state(Enable/Disable) of the spanning_tree_802_1w in the current vlan
- type: bool
- type: dict
- aggregate:
- description:
- - List of VLANs definitions.
- type: list
- suboptions:
- name:
- description:
- - Name of the VLAN.
- type: str
- vlan_id:
- description:
- - ID of the VLAN. Range 1-4094.
- required: true
- type: str
- ip_dhcp_snooping:
- description:
- - Enables DHCP snooping on a VLAN.
- type: bool
- ip_arp_inspection:
- description:
- - Enables dynamic ARP inspection on a VLAN.
- type: bool
- tagged:
- description:
- - List of ethernet ports or LAGS to be added as trunk(tagged) ports to the vlan.
- To add a range of ports use 'to' keyword. See the example.
- suboptions:
- name:
- description:
- - Name of the interface or lag
- type: list
- purge:
- description:
- - Purge interfaces not defined in the I(name)
- type: bool
- type: dict
- interfaces:
- description:
- - List of ethernet ports or LAGS to be added as access(untagged) ports to the vlan.
- To add a range of ports use 'to' keyword. See the example.
- suboptions:
- name:
- description:
- - Name of the interface or lag
- type: list
- purge:
- description:
- - Purge interfaces not defined in the I(name)
- type: bool
- type: dict
- delay:
- description:
- - Delay the play should wait to check for declarative intent params values.
- type: int
- stp:
- description:
- - Enable spanning-tree 802-1w/rstp for this vlan.
- suboptions:
- type:
- description:
- - Specify the type of spanning-tree
- type: str
- default: 802-1w
- choices: ['802-1w','rstp']
- priority:
- description:
- - Configures the priority of the bridge. The value ranges from
- 0 through 65535. A lower numerical value means the bridge has
- a higher priority. Thus, the highest priority is 0. The default is 32768.
- type: str
- enabled:
- description:
- - Manage the state(Enable/Disable) of the spanning_tree_802_1w in the current vlan
- type: bool
- type: dict
- state:
- description:
- - State of the VLAN configuration.
- type: str
- choices: ['present', 'absent']
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- Module will use environment variable value(default:True), unless it is overridden, by specifying it as module parameter.
- type: bool
- associated_interfaces:
- description:
- - This is a intent option and checks the operational state of the for given vlan C(name)
- for associated interfaces. If the value in the C(associated_interfaces) does not match with
- the operational state of vlan interfaces on device it will result in failure.
- type: list
- associated_tagged:
- description:
- - This is a intent option and checks the operational state of given vlan C(name)
- for associated tagged ports and lags. If the value in the C(associated_tagged) does not match with
- the operational state of vlan interfaces on device it will result in failure.
- type: list
- purge:
- description:
- - Purge VLANs not defined in the I(aggregate) parameter.
- default: no
- type: bool
- state:
- description:
- - State of the VLAN configuration.
- type: str
- default: present
- choices: ['present', 'absent']
- check_running_config:
- description:
- - Check running configuration. This can be set as environment variable.
- Module will use environment variable value(default:True), unless it is overridden, by specifying it as module parameter.
- type: bool
- default: yes
-'''
-
-EXAMPLES = """
-- name: Add a single ethernet 1/1/48 as access(untagged) port to vlan 20
- icx_vlan:
- name: test-vlan
- vlan_id: 20
- interfaces:
- name:
- - ethernet 1/1/48
-
-- name: Add a single LAG 10 as access(untagged) port to vlan 20
- icx_vlan:
- vlan_id: 20
- interfaces:
- name:
- - lag 10
-
-- name: Add a range of ethernet ports as trunk(tagged) ports to vlan 20 by port
- icx_vlan:
- vlan_id: 20
- tagged:
- name:
- - ethernet 1/1/40 to 1/1/48
-
-- name: Add discontinuous lags, ethernet ports as access(untagged) and trunk(tagged) port to vlan 20.
- icx_vlan:
- vlan_id: 20
- interfaces:
- name:
- - ethernet 1/1/40 to 1/1/48
- - ethernet 2/1/1
- - lag 1
- - lag 3 to 5
- tagged:
- name:
- - ethernet 1/1/20 to 1/1/25
- - lag 1 to 3
-
-- name: Remove an access and range of trunk ports from vlan
- icx_vlan:
- vlan_id: 20
- interfaces:
- name:
- - ethernet 1/1/40
- tagged:
- name:
- - ethernet 1/1/39 to 1/1/70
-
-- name: Enable dhcp snooping, disable arp inspection in vlan
- icx_vlan:
- vlan_id: 20
- ip_dhcp_snooping: present
- ip_arp_inspection: absent
-
-- name: Create vlan 20. Enable arp inspection in vlan. Purge all other vlans.
- icx_vlan:
- vlan_id: 20
- ip_arp_inspection: present
- purge: present
-
-- name: Remove vlan 20.
- icx_vlan:
- vlan_id: 20
- state: absent
-"""
-
-RETURN = """
-commands:
- description: The list of configuration mode commands to send to the device
- returned: always
- type: list
- sample:
- - vlan 100
- - name test-vlan
-"""
-
-import re
-from time import sleep
-import itertools
-from copy import deepcopy
-from time import sleep
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import AnsibleModule, env_fallback
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig
-from ansible_collections.community.general.plugins.module_utils.network.icx.icx import load_config, get_config
-from ansible.module_utils.connection import Connection, ConnectionError, exec_command
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import conditional, remove_default_spec
-
-
-def search_obj_in_list(vlan_id, lst):
- obj = list()
- for o in lst:
- if str(o['vlan_id']) == vlan_id:
- return o
-
-
-def parse_vlan_brief(module, vlan_id):
- command = 'show run vlan %s' % vlan_id
- rc, out, err = exec_command(module, command)
- lines = out.split('\n')
- untagged_ports = list()
- untagged_lags = list()
- tagged_ports = list()
- tagged_lags = list()
-
- for line in lines:
- if 'tagged' in line.split():
- lags = line.split(" lag ")
- ports = lags[0].split(" ethe ")
- del ports[0]
- del lags[0]
- for port in ports:
- if "to" in port:
- p = port.split(" to ")
- pr = int(p[1].split('/')[2]) - int(p[0].split('/')[2])
- for i in range(0, pr + 1):
- tagged_ports.append((int(p[0].split('/')[2]) + i))
- else:
- tagged_ports.append(int(port.split('/')[2]))
- for lag in lags:
- if "to" in lag:
- l = lag.split(" to ")
- lr = int(l[1]) - int(l[0])
- for i in range(0, lr + 1):
- tagged_lags.append((int(l[0]) + i))
- else:
- tagged_lags.append(int(lag))
- if 'untagged' in line.split():
- lags = line.split(" lag ")
- ports = lags[0].split(" ethe ")
- del ports[0]
- del lags[0]
- for port in ports:
- if "to" in port:
- p = port.split(" to ")
- pr = int(p[1].split('/')[2]) - int(p[0].split('/')[2])
- for i in range(0, pr + 1):
- untagged_ports.append((int(p[0].split('/')[2]) + i))
- else:
- untagged_ports.append(int(port.split('/')[2]))
- for lag in lags:
- if "to" in lag:
- l = lag.split(" to ")
- lr = int(l[1]) - int(l[0])
- for i in range(0, lr + 1):
- untagged_lags.append((int(l[0]) + i))
- else:
- untagged_lags.append(int(lag))
-
- return untagged_ports, untagged_lags, tagged_ports, tagged_lags
-
-
-def extract_list_from_interface(interface):
- if 'ethernet' in interface:
- if 'to' in interface:
- s = re.search(r"\d+\/\d+/(?P\d+)\sto\s+\d+\/\d+/(?P\d+)", interface)
- low = int(s.group('low'))
- high = int(s.group('high'))
- else:
- s = re.search(r"\d+\/\d+/(?P\d+)", interface)
- low = int(s.group('low'))
- high = int(s.group('low'))
- elif 'lag' in interface:
- if 'to' in interface:
- s = re.search(r"(?P\d+)\sto\s(?P\d+)", interface)
- low = int(s.group('low'))
- high = int(s.group('high'))
- else:
- s = re.search(r"(?P\d+)", interface)
- low = int(s.group('low'))
- high = int(s.group('low'))
-
- return low, high
-
-
-def parse_vlan_id(module):
- vlans = []
- command = 'show vlan brief'
- rc, out, err = exec_command(module, command)
- lines = out.split('\n')
- for line in lines:
- if 'VLANs Configured :' in line:
- values = line.split(':')[1]
- vlans = [s for s in values.split() if s.isdigit()]
- s = re.findall(r"(?P\d+)\sto\s(?P\d+)", values)
- for ranges in s:
- low = int(ranges[0]) + 1
- high = int(ranges[1])
- while(high > low):
- vlans.append(str(low))
- low = low + 1
- return vlans
-
-
-def spanning_tree(module, stp):
- stp_cmd = list()
- if stp.get('enabled') is False:
- if stp.get('type') == '802-1w':
- stp_cmd.append('no spanning-tree' + ' ' + stp.get('type'))
- stp_cmd.append('no spanning-tree')
-
- elif stp.get('type'):
- stp_cmd.append('spanning-tree' + ' ' + stp.get('type'))
- if stp.get('priority') and stp.get('type') == 'rstp':
- module.fail_json(msg='spanning-tree 802-1w only can have priority')
- elif stp.get('priority'):
- stp_cmd.append('spanning-tree' + ' ' + stp.get('type') + ' ' + 'priority' + ' ' + stp.get('priority'))
-
- return stp_cmd
-
-
-def map_params_to_obj(module):
- obj = []
- aggregate = module.params.get('aggregate')
- if aggregate:
- for item in aggregate:
- for key in item:
- if item.get(key) is None:
- item[key] = module.params[key]
- stp = item.get('stp')
- if stp:
- stp_cmd = spanning_tree(module, stp)
- item.update({'stp': stp_cmd})
-
- d = item.copy()
-
- obj.append(d)
-
- else:
- params = {
- 'name': module.params['name'],
- 'vlan_id': module.params['vlan_id'],
- 'interfaces': module.params['interfaces'],
- 'tagged': module.params['tagged'],
- 'associated_interfaces': module.params['associated_interfaces'],
- 'associated_tagged': module.params['associated_tagged'],
- 'delay': module.params['delay'],
- 'ip_dhcp_snooping': module.params['ip_dhcp_snooping'],
- 'ip_arp_inspection': module.params['ip_arp_inspection'],
- 'state': module.params['state'],
- }
-
- stp = module.params.get('stp')
- if stp:
- stp_cmd = spanning_tree(module, stp)
- params.update({'stp': stp_cmd})
-
- obj.append(params)
-
- return obj
-
-
-def map_obj_to_commands(updates, module):
- commands = list()
- want, have = updates
- purge = module.params['purge']
-
- for w in want:
- vlan_id = w['vlan_id']
- state = w['state']
- name = w['name']
- interfaces = w.get('interfaces')
- tagged = w.get('tagged')
- dhcp = w.get('ip_dhcp_snooping')
- arp = w.get('ip_arp_inspection')
- stp = w.get('stp')
- obj_in_have = search_obj_in_list(str(vlan_id), have)
-
- if state == 'absent':
- if have == []:
- commands.append('no vlan {0}'.format(vlan_id))
- if obj_in_have:
- commands.append('no vlan {0}'.format(vlan_id))
-
- elif state == 'present':
- if not obj_in_have:
- commands.append('vlan {0}'.format(vlan_id))
- if name:
- commands.append('vlan {0} name {1}'.format(vlan_id, name))
-
- if interfaces:
- if interfaces['name']:
- for item in interfaces['name']:
- commands.append('untagged {0}'.format(item))
-
- if tagged:
- if tagged['name']:
- for item in tagged['name']:
- commands.append('tagged {0}'.format(item))
-
- if dhcp is True:
- commands.append('ip dhcp snooping vlan {0}'.format(vlan_id))
- elif dhcp is False:
- commands.append('no ip dhcp snooping vlan {0}'.format(vlan_id))
-
- if arp is True:
- commands.append('ip arp inspection vlan {0}'.format(vlan_id))
- elif dhcp is False:
- commands.append('no ip arp inspection vlan {0}'.format(vlan_id))
-
- if stp:
- if w.get('stp'):
- [commands.append(cmd) for cmd in w['stp']]
-
- else:
- commands.append('vlan {0}'.format(vlan_id))
- if name:
- if name != obj_in_have['name']:
- commands.append('vlan {0} name {1}'.format(vlan_id, name))
-
- if interfaces:
- if interfaces['name']:
- have_interfaces = list()
- for interface in interfaces['name']:
- low, high = extract_list_from_interface(interface)
-
- while(high >= low):
- if 'ethernet' in interface:
- have_interfaces.append('ethernet 1/1/{0}'.format(low))
- if 'lag' in interface:
- have_interfaces.append('lag {0}'.format(low))
- low = low + 1
-
- if interfaces['purge'] is True:
- remove_interfaces = list(set(obj_in_have['interfaces']) - set(have_interfaces))
- for item in remove_interfaces:
- commands.append('no untagged {0}'.format(item))
-
- if interfaces['name']:
- add_interfaces = list(set(have_interfaces) - set(obj_in_have['interfaces']))
- for item in add_interfaces:
- commands.append('untagged {0}'.format(item))
-
- if tagged:
- if tagged['name']:
- have_tagged = list()
- for tag in tagged['name']:
- low, high = extract_list_from_interface(tag)
-
- while(high >= low):
- if 'ethernet' in tag:
- have_tagged.append('ethernet 1/1/{0}'.format(low))
- if 'lag' in tag:
- have_tagged.append('lag {0}'.format(low))
- low = low + 1
- if tagged['purge'] is True:
- remove_tagged = list(set(obj_in_have['tagged']) - set(have_tagged))
- for item in remove_tagged:
- commands.append('no tagged {0}'.format(item))
-
- if tagged['name']:
- add_tagged = list(set(have_tagged) - set(obj_in_have['tagged']))
- for item in add_tagged:
- commands.append('tagged {0}'.format(item))
-
- if dhcp != obj_in_have['ip_dhcp_snooping']:
- if dhcp is True:
- commands.append('ip dhcp snooping vlan {0}'.format(vlan_id))
- elif dhcp is False:
- commands.append('no ip dhcp snooping vlan {0}'.format(vlan_id))
-
- if arp != obj_in_have['ip_arp_inspection']:
- if arp is True:
- commands.append('ip arp inspection vlan {0}'.format(vlan_id))
- elif arp is False:
- commands.append('no ip arp inspection vlan {0}'.format(vlan_id))
-
- if stp:
- if w.get('stp'):
- [commands.append(cmd) for cmd in w['stp']]
-
- if len(commands) == 1 and 'vlan ' + str(vlan_id) in commands:
- commands = []
-
- if purge:
- commands = []
- vlans = parse_vlan_id(module)
- for h in vlans:
- obj_in_want = search_obj_in_list(h, want)
- if not obj_in_want and h != '1':
- commands.append('no vlan {0}'.format(h))
-
- return commands
-
-
-def parse_name_argument(module, item):
- command = 'show vlan {0}'.format(item)
- rc, out, err = exec_command(module, command)
- match = re.search(r"Name (\S+),", out)
- if match:
- return match.group(1)
-
-
-def parse_interfaces_argument(module, item, port_type):
- untagged_ports, untagged_lags, tagged_ports, tagged_lags = parse_vlan_brief(module, item)
- ports = list()
- if port_type == "interfaces":
- if untagged_ports:
- for port in untagged_ports:
- ports.append('ethernet 1/1/' + str(port))
- if untagged_lags:
- for port in untagged_lags:
- ports.append('lag ' + str(port))
-
- elif port_type == "tagged":
- if tagged_ports:
- for port in tagged_ports:
- ports.append('ethernet 1/1/' + str(port))
- if tagged_lags:
- for port in tagged_lags:
- ports.append('lag ' + str(port))
-
- return ports
-
-
-def parse_config_argument(config, arg):
- match = re.search(arg, config, re.M)
- if match:
- return True
- else:
- return False
-
-
-def map_config_to_obj(module):
- config = get_config(module)
- vlans = parse_vlan_id(module)
- instance = list()
-
- for item in set(vlans):
- obj = {
- 'vlan_id': item,
- 'name': parse_name_argument(module, item),
- 'interfaces': parse_interfaces_argument(module, item, 'interfaces'),
- 'tagged': parse_interfaces_argument(module, item, 'tagged'),
- 'ip_dhcp_snooping': parse_config_argument(config, 'ip dhcp snooping vlan {0}'.format(item)),
- 'ip_arp_inspection': parse_config_argument(config, 'ip arp inspection vlan {0}'.format(item)),
- }
- instance.append(obj)
- return instance
-
-
-def check_fail(module, output):
- error = [
- re.compile(r"^error", re.I)
- ]
- for x in output:
- for regex in error:
- if regex.search(x):
- module.fail_json(msg=x)
-
-
-def check_declarative_intent_params(want, module, result):
- def parse_ports(interfaces, ports, lags):
- for interface in interfaces:
- low, high = extract_list_from_interface(interface)
-
- while(high >= low):
- if 'ethernet' in interface:
- if not (low in ports):
- module.fail_json(msg='One or more conditional statements have not been satisfied ' + interface)
- if 'lag' in interface:
- if not (low in lags):
- module.fail_json(msg='One or more conditional statements have not been satisfied ' + interface)
- low = low + 1
-
- is_delay = False
- low = 0
- high = 0
- for w in want:
- if w.get('associated_interfaces') is None and w.get('associated_tagged') is None:
- continue
-
- if result['changed'] and not is_delay:
- sleep(module.params['delay'])
- is_delay = True
-
- untagged_ports, untagged_lags, tagged_ports, tagged_lags = parse_vlan_brief(module, w['vlan_id'])
-
- if w['associated_interfaces']:
- parse_ports(w.get('associated_interfaces'), untagged_ports, untagged_lags)
-
- if w['associated_tagged']:
- parse_ports(w.get('associated_tagged'), tagged_ports, tagged_lags)
-
-
-def main():
- """ main entry point for module execution
- """
- stp_spec = dict(
- type=dict(default='802-1w', choices=['802-1w', 'rstp']),
- priority=dict(),
- enabled=dict(type='bool'),
- )
- inter_spec = dict(
- name=dict(type='list'),
- purge=dict(type='bool')
- )
- tagged_spec = dict(
- name=dict(type='list'),
- purge=dict(type='bool')
- )
- element_spec = dict(
- vlan_id=dict(type='int'),
- name=dict(),
- interfaces=dict(type='dict', options=inter_spec),
- tagged=dict(type='dict', options=tagged_spec),
- ip_dhcp_snooping=dict(type='bool'),
- ip_arp_inspection=dict(type='bool'),
- associated_interfaces=dict(type='list'),
- associated_tagged=dict(type='list'),
- delay=dict(default=10, type='int'),
- stp=dict(type='dict', options=stp_spec),
- state=dict(default='present', choices=['present', 'absent']),
- check_running_config=dict(default=True, type='bool', fallback=(env_fallback, ['ANSIBLE_CHECK_ICX_RUNNING_CONFIG']))
- )
- aggregate_spec = deepcopy(element_spec)
- aggregate_spec['vlan_id'] = dict(required=True)
-
- remove_default_spec(aggregate_spec)
-
- argument_spec = dict(
- aggregate=dict(type='list', elements='dict', options=aggregate_spec),
- purge=dict(default=False, type='bool')
- )
- argument_spec.update(element_spec)
- required_one_of = [['vlan_id', 'aggregate']]
- mutually_exclusive = [['vlan_id', 'aggregate']]
-
- module = AnsibleModule(argument_spec=argument_spec,
- required_one_of=required_one_of,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
- warnings = list()
- result = {}
- result['changed'] = False
- if warnings:
- result['warnings'] = warnings
- exec_command(module, 'skip')
- want = map_params_to_obj(module)
- if module.params['check_running_config'] is False:
- have = []
- else:
- have = map_config_to_obj(module)
- commands = map_obj_to_commands((want, have), module)
- result['commands'] = commands
-
- if commands:
- if not module.check_mode:
- output = load_config(module, commands)
- if output:
- check_fail(module, output)
- result['output'] = output
- result['changed'] = True
-
- check_declarative_intent_params(want, module, result)
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/illumos/dladm_etherstub.py b/plugins/modules/network/illumos/dladm_etherstub.py
deleted file mode 100644
index d9410c2336..0000000000
--- a/plugins/modules/network/illumos/dladm_etherstub.py
+++ /dev/null
@@ -1,170 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2015, Adam Å tevko
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: dladm_etherstub
-short_description: Manage etherstubs on Solaris/illumos systems.
-description:
- - Create or delete etherstubs on Solaris/illumos systems.
-author: Adam Å tevko (@xen0l)
-options:
- name:
- description:
- - Etherstub name.
- required: true
- temporary:
- description:
- - Specifies that the etherstub is temporary. Temporary etherstubs
- do not persist across reboots.
- required: false
- default: false
- type: bool
- state:
- description:
- - Create or delete Solaris/illumos etherstub.
- required: false
- default: "present"
- choices: [ "present", "absent" ]
-'''
-
-EXAMPLES = '''
-# Create 'stub0' etherstub
-- dladm_etherstub:
- name: stub0
- state: present
-
-# Remove 'stub0 etherstub
-- dladm_etherstub:
- name: stub0
- state: absent
-'''
-
-RETURN = '''
-name:
- description: etherstub name
- returned: always
- type: str
- sample: "switch0"
-state:
- description: state of the target
- returned: always
- type: str
- sample: "present"
-temporary:
- description: etherstub's persistence
- returned: always
- type: bool
- sample: "True"
-'''
-from ansible.module_utils.basic import AnsibleModule
-
-
-class Etherstub(object):
-
- def __init__(self, module):
- self.module = module
-
- self.name = module.params['name']
- self.temporary = module.params['temporary']
- self.state = module.params['state']
-
- def etherstub_exists(self):
- cmd = [self.module.get_bin_path('dladm', True)]
-
- cmd.append('show-etherstub')
- cmd.append(self.name)
-
- (rc, _, _) = self.module.run_command(cmd)
-
- if rc == 0:
- return True
- else:
- return False
-
- def create_etherstub(self):
- cmd = [self.module.get_bin_path('dladm', True)]
-
- cmd.append('create-etherstub')
-
- if self.temporary:
- cmd.append('-t')
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
- def delete_etherstub(self):
- cmd = [self.module.get_bin_path('dladm', True)]
-
- cmd.append('delete-etherstub')
-
- if self.temporary:
- cmd.append('-t')
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- name=dict(required=True),
- temporary=dict(default=False, type='bool'),
- state=dict(default='present', choices=['absent', 'present']),
- ),
- supports_check_mode=True
- )
-
- etherstub = Etherstub(module)
-
- rc = None
- out = ''
- err = ''
- result = {}
- result['name'] = etherstub.name
- result['state'] = etherstub.state
- result['temporary'] = etherstub.temporary
-
- if etherstub.state == 'absent':
- if etherstub.etherstub_exists():
- if module.check_mode:
- module.exit_json(changed=True)
- (rc, out, err) = etherstub.delete_etherstub()
- if rc != 0:
- module.fail_json(name=etherstub.name, msg=err, rc=rc)
- elif etherstub.state == 'present':
- if not etherstub.etherstub_exists():
- if module.check_mode:
- module.exit_json(changed=True)
- (rc, out, err) = etherstub.create_etherstub()
-
- if rc is not None and rc != 0:
- module.fail_json(name=etherstub.name, msg=err, rc=rc)
-
- if rc is None:
- result['changed'] = False
- else:
- result['changed'] = True
-
- if out:
- result['stdout'] = out
- if err:
- result['stderr'] = err
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/illumos/dladm_iptun.py b/plugins/modules/network/illumos/dladm_iptun.py
deleted file mode 100644
index 9e48be0d49..0000000000
--- a/plugins/modules/network/illumos/dladm_iptun.py
+++ /dev/null
@@ -1,277 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2016, Adam Å tevko
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: dladm_iptun
-short_description: Manage IP tunnel interfaces on Solaris/illumos systems.
-description:
- - Manage IP tunnel interfaces on Solaris/illumos systems.
-author: Adam Å tevko (@xen0l)
-options:
- name:
- description:
- - IP tunnel interface name.
- required: true
- temporary:
- description:
- - Specifies that the IP tunnel interface is temporary. Temporary IP tunnel
- interfaces do not persist across reboots.
- required: false
- default: false
- type: bool
- type:
- description:
- - Specifies the type of tunnel to be created.
- required: false
- default: "ipv4"
- choices: [ "ipv4", "ipv6", "6to4" ]
- aliases: ['tunnel_type']
- local_address:
- description:
- - Literal IP address or hostname corresponding to the tunnel source.
- required: false
- aliases: [ "local" ]
- remote_address:
- description:
- - Literal IP address or hostname corresponding to the tunnel destination.
- required: false
- aliases: [ "remote" ]
- state:
- description:
- - Create or delete Solaris/illumos VNIC.
- required: false
- default: "present"
- choices: [ "present", "absent" ]
-'''
-
-EXAMPLES = '''
-- name: Create IPv4 tunnel interface 'iptun0'
- dladm_iptun: name=iptun0 local_address=192.0.2.23 remote_address=203.0.113.10 state=present
-
-- name: Change IPv4 tunnel remote address
- dladm_iptun: name=iptun0 type=ipv4 local_address=192.0.2.23 remote_address=203.0.113.11
-
-- name: Create IPv6 tunnel interface 'tun0'
- dladm_iptun: name=tun0 type=ipv6 local_address=192.0.2.23 remote_address=203.0.113.42
-
-- name: Remove 'iptun0' tunnel interface
- dladm_iptun: name=iptun0 state=absent
-'''
-
-RETURN = '''
-name:
- description: tunnel interface name
- returned: always
- type: str
- sample: iptun0
-state:
- description: state of the target
- returned: always
- type: str
- sample: present
-temporary:
- description: specifies if operation will persist across reboots
- returned: always
- type: bool
- sample: True
-local_address:
- description: local IP address
- returned: always
- type: str
- sample: 1.1.1.1/32
-remote_address:
- description: remote IP address
- returned: always
- type: str
- sample: 2.2.2.2/32
-type:
- description: tunnel type
- returned: always
- type: str
- sample: ipv4
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-
-
-SUPPORTED_TYPES = ['ipv4', 'ipv6', '6to4']
-
-
-class IPTun(object):
-
- def __init__(self, module):
- self.module = module
-
- self.name = module.params['name']
- self.type = module.params['type']
- self.local_address = module.params['local_address']
- self.remote_address = module.params['remote_address']
- self.temporary = module.params['temporary']
- self.state = module.params['state']
-
- self.dladm_bin = self.module.get_bin_path('dladm', True)
-
- def iptun_exists(self):
- cmd = [self.dladm_bin]
-
- cmd.append('show-iptun')
- cmd.append(self.name)
-
- (rc, _, _) = self.module.run_command(cmd)
-
- if rc == 0:
- return True
- else:
- return False
-
- def create_iptun(self):
- cmd = [self.dladm_bin]
-
- cmd.append('create-iptun')
-
- if self.temporary:
- cmd.append('-t')
-
- cmd.append('-T')
- cmd.append(self.type)
- cmd.append('-a')
- cmd.append('local=' + self.local_address + ',remote=' + self.remote_address)
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
- def delete_iptun(self):
- cmd = [self.dladm_bin]
-
- cmd.append('delete-iptun')
-
- if self.temporary:
- cmd.append('-t')
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
- def update_iptun(self):
- cmd = [self.dladm_bin]
-
- cmd.append('modify-iptun')
-
- if self.temporary:
- cmd.append('-t')
- cmd.append('-a')
- cmd.append('local=' + self.local_address + ',remote=' + self.remote_address)
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
- def _query_iptun_props(self):
- cmd = [self.dladm_bin]
-
- cmd.append('show-iptun')
- cmd.append('-p')
- cmd.append('-c')
- cmd.append('link,type,flags,local,remote')
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
- def iptun_needs_updating(self):
- (rc, out, err) = self._query_iptun_props()
-
- NEEDS_UPDATING = False
-
- if rc == 0:
- configured_local, configured_remote = out.split(':')[3:]
-
- if self.local_address != configured_local or self.remote_address != configured_remote:
- NEEDS_UPDATING = True
-
- return NEEDS_UPDATING
- else:
- self.module.fail_json(msg='Failed to query tunnel interface %s properties' % self.name,
- err=err,
- rc=rc)
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- name=dict(required=True, type='str'),
- type=dict(default='ipv4', type='str', aliases=['tunnel_type'],
- choices=SUPPORTED_TYPES),
- local_address=dict(type='str', aliases=['local']),
- remote_address=dict(type='str', aliases=['remote']),
- temporary=dict(default=False, type='bool'),
- state=dict(default='present', choices=['absent', 'present']),
- ),
- required_if=[
- ['state', 'present', ['local_address', 'remote_address']],
- ],
- supports_check_mode=True
- )
-
- iptun = IPTun(module)
-
- rc = None
- out = ''
- err = ''
- result = {}
- result['name'] = iptun.name
- result['type'] = iptun.type
- result['local_address'] = iptun.local_address
- result['remote_address'] = iptun.remote_address
- result['state'] = iptun.state
- result['temporary'] = iptun.temporary
-
- if iptun.state == 'absent':
- if iptun.iptun_exists():
- if module.check_mode:
- module.exit_json(changed=True)
- (rc, out, err) = iptun.delete_iptun()
- if rc != 0:
- module.fail_json(name=iptun.name, msg=err, rc=rc)
- elif iptun.state == 'present':
- if not iptun.iptun_exists():
- if module.check_mode:
- module.exit_json(changed=True)
- (rc, out, err) = iptun.create_iptun()
-
- if rc is not None and rc != 0:
- module.fail_json(name=iptun.name, msg=err, rc=rc)
- else:
- if iptun.iptun_needs_updating():
- (rc, out, err) = iptun.update_iptun()
- if rc != 0:
- module.fail_json(msg='Error while updating tunnel interface: "%s"' % err,
- name=iptun.name,
- stderr=err,
- rc=rc)
-
- if rc is None:
- result['changed'] = False
- else:
- result['changed'] = True
-
- if out:
- result['stdout'] = out
- if err:
- result['stderr'] = err
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/illumos/dladm_linkprop.py b/plugins/modules/network/illumos/dladm_linkprop.py
deleted file mode 100644
index de8d699e4a..0000000000
--- a/plugins/modules/network/illumos/dladm_linkprop.py
+++ /dev/null
@@ -1,289 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2016, Adam Å tevko
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: dladm_linkprop
-short_description: Manage link properties on Solaris/illumos systems.
-description:
- - Set / reset link properties on Solaris/illumos systems.
-author: Adam Å tevko (@xen0l)
-options:
- link:
- description:
- - Link interface name.
- required: true
- aliases: [ "nic", "interface" ]
- property:
- description:
- - Specifies the name of the property we want to manage.
- required: true
- aliases: [ "name" ]
- value:
- description:
- - Specifies the value we want to set for the link property.
- required: false
- temporary:
- description:
- - Specifies that lin property configuration is temporary. Temporary
- link property configuration does not persist across reboots.
- required: false
- type: bool
- default: false
- state:
- description:
- - Set or reset the property value.
- required: false
- default: "present"
- choices: [ "present", "absent", "reset" ]
-'''
-
-EXAMPLES = '''
-- name: Set 'maxbw' to 100M on e1000g1
- dladm_linkprop: name=e1000g1 property=maxbw value=100M state=present
-
-- name: Set 'mtu' to 9000 on e1000g1
- dladm_linkprop: name=e1000g1 property=mtu value=9000
-
-- name: Reset 'mtu' property on e1000g1
- dladm_linkprop: name=e1000g1 property=mtu state=reset
-'''
-
-RETURN = '''
-property:
- description: property name
- returned: always
- type: str
- sample: mtu
-state:
- description: state of the target
- returned: always
- type: str
- sample: present
-temporary:
- description: specifies if operation will persist across reboots
- returned: always
- type: bool
- sample: True
-link:
- description: link name
- returned: always
- type: str
- sample: e100g0
-value:
- description: property value
- returned: always
- type: str
- sample: 9000
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-
-
-class LinkProp(object):
-
- def __init__(self, module):
- self.module = module
-
- self.link = module.params['link']
- self.property = module.params['property']
- self.value = module.params['value']
- self.temporary = module.params['temporary']
- self.state = module.params['state']
-
- self.dladm_bin = self.module.get_bin_path('dladm', True)
-
- def property_exists(self):
- cmd = [self.dladm_bin]
-
- cmd.append('show-linkprop')
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append(self.link)
-
- (rc, _, _) = self.module.run_command(cmd)
-
- if rc == 0:
- return True
- else:
- self.module.fail_json(msg='Unknown property "%s" on link %s' %
- (self.property, self.link),
- property=self.property,
- link=self.link)
-
- def property_is_modified(self):
- cmd = [self.dladm_bin]
-
- cmd.append('show-linkprop')
- cmd.append('-c')
- cmd.append('-o')
- cmd.append('value,default')
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append(self.link)
-
- (rc, out, _) = self.module.run_command(cmd)
-
- out = out.rstrip()
- (value, default) = out.split(':')
-
- if rc == 0 and value == default:
- return True
- else:
- return False
-
- def property_is_readonly(self):
- cmd = [self.dladm_bin]
-
- cmd.append('show-linkprop')
- cmd.append('-c')
- cmd.append('-o')
- cmd.append('perm')
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append(self.link)
-
- (rc, out, _) = self.module.run_command(cmd)
-
- out = out.rstrip()
-
- if rc == 0 and out == 'r-':
- return True
- else:
- return False
-
- def property_is_set(self):
- cmd = [self.dladm_bin]
-
- cmd.append('show-linkprop')
- cmd.append('-c')
- cmd.append('-o')
- cmd.append('value')
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append(self.link)
-
- (rc, out, _) = self.module.run_command(cmd)
-
- out = out.rstrip()
-
- if rc == 0 and self.value == out:
- return True
- else:
- return False
-
- def set_property(self):
- cmd = [self.dladm_bin]
-
- cmd.append('set-linkprop')
-
- if self.temporary:
- cmd.append('-t')
-
- cmd.append('-p')
- cmd.append(self.property + '=' + self.value)
- cmd.append(self.link)
-
- return self.module.run_command(cmd)
-
- def reset_property(self):
- cmd = [self.dladm_bin]
-
- cmd.append('reset-linkprop')
-
- if self.temporary:
- cmd.append('-t')
-
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append(self.link)
-
- return self.module.run_command(cmd)
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- link=dict(required=True, default=None, type='str', aliases=['nic', 'interface']),
- property=dict(required=True, type='str', aliases=['name']),
- value=dict(required=False, type='str'),
- temporary=dict(default=False, type='bool'),
- state=dict(
- default='present', choices=['absent', 'present', 'reset']),
- ),
- required_if=[
- ['state', 'present', ['value']],
- ],
-
- supports_check_mode=True
- )
-
- linkprop = LinkProp(module)
-
- rc = None
- out = ''
- err = ''
- result = {}
- result['property'] = linkprop.property
- result['link'] = linkprop.link
- result['state'] = linkprop.state
- if linkprop.value:
- result['value'] = linkprop.value
-
- if linkprop.state == 'absent' or linkprop.state == 'reset':
- if linkprop.property_exists():
- if not linkprop.property_is_modified():
- if module.check_mode:
- module.exit_json(changed=True)
- (rc, out, err) = linkprop.reset_property()
- if rc != 0:
- module.fail_json(property=linkprop.property,
- link=linkprop.link,
- msg=err,
- rc=rc)
-
- elif linkprop.state == 'present':
- if linkprop.property_exists():
- if not linkprop.property_is_readonly():
- if not linkprop.property_is_set():
- if module.check_mode:
- module.exit_json(changed=True)
-
- (rc, out, err) = linkprop.set_property()
- if rc != 0:
- module.fail_json(property=linkprop.property,
- link=linkprop.link,
- msg=err,
- rc=rc)
- else:
- module.fail_json(msg='Property "%s" is read-only!' % (linkprop.property),
- property=linkprop.property,
- link=linkprop.link)
-
- if rc is None:
- result['changed'] = False
- else:
- result['changed'] = True
-
- if out:
- result['stdout'] = out
- if err:
- result['stderr'] = err
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/illumos/dladm_vlan.py b/plugins/modules/network/illumos/dladm_vlan.py
deleted file mode 100644
index a651abd1fd..0000000000
--- a/plugins/modules/network/illumos/dladm_vlan.py
+++ /dev/null
@@ -1,213 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2016, Adam Å tevko
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: dladm_vlan
-short_description: Manage VLAN interfaces on Solaris/illumos systems.
-description:
- - Create or delete VLAN interfaces on Solaris/illumos systems.
-author: Adam Å tevko (@xen0l)
-options:
- name:
- description:
- - VLAN interface name.
- required: true
- link:
- description:
- - VLAN underlying link name.
- required: true
- temporary:
- description:
- - Specifies that the VLAN interface is temporary. Temporary VLANs
- do not persist across reboots.
- required: false
- default: false
- type: bool
- vlan_id:
- description:
- - VLAN ID value for VLAN interface.
- required: false
- default: false
- aliases: [ "vid" ]
- state:
- description:
- - Create or delete Solaris/illumos VNIC.
- required: false
- default: "present"
- choices: [ "present", "absent" ]
-'''
-
-EXAMPLES = '''
-- name: Create 'vlan42' VLAN over 'bnx0' link
- dladm_vlan: name=vlan42 link=bnx0 vlan_id=42 state=present
-
-- name: Remove 'vlan1337' VLAN interface
- dladm_vlan: name=vlan1337 state=absent
-'''
-
-RETURN = '''
-name:
- description: VLAN name
- returned: always
- type: str
- sample: vlan42
-state:
- description: state of the target
- returned: always
- type: str
- sample: present
-temporary:
- description: specifies if operation will persist across reboots
- returned: always
- type: bool
- sample: True
-link:
- description: VLAN's underlying link name
- returned: always
- type: str
- sample: e100g0
-vlan_id:
- description: VLAN ID
- returned: always
- type: str
- sample: 42
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-
-
-class VLAN(object):
-
- def __init__(self, module):
- self.module = module
-
- self.name = module.params['name']
- self.link = module.params['link']
- self.vlan_id = module.params['vlan_id']
- self.temporary = module.params['temporary']
- self.state = module.params['state']
-
- def vlan_exists(self):
- cmd = [self.module.get_bin_path('dladm', True)]
-
- cmd.append('show-vlan')
- cmd.append(self.name)
-
- (rc, _, _) = self.module.run_command(cmd)
-
- if rc == 0:
- return True
- else:
- return False
-
- def create_vlan(self):
- cmd = [self.module.get_bin_path('dladm', True)]
-
- cmd.append('create-vlan')
-
- if self.temporary:
- cmd.append('-t')
-
- cmd.append('-l')
- cmd.append(self.link)
- cmd.append('-v')
- cmd.append(self.vlan_id)
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
- def delete_vlan(self):
- cmd = [self.module.get_bin_path('dladm', True)]
-
- cmd.append('delete-vlan')
-
- if self.temporary:
- cmd.append('-t')
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
- def is_valid_vlan_id(self):
-
- return 0 <= int(self.vlan_id) <= 4095
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- name=dict(required=True, type='str'),
- link=dict(default=None, type='str'),
- vlan_id=dict(default=0, aliases=['vid']),
- temporary=dict(default=False, type='bool'),
- state=dict(default='present', choices=['absent', 'present']),
- ),
- required_if=[
- ['state', 'present', ['vlan_id', 'link', 'name']],
- ],
- supports_check_mode=True
- )
-
- vlan = VLAN(module)
-
- rc = None
- out = ''
- err = ''
- result = {}
- result['name'] = vlan.name
- result['link'] = vlan.link
- result['state'] = vlan.state
- result['temporary'] = vlan.temporary
-
- if int(vlan.vlan_id) != 0:
- if not vlan.is_valid_vlan_id():
- module.fail_json(msg='Invalid VLAN id value',
- name=vlan.name,
- state=vlan.state,
- link=vlan.link,
- vlan_id=vlan.vlan_id)
- result['vlan_id'] = vlan.vlan_id
-
- if vlan.state == 'absent':
- if vlan.vlan_exists():
- if module.check_mode:
- module.exit_json(changed=True)
- (rc, out, err) = vlan.delete_vlan()
- if rc != 0:
- module.fail_json(name=vlan.name, msg=err, rc=rc)
- elif vlan.state == 'present':
- if not vlan.vlan_exists():
- if module.check_mode:
- module.exit_json(changed=True)
- (rc, out, err) = vlan.create_vlan()
-
- if rc is not None and rc != 0:
- module.fail_json(name=vlan.name, msg=err, rc=rc)
-
- if rc is None:
- result['changed'] = False
- else:
- result['changed'] = True
-
- if out:
- result['stdout'] = out
- if err:
- result['stderr'] = err
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/illumos/dladm_vnic.py b/plugins/modules/network/illumos/dladm_vnic.py
deleted file mode 100644
index cd7b86a6aa..0000000000
--- a/plugins/modules/network/illumos/dladm_vnic.py
+++ /dev/null
@@ -1,265 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2015, Adam Å tevko
-#
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: dladm_vnic
-short_description: Manage VNICs on Solaris/illumos systems.
-description:
- - Create or delete VNICs on Solaris/illumos systems.
-author: Adam Å tevko (@xen0l)
-options:
- name:
- description:
- - VNIC name.
- required: true
- link:
- description:
- - VNIC underlying link name.
- required: true
- temporary:
- description:
- - Specifies that the VNIC is temporary. Temporary VNICs
- do not persist across reboots.
- required: false
- default: false
- type: bool
- mac:
- description:
- - Sets the VNIC's MAC address. Must be valid unicast MAC address.
- required: false
- default: false
- aliases: [ "macaddr" ]
- vlan:
- description:
- - Enable VLAN tagging for this VNIC. The VLAN tag will have id
- I(vlan).
- required: false
- default: false
- aliases: [ "vlan_id" ]
- state:
- description:
- - Create or delete Solaris/illumos VNIC.
- required: false
- default: "present"
- choices: [ "present", "absent" ]
-'''
-
-EXAMPLES = '''
-# Create 'vnic0' VNIC over 'bnx0' link
-- dladm_vnic:
- name: vnic0
- link: bnx0
- state: present
-
-# Create VNIC with specified MAC and VLAN tag over 'aggr0'
-- dladm_vnic:
- name: vnic1
- link: aggr0
- mac: '00:00:5E:00:53:23'
- vlan: 4
-
-# Remove 'vnic0' VNIC
-- dladm_vnic:
- name: vnic0
- link: bnx0
- state: absent
-'''
-
-RETURN = '''
-name:
- description: VNIC name
- returned: always
- type: str
- sample: "vnic0"
-link:
- description: VNIC underlying link name
- returned: always
- type: str
- sample: "igb0"
-state:
- description: state of the target
- returned: always
- type: str
- sample: "present"
-temporary:
- description: VNIC's persistence
- returned: always
- type: bool
- sample: "True"
-mac:
- description: MAC address to use for VNIC
- returned: if mac is specified
- type: str
- sample: "00:00:5E:00:53:42"
-vlan:
- description: VLAN to use for VNIC
- returned: success
- type: int
- sample: 42
-'''
-
-import re
-
-from ansible.module_utils.basic import AnsibleModule
-
-
-class VNIC(object):
-
- UNICAST_MAC_REGEX = r'^[a-f0-9][2-9a-f0]:([a-f0-9]{2}:){4}[a-f0-9]{2}$'
-
- def __init__(self, module):
- self.module = module
-
- self.name = module.params['name']
- self.link = module.params['link']
- self.mac = module.params['mac']
- self.vlan = module.params['vlan']
- self.temporary = module.params['temporary']
- self.state = module.params['state']
-
- def vnic_exists(self):
- cmd = [self.module.get_bin_path('dladm', True)]
-
- cmd.append('show-vnic')
- cmd.append(self.name)
-
- (rc, _, _) = self.module.run_command(cmd)
-
- if rc == 0:
- return True
- else:
- return False
-
- def create_vnic(self):
- cmd = [self.module.get_bin_path('dladm', True)]
-
- cmd.append('create-vnic')
-
- if self.temporary:
- cmd.append('-t')
-
- if self.mac:
- cmd.append('-m')
- cmd.append(self.mac)
-
- if self.vlan:
- cmd.append('-v')
- cmd.append(self.vlan)
-
- cmd.append('-l')
- cmd.append(self.link)
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
- def delete_vnic(self):
- cmd = [self.module.get_bin_path('dladm', True)]
-
- cmd.append('delete-vnic')
-
- if self.temporary:
- cmd.append('-t')
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
- def is_valid_unicast_mac(self):
-
- mac_re = re.match(self.UNICAST_MAC_REGEX, self.mac)
-
- return mac_re is None
-
- def is_valid_vlan_id(self):
-
- return 0 <= self.vlan <= 4095
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- name=dict(required=True),
- link=dict(required=True),
- mac=dict(default=None, aliases=['macaddr']),
- vlan=dict(default=None, aliases=['vlan_id']),
- temporary=dict(default=False, type='bool'),
- state=dict(default='present', choices=['absent', 'present']),
- ),
- supports_check_mode=True
- )
-
- vnic = VNIC(module)
-
- rc = None
- out = ''
- err = ''
- result = {}
- result['name'] = vnic.name
- result['link'] = vnic.link
- result['state'] = vnic.state
- result['temporary'] = vnic.temporary
-
- if vnic.mac is not None:
- if vnic.is_valid_unicast_mac():
- module.fail_json(msg='Invalid unicast MAC address',
- mac=vnic.mac,
- name=vnic.name,
- state=vnic.state,
- link=vnic.link,
- vlan=vnic.vlan)
- result['mac'] = vnic.mac
-
- if vnic.vlan is not None:
- if vnic.is_valid_vlan_id():
- module.fail_json(msg='Invalid VLAN tag',
- mac=vnic.mac,
- name=vnic.name,
- state=vnic.state,
- link=vnic.link,
- vlan=vnic.vlan)
- result['vlan'] = vnic.vlan
-
- if vnic.state == 'absent':
- if vnic.vnic_exists():
- if module.check_mode:
- module.exit_json(changed=True)
- (rc, out, err) = vnic.delete_vnic()
- if rc != 0:
- module.fail_json(name=vnic.name, msg=err, rc=rc)
- elif vnic.state == 'present':
- if not vnic.vnic_exists():
- if module.check_mode:
- module.exit_json(changed=True)
- (rc, out, err) = vnic.create_vnic()
-
- if rc is not None and rc != 0:
- module.fail_json(name=vnic.name, msg=err, rc=rc)
-
- if rc is None:
- result['changed'] = False
- else:
- result['changed'] = True
-
- if out:
- result['stdout'] = out
- if err:
- result['stderr'] = err
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/illumos/flowadm.py b/plugins/modules/network/illumos/flowadm.py
deleted file mode 100644
index b35a65fd45..0000000000
--- a/plugins/modules/network/illumos/flowadm.py
+++ /dev/null
@@ -1,513 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2016, Adam Å tevko
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: flowadm
-short_description: Manage bandwidth resource control and priority for protocols, services and zones on Solaris/illumos systems
-description:
- - Create/modify/remove networking bandwidth and associated resources for a type of traffic on a particular link.
-author: Adam Å tevko (@xen0l)
-options:
- name:
- description: >
- - A flow is defined as a set of attributes based on Layer 3 and Layer 4
- headers, which can be used to identify a protocol, service, or a zone.
- required: true
- aliases: [ 'flow' ]
- link:
- description:
- - Specifiies a link to configure flow on.
- required: false
- local_ip:
- description:
- - Identifies a network flow by the local IP address.
- required: false
- remote_ip:
- description:
- - Identifies a network flow by the remote IP address.
- required: false
- transport:
- description: >
- - Specifies a Layer 4 protocol to be used. It is typically used in combination with I(local_port) to
- identify the service that needs special attention.
- required: false
- local_port:
- description:
- - Identifies a service specified by the local port.
- required: false
- dsfield:
- description: >
- - Identifies the 8-bit differentiated services field (as defined in
- RFC 2474). The optional dsfield_mask is used to state the bits of interest in
- the differentiated services field when comparing with the dsfield
- value. Both values must be in hexadecimal.
- required: false
- maxbw:
- description: >
- - Sets the full duplex bandwidth for the flow. The bandwidth is
- specified as an integer with one of the scale suffixes(K, M, or G
- for Kbps, Mbps, and Gbps). If no units are specified, the input
- value will be read as Mbps.
- required: false
- priority:
- description:
- - Sets the relative priority for the flow.
- required: false
- default: 'medium'
- choices: [ 'low', 'medium', 'high' ]
- temporary:
- description:
- - Specifies that the configured flow is temporary. Temporary
- flows do not persist across reboots.
- required: false
- default: false
- type: bool
- state:
- description:
- - Create/delete/enable/disable an IP address on the network interface.
- required: false
- default: present
- choices: [ 'absent', 'present', 'resetted' ]
-'''
-
-EXAMPLES = '''
-# Limit SSH traffic to 100M via vnic0 interface
-- flowadm:
- link: vnic0
- flow: ssh_out
- transport: tcp
- local_port: 22
- maxbw: 100M
- state: present
-
-# Reset flow properties
-- flowadm:
- name: dns
- state: resetted
-
-# Configure policy for EF PHB (DSCP value of 101110 from RFC 2598) with a bandwidth of 500 Mbps and a high priority.
-- flowadm:
- link: bge0
- dsfield: '0x2e:0xfc'
- maxbw: 500M
- priority: high
- flow: efphb-flow
- state: present
-'''
-
-RETURN = '''
-name:
- description: flow name
- returned: always
- type: str
- sample: "http_drop"
-link:
- description: flow's link
- returned: if link is defined
- type: str
- sample: "vnic0"
-state:
- description: state of the target
- returned: always
- type: str
- sample: "present"
-temporary:
- description: flow's persistence
- returned: always
- type: bool
- sample: "True"
-priority:
- description: flow's priority
- returned: if priority is defined
- type: str
- sample: "low"
-transport:
- description: flow's transport
- returned: if transport is defined
- type: str
- sample: "tcp"
-maxbw:
- description: flow's maximum bandwidth
- returned: if maxbw is defined
- type: str
- sample: "100M"
-local_Ip:
- description: flow's local IP address
- returned: if local_ip is defined
- type: str
- sample: "10.0.0.42"
-local_port:
- description: flow's local port
- returned: if local_port is defined
- type: int
- sample: 1337
-remote_Ip:
- description: flow's remote IP address
- returned: if remote_ip is defined
- type: str
- sample: "10.0.0.42"
-dsfield:
- description: flow's differentiated services value
- returned: if dsfield is defined
- type: str
- sample: "0x2e:0xfc"
-'''
-
-
-import socket
-
-from ansible.module_utils.basic import AnsibleModule
-
-
-SUPPORTED_TRANSPORTS = ['tcp', 'udp', 'sctp', 'icmp', 'icmpv6']
-SUPPORTED_PRIORITIES = ['low', 'medium', 'high']
-
-SUPPORTED_ATTRIBUTES = ['local_ip', 'remote_ip', 'transport', 'local_port', 'dsfield']
-SUPPORTPED_PROPERTIES = ['maxbw', 'priority']
-
-
-class Flow(object):
-
- def __init__(self, module):
- self.module = module
-
- self.name = module.params['name']
- self.link = module.params['link']
- self.local_ip = module.params['local_ip']
- self.remote_ip = module.params['remote_ip']
- self.transport = module.params['transport']
- self.local_port = module.params['local_port']
- self.dsfield = module.params['dsfield']
- self.maxbw = module.params['maxbw']
- self.priority = module.params['priority']
- self.temporary = module.params['temporary']
- self.state = module.params['state']
-
- self._needs_updating = {
- 'maxbw': False,
- 'priority': False,
- }
-
- @classmethod
- def is_valid_port(cls, port):
- return 1 <= int(port) <= 65535
-
- @classmethod
- def is_valid_address(cls, ip):
-
- if ip.count('/') == 1:
- ip_address, netmask = ip.split('/')
- else:
- ip_address = ip
-
- if len(ip_address.split('.')) == 4:
- try:
- socket.inet_pton(socket.AF_INET, ip_address)
- except socket.error:
- return False
-
- if not 0 <= netmask <= 32:
- return False
- else:
- try:
- socket.inet_pton(socket.AF_INET6, ip_address)
- except socket.error:
- return False
-
- if not 0 <= netmask <= 128:
- return False
-
- return True
-
- @classmethod
- def is_hex(cls, number):
- try:
- int(number, 16)
- except ValueError:
- return False
-
- return True
-
- @classmethod
- def is_valid_dsfield(cls, dsfield):
-
- dsmask = None
-
- if dsfield.count(':') == 1:
- dsval = dsfield.split(':')[0]
- else:
- dsval, dsmask = dsfield.split(':')
-
- if dsmask and not 0x01 <= int(dsmask, 16) <= 0xff and not 0x01 <= int(dsval, 16) <= 0xff:
- return False
- elif not 0x01 <= int(dsval, 16) <= 0xff:
- return False
-
- return True
-
- def flow_exists(self):
- cmd = [self.module.get_bin_path('flowadm')]
-
- cmd.append('show-flow')
- cmd.append(self.name)
-
- (rc, _, _) = self.module.run_command(cmd)
-
- if rc == 0:
- return True
- else:
- return False
-
- def delete_flow(self):
- cmd = [self.module.get_bin_path('flowadm')]
-
- cmd.append('remove-flow')
- if self.temporary:
- cmd.append('-t')
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
- def create_flow(self):
- cmd = [self.module.get_bin_path('flowadm')]
-
- cmd.append('add-flow')
- cmd.append('-l')
- cmd.append(self.link)
-
- if self.local_ip:
- cmd.append('-a')
- cmd.append('local_ip=' + self.local_ip)
-
- if self.remote_ip:
- cmd.append('-a')
- cmd.append('remote_ip=' + self.remote_ip)
-
- if self.transport:
- cmd.append('-a')
- cmd.append('transport=' + self.transport)
-
- if self.local_port:
- cmd.append('-a')
- cmd.append('local_port=' + self.local_port)
-
- if self.dsfield:
- cmd.append('-a')
- cmd.append('dsfield=' + self.dsfield)
-
- if self.maxbw:
- cmd.append('-p')
- cmd.append('maxbw=' + self.maxbw)
-
- if self.priority:
- cmd.append('-p')
- cmd.append('priority=' + self.priority)
-
- if self.temporary:
- cmd.append('-t')
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
- def _query_flow_props(self):
- cmd = [self.module.get_bin_path('flowadm')]
-
- cmd.append('show-flowprop')
- cmd.append('-c')
- cmd.append('-o')
- cmd.append('property,possible')
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
- def flow_needs_udpating(self):
- (rc, out, err) = self._query_flow_props()
-
- NEEDS_UPDATING = False
-
- if rc == 0:
- properties = (line.split(':') for line in out.rstrip().split('\n'))
- for prop, value in properties:
- if prop == 'maxbw' and self.maxbw != value:
- self._needs_updating.update({prop: True})
- NEEDS_UPDATING = True
-
- elif prop == 'priority' and self.priority != value:
- self._needs_updating.update({prop: True})
- NEEDS_UPDATING = True
-
- return NEEDS_UPDATING
- else:
- self.module.fail_json(msg='Error while checking flow properties: %s' % err,
- stderr=err,
- rc=rc)
-
- def update_flow(self):
- cmd = [self.module.get_bin_path('flowadm')]
-
- cmd.append('set-flowprop')
-
- if self.maxbw and self._needs_updating['maxbw']:
- cmd.append('-p')
- cmd.append('maxbw=' + self.maxbw)
-
- if self.priority and self._needs_updating['priority']:
- cmd.append('-p')
- cmd.append('priority=' + self.priority)
-
- if self.temporary:
- cmd.append('-t')
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- name=dict(required=True, aliases=['flow']),
- link=dict(required=False),
- local_ip=dict(required=False),
- remote_ip=dict(required=False),
- transport=dict(required=False, choices=SUPPORTED_TRANSPORTS),
- local_port=dict(required=False),
- dsfield=dict(required=False),
- maxbw=dict(required=False),
- priority=dict(required=False,
- default='medium',
- choices=SUPPORTED_PRIORITIES),
- temporary=dict(default=False, type='bool'),
- state=dict(required=False,
- default='present',
- choices=['absent', 'present', 'resetted']),
- ),
- mutually_exclusive=[
- ('local_ip', 'remote_ip'),
- ('local_ip', 'transport'),
- ('local_ip', 'local_port'),
- ('local_ip', 'dsfield'),
- ('remote_ip', 'transport'),
- ('remote_ip', 'local_port'),
- ('remote_ip', 'dsfield'),
- ('transport', 'dsfield'),
- ('local_port', 'dsfield'),
- ],
- supports_check_mode=True
- )
-
- flow = Flow(module)
-
- rc = None
- out = ''
- err = ''
- result = {}
- result['name'] = flow.name
- result['state'] = flow.state
- result['temporary'] = flow.temporary
-
- if flow.link:
- result['link'] = flow.link
-
- if flow.maxbw:
- result['maxbw'] = flow.maxbw
-
- if flow.priority:
- result['priority'] = flow.priority
-
- if flow.local_ip:
- if flow.is_valid_address(flow.local_ip):
- result['local_ip'] = flow.local_ip
-
- if flow.remote_ip:
- if flow.is_valid_address(flow.remote_ip):
- result['remote_ip'] = flow.remote_ip
-
- if flow.transport:
- result['transport'] = flow.transport
-
- if flow.local_port:
- if flow.is_valid_port(flow.local_port):
- result['local_port'] = flow.local_port
- else:
- module.fail_json(msg='Invalid port: %s' % flow.local_port,
- rc=1)
-
- if flow.dsfield:
- if flow.is_valid_dsfield(flow.dsfield):
- result['dsfield'] = flow.dsfield
- else:
- module.fail_json(msg='Invalid dsfield: %s' % flow.dsfield,
- rc=1)
-
- if flow.state == 'absent':
- if flow.flow_exists():
- if module.check_mode:
- module.exit_json(changed=True)
-
- (rc, out, err) = flow.delete_flow()
- if rc != 0:
- module.fail_json(msg='Error while deleting flow: "%s"' % err,
- name=flow.name,
- stderr=err,
- rc=rc)
-
- elif flow.state == 'present':
- if not flow.flow_exists():
- if module.check_mode:
- module.exit_json(changed=True)
-
- (rc, out, err) = flow.create_flow()
- if rc != 0:
- module.fail_json(msg='Error while creating flow: "%s"' % err,
- name=flow.name,
- stderr=err,
- rc=rc)
- else:
- if flow.flow_needs_udpating():
- (rc, out, err) = flow.update_flow()
- if rc != 0:
- module.fail_json(msg='Error while updating flow: "%s"' % err,
- name=flow.name,
- stderr=err,
- rc=rc)
-
- elif flow.state == 'resetted':
- if flow.flow_exists():
- if module.check_mode:
- module.exit_json(changed=True)
-
- (rc, out, err) = flow.reset_flow()
- if rc != 0:
- module.fail_json(msg='Error while resetting flow: "%s"' % err,
- name=flow.name,
- stderr=err,
- rc=rc)
-
- if rc is None:
- result['changed'] = False
- else:
- result['changed'] = True
-
- if out:
- result['stdout'] = out
- if err:
- result['stderr'] = err
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/illumos/ipadm_addr.py b/plugins/modules/network/illumos/ipadm_addr.py
deleted file mode 100644
index d898d6c4bd..0000000000
--- a/plugins/modules/network/illumos/ipadm_addr.py
+++ /dev/null
@@ -1,403 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2016, Adam Å tevko
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: ipadm_addr
-short_description: Manage IP addresses on an interface on Solaris/illumos systems
-description:
- - Create/delete static/dynamic IP addresses on network interfaces on Solaris/illumos systems.
- - Up/down static/dynamic IP addresses on network interfaces on Solaris/illumos systems.
- - Manage IPv6 link-local addresses on network interfaces on Solaris/illumos systems.
-author: Adam Å tevko (@xen0l)
-options:
- address:
- description:
- - Specifiies an IP address to configure in CIDR notation.
- required: false
- aliases: [ "addr" ]
- addrtype:
- description:
- - Specifiies a type of IP address to configure.
- required: false
- default: static
- choices: [ 'static', 'dhcp', 'addrconf' ]
- addrobj:
- description:
- - Specifies an unique IP address on the system.
- required: true
- temporary:
- description:
- - Specifies that the configured IP address is temporary. Temporary
- IP addresses do not persist across reboots.
- required: false
- default: false
- type: bool
- wait:
- description:
- - Specifies the time in seconds we wait for obtaining address via DHCP.
- required: false
- default: 60
- state:
- description:
- - Create/delete/enable/disable an IP address on the network interface.
- required: false
- default: present
- choices: [ 'absent', 'present', 'up', 'down', 'enabled', 'disabled', 'refreshed' ]
-'''
-
-EXAMPLES = '''
-- name: Configure IP address 10.0.0.1 on e1000g0
- ipadm_addr: addr=10.0.0.1/32 addrobj=e1000g0/v4 state=present
-
-- name: Delete addrobj
- ipadm_addr: addrobj=e1000g0/v4 state=absent
-
-- name: Configure link-local IPv6 address
- ipadm_addr: addtype=addrconf addrobj=vnic0/v6
-
-- name: Configure address via DHCP and wait 180 seconds for address obtaining
- ipadm_addr: addrobj=vnic0/dhcp addrtype=dhcp wait=180
-'''
-
-RETURN = '''
-addrobj:
- description: address object name
- returned: always
- type: str
- sample: bge0/v4
-state:
- description: state of the target
- returned: always
- type: str
- sample: present
-temporary:
- description: specifies if operation will persist across reboots
- returned: always
- type: bool
- sample: True
-addrtype:
- description: address type
- returned: always
- type: str
- sample: static
-address:
- description: IP address
- returned: only if addrtype is 'static'
- type: str
- sample: 1.3.3.7/32
-wait:
- description: time we wait for DHCP
- returned: only if addrtype is 'dhcp'
- type: str
- sample: 10
-'''
-
-import socket
-
-from ansible.module_utils.basic import AnsibleModule
-
-
-SUPPORTED_TYPES = ['static', 'addrconf', 'dhcp']
-
-
-class Addr(object):
-
- def __init__(self, module):
- self.module = module
-
- self.address = module.params['address']
- self.addrtype = module.params['addrtype']
- self.addrobj = module.params['addrobj']
- self.temporary = module.params['temporary']
- self.state = module.params['state']
- self.wait = module.params['wait']
-
- def is_cidr_notation(self):
-
- return self.address.count('/') == 1
-
- def is_valid_address(self):
-
- ip_address = self.address.split('/')[0]
-
- try:
- if len(ip_address.split('.')) == 4:
- socket.inet_pton(socket.AF_INET, ip_address)
- else:
- socket.inet_pton(socket.AF_INET6, ip_address)
- except socket.error:
- return False
-
- return True
-
- def is_dhcp(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('show-addr')
- cmd.append('-p')
- cmd.append('-o')
- cmd.append('type')
- cmd.append(self.addrobj)
-
- (rc, out, err) = self.module.run_command(cmd)
-
- if rc == 0:
- if out.rstrip() != 'dhcp':
- return False
-
- return True
- else:
- self.module.fail_json(msg='Wrong addrtype %s for addrobj "%s": %s' % (out, self.addrobj, err),
- rc=rc,
- stderr=err)
-
- def addrobj_exists(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('show-addr')
- cmd.append(self.addrobj)
-
- (rc, _, _) = self.module.run_command(cmd)
-
- if rc == 0:
- return True
- else:
- return False
-
- def delete_addr(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('delete-addr')
- cmd.append(self.addrobj)
-
- return self.module.run_command(cmd)
-
- def create_addr(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('create-addr')
- cmd.append('-T')
- cmd.append(self.addrtype)
-
- if self.temporary:
- cmd.append('-t')
-
- if self.addrtype == 'static':
- cmd.append('-a')
- cmd.append(self.address)
-
- if self.addrtype == 'dhcp' and self.wait:
- cmd.append('-w')
- cmd.append(self.wait)
-
- cmd.append(self.addrobj)
-
- return self.module.run_command(cmd)
-
- def up_addr(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('up-addr')
-
- if self.temporary:
- cmd.append('-t')
-
- cmd.append(self.addrobj)
-
- return self.module.run_command(cmd)
-
- def down_addr(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('down-addr')
-
- if self.temporary:
- cmd.append('-t')
-
- cmd.append(self.addrobj)
-
- return self.module.run_command(cmd)
-
- def enable_addr(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('enable-addr')
- cmd.append('-t')
- cmd.append(self.addrobj)
-
- return self.module.run_command(cmd)
-
- def disable_addr(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('disable-addr')
- cmd.append('-t')
- cmd.append(self.addrobj)
-
- return self.module.run_command(cmd)
-
- def refresh_addr(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('refresh-addr')
- cmd.append(self.addrobj)
-
- return self.module.run_command(cmd)
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- address=dict(aliases=['addr']),
- addrtype=dict(default='static', choices=SUPPORTED_TYPES),
- addrobj=dict(required=True),
- temporary=dict(default=False, type='bool'),
- state=dict(
- default='present', choices=['absent', 'present', 'up', 'down', 'enabled', 'disabled', 'refreshed']),
- wait=dict(default=60, type='int'),
- ),
- mutually_exclusive=[
- ('address', 'wait'),
- ],
- supports_check_mode=True
- )
-
- addr = Addr(module)
-
- rc = None
- out = ''
- err = ''
- result = {}
- result['addrobj'] = addr.addrobj
- result['state'] = addr.state
- result['temporary'] = addr.temporary
- result['addrtype'] = addr.addrtype
-
- if addr.addrtype == 'static' and addr.address:
- if addr.is_cidr_notation() and addr.is_valid_address():
- result['address'] = addr.address
- else:
- module.fail_json(msg='Invalid IP address: %s' % addr.address)
-
- if addr.addrtype == 'dhcp' and addr.wait:
- result['wait'] = addr.wait
-
- if addr.state == 'absent':
- if addr.addrobj_exists():
- if module.check_mode:
- module.exit_json(changed=True)
-
- (rc, out, err) = addr.delete_addr()
- if rc != 0:
- module.fail_json(msg='Error while deleting addrobj: "%s"' % err,
- addrobj=addr.addrobj,
- stderr=err,
- rc=rc)
-
- elif addr.state == 'present':
- if not addr.addrobj_exists():
- if module.check_mode:
- module.exit_json(changed=True)
-
- (rc, out, err) = addr.create_addr()
- if rc != 0:
- module.fail_json(msg='Error while configuring IP address: "%s"' % err,
- addrobj=addr.addrobj,
- addr=addr.address,
- stderr=err,
- rc=rc)
-
- elif addr.state == 'up':
- if addr.addrobj_exists():
- if module.check_mode:
- module.exit_json(changed=True)
-
- (rc, out, err) = addr.up_addr()
- if rc != 0:
- module.fail_json(msg='Error while bringing IP address up: "%s"' % err,
- addrobj=addr.addrobj,
- stderr=err,
- rc=rc)
-
- elif addr.state == 'down':
- if addr.addrobj_exists():
- if module.check_mode:
- module.exit_json(changed=True)
-
- (rc, out, err) = addr.down_addr()
- if rc != 0:
- module.fail_json(msg='Error while bringing IP address down: "%s"' % err,
- addrobj=addr.addrobj,
- stderr=err,
- rc=rc)
-
- elif addr.state == 'refreshed':
- if addr.addrobj_exists():
- if addr.is_dhcp():
- if module.check_mode:
- module.exit_json(changed=True)
-
- (rc, out, err) = addr.refresh_addr()
- if rc != 0:
- module.fail_json(msg='Error while refreshing IP address: "%s"' % err,
- addrobj=addr.addrobj,
- stderr=err,
- rc=rc)
- else:
- module.fail_json(msg='state "refreshed" cannot be used with "%s" addrtype' % addr.addrtype,
- addrobj=addr.addrobj,
- stderr=err,
- rc=1)
-
- elif addr.state == 'enabled':
- if addr.addrobj_exists():
- if module.check_mode:
- module.exit_json(changed=True)
-
- (rc, out, err) = addr.enable_addr()
- if rc != 0:
- module.fail_json(msg='Error while enabling IP address: "%s"' % err,
- addrobj=addr.addrobj,
- stderr=err,
- rc=rc)
-
- elif addr.state == 'disabled':
- if addr.addrobj_exists():
- if module.check_mode:
- module.exit_json(changed=True)
-
- (rc, out, err) = addr.disable_addr()
- if rc != 0:
- module.fail_json(msg='Error while disabling IP address: "%s"' % err,
- addrobj=addr.addrobj,
- stderr=err,
- rc=rc)
-
- if rc is None:
- result['changed'] = False
- else:
- result['changed'] = True
-
- if out:
- result['stdout'] = out
- if err:
- result['stderr'] = err
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/illumos/ipadm_addrprop.py b/plugins/modules/network/illumos/ipadm_addrprop.py
deleted file mode 100644
index 574c6b3ee4..0000000000
--- a/plugins/modules/network/illumos/ipadm_addrprop.py
+++ /dev/null
@@ -1,259 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2016, Adam Å tevko
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: ipadm_addrprop
-short_description: Manage IP address properties on Solaris/illumos systems.
-description:
- - Modify IP address properties on Solaris/illumos systems.
-author: Adam Å tevko (@xen0l)
-options:
- addrobj:
- description:
- - Specifies the address object we want to manage.
- required: true
- aliases: [nic, interface]
- property:
- description:
- - Specifies the name of the address property we want to manage.
- required: true
- aliases: [name]
- value:
- description:
- - Specifies the value we want to set for the address property.
- required: false
- temporary:
- description:
- - Specifies that the address property value is temporary.
- Temporary values do not persist across reboots.
- required: false
- default: false
- type: bool
- state:
- description:
- - Set or reset the property value.
- required: false
- default: present
- choices: [ "present", "absent", "reset" ]
-'''
-
-EXAMPLES = '''
-- name: Mark address on addrobj as deprecated
- ipadm_addrprop: property=deprecated value=on addrobj=e1000g0/v6
-
-- name: Set network prefix length for addrobj
- ipadm_addrprop: addrobj=bge0/v4 name=prefixlen value=26
-'''
-
-RETURN = '''
-property:
- description: property name
- returned: always
- type: str
- sample: deprecated
-addrobj:
- description: address object name
- returned: always
- type: str
- sample: bge0/v4
-state:
- description: state of the target
- returned: always
- type: str
- sample: present
-temporary:
- description: specifies if operation will persist across reboots
- returned: always
- type: bool
- sample: True
-value:
- description: property value
- returned: when value is provided
- type: str
- sample: 26
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-
-
-class AddrProp(object):
-
- def __init__(self, module):
- self.module = module
-
- self.addrobj = module.params['addrobj']
- self.property = module.params['property']
- self.value = module.params['value']
- self.temporary = module.params['temporary']
- self.state = module.params['state']
-
- def property_exists(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('show-addrprop')
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append(self.addrobj)
-
- (rc, _, _) = self.module.run_command(cmd)
-
- if rc == 0:
- return True
- else:
- self.module.fail_json(msg='Unknown property "%s" on addrobj %s' %
- (self.property, self.addrobj),
- property=self.property,
- addrobj=self.addrobj)
-
- def property_is_modified(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('show-addrprop')
- cmd.append('-c')
- cmd.append('-o')
- cmd.append('current,default')
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append(self.addrobj)
-
- (rc, out, _) = self.module.run_command(cmd)
-
- out = out.rstrip()
- (value, default) = out.split(':')
-
- if rc == 0 and value == default:
- return True
- else:
- return False
-
- def property_is_set(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('show-addrprop')
- cmd.append('-c')
- cmd.append('-o')
- cmd.append('current')
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append(self.addrobj)
-
- (rc, out, _) = self.module.run_command(cmd)
-
- out = out.rstrip()
-
- if rc == 0 and self.value == out:
- return True
- else:
- return False
-
- def set_property(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('set-addrprop')
-
- if self.temporary:
- cmd.append('-t')
-
- cmd.append('-p')
- cmd.append(self.property + '=' + self.value)
- cmd.append(self.addrobj)
-
- return self.module.run_command(cmd)
-
- def reset_property(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('reset-addrprop')
-
- if self.temporary:
- cmd.append('-t')
-
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append(self.addrobj)
-
- return self.module.run_command(cmd)
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- addrobj=dict(required=True, default=None, aliases=['nic', 'interface']),
- property=dict(required=True, aliases=['name']),
- value=dict(required=False),
- temporary=dict(default=False, type='bool'),
- state=dict(
- default='present', choices=['absent', 'present', 'reset']),
- ),
- supports_check_mode=True
- )
-
- addrprop = AddrProp(module)
-
- rc = None
- out = ''
- err = ''
- result = {}
- result['property'] = addrprop.property
- result['addrobj'] = addrprop.addrobj
- result['state'] = addrprop.state
- result['temporary'] = addrprop.temporary
- if addrprop.value:
- result['value'] = addrprop.value
-
- if addrprop.state == 'absent' or addrprop.state == 'reset':
- if addrprop.property_exists():
- if not addrprop.property_is_modified():
- if module.check_mode:
- module.exit_json(changed=True)
- (rc, out, err) = addrprop.reset_property()
- if rc != 0:
- module.fail_json(property=addrprop.property,
- addrobj=addrprop.addrobj,
- msg=err,
- rc=rc)
-
- elif addrprop.state == 'present':
- if addrprop.value is None:
- module.fail_json(msg='Value is mandatory with state "present"')
-
- if addrprop.property_exists():
- if not addrprop.property_is_set():
- if module.check_mode:
- module.exit_json(changed=True)
-
- (rc, out, err) = addrprop.set_property()
- if rc != 0:
- module.fail_json(property=addrprop.property,
- addrobj=addrprop.addrobj,
- msg=err,
- rc=rc)
-
- if rc is None:
- result['changed'] = False
- else:
- result['changed'] = True
-
- if out:
- result['stdout'] = out
- if err:
- result['stderr'] = err
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/illumos/ipadm_if.py b/plugins/modules/network/illumos/ipadm_if.py
deleted file mode 100644
index 89da9a8553..0000000000
--- a/plugins/modules/network/illumos/ipadm_if.py
+++ /dev/null
@@ -1,221 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2015, Adam Å tevko
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: ipadm_if
-short_description: Manage IP interfaces on Solaris/illumos systems.
-description:
- - Create, delete, enable or disable IP interfaces on Solaris/illumos
- systems.
-author: Adam Å tevko (@xen0l)
-options:
- name:
- description:
- - IP interface name.
- required: true
- temporary:
- description:
- - Specifies that the IP interface is temporary. Temporary IP
- interfaces do not persist across reboots.
- required: false
- default: false
- type: bool
- state:
- description:
- - Create or delete Solaris/illumos IP interfaces.
- required: false
- default: "present"
- choices: [ "present", "absent", "enabled", "disabled" ]
-'''
-
-EXAMPLES = '''
-# Create vnic0 interface
-- ipadm_if:
- name: vnic0
- state: enabled
-
-# Disable vnic0 interface
-- ipadm_if:
- name: vnic0
- state: disabled
-'''
-
-RETURN = '''
-name:
- description: IP interface name
- returned: always
- type: str
- sample: "vnic0"
-state:
- description: state of the target
- returned: always
- type: str
- sample: "present"
-temporary:
- description: persistence of a IP interface
- returned: always
- type: bool
- sample: "True"
-'''
-from ansible.module_utils.basic import AnsibleModule
-
-
-class IPInterface(object):
-
- def __init__(self, module):
- self.module = module
-
- self.name = module.params['name']
- self.temporary = module.params['temporary']
- self.state = module.params['state']
-
- def interface_exists(self):
- cmd = [self.module.get_bin_path('ipadm', True)]
-
- cmd.append('show-if')
- cmd.append(self.name)
-
- (rc, _, _) = self.module.run_command(cmd)
- if rc == 0:
- return True
- else:
- return False
-
- def interface_is_disabled(self):
- cmd = [self.module.get_bin_path('ipadm', True)]
-
- cmd.append('show-if')
- cmd.append('-o')
- cmd.append('state')
- cmd.append(self.name)
-
- (rc, out, err) = self.module.run_command(cmd)
- if rc != 0:
- self.module.fail_json(name=self.name, rc=rc, msg=err)
-
- return 'disabled' in out
-
- def create_interface(self):
- cmd = [self.module.get_bin_path('ipadm', True)]
-
- cmd.append('create-if')
-
- if self.temporary:
- cmd.append('-t')
-
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
- def delete_interface(self):
- cmd = [self.module.get_bin_path('ipadm', True)]
-
- cmd.append('delete-if')
-
- if self.temporary:
- cmd.append('-t')
-
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
- def enable_interface(self):
- cmd = [self.module.get_bin_path('ipadm', True)]
-
- cmd.append('enable-if')
- cmd.append('-t')
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
- def disable_interface(self):
- cmd = [self.module.get_bin_path('ipadm', True)]
-
- cmd.append('disable-if')
- cmd.append('-t')
- cmd.append(self.name)
-
- return self.module.run_command(cmd)
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- name=dict(required=True),
- temporary=dict(default=False, type='bool'),
- state=dict(default='present', choices=['absent',
- 'present',
- 'enabled',
- 'disabled']),
- ),
- supports_check_mode=True
- )
-
- interface = IPInterface(module)
-
- rc = None
- out = ''
- err = ''
- result = {}
- result['name'] = interface.name
- result['state'] = interface.state
- result['temporary'] = interface.temporary
-
- if interface.state == 'absent':
- if interface.interface_exists():
- if module.check_mode:
- module.exit_json(changed=True)
- (rc, out, err) = interface.delete_interface()
- if rc != 0:
- module.fail_json(name=interface.name, msg=err, rc=rc)
- elif interface.state == 'present':
- if not interface.interface_exists():
- if module.check_mode:
- module.exit_json(changed=True)
- (rc, out, err) = interface.create_interface()
-
- if rc is not None and rc != 0:
- module.fail_json(name=interface.name, msg=err, rc=rc)
-
- elif interface.state == 'enabled':
- if interface.interface_is_disabled():
- (rc, out, err) = interface.enable_interface()
-
- if rc is not None and rc != 0:
- module.fail_json(name=interface.name, msg=err, rc=rc)
-
- elif interface.state == 'disabled':
- if not interface.interface_is_disabled():
- (rc, out, err) = interface.disable_interface()
-
- if rc is not None and rc != 0:
- module.fail_json(name=interface.name, msg=err, rc=rc)
-
- if rc is None:
- result['changed'] = False
- else:
- result['changed'] = True
-
- if out:
- result['stdout'] = out
- if err:
- result['stderr'] = err
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/illumos/ipadm_ifprop.py b/plugins/modules/network/illumos/ipadm_ifprop.py
deleted file mode 100644
index 3ba86abe81..0000000000
--- a/plugins/modules/network/illumos/ipadm_ifprop.py
+++ /dev/null
@@ -1,287 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2016, Adam Å tevko
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: ipadm_ifprop
-short_description: Manage IP interface properties on Solaris/illumos systems.
-description:
- - Modify IP interface properties on Solaris/illumos systems.
-author: Adam Å tevko (@xen0l)
-options:
- interface:
- description:
- - Specifies the IP interface we want to manage.
- required: true
- aliases: [nic]
- protocol:
- description:
- - Specifies the protocol for which we want to manage properties.
- required: true
- property:
- description:
- - Specifies the name of the property we want to manage.
- required: true
- aliases: [name]
- value:
- description:
- - Specifies the value we want to set for the property.
- required: false
- temporary:
- description:
- - Specifies that the property value is temporary. Temporary
- property values do not persist across reboots.
- required: false
- default: false
- type: bool
- state:
- description:
- - Set or reset the property value.
- required: false
- default: present
- choices: [ "present", "absent", "reset" ]
-'''
-
-EXAMPLES = '''
-- name: Allow forwarding of IPv4 packets on network interface e1000g0
- ipadm_ifprop: protocol=ipv4 property=forwarding value=on interface=e1000g0
-
-- name: Temporarily reset IPv4 forwarding property on network interface e1000g0
- ipadm_ifprop: protocol=ipv4 interface=e1000g0 temporary=true property=forwarding state=reset
-
-- name: Configure IPv6 metric on network interface e1000g0
- ipadm_ifprop: protocol=ipv6 nic=e1000g0 name=metric value=100
-
-- name: Set IPv6 MTU on network interface bge0
- ipadm_ifprop: interface=bge0 name=mtu value=1280 protocol=ipv6
-'''
-
-RETURN = '''
-protocol:
- description: property's protocol
- returned: always
- type: str
- sample: ipv4
-property:
- description: property's name
- returned: always
- type: str
- sample: mtu
-interface:
- description: interface name we want to set property on
- returned: always
- type: str
- sample: e1000g0
-state:
- description: state of the target
- returned: always
- type: str
- sample: present
-value:
- description: property's value
- returned: when value is provided
- type: str
- sample: 1280
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-
-
-SUPPORTED_PROTOCOLS = ['ipv4', 'ipv6']
-
-
-class IfProp(object):
-
- def __init__(self, module):
- self.module = module
-
- self.interface = module.params['interface']
- self.protocol = module.params['protocol']
- self.property = module.params['property']
- self.value = module.params['value']
- self.temporary = module.params['temporary']
- self.state = module.params['state']
-
- def property_exists(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('show-ifprop')
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append('-m')
- cmd.append(self.protocol)
- cmd.append(self.interface)
-
- (rc, _, _) = self.module.run_command(cmd)
-
- if rc == 0:
- return True
- else:
- self.module.fail_json(msg='Unknown %s property "%s" on IP interface %s' %
- (self.protocol, self.property, self.interface),
- protocol=self.protocol,
- property=self.property,
- interface=self.interface)
-
- def property_is_modified(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('show-ifprop')
- cmd.append('-c')
- cmd.append('-o')
- cmd.append('current,default')
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append('-m')
- cmd.append(self.protocol)
- cmd.append(self.interface)
-
- (rc, out, _) = self.module.run_command(cmd)
-
- out = out.rstrip()
- (value, default) = out.split(':')
-
- if rc == 0 and value == default:
- return True
- else:
- return False
-
- def property_is_set(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('show-ifprop')
- cmd.append('-c')
- cmd.append('-o')
- cmd.append('current')
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append('-m')
- cmd.append(self.protocol)
- cmd.append(self.interface)
-
- (rc, out, _) = self.module.run_command(cmd)
-
- out = out.rstrip()
-
- if rc == 0 and self.value == out:
- return True
- else:
- return False
-
- def set_property(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('set-ifprop')
-
- if self.temporary:
- cmd.append('-t')
-
- cmd.append('-p')
- cmd.append(self.property + "=" + self.value)
- cmd.append('-m')
- cmd.append(self.protocol)
- cmd.append(self.interface)
-
- return self.module.run_command(cmd)
-
- def reset_property(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('reset-ifprop')
-
- if self.temporary:
- cmd.append('-t')
-
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append('-m')
- cmd.append(self.protocol)
- cmd.append(self.interface)
-
- return self.module.run_command(cmd)
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- protocol=dict(required=True, choices=SUPPORTED_PROTOCOLS),
- property=dict(required=True, aliases=['name']),
- value=dict(required=False),
- temporary=dict(default=False, type='bool'),
- interface=dict(required=True, default=None, aliases=['nic']),
- state=dict(
- default='present', choices=['absent', 'present', 'reset']),
- ),
- supports_check_mode=True
- )
-
- ifprop = IfProp(module)
-
- rc = None
- out = ''
- err = ''
- result = {}
- result['protocol'] = ifprop.protocol
- result['property'] = ifprop.property
- result['interface'] = ifprop.interface
- result['state'] = ifprop.state
- if ifprop.value:
- result['value'] = ifprop.value
-
- if ifprop.state == 'absent' or ifprop.state == 'reset':
- if ifprop.property_exists():
- if not ifprop.property_is_modified():
- if module.check_mode:
- module.exit_json(changed=True)
- (rc, out, err) = ifprop.reset_property()
- if rc != 0:
- module.fail_json(protocol=ifprop.protocol,
- property=ifprop.property,
- interface=ifprop.interface,
- msg=err,
- rc=rc)
-
- elif ifprop.state == 'present':
- if ifprop.value is None:
- module.fail_json(msg='Value is mandatory with state "present"')
-
- if ifprop.property_exists():
- if not ifprop.property_is_set():
- if module.check_mode:
- module.exit_json(changed=True)
-
- (rc, out, err) = ifprop.set_property()
- if rc != 0:
- module.fail_json(protocol=ifprop.protocol,
- property=ifprop.property,
- interface=ifprop.interface,
- msg=err,
- rc=rc)
-
- if rc is None:
- result['changed'] = False
- else:
- result['changed'] = True
-
- if out:
- result['stdout'] = out
- if err:
- result['stderr'] = err
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/illumos/ipadm_prop.py b/plugins/modules/network/illumos/ipadm_prop.py
deleted file mode 100644
index 83512c4c80..0000000000
--- a/plugins/modules/network/illumos/ipadm_prop.py
+++ /dev/null
@@ -1,260 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2015, Adam Å tevko
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: ipadm_prop
-short_description: Manage protocol properties on Solaris/illumos systems.
-description:
- - Modify protocol properties on Solaris/illumos systems.
-author: Adam Å tevko (@xen0l)
-options:
- protocol:
- description:
- - Specifies the protocol for which we want to manage properties.
- required: true
- property:
- description:
- - Specifies the name of property we want to manage.
- required: true
- value:
- description:
- - Specifies the value we want to set for the property.
- required: false
- temporary:
- description:
- - Specifies that the property value is temporary. Temporary
- property values do not persist across reboots.
- required: false
- default: false
- type: bool
- state:
- description:
- - Set or reset the property value.
- required: false
- default: present
- choices: [ "present", "absent", "reset" ]
-'''
-
-EXAMPLES = '''
-# Set TCP receive buffer size
-- ipadm_prop: protocol=tcp property=recv_buf value=65536
-
-# Reset UDP send buffer size to the default value
-- ipadm_prop: protocol=udp property=send_buf state=reset
-'''
-
-RETURN = '''
-protocol:
- description: property's protocol
- returned: always
- type: str
- sample: "TCP"
-property:
- description: name of the property
- returned: always
- type: str
- sample: "recv_maxbuf"
-state:
- description: state of the target
- returned: always
- type: str
- sample: "present"
-temporary:
- description: property's persistence
- returned: always
- type: bool
- sample: "True"
-value:
- description: value of the property. May be int or string depending on property.
- returned: always
- type: int
- sample: "'1024' or 'never'"
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-
-
-SUPPORTED_PROTOCOLS = ['ipv4', 'ipv6', 'icmp', 'tcp', 'udp', 'sctp']
-
-
-class Prop(object):
-
- def __init__(self, module):
- self.module = module
-
- self.protocol = module.params['protocol']
- self.property = module.params['property']
- self.value = module.params['value']
- self.temporary = module.params['temporary']
- self.state = module.params['state']
-
- def property_exists(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('show-prop')
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append(self.protocol)
-
- (rc, _, _) = self.module.run_command(cmd)
-
- if rc == 0:
- return True
- else:
- self.module.fail_json(msg='Unknown property "%s" for protocol %s' %
- (self.property, self.protocol),
- protocol=self.protocol,
- property=self.property)
-
- def property_is_modified(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('show-prop')
- cmd.append('-c')
- cmd.append('-o')
- cmd.append('current,default')
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append(self.protocol)
-
- (rc, out, _) = self.module.run_command(cmd)
-
- out = out.rstrip()
- (value, default) = out.split(':')
-
- if rc == 0 and value == default:
- return True
- else:
- return False
-
- def property_is_set(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('show-prop')
- cmd.append('-c')
- cmd.append('-o')
- cmd.append('current')
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append(self.protocol)
-
- (rc, out, _) = self.module.run_command(cmd)
-
- out = out.rstrip()
-
- if rc == 0 and self.value == out:
- return True
- else:
- return False
-
- def set_property(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('set-prop')
-
- if self.temporary:
- cmd.append('-t')
-
- cmd.append('-p')
- cmd.append(self.property + "=" + self.value)
- cmd.append(self.protocol)
-
- return self.module.run_command(cmd)
-
- def reset_property(self):
- cmd = [self.module.get_bin_path('ipadm')]
-
- cmd.append('reset-prop')
-
- if self.temporary:
- cmd.append('-t')
-
- cmd.append('-p')
- cmd.append(self.property)
- cmd.append(self.protocol)
-
- return self.module.run_command(cmd)
-
-
-def main():
- module = AnsibleModule(
- argument_spec=dict(
- protocol=dict(required=True, choices=SUPPORTED_PROTOCOLS),
- property=dict(required=True),
- value=dict(required=False),
- temporary=dict(default=False, type='bool'),
- state=dict(
- default='present', choices=['absent', 'present', 'reset']),
- ),
- supports_check_mode=True
- )
-
- prop = Prop(module)
-
- rc = None
- out = ''
- err = ''
- result = {}
- result['protocol'] = prop.protocol
- result['property'] = prop.property
- result['state'] = prop.state
- result['temporary'] = prop.temporary
- if prop.value:
- result['value'] = prop.value
-
- if prop.state == 'absent' or prop.state == 'reset':
- if prop.property_exists():
- if not prop.property_is_modified():
- if module.check_mode:
- module.exit_json(changed=True)
- (rc, out, err) = prop.reset_property()
- if rc != 0:
- module.fail_json(protocol=prop.protocol,
- property=prop.property,
- msg=err,
- rc=rc)
-
- elif prop.state == 'present':
- if prop.value is None:
- module.fail_json(msg='Value is mandatory with state "present"')
-
- if prop.property_exists():
- if not prop.property_is_set():
- if module.check_mode:
- module.exit_json(changed=True)
-
- (rc, out, err) = prop.set_property()
- if rc != 0:
- module.fail_json(protocol=prop.protocol,
- property=prop.property,
- msg=err,
- rc=rc)
-
- if rc is None:
- result['changed'] = False
- else:
- result['changed'] = True
-
- if out:
- result['stdout'] = out
- if err:
- result['stderr'] = err
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/ingate/ig_config.py b/plugins/modules/network/ingate/ig_config.py
deleted file mode 100644
index 5e02e6c4c1..0000000000
--- a/plugins/modules/network/ingate/ig_config.py
+++ /dev/null
@@ -1,567 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2018, Ingate Systems AB
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: ig_config
-short_description: Manage the configuration database on an Ingate SBC.
-description:
- - Manage the configuration database on an Ingate SBC.
-extends_documentation_fragment:
-- community.general.ingate
-
-options:
- add:
- description:
- - Add a row to a table.
- type: bool
- delete:
- description:
- - Delete all rows in a table or a specific row.
- type: bool
- get:
- description:
- - Return all rows in a table or a specific row.
- type: bool
- modify:
- description:
- - Modify a row in a table.
- type: bool
- revert:
- description:
- - Reset the preliminary configuration.
- type: bool
- factory:
- description:
- - Reset the preliminary configuration to its factory defaults.
- type: bool
- store:
- description:
- - Store the preliminary configuration.
- type: bool
- no_response:
- description:
- - Expect no response when storing the preliminary configuration.
- Refer to the C(store) option.
- type: bool
- return_rowid:
- description:
- - Get rowid(s) from a table where the columns match.
- type: bool
- download:
- description:
- - Download the configuration database from the unit.
- type: bool
- store_download:
- description:
- - If the downloaded configuration should be stored on disk.
- Refer to the C(download) option.
- type: bool
- default: false
- path:
- description:
- - Where in the filesystem to store the downloaded configuration.
- Refer to the C(download) option.
- filename:
- description:
- - The name of the file to store the downloaded configuration in.
- Refer to the C(download) option.
- table:
- description:
- - The name of the table.
- rowid:
- description:
- - A row id.
- type: int
- columns:
- description:
- - A dict containing column names/values.
-notes:
- - If C(store_download) is set to True, and C(path) and C(filename) is omitted,
- the file will be stored in the current directory with an automatic filename.
-author:
- - Ingate Systems AB (@ingatesystems)
-'''
-
-EXAMPLES = '''
-- name: Add/remove DNS servers
- hosts: 192.168.1.1
- connection: local
- vars:
- client_rw:
- version: v1
- address: "{{ inventory_hostname }}"
- scheme: http
- username: alice
- password: foobar
- tasks:
-
- - name: Load factory defaults
- ig_config:
- client: "{{ client_rw }}"
- factory: true
- register: result
- - debug:
- var: result
-
- - name: Revert to last known applied configuration
- ig_config:
- client: "{{ client_rw }}"
- revert: true
- register: result
- - debug:
- var: result
-
- - name: Change the unit name
- ig_config:
- client: "{{ client_rw }}"
- modify: true
- table: misc.unitname
- columns:
- unitname: "Test Ansible"
- register: result
- - debug:
- var: result
-
- - name: Add a DNS server
- ig_config:
- client: "{{ client_rw }}"
- add: true
- table: misc.dns_servers
- columns:
- server: 192.168.1.21
- register: result
- - debug:
- var: result
-
- - name: Add a DNS server
- ig_config:
- client: "{{ client_rw }}"
- add: true
- table: misc.dns_servers
- columns:
- server: 192.168.1.22
- register: result
- - debug:
- var: result
-
- - name: Add a DNS server
- ig_config:
- client: "{{ client_rw }}"
- add: true
- table: misc.dns_servers
- columns:
- server: 192.168.1.23
- register: last_dns
- - debug:
- var: last_dns
-
- - name: Modify the last added DNS server
- ig_config:
- client: "{{ client_rw }}"
- modify: true
- table: misc.dns_servers
- rowid: "{{ last_dns['add'][0]['id'] }}"
- columns:
- server: 192.168.1.24
- register: result
- - debug:
- var: result
-
- - name: Return the last added DNS server
- ig_config:
- client: "{{ client_rw }}"
- get: true
- table: misc.dns_servers
- rowid: "{{ last_dns['add'][0]['id'] }}"
- register: result
- - debug:
- var: result
-
- - name: Remove last added DNS server
- ig_config:
- client: "{{ client_rw }}"
- delete: true
- table: misc.dns_servers
- rowid: "{{ last_dns['add'][0]['id'] }}"
- register: result
- - debug:
- var: result
-
- - name: Return the all rows from table misc.dns_servers
- ig_config:
- client: "{{ client_rw }}"
- get: true
- table: misc.dns_servers
- register: result
- - debug:
- var: result
-
- - name: Remove remaining DNS servers
- ig_config:
- client: "{{ client_rw }}"
- delete: true
- table: misc.dns_servers
- register: result
- - debug:
- var: result
-
- - name: Get rowid for interface eth0
- ig_config:
- client: "{{ client_rw }}"
- return_rowid: true
- table: network.local_nets
- columns:
- interface: eth0
- register: result
- - debug:
- var: result
-
- - name: Store the preliminary configuration
- ig_config:
- client: "{{ client_rw }}"
- store: true
- register: result
- - debug:
- var: result
-
- - name: Do backup of the configuration database
- ig_config:
- client: "{{ client_rw }}"
- download: true
- store_download: true
- register: result
- - debug:
- var: result
-'''
-
-RETURN = '''
-add:
- description: A list containing information about the added row
- returned: when C(add) is yes and success
- type: complex
- contains:
- href:
- description: The REST API URL to the added row
- returned: success
- type: str
- sample: http://192.168.1.1/api/v1/misc/dns_servers/2
- data:
- description: Column names/values
- returned: success
- type: complex
- sample: {'number': '2', 'server': '10.48.254.33'}
- id:
- description: The row id
- returned: success
- type: int
- sample: 22
-delete:
- description: A list containing information about the deleted row(s)
- returned: when C(delete) is yes and success
- type: complex
- contains:
- table:
- description: The name of the table
- returned: success
- type: str
- sample: misc.dns_servers
- data:
- description: Column names/values
- returned: success
- type: complex
- sample: {'number': '2', 'server': '10.48.254.33'}
- id:
- description: The row id
- returned: success
- type: int
- sample: 22
-get:
- description: A list containing information about the row(s)
- returned: when C(get) is yes and success
- type: complex
- contains:
- table:
- description: The name of the table
- returned: success
- type: str
- sample: Testname
- href:
- description: The REST API URL to the row
- returned: success
- type: str
- sample: http://192.168.1.1/api/v1/misc/dns_servers/1
- data:
- description: Column names/values
- returned: success
- type: complex
- sample: {'number': '2', 'server': '10.48.254.33'}
- id:
- description: The row id
- returned: success
- type: int
- sample: 1
-modify:
- description: A list containing information about the modified row
- returned: when C(modify) is yes and success
- type: complex
- contains:
- table:
- description: The name of the table
- returned: success
- type: str
- sample: Testname
- href:
- description: The REST API URL to the modified row
- returned: success
- type: str
- sample: http://192.168.1.1/api/v1/misc/dns_servers/1
- data:
- description: Column names/values
- returned: success
- type: complex
- sample: {'number': '2', 'server': '10.48.254.33'}
- id:
- description: The row id
- returned: success
- type: int
- sample: 10
-revert:
- description: A command status message
- returned: when C(revert) is yes and success
- type: complex
- contains:
- msg:
- description: The command status message
- returned: success
- type: str
- sample: reverted the configuration to the last applied configuration.
-factory:
- description: A command status message
- returned: when C(factory) is yes and success
- type: complex
- contains:
- msg:
- description: The command status message
- returned: success
- type: str
- sample: reverted the configuration to the factory configuration.
-store:
- description: A command status message
- returned: when C(store) is yes and success
- type: complex
- contains:
- msg:
- description: The command status message
- returned: success
- type: str
- sample: Successfully applied and saved the configuration.
-return_rowid:
- description: The matched row id(s).
- returned: when C(return_rowid) is yes and success
- type: list
- sample: [1, 3]
-download:
- description: Configuration database and meta data
- returned: when C(download) is yes and success
- type: complex
- contains:
- config:
- description: The configuration database
- returned: success
- type: str
- filename:
- description: A suggested name for the configuration
- returned: success
- type: str
- sample: testname_2018-10-01T214040.cfg
- mimetype:
- description: The mimetype
- returned: success
- type: str
- sample: application/x-config-database
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.ingate.common import (ingate_argument_spec,
- ingate_create_client)
-
-try:
- from ingate import ingatesdk
- HAS_INGATESDK = True
-except ImportError:
- HAS_INGATESDK = False
-
-
-def make_request(module):
- # Create client and authenticate.
- api_client = ingate_create_client(**module.params)
-
- if module.params.get('add'):
- # Add a row to a table.
- table = module.params['table']
- columns = module.params['columns']
- response = api_client.add_row(table, **columns)
- return True, 'add', response
- elif module.params.get('delete'):
- # Delete a row/table.
- changed = False
- table = module.params['table']
- rowid = module.params.get('rowid')
- if rowid:
- response = api_client.delete_row(table, rowid=rowid)
- else:
- response = api_client.delete_table(table)
- if response:
- changed = True
- return changed, 'delete', response
- elif module.params.get('get'):
- # Get the contents of a table/row.
- table = module.params['table']
- rowid = module.params.get('rowid')
- if rowid:
- response = api_client.dump_row(table, rowid=rowid)
- else:
- response = api_client.dump_table(table)
- if response:
- changed = True
- return changed, 'get', response
- elif module.params.get('modify'):
- # Modify a table row.
- table = module.params['table']
- columns = module.params['columns']
- rowid = module.params.get('rowid')
- if rowid:
- response = api_client.modify_row(table, rowid=rowid, **columns)
- else:
- response = api_client.modify_single_row(table, **columns)
- if response:
- changed = True
- return changed, 'modify', response
- elif module.params.get('revert'):
- # Revert edits.
- response = api_client.revert_edits()
- if response:
- response = response[0]['revert-edits']
- return True, 'revert', response
- elif module.params.get('factory'):
- # Load factory defaults.
- response = api_client.load_factory()
- if response:
- response = response[0]['load-factory']
- return True, 'factory', response
- elif module.params.get('store'):
- # Store edit.
- no_response = module.params.get('no_response')
- response = api_client.store_edit(no_response=no_response)
- if response:
- response = response[0]['store-edit']
- return True, 'store', response
- elif module.params.get('return_rowid'):
- # Find matching rowid(s) in a table.
- table = module.params['table']
- columns = module.params['columns']
- response = api_client.dump_table(table)
- rowids = []
- for row in response:
- match = False
- for (name, value) in columns.items():
- if name not in row['data']:
- continue
- if not row['data'][name] == value:
- match = False
- break
- else:
- match = True
- if match:
- rowids.append(row['id'])
- return False, 'return_rowid', rowids
- elif module.params.get('download'):
- # Download the configuration database.
- store = module.params.get('store_download')
- path = module.params.get('path')
- filename = module.params.get('filename')
- response = api_client.download_config(store=store, path=path,
- filename=filename)
- if response:
- response = response[0]['download-config']
- return False, 'download', response
- return False, '', {}
-
-
-def main():
- argument_spec = ingate_argument_spec(
- add=dict(type='bool'),
- delete=dict(type='bool'),
- get=dict(type='bool'),
- modify=dict(type='bool'),
- revert=dict(type='bool'),
- factory=dict(type='bool'),
- store=dict(type='bool'),
- no_response=dict(type='bool', default=False),
- return_rowid=dict(type='bool'),
- download=dict(type='bool'),
- store_download=dict(type='bool', default=False),
- path=dict(),
- filename=dict(),
- table=dict(),
- rowid=dict(type='int'),
- columns=dict(type='dict'),
- )
-
- mutually_exclusive = [('add', 'delete', 'get', 'modify', 'revert',
- 'factory', 'store', 'return_rowid', 'download')]
- required_one_of = [['add', 'delete', 'get', 'modify', 'revert', 'factory',
- 'store', 'return_rowid', 'download']]
- required_if = [('add', True, ['table', 'columns']),
- ('delete', True, ['table']),
- ('get', True, ['table']),
- ('modify', True, ['table', 'columns']),
- ('return_rowid', True, ['table', 'columns'])]
-
- module = AnsibleModule(argument_spec=argument_spec,
- mutually_exclusive=mutually_exclusive,
- required_if=required_if,
- required_one_of=required_one_of,
- supports_check_mode=False)
- if not HAS_INGATESDK:
- module.fail_json(msg='The Ingate Python SDK module is required')
-
- result = dict(changed=False)
- try:
- changed, command, response = make_request(module)
- if response and command:
- result[command] = response
- result['changed'] = changed
- except ingatesdk.SdkError as e:
- module.fail_json(msg=str(e))
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/ingate/ig_unit_information.py b/plugins/modules/network/ingate/ig_unit_information.py
deleted file mode 100644
index 4727d46f4a..0000000000
--- a/plugins/modules/network/ingate/ig_unit_information.py
+++ /dev/null
@@ -1,162 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Ingate Systems AB
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {
- 'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'
-}
-
-DOCUMENTATION = '''
----
-module: ig_unit_information
-short_description: Get unit information from an Ingate SBC.
-description:
- - Get unit information from an Ingate SBC.
-extends_documentation_fragment:
-- community.general.ingate
-
-author:
- - Ingate Systems AB (@ingatesystems)
-'''
-
-EXAMPLES = '''
-- name: Get unit information
- ig_unit_information:
- client:
- version: v1
- scheme: http
- address: 192.168.1.1
- username: alice
- password: foobar
-'''
-
-RETURN = '''
-unit-information:
- description: Information about the unit
- returned: success
- type: complex
- contains:
- installid:
- description: The installation identifier
- returned: success
- type: str
- sample: any
- interfaces:
- description: List of interface names
- returned: success
- type: str
- sample: eth0 eth1 eth2 eth3 eth4 eth5
- lang:
- description: The unit's language
- returned: success
- type: str
- sample: en
- lic_email:
- description: License email information
- returned: success
- type: str
- sample: example@example.com
- lic_mac:
- description: License MAC information
- returned: success
- type: str
- sample: any
- lic_name:
- description: License name information
- returned: success
- type: str
- sample: Example Inc
- macaddr:
- description: The MAC address of the first interface
- returned: success
- type: str
- sample: 52:54:00:4c:e2:07
- mode:
- description: Operational mode of the unit
- returned: success
- type: str
- sample: Siparator
- modules:
- description: Installed module licenses
- returned: success
- type: str
- sample: failover vpn sip qturn ems qos rsc voipsm
- patches:
- description: Installed patches on the unit
- returned: success
- type: list
- sample: []
- product:
- description: The product name
- returned: success
- type: str
- sample: Software SIParator/Firewall
- serial:
- description: The serial number of the unit
- returned: success
- type: str
- sample: IG-200-839-2008-0
- systemid:
- description: The system identifier of the unit
- returned: success
- type: str
- sample: IG-200-839-2008-0
- unitname:
- description: The name of the unit
- returned: success
- type: str
- sample: Testname
- version:
- description: Firmware version
- returned: success
- type: str
- sample: 6.2.0-beta2
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils._text import to_native
-from ansible_collections.community.general.plugins.module_utils.network.ingate.common import (ingate_argument_spec,
- ingate_create_client,
- is_ingatesdk_installed)
-
-try:
- from ingate import ingatesdk
-except ImportError:
- pass
-
-
-def make_request(module):
- # Create client and authenticate.
- api_client = ingate_create_client(**module.params)
-
- # Get unit information.
- response = api_client.unit_information()
- return response
-
-
-def main():
- argument_spec = ingate_argument_spec()
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=False)
-
- is_ingatesdk_installed(module)
-
- result = dict(changed=False)
- try:
- response = make_request(module)
- result.update(response[0])
- except ingatesdk.SdkError as e:
- module.fail_json(msg=to_native(e))
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/ironware/ironware_command.py b/plugins/modules/network/ironware/ironware_command.py
deleted file mode 100644
index 9584fd17bc..0000000000
--- a/plugins/modules/network/ironware/ironware_command.py
+++ /dev/null
@@ -1,173 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: ironware_command
-author: "Paul Baker (@paulquack)"
-short_description: Run arbitrary commands on Extreme IronWare devices
-description:
- - Sends arbitrary commands to a Extreme Ironware node and returns the
- results read from the device. This module includes a I(wait_for)
- argument that will cause the module to wait for a specific condition
- before returning or timing out if the condition is not met.
-extends_documentation_fragment:
-- community.general.ironware
-
-options:
- commands:
- description:
- - List of commands to send to the remote device over the
- configured provider. The resulting output from the command
- is returned. If the I(wait_for) argument is provided, the
- module is not returned until the condition is satisfied or
- the number of retires as expired.
- required: true
- wait_for:
- description:
- - List of conditions to evaluate against the output of the
- command. The task will wait for each condition to be true
- before moving forward. If the conditional is not true
- within the configured number of retries, the task fails.
- See examples.
- match:
- description:
- - The I(match) argument is used in conjunction with the
- I(wait_for) argument to specify the match policy. If the value
- is set to C(all) then all conditionals in the I(wait_for) must be
- satisfied. If the value is set to C(any) then only one of the
- values must be satisfied.
- default: all
- choices: ['any', 'all']
- retries:
- description:
- - Specifies the number of retries a command should by tried
- before it is considered failed. The command is run on the
- target device every retry and evaluated against the
- I(wait_for) conditions.
- default: 10
- interval:
- description:
- - Configures the interval in seconds to wait between retries
- of the command. If the command does not pass the specified
- conditions, the interval indicates how long to wait before
- trying the command again.
- default: 1
-'''
-
-EXAMPLES = """
-- ironware_command:
- commands:
- - show version
-
-- ironware_command:
- commands:
- - show interfaces brief wide
- - show mpls vll
-"""
-
-RETURN = """
-stdout:
- description: the set of responses from the commands
- returned: always
- type: list
- sample: ['...', '...']
-
-stdout_lines:
- description: The value of stdout split into a list
- returned: always
- type: list
- sample: [['...', '...'], ['...'], ['...']]
-
-failed_conditions:
- description: the conditionals that failed
- returned: failed
- type: list
- sample: ['...', '...']
-"""
-import time
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.ironware.ironware import ironware_argument_spec, check_args
-from ansible_collections.community.general.plugins.module_utils.network.ironware.ironware import run_commands
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import Conditional
-from ansible.module_utils.six import string_types
-
-
-def to_lines(stdout):
- for item in stdout:
- if isinstance(item, string_types):
- item = str(item).split('\n')
- yield item
-
-
-def main():
- spec = dict(
- # { command: , prompt: , response: }
- commands=dict(type='list', required=True),
-
- wait_for=dict(type='list'),
- match=dict(default='all', choices=['all', 'any']),
-
- retries=dict(default=10, type='int'),
- interval=dict(default=1, type='int')
- )
-
- spec.update(ironware_argument_spec)
-
- module = AnsibleModule(argument_spec=spec, supports_check_mode=True)
- check_args(module)
-
- result = {'changed': False}
-
- wait_for = module.params['wait_for'] or list()
- conditionals = [Conditional(c) for c in wait_for]
-
- commands = module.params['commands']
- retries = module.params['retries']
- interval = module.params['interval']
- match = module.params['match']
-
- while retries > 0:
- responses = run_commands(module, commands)
-
- for item in list(conditionals):
- if item(responses):
- if match == 'any':
- conditionals = list()
- break
- conditionals.remove(item)
-
- if not conditionals:
- break
-
- time.sleep(interval)
- retries -= 1
-
- if conditionals:
- failed_conditions = [item.raw for item in conditionals]
- msg = 'One or more conditional statements have not been satisfied'
- module.fail_json(msg=msg, failed_conditions=failed_conditions)
-
- result.update({
- 'changed': False,
- 'stdout': responses,
- 'stdout_lines': list(to_lines(responses))
- })
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/ironware/ironware_config.py b/plugins/modules/network/ironware/ironware_config.py
deleted file mode 100644
index 02e59fec00..0000000000
--- a/plugins/modules/network/ironware/ironware_config.py
+++ /dev/null
@@ -1,291 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: ironware_config
-author: "Paul Baker (@paulquack)"
-short_description: Manage configuration sections on Extreme Ironware devices
-description:
- - Extreme Ironware configurations use a simple block indent file syntax
- for segmenting configuration into sections. This module provides
- an implementation for working with Ironware configuration sections in
- a deterministic way.
-extends_documentation_fragment:
-- community.general.ironware
-
-options:
- lines:
- description:
- - The ordered set of commands that should be configured in the
- section. The commands must be the exact same commands as found
- in the device running-config. Be sure to note the configuration
- command syntax as some commands are automatically modified by the
- device config parser.
- aliases: ['commands']
- parents:
- description:
- - The ordered set of parents that uniquely identify the section
- the commands should be checked against. If the parents argument
- is omitted, the commands are checked against the set of top
- level or global commands.
- src:
- description:
- - Specifies the source path to the file that contains the configuration
- or configuration template to load. The path to the source file can
- either be the full path on the Ansible control host or a relative
- path from the playbook or role root directory. This argument is mutually
- exclusive with I(lines), I(parents).
- before:
- description:
- - The ordered set of commands to push on to the command stack if
- a change needs to be made. This allows the playbook designer
- the opportunity to perform configuration commands prior to pushing
- any changes without affecting how the set of commands are matched
- against the system
- after:
- description:
- - The ordered set of commands to append to the end of the command
- stack if a change needs to be made. Just like with I(before) this
- allows the playbook designer to append a set of commands to be
- executed after the command set.
- match:
- description:
- - Instructs the module on the way to perform the matching of
- the set of commands against the current device config. If
- match is set to I(line), commands are matched line by line. If
- match is set to I(strict), command lines are matched with respect
- to position. If match is set to I(exact), command lines
- must be an equal match. Finally, if match is set to I(none), the
- module will not attempt to compare the source configuration with
- the running configuration on the remote device.
- default: line
- choices: ['line', 'strict', 'exact', 'none']
- replace:
- description:
- - Instructs the module on the way to perform the configuration
- on the device. If the replace argument is set to I(line) then
- the modified lines are pushed to the device in configuration
- mode. If the replace argument is set to I(block) then the entire
- command block is pushed to the device in configuration mode if any
- line is not correct
- default: line
- choices: ['line', 'block']
- update:
- description:
- - The I(update) argument controls how the configuration statements
- are processed on the remote device. Valid choices for the I(update)
- argument are I(merge) and I(check). When the argument is set to
- I(merge), the configuration changes are merged with the current
- device running configuration. When the argument is set to I(check)
- the configuration updates are determined but not actually configured
- on the remote device.
- default: merge
- choices: ['merge', 'check']
- commit:
- description:
- - This argument specifies the update method to use when applying the
- configuration changes to the remote node. If the value is set to
- I(merge) the configuration updates are merged with the running-
- config. If the value is set to I(check), no changes are made to
- the remote host.
- default: merge
- choices: ['merge', 'check']
- backup:
- description:
- - This argument will cause the module to create a full backup of
- the current C(running-config) from the remote device before any
- changes are made. If the C(backup_options) value is not given,
- the backup file is written to the C(backup) folder in the playbook
- root directory. If the directory does not exist, it is created.
- type: bool
- default: 'no'
- config:
- description:
- - The C(config) argument allows the playbook designer to supply
- the base configuration to be used to validate configuration
- changes necessary. If this argument is provided, the module
- will not download the running-config from the remote node.
- save_when:
- description:
- - When changes are made to the device running-configuration, the
- changes are not copied to non-volatile storage by default. Using
- this argument will change that before. If the argument is set to
- I(always), then the running-config will always be copied to the
- startup-config and the I(modified) flag will always be set to
- True. If the argument is set to I(modified), then the running-config
- will only be copied to the startup-config if it has changed since
- the last save to startup-config. If the argument is set to
- I(never), the running-config will never be copied to the
- startup-config
- default: never
- choices: ['always', 'never', 'modified']
- backup_options:
- description:
- - This is a dict object containing configurable options related to backup file path.
- The value of this option is read only when C(backup) is set to I(yes), if C(backup) is set
- to I(no) this option will be silently ignored.
- suboptions:
- filename:
- description:
- - The filename to be used to store the backup configuration. If the filename
- is not given it will be generated based on the hostname, current time and date
- in format defined by _config.@
- dir_path:
- description:
- - This option provides the path ending with directory name in which the backup
- configuration file will be stored. If the directory does not exist it will be first
- created and the filename is either the value of C(filename) or default filename
- as described in C(filename) options description. If the path value is not given
- in that case a I(backup) directory will be created in the current working directory
- and backup configuration will be copied in C(filename) within I(backup) directory.
- type: path
- type: dict
-'''
-
-EXAMPLES = """
-- ironware_config:
- lines:
- - port-name test
- - enable
- - load-interval 30
- - rate-limit input broadcast unknown-unicast multicast 521216 64000
- parents: ['interface ethernet 1/2']
-"""
-
-RETURN = """
-updates:
- description: The set of commands that will be pushed to the remote device
- returned: always
- type: list
- sample: ['...', '...']
-backup_path:
- description: The full path to the backup file
- returned: when backup is yes
- type: str
- sample: /playbooks/ansible/backup/ironware_config.2016-07-16@22:28:34
-"""
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.ironware.ironware import ironware_argument_spec, check_args
-from ansible_collections.community.general.plugins.module_utils.network.ironware.ironware import get_config, load_config, run_commands
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, dumps
-
-
-def get_candidate(module):
- candidate = NetworkConfig(indent=1)
- if module.params['src']:
- candidate.load(module.params['src'])
- elif module.params['lines']:
- parents = module.params['parents'] or list()
- candidate.add(module.params['lines'], parents=parents)
- return candidate
-
-
-def run(module, result):
- match = module.params['match']
- replace = module.params['replace']
- path = module.params['parents']
- configobjs = None
-
- candidate = get_candidate(module)
- if match != 'none':
- contents = module.params['config']
- if not contents:
- contents = get_config(module)
- config = NetworkConfig(indent=1, contents=contents)
- configobjs = candidate.difference(config, path=path, match=match,
- replace=replace)
-
- else:
- configobjs = candidate.items
- if configobjs:
- commands = dumps(configobjs, 'commands').split('\n')
-
- if module.params['lines']:
- if module.params['before']:
- commands[:0] = module.params['before']
-
- if module.params['after']:
- commands.extend(module.params['after'])
-
- result['updates'] = commands
-
- # send the configuration commands to the device and merge
- # them with the current running config
- if not module.check_mode:
- load_config(module, commands)
- result['changed'] = True
-
- if result['changed'] or module.params['save_when'] == 'always':
- result['changed'] = True
- if not module.check_mode:
- cmd = {'command': 'write memory'}
- run_commands(module, [cmd])
-
-
-def main():
- """ main entry point for module execution
- """
- backup_spec = dict(
- filename=dict(),
- dir_path=dict(type='path')
- )
- argument_spec = dict(
- src=dict(type='path'),
-
- lines=dict(aliases=['commands'], type='list'),
- parents=dict(type='list'),
-
- before=dict(type='list'),
- after=dict(type='list'),
-
- match=dict(default='line', choices=['line', 'strict', 'exact', 'none']),
- replace=dict(default='line', choices=['line', 'block']),
-
- config=dict(),
-
- backup=dict(type='bool', default=False),
- backup_options=dict(type='dict', options=backup_spec),
- save_when=dict(choices=['always', 'never', 'modified'], default='never')
-
- )
-
- argument_spec.update(ironware_argument_spec)
-
- mutually_exclusive = [('lines', 'src'),
- ('parents', 'src')]
-
- required_if = [('match', 'strict', ['lines']),
- ('match', 'exact', ['lines']),
- ('replace', 'block', ['lines'])]
-
- module = AnsibleModule(argument_spec=argument_spec,
- mutually_exclusive=mutually_exclusive,
- required_if=required_if,
- supports_check_mode=True)
-
- result = {'changed': False}
-
- check_args(module)
-
- if module.params['backup']:
- result['__backup__'] = get_config(module)
-
- run(module, result)
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/ironware/ironware_facts.py b/plugins/modules/network/ironware/ironware_facts.py
deleted file mode 100644
index 1aa738dbeb..0000000000
--- a/plugins/modules/network/ironware/ironware_facts.py
+++ /dev/null
@@ -1,652 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: ironware_facts
-author: "Paul Baker (@paulquack)"
-short_description: Collect facts from devices running Extreme Ironware
-description:
- - Collects a base set of device facts from a remote device that
- is running Ironware. This module prepends all of the
- base network fact keys with C(ansible_net_). The facts
- module will always collect a base set of facts from the device
- and can enable or disable collection of additional facts.
-extends_documentation_fragment:
-- community.general.ironware
-
-notes:
- - Tested against Ironware 5.8e
-options:
- gather_subset:
- description:
- - When supplied, this argument will restrict the facts collected
- to a given subset. Possible values for this argument include
- all, hardware, config, mpls and interfaces. Can specify a list of
- values to include a larger subset. Values can also be used
- with an initial C(M(!)) to specify that a specific subset should
- not be collected.
- required: false
- default: ['!config','!mpls']
-'''
-
-EXAMPLES = """
-# Collect all facts from the device
-- ironware_facts:
- gather_subset: all
-
-# Collect only the config and default facts
-- ironware_facts:
- gather_subset:
- - config
-
-# Do not collect hardware facts
-- ironware_facts:
- gather_subset:
- - "!hardware"
-"""
-
-RETURN = """
-ansible_net_gather_subset:
- description: The list of fact subsets collected from the device
- returned: always
- type: list
-
-# default
-ansible_net_model:
- description: The model name returned from the device
- returned: always
- type: str
-ansible_net_serialnum:
- description: The serial number of the remote device
- returned: always
- type: str
-ansible_net_version:
- description: The operating system version running on the remote device
- returned: always
- type: str
-
-# hardware
-ansible_net_filesystems:
- description: All file system names available on the device
- returned: when hardware is configured
- type: list
-ansible_net_memfree_mb:
- description: The available free memory on the remote device in Mb
- returned: when hardware is configured
- type: int
-ansible_net_memtotal_mb:
- description: The total memory on the remote device in Mb
- returned: when hardware is configured
- type: int
-
-# config
-ansible_net_config:
- description: The current active config from the device
- returned: when config is configured
- type: str
-
-# mpls
-ansible_net_mpls_lsps:
- description: All MPLS LSPs configured on the device
- returned: When LSP is configured
- type: dict
-ansible_net_mpls_vll:
- description: All VLL instances configured on the device
- returned: When MPLS VLL is configured
- type: dict
-ansible_net_mpls_vll_local:
- description: All VLL-LOCAL instances configured on the device
- returned: When MPLS VLL-LOCAL is configured
- type: dict
-ansible_net_mpls_vpls:
- description: All VPLS instances configured on the device
- returned: When MPLS VPLS is configured
- type: dict
-
-# interfaces
-ansible_net_all_ipv4_addresses:
- description: All IPv4 addresses configured on the device
- returned: when interfaces is configured
- type: list
-ansible_net_all_ipv6_addresses:
- description: All IPv6 addresses configured on the device
- returned: when interfaces is configured
- type: list
-ansible_net_interfaces:
- description: A hash of all interfaces running on the system
- returned: when interfaces is configured
- type: dict
-ansible_net_neighbors:
- description: The list of LLDP neighbors from the remote device
- returned: when interfaces is configured
- type: dict
-"""
-import re
-
-from ansible_collections.community.general.plugins.module_utils.network.ironware.ironware import run_commands
-from ansible_collections.community.general.plugins.module_utils.network.ironware.ironware import ironware_argument_spec, check_args
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.six import iteritems
-
-
-class FactsBase(object):
-
- COMMANDS = list()
-
- def __init__(self, module):
- self.module = module
- self.facts = dict()
- self.responses = None
-
- def populate(self):
- self.responses = run_commands(self.module, self.COMMANDS, check_rc=False)
-
- def run(self, cmd):
- return run_commands(self.module, cmd, check_rc=False)
-
-
-class Default(FactsBase):
-
- COMMANDS = [
- 'show version',
- 'show chassis'
- ]
-
- def populate(self):
- super(Default, self).populate()
- data = self.responses[0]
- if data:
- self.facts['version'] = self.parse_version(data)
- self.facts['serialnum'] = self.parse_serialnum(data)
-
- data = self.responses[1]
- if data:
- self.facts['model'] = self.parse_model(data)
-
- def parse_version(self, data):
- match = re.search(r'IronWare : Version (\S+)', data)
- if match:
- return match.group(1)
-
- def parse_model(self, data):
- match = re.search(r'^\*\*\* (.+) \*\*\*$', data, re.M)
- if match:
- return match.group(1)
-
- def parse_serialnum(self, data):
- match = re.search(r'Serial #: (\S+),', data)
- if match:
- return match.group(1)
-
-
-class Hardware(FactsBase):
-
- COMMANDS = [
- 'dir | include Directory',
- 'show memory'
- ]
-
- def populate(self):
- super(Hardware, self).populate()
- data = self.responses[0]
- if data:
- self.facts['filesystems'] = self.parse_filesystems(data)
-
- data = self.responses[1]
- if data:
- self.facts['memtotal_mb'] = int(round(int(self.parse_memtotal(data)) / 1024 / 1024, 0))
- self.facts['memfree_mb'] = int(round(int(self.parse_memfree(data)) / 1024 / 1024, 0))
-
- def parse_filesystems(self, data):
- return re.findall(r'^Directory of (\S+)', data, re.M)
-
- def parse_memtotal(self, data):
- match = re.search(r'Total SDRAM\D*(\d+)\s', data, re.M)
- if match:
- return match.group(1)
-
- def parse_memfree(self, data):
- match = re.search(r'(Total Free Memory|Available Memory)\D*(\d+)\s', data, re.M)
- if match:
- return match.group(2)
-
-
-class Config(FactsBase):
-
- COMMANDS = ['show running-config']
-
- def populate(self):
- super(Config, self).populate()
- data = self.responses[0]
- if data:
- self.facts['config'] = data
-
-
-class MPLS(FactsBase):
-
- COMMANDS = [
- 'show mpls lsp detail',
- 'show mpls vll-local detail',
- 'show mpls vll detail',
- 'show mpls vpls detail'
- ]
-
- def populate(self):
- super(MPLS, self).populate()
- data = self.responses[0]
- if data:
- data = self.parse_mpls(data)
- self.facts['mpls_lsps'] = self.populate_lsps(data)
-
- data = self.responses[1]
- if data:
- data = self.parse_mpls(data)
- self.facts['mpls_vll_local'] = self.populate_vll_local(data)
-
- data = self.responses[2]
- if data:
- data = self.parse_mpls(data)
- self.facts['mpls_vll'] = self.populate_vll(data)
-
- data = self.responses[3]
- if data:
- data = self.parse_mpls(data)
- self.facts['mpls_vpls'] = self.populate_vpls(data)
-
- def parse_mpls(self, data):
- parsed = dict()
- for line in data.split('\n'):
- if not line:
- continue
- elif line[0] == ' ':
- parsed[key] += '\n%s' % line
- else:
- match = re.match(r'^(LSP|VLL|VPLS) ([^\s,]+)', line)
- if match:
- key = match.group(2)
- parsed[key] = line
- return parsed
-
- def populate_vpls(self, vpls):
- facts = dict()
- for key, value in iteritems(vpls):
- vpls = dict()
- vpls['endpoints'] = self.parse_vpls_endpoints(value)
- vpls['vc-id'] = self.parse_vpls_vcid(value)
- facts[key] = vpls
- return facts
-
- def populate_vll_local(self, vll_locals):
- facts = dict()
- for key, value in iteritems(vll_locals):
- vll = dict()
- vll['endpoints'] = self.parse_vll_endpoints(value)
- facts[key] = vll
- return facts
-
- def populate_vll(self, vlls):
- facts = dict()
- for key, value in iteritems(vlls):
- vll = dict()
- vll['endpoints'] = self.parse_vll_endpoints(value)
- vll['vc-id'] = self.parse_vll_vcid(value)
- vll['cos'] = self.parse_vll_cos(value)
- facts[key] = vll
- return facts
-
- def parse_vll_vcid(self, data):
- match = re.search(r'VC-ID (\d+),', data, re.M)
- if match:
- return match.group(1)
-
- def parse_vll_cos(self, data):
- match = re.search(r'COS +: +(\d+)', data, re.M)
- if match:
- return match.group(1)
-
- def parse_vll_endpoints(self, data):
- facts = list()
- regex = r'End-point[0-9 ]*: +(?Ptagged|untagged) +(vlan +(?P[0-9]+) +)?(inner- vlan +(?P[0-9]+) +)?(?Pe [0-9/]+|--)'
- matches = re.finditer(regex, data, re.IGNORECASE | re.DOTALL)
- for match in matches:
- f = match.groupdict()
- f['type'] = 'local'
- facts.append(f)
-
- regex = r'Vll-Peer +: +(?P[0-9\.]+).*Tunnel LSP +: +(?P\S+)'
- matches = re.finditer(regex, data, re.IGNORECASE | re.DOTALL)
- for match in matches:
- f = match.groupdict()
- f['type'] = 'remote'
- facts.append(f)
-
- return facts
-
- def parse_vpls_vcid(self, data):
- match = re.search(r'Id (\d+),', data, re.M)
- if match:
- return match.group(1)
-
- def parse_vpls_endpoints(self, data):
- facts = list()
- regex = r'Vlan (?P[0-9]+)\s(?: +(?:L2.*)\s| +Tagged: (?P.+)+\s| +Untagged: (?P.+)\s)*'
- matches = re.finditer(regex, data, re.IGNORECASE)
- for match in matches:
- f = match.groupdict()
- f['type'] = 'local'
- facts.append(f)
-
- regex = r'Peer address: (?P[0-9\.]+)'
- matches = re.finditer(regex, data, re.IGNORECASE)
- for match in matches:
- f = match.groupdict()
- f['type'] = 'remote'
- facts.append(f)
-
- return facts
-
- def populate_lsps(self, lsps):
- facts = dict()
- for key, value in iteritems(lsps):
- lsp = dict()
- lsp['to'] = self.parse_lsp_to(value)
- lsp['from'] = self.parse_lsp_from(value)
- lsp['adminstatus'] = self.parse_lsp_adminstatus(value)
- lsp['operstatus'] = self.parse_lsp_operstatus(value)
- lsp['pri_path'] = self.parse_lsp_pripath(value)
- lsp['sec_path'] = self.parse_lsp_secpath(value)
- lsp['frr'] = self.parse_lsp_frr(value)
-
- facts[key] = lsp
-
- return facts
-
- def parse_lsp_to(self, data):
- match = re.search(r'^LSP .* to (\S+)', data, re.M)
- if match:
- return match.group(1)
-
- def parse_lsp_from(self, data):
- match = re.search(r'From: ([^\s,]+),', data, re.M)
- if match:
- return match.group(1)
-
- def parse_lsp_adminstatus(self, data):
- match = re.search(r'admin: (\w+),', data, re.M)
- if match:
- return match.group(1)
-
- def parse_lsp_operstatus(self, data):
- match = re.search(r'From: .* status: (\w+)', data, re.M)
- if match:
- return match.group(1)
-
- def parse_lsp_pripath(self, data):
- match = re.search(r'Pri\. path: ([^\s,]+), up: (\w+), active: (\w+)', data, re.M)
- if match:
- path = dict()
- path['name'] = match.group(1) if match.group(1) != 'NONE' else None
- path['up'] = True if match.group(2) == 'yes' else False
- path['active'] = True if match.group(3) == 'yes' else False
- return path
-
- def parse_lsp_secpath(self, data):
- match = re.search(r'Sec\. path: ([^\s,]+), active: (\w+).*\n.* status: (\w+)', data, re.M)
- if match:
- path = dict()
- path['name'] = match.group(1) if match.group(1) != 'NONE' else None
- path['up'] = True if match.group(3) == 'up' else False
- path['active'] = True if match.group(2) == 'yes' else False
- return path
-
- def parse_lsp_frr(self, data):
- match = re.search(r'Backup LSP: (\w+)', data, re.M)
- if match:
- path = dict()
- path['up'] = True if match.group(1) == 'UP' else False
- path['name'] = None
- if path['up']:
- match = re.search(r'bypass_lsp: (\S)', data, re.M)
- path['name'] = match.group(1) if match else None
- return path
-
-
-class Interfaces(FactsBase):
-
- COMMANDS = [
- 'show interfaces',
- 'show ipv6 interface',
- 'show lldp neighbors'
- ]
-
- def populate(self):
- super(Interfaces, self).populate()
-
- self.facts['all_ipv4_addresses'] = list()
- self.facts['all_ipv6_addresses'] = list()
-
- data = self.responses[0]
- if data:
- interfaces = self.parse_interfaces(data)
- self.facts['interfaces'] = self.populate_interfaces(interfaces)
-
- data = self.responses[1]
- if data:
- data = self.parse_interfaces(data)
- self.populate_ipv6_interfaces(data)
-
- data = self.responses[2]
- if data and 'LLDP is not running' not in data:
- self.facts['neighbors'] = self.parse_neighbors(data)
-
- def populate_interfaces(self, interfaces):
- facts = dict()
- for key, value in iteritems(interfaces):
- intf = dict()
- intf['description'] = self.parse_description(value)
- intf['macaddress'] = self.parse_macaddress(value)
-
- ipv4 = self.parse_ipv4(value)
- intf['ipv4'] = self.parse_ipv4(value)
- if ipv4:
- self.add_ip_address(ipv4['address'], 'ipv4')
-
- intf['mtu'] = self.parse_mtu(value)
- intf['bandwidth'] = self.parse_bandwidth(value)
- intf['duplex'] = self.parse_duplex(value)
- intf['lineprotocol'] = self.parse_lineprotocol(value)
- intf['operstatus'] = self.parse_operstatus(value)
- intf['type'] = self.parse_type(value)
-
- facts[key] = intf
- return facts
-
- def populate_ipv6_interfaces(self, data):
- for key, value in iteritems(data):
- self.facts['interfaces'][key]['ipv6'] = list()
- addresses = re.findall(r'\s([0-9a-f]+:+[0-9a-f:]+\/\d+)\s', value, re.M)
- for addr in addresses:
- address, masklen = addr.split('/')
- ipv6 = dict(address=address, masklen=int(masklen))
- self.add_ip_address(ipv6['address'], 'ipv6')
- self.facts['interfaces'][key]['ipv6'].append(ipv6)
-
- def add_ip_address(self, address, family):
- if family == 'ipv4':
- self.facts['all_ipv4_addresses'].append(address)
- else:
- self.facts['all_ipv6_addresses'].append(address)
-
- def parse_neighbors(self, neighbors):
- facts = dict()
- for line in neighbors.split('\n'):
- if line == '':
- continue
- match = re.search(r'([\d\/]+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)', line, re.M)
- if match:
- intf = match.group(1)
- if intf not in facts:
- facts[intf] = list()
- fact = dict()
- fact['host'] = match.group(5)
- fact['port'] = match.group(3)
- facts[intf].append(fact)
- return facts
-
- def parse_interfaces(self, data):
- parsed = dict()
- for line in data.split('\n'):
- if not line:
- continue
- elif line[0] == ' ':
- parsed[key] += '\n%s' % line
- else:
- match = re.match(r'^(\S+Ethernet|eth )(\S+)', line)
- if match:
- key = match.group(2)
- parsed[key] = line
- return parsed
-
- def parse_description(self, data):
- match = re.search(r'Port name is (.+)$', data, re.M)
- if match:
- return match.group(1)
-
- def parse_macaddress(self, data):
- match = re.search(r'address is (\S+)', data)
- if match:
- return match.group(1)
-
- def parse_ipv4(self, data):
- match = re.search(r'Internet address is ([^\s,]+)', data)
- if match:
- addr, masklen = match.group(1).split('/')
- return dict(address=addr, masklen=int(masklen))
-
- def parse_mtu(self, data):
- match = re.search(r'MTU (\d+)', data)
- if match:
- return int(match.group(1))
-
- def parse_bandwidth(self, data):
- match = re.search(r'BW is (\d+)', data)
- if match:
- return int(match.group(1))
-
- def parse_duplex(self, data):
- match = re.search(r'configured duplex \S+ actual (\S+)', data, re.M)
- if match:
- return match.group(1)
-
- def parse_mediatype(self, data):
- match = re.search(r'Type\s*:\s*(.+)$', data, re.M)
- if match:
- return match.group(1)
-
- def parse_type(self, data):
- match = re.search(r'Hardware is (.+),', data, re.M)
- if match:
- return match.group(1)
-
- def parse_lineprotocol(self, data):
- match = re.search(r'line protocol is (\S+)', data, re.M)
- if match:
- return match.group(1)
-
- def parse_operstatus(self, data):
- match = re.search(r'^(?:.+) is (.+),', data, re.M)
- if match:
- return match.group(1)
-
-
-FACT_SUBSETS = dict(
- default=Default,
- hardware=Hardware,
- interfaces=Interfaces,
- config=Config,
- mpls=MPLS,
-)
-
-VALID_SUBSETS = frozenset(FACT_SUBSETS.keys())
-
-
-def main():
- """main entry point for module execution
- """
- argument_spec = dict(
- gather_subset=dict(default=["!config", "!mpls"], type='list')
- )
-
- argument_spec.update(ironware_argument_spec)
-
- module = AnsibleModule(argument_spec=argument_spec,
- supports_check_mode=True)
-
- gather_subset = module.params['gather_subset']
-
- runable_subsets = set()
- exclude_subsets = set()
-
- for subset in gather_subset:
- if subset == 'all':
- runable_subsets.update(VALID_SUBSETS)
- continue
-
- if subset.startswith('!'):
- subset = subset[1:]
- if subset == 'all':
- exclude_subsets.update(VALID_SUBSETS)
- continue
- exclude = True
- else:
- exclude = False
-
- if subset not in VALID_SUBSETS:
- module.fail_json(msg='Bad subset')
-
- if exclude:
- exclude_subsets.add(subset)
- else:
- runable_subsets.add(subset)
-
- if not runable_subsets:
- runable_subsets.update(VALID_SUBSETS)
-
- runable_subsets.difference_update(exclude_subsets)
- runable_subsets.add('default')
-
- facts = dict()
- facts['gather_subset'] = list(runable_subsets)
-
- instances = list()
- for key in runable_subsets:
- instances.append(FACT_SUBSETS[key](module))
-
- for inst in instances:
- inst.populate()
- facts.update(inst.facts)
-
- ansible_facts = dict()
- for key, value in iteritems(facts):
- key = 'ansible_net_%s' % key
- ansible_facts[key] = value
-
- check_args(module)
-
- module.exit_json(ansible_facts=ansible_facts)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/itential/iap_start_workflow.py b/plugins/modules/network/itential/iap_start_workflow.py
deleted file mode 100644
index 9717cc3977..0000000000
--- a/plugins/modules/network/itential/iap_start_workflow.py
+++ /dev/null
@@ -1,183 +0,0 @@
-#!/usr/bin/python
-
-# Copyright: (c) 2018, Itential
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-This module provides the ability to start a workflow from Itential Automation Platform
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: iap_start_workflow
-author: "Itential (@cma0) "
-short_description: Start a workflow in the Itential Automation Platform
-description:
- - This will start a specified workflow in the Itential Automation Platform with given arguments.
-options:
- iap_port:
- description:
- - Provide the port number for the Itential Automation Platform
- required: true
- type: str
- default: null
-
- iap_fqdn:
- description:
- - Provide the fqdn for the Itential Automation Platform
- required: true
- type: str
- default: null
-
- token_key:
- description:
- - Token key generated by iap_token module for the Itential Automation Platform
- required: true
- type: str
- default: null
-
- workflow_name:
- description:
- - Provide the workflow name
- required: true
- type: str
- default: null
-
- description:
- description:
- - Provide the description for the workflow
- required: true
- type: str
- default: null
-
- variables:
- description:
- - Provide the values to the job variables
- required: true
- type: dict
- default: null
-
- https:
- description:
- - Use HTTPS to connect
- - By default using http
- type: bool
- default: False
-
- validate_certs:
- description:
- - If C(no), SSL certificates for the target url will not be validated. This should only be used
- on personally controlled sites using self-signed certificates.
- type: bool
- default: False
-'''
-
-EXAMPLES = '''
-- name: Start a workflow in the Itential Automation Platform
- iap_start_workflow:
- iap_port: 3000
- iap_fqdn: localhost
- token_key: "DFSFSFHFGFGF[DSFSFAADAFASD%3D"
- workflow_name: "RouterUpgradeWorkflow"
- description: "OS-Router-Upgrade"
- variables: {"deviceName":"ASR9K"}
- register: result
-
-- debug: var=result
-'''
-
-RETURN = '''
-response:
- description: The result contains the response from the call
- type: dict
- returned: always
-msg:
- description: The msg will contain the error code or status of the workflow
- type: str
- returned: always
-'''
-
-# Ansible imports
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.urls import fetch_url
-
-# Standard library imports
-import json
-
-
-def start_workflow(module):
- """
- :param module:
- :return: response and msg
- """
- # By default this will be http.
- # By default when using https, self signed certificate is used
- # If https needs to pass certificate then use validate_certs as true
- if module.params['https']:
- transport_protocol = 'https'
- else:
- transport_protocol = 'http'
-
- application_token = str(module.params['token_key'])
- url = str(transport_protocol) + "://" + str(module.params['iap_fqdn']) + ":" + str(module.params[
- 'iap_port']) + "/workflow_engine/startJobWithOptions/" \
- + str(module.params['workflow_name']) + "?token=" + str(application_token)
- options = {
- "variables": module.params['variables'],
- "description": str(module.params['description'])
- }
-
- payload = {
- "workflow": module.params['workflow_name'],
- "options": options
- }
-
- json_body = module.jsonify(payload)
- headers = dict()
- headers['Content-Type'] = 'application/json'
-
- # Using fetch url instead of requests
- response, info = fetch_url(module, url, data=json_body, headers=headers)
- response_code = str(info['status'])
- if info['status'] not in [200, 201]:
- module.fail_json(msg="Failed to connect to Itential Automation Platform. Response code is " + response_code)
-
- # in the event of a successful module execution, you will want to
- # simple AnsibleModule.exit_json(), passing the key/value results
- jsonResponse = json.loads(response.read().decode('utf-8'))
- module.exit_json(changed=True, msg={"workflow_name": module.params['workflow_name'], "status": "started"},
- response=jsonResponse)
-
-
-def main():
- """
- :return: response and msg
- """
- # define the available arguments/parameters that a user can pass to
- # the module
- # the AnsibleModule object will be our abstraction working with Ansible
- # this includes instantiation, a couple of common attr would be the
- # args/params passed to the execution, as well as if the module
- # supports check mode
- module = AnsibleModule(
- argument_spec=dict(
- iap_port=dict(type='str', required=True),
- iap_fqdn=dict(type='str', required=True),
- token_key=dict(type='str', required=True),
- workflow_name=dict(type='str', required=True),
- description=dict(type='str', required=True),
- variables=dict(type='dict', required=False),
- https=(dict(type='bool', default=False)),
- validate_certs=dict(type='bool', default=False)
- )
- )
- start_workflow(module)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/itential/iap_token.py b/plugins/modules/network/itential/iap_token.py
deleted file mode 100644
index 96b5607ca4..0000000000
--- a/plugins/modules/network/itential/iap_token.py
+++ /dev/null
@@ -1,142 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright: (c) 2018, Itential
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-This module provides the token for Itential Automation Platform
-"""
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: iap_token
-author: "Itential (@cma0) "
-short_description: Get token for the Itential Automation Platform
-description:
- - Checks the connection to IAP and retrieves a login token.
-options:
- iap_port:
- description:
- - Provide the port number for the Itential Automation Platform
- required: true
- default: null
-
- iap_fqdn:
- description:
- - Provide the fqdn or ip-address for the Itential Automation Platform
- required: true
- default: null
-
- username:
- description:
- - Provide the username for the Itential Automation Platform
- required: true
- default: null
-
- password:
- description:
- - Provide the password for the Itential Automation Platform
- required: true
- default: null
-
- https:
- description:
- - Use HTTPS to connect
- - By default using http
- type: bool
- default: False
-
- validate_certs:
- description:
- - If C(no), SSL certificates for the target url will not be validated. This should only be used
- on personally controlled sites using self-signed certificates.
- type: bool
- default: False
-'''
-
-EXAMPLES = '''
-- name: Get token for the Itential Automation Platform
- iap_token:
- iap_port: 3000
- iap_fqdn: localhost
- username: myusername
- password: mypass
- register: result
-
-- debug: var=result.token
-'''
-
-RETURN = '''
-token:
- description: The token acquired from the Itential Automation Platform
- type: str
- returned: always
-'''
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.urls import fetch_url
-
-
-def get_token(module):
- """
- :param module:
- :return: token
- """
- # defaulting the value for transport_protocol to be : http
- transport_protocol = 'http'
- if module.params['https'] or module.params['validate_certs'] is True:
- transport_protocol = 'https'
-
- url = transport_protocol + "://" + module.params['iap_fqdn'] + ":" + module.params['iap_port'] + "/login"
- username = module.params['username']
- password = module.params['password']
-
- login = {
- "user": {
- "username": username,
- "password": password
- }
- }
- json_body = module.jsonify(login)
- headers = {}
- headers['Content-Type'] = 'application/json'
-
- # Using fetch url instead of requests
- response, info = fetch_url(module, url, data=json_body, headers=headers)
- response_code = str(info['status'])
- if info['status'] not in [200, 201]:
- module.fail_json(msg="Failed to connect to Itential Automation Platform" + response_code)
- response = response.read()
- module.exit_json(changed=True, token=response)
-
-
-def main():
- """
- :return: token
- """
- # define the available arguments/parameters that a user can pass to
- # the module
- # the AnsibleModule object will be our abstraction working with Ansible
- # this includes instantiation, a couple of common attr would be the
- # args/params passed to the execution, as well as if the module
- # supports check mode
- module = AnsibleModule(
- argument_spec=dict(
- iap_port=dict(type='int', required=True),
- iap_fqdn=dict(type='str', required=True),
- username=dict(type='str', required=True),
- password=dict(type='str', required=True, no_log=True),
- https=(dict(type='bool', default=False)),
- validate_certs=dict(type='bool', default=False)
- )
- )
- get_token(module)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/netact/netact_cm_command.py b/plugins/modules/network/netact/netact_cm_command.py
deleted file mode 100644
index 74b077667f..0000000000
--- a/plugins/modules/network/netact/netact_cm_command.py
+++ /dev/null
@@ -1,366 +0,0 @@
-#!/usr/bin/python
-# Copyright: Nokia
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-# pylint: disable=invalid-name
-# pylint: disable=wrong-import-position
-# pylint: disable=too-many-locals
-# pylint: disable=too-many-branches
-# pylint: disable=too-many-statements
-
-"""
-NetAct CM ansible command module
-"""
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- 'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'
-}
-
-DOCUMENTATION = '''
----
-module: netact_cm_command
-
-short_description: Manage network configuration data in Nokia Core and Radio networks
-
-
-description:
- netact_cm_command can be used to run various configuration management operations.
- This module requires that the target hosts have Nokia NetAct network management system installed.
- Module will access the Configurator command line interface in NetAct to upload network configuration to NetAct,
- run configuration export, plan import and configuration provision operations
- To set the scope of the operation, define Distinguished Name (DN) or Working Set (WS) or
- Maintenance Region (MR) as input
-options:
- operation:
- description:
- Supported operations allow user to upload actual configuration from the network, to import and
- provision prepared plans, or export reference or actual configuration for planning purposes.
- Provision_Mass_Modification enables provisioning the same parameters to multiple network elements.
- This operation supports modifications only to one object class at a time. With this option
- NetAct Configurator creates and provisions a plan to the network with the given scope and options.
- required: true
- choices:
- - upload
- - provision
- - import
- - export
- - Provision_Mass_Modification
- aliases:
- - op
- opsName:
- description:
- - user specified operation name
- required: false
- DN:
- description:
- Sets the exact scope of the operation in form of a list of managed object
- Distinguished Names (DN) in the network.
- A single DN or a list of DNs can be given (comma separated list without spaces).
- Alternatively, if DN or a list of DNs is not given, working set (WS) or Maintenance Region (MR)
- must be provided as parameter to set the scope of operation.
- required: false
-
- WS:
- description:
- Sets the scope of the operation to use one or more pre-defined working sets (WS) in NetAct.
- A working set contains network elements selected by user according to defined criteria.
- A single WS name, or multiple WSs can be provided (comma-separated list without spaces).
- Alternatively, if a WS name or a list of WSs is not given, Distinguished Name (DN) or
- Maintenance Region(MR) must be provided as parameter to set the scope of operation.
- required: false
- MR:
- description:
- Sets the scope of the operation to network elements assigned to a Maintenance Region (MR)
- Value can be set as MR IDs including the Maintenance Region Collection (MRC)
- information (for example MRC-FIN1/MR-Hel).
- Multiple MRs can be given (comma-separated list without spaces)
- The value of this parameter is searched through MR IDs under given MRC. If there is no match,
- then it is searched from all MR names.
- Alternatively, if MR ID or a list or MR IDs is not given, Distinguished Name (DN) or Working Set (WS)
- must be provided as parameter to set the scope of operation.
- required: false
- planName:
- description:
- - Specifies a plan name.
- required: false
- typeOption:
- description:
- Specifies the type of the export operation.
- required: false
- choices:
- - plan
- - actual
- - reference
- - template
- - siteTemplate
- aliases:
- - type
- fileFormat:
- description:
- Indicates file format.
- required: false
- choices:
- - RAML2
- - CSV
- - XLSX
- fileName:
- description:
- - Specifies a file name. Valid for Import and Export operations.
- required: false
- inputFile:
- description:
- Specifies full path to plan file location for the import operation.
- This parameter (inputFile) or the fileName parameter must be filled. If both are present then
- the inputFile is used.
- required: false
- createBackupPlan:
- description:
- - Specifies if backup plan generation is enabled.
- required: false
- type: bool
- backupPlanName:
- description:
- - Specifies a backup plan name
- required: false
- verbose:
- description:
- NetAct Configurator will print more info
- required: false
- extra_opts:
- description:
- Extra options to be set for operations. Check Configuration Management > Configuration Management
- Operating Procedures > Command Line Operations in Nokia NetAct user documentation for further
- information for extra options.
- required: false
-notes:
- - Check mode is not currently supported
-author:
- - Harri Tuominen (@hatuomin)
-'''
-
-EXAMPLES = '''
-# Pass in a message
-- name: Upload
- netact_cm_command:
- operation: "Upload"
- opsname: 'Uploading_test'
- dn: "PLMN-PLMN/MRBTS-746"
- extra_opts: '-btsContentInUse true'
-
-- name: Provision
- netact_cm_command:
- operation: "Provision"
- opsname: 'Provision_test'
- dn: "PLMN-PLMN/MRBTS-746"
- planName: 'mySiteTemplate'
- type: 'actual'
- createBackupPlan: true
- backupPlanName: 'myBackupPlanName'
-
-- name: Export and fetching data from target
- netact_cm_command:
- operation: "Export"
- opsname: 'Export_test'
- planName: 'mySiteTemplate'
- type: 'actual'
- fileName: 'exportTest.xml'
-- fetch:
- src: /var/opt/nokia/oss/global/racops/export/exportTest.xml
- dest: fetched
-
-- name: Import
- netact_cm_command:
- operation: "Import"
- opsname: 'Import_test'
- fileFormat: 'CSV'
- type: 'plan'
- fileName: 'myCSVFile'
- planName: 'myPlanName'
- extra_ops: 'enablePolicyPlans true'
-
-# fail the module
-- name: Test failure of the module
- netact_cm_command:
- name: fail me
-'''
-
-RETURN = '''
-original_message:
- description: The original name param that was passed in
- returned: Command line
- type: str
- sample: '/opt/oss/bin/racclimx.sh -op Upload -opsName Uploading_testi -DN PLMN-PLMN/MRBTS-746'
-message:
- description: The output message that the netact_cm_command module generates
- returned: Command output message
- type: str
-changed:
- description: data changed
- returned: true if data is changed
- type: bool
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-
-racclimx = '/opt/oss/bin/racclimx.sh'
-
-
-def main():
- """
- Main module where option are handled and command is executed
- :return:
- """
- # define the available arguments/parameters that a user can pass to
- # the module
- module_args = dict(
- operation=dict(type='str', required=True,
- aliases=['op'],
- choices=['Upload', 'Provision', 'Import',
- 'Export', 'Provision_Mass_Modification']),
- opsName=dict(type='str', required=False),
- DN=dict(type='str', required=False),
- WS=dict(type='str', required=False),
- MR=dict(type='str', required=False),
-
- planName=dict(type='str', required=False),
- typeOption=dict(type='str', required=False, aliases=['type'],
- choices=['plan', 'actual', 'reference', 'template', 'siteTemplate']),
- fileFormat=dict(type='str', required=False, choices=['CSV', 'RAML2', 'XLSX']),
- fileName=dict(type='str', required=False),
- createBackupPlan=dict(type='bool', required=False),
- backupPlanName=dict(type='str', required=False),
- inputFile=dict(type='str', required=False),
-
- verbose=dict(type='str', required=False),
- extra_opts=dict(type='str', required=False)
- )
-
- # seed the result dict in the object
- # we primarily care about changed and state
- # change is if this module effectively modified the target
- # state will include any data that you want your module to pass back
- # for consumption, for example, in a subsequent task
- result = dict(
- changed=False,
- original_message='',
- cmd='',
- message=''
- )
-
- # the AnsibleModule object will be our abstraction working with Ansible
- # this includes instantiation, a couple of common attr would be the
- # args/params passed to the execution, as well as if the module
- # supports check mode
- module = AnsibleModule(
- argument_spec=module_args,
- supports_check_mode=True
- )
-
- # if the user is working with this module in only check mode we do not
- # want to make any changes to the environment, just return the current
- # state with no modifications
- if module.check_mode:
- result['skipped'] = True
- result['msg'] = 'check mode not (yet) supported for this module'
- module.exit_json(**result)
-
- # manipulate or modify the state as needed (this is going to be the
- # part where your module will do what it needs to do)
-
- operation = module.params.get('operation')
- if not operation:
- module.fail_json(msg='Operation not defined', **result)
-
- opsname = module.params.get('opsName')
- dn = module.params.get('DN')
- ws = module.params.get('WS')
- mr = module.params.get('MR')
-
- planname = module.params.get('planName')
- typeoption = module.params.get('typeOption')
- fileformat = module.params.get('fileFormat')
- filename = module.params.get('fileName')
-
- createBackupPlan = module.params.get('createBackupPlan')
- backupPlanName = module.params.get('backupPlanName')
- inputfile = module.params.get('inputFile')
-
- extra_opts = module.params.get('extra_opts')
- verbose = module.params.get('verbose')
-
- # parameter checks
-
- command = [racclimx, '-op', operation]
-
- if opsname:
- command.append('-opsName')
- command.append(opsname)
-
- if dn:
- command.append('-DN')
- command.append(dn)
-
- if ws:
- command.append('-WS')
- command.append(ws)
-
- if mr:
- command.append('-MR')
- command.append(mr)
-
- if planname:
- command.append('-planName')
- command.append(planname)
-
- if typeoption:
- command.append('-type')
- command.append(typeoption)
-
- if fileformat:
- command.append('-fileFormat')
- command.append(fileformat)
-
- if filename:
- command.append('-fileName')
- command.append(filename)
-
- if createBackupPlan:
- command.append('-createBackupPlan')
- command.append('true')
-
- if backupPlanName:
- command.append('-backupPlanName')
- command.append(backupPlanName)
-
- if inputfile:
- command.append('-inputFile')
- command.append(inputfile)
-
- if extra_opts:
- command = command + extra_opts.split(" ")
-
- if verbose:
- if verbose == 'True':
- command.append("-v")
-
- rc, out, err = module.run_command(command, check_rc=True)
- if rc != 0:
- result['changed'] = False
- module.fail_json(msg=err)
- else:
- result['changed'] = True
- result['original_message'] = out
- result['cmd'] = command
- result['message'] = out
-
- # in the event of a successful module execution, you will want to
- # simple AnsibleModule.exit_json(), passing the key/value results
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/plugins/modules/network/netscaler/netscaler_cs_action.py b/plugins/modules/network/netscaler/netscaler_cs_action.py
deleted file mode 100644
index 7f2e16a273..0000000000
--- a/plugins/modules/network/netscaler/netscaler_cs_action.py
+++ /dev/null
@@ -1,288 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2017 Citrix Systems
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: netscaler_cs_action
-short_description: Manage content switching actions
-description:
- - Manage content switching actions
- - This module is intended to run either on the ansible control node or a bastion (jumpserver) with access to the actual netscaler instance
-
-
-author: George Nikolopoulos (@giorgos-nikolopoulos)
-
-options:
-
- name:
- description:
- - >-
- Name for the content switching action. Must begin with an ASCII alphanumeric or underscore C(_)
- character, and must contain only ASCII alphanumeric, underscore C(_), hash C(#), period C(.), space C( ), colon
- C(:), at sign C(@), equal sign C(=), and hyphen C(-) characters. Can be changed after the content
- switching action is created.
-
- targetlbvserver:
- description:
- - "Name of the load balancing virtual server to which the content is switched."
-
- targetvserver:
- description:
- - "Name of the VPN virtual server to which the content is switched."
-
- targetvserverexpr:
- description:
- - "Information about this content switching action."
-
- comment:
- description:
- - "Comments associated with this cs action."
-
-extends_documentation_fragment:
-- community.general.netscaler
-
-requirements:
- - nitro python sdk
-'''
-
-EXAMPLES = '''
-# lb_vserver_1 must have been already created with the netscaler_lb_vserver module
-
-- name: Configure netscaler content switching action
- delegate_to: localhost
- netscaler_cs_action:
- nsip: 172.18.0.2
- nitro_user: nsroot
- nitro_pass: nsroot
- validate_certs: no
-
- state: present
-
- name: action-1
- targetlbvserver: lb_vserver_1
-'''
-
-RETURN = '''
-loglines:
- description: list of logged messages by the module
- returned: always
- type: list
- sample: "['message 1', 'message 2']"
-
-msg:
- description: Message detailing the failure reason
- returned: failure
- type: str
- sample: "Action does not exist"
-
-diff:
- description: List of differences between the actual configured object and the configuration specified in the module
- returned: failure
- type: dict
- sample: "{ 'targetlbvserver': 'difference. ours: (str) server1 other: (str) server2' }"
-'''
-
-import json
-
-try:
- from nssrc.com.citrix.netscaler.nitro.resource.config.cs.csaction import csaction
- from nssrc.com.citrix.netscaler.nitro.exception.nitro_exception import nitro_exception
- PYTHON_SDK_IMPORTED = True
-except ImportError as e:
- PYTHON_SDK_IMPORTED = False
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.netscaler.netscaler import (
- ConfigProxy,
- get_nitro_client,
- netscaler_common_arguments,
- log, loglines,
- ensure_feature_is_enabled,
- get_immutables_intersection
-)
-
-
-def action_exists(client, module):
- if csaction.count_filtered(client, 'name:%s' % module.params['name']) > 0:
- return True
- else:
- return False
-
-
-def action_identical(client, module, csaction_proxy):
- if len(diff_list(client, module, csaction_proxy)) == 0:
- return True
- else:
- return False
-
-
-def diff_list(client, module, csaction_proxy):
- action_list = csaction.get_filtered(client, 'name:%s' % module.params['name'])
- diff_list = csaction_proxy.diff_object(action_list[0])
- if False and 'targetvserverexpr' in diff_list:
- json_value = json.loads(action_list[0].targetvserverexpr)
- if json_value == module.params['targetvserverexpr']:
- del diff_list['targetvserverexpr']
- return diff_list
-
-
-def main():
-
- module_specific_arguments = dict(
-
- name=dict(type='str'),
- targetlbvserver=dict(type='str'),
- targetvserverexpr=dict(type='str'),
- comment=dict(type='str'),
- )
-
- argument_spec = dict()
-
- argument_spec.update(netscaler_common_arguments)
-
- argument_spec.update(module_specific_arguments)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- )
- module_result = dict(
- changed=False,
- failed=False,
- loglines=loglines
- )
-
- # Fail the module if imports failed
- if not PYTHON_SDK_IMPORTED:
- module.fail_json(msg='Could not load nitro python sdk')
-
- # Fallthrough to rest of execution
- client = get_nitro_client(module)
-
- try:
- client.login()
- except nitro_exception as e:
- msg = "nitro exception during login. errorcode=%s, message=%s" % (str(e.errorcode), e.message)
- module.fail_json(msg=msg)
- except Exception as e:
- if str(type(e)) == "":
- module.fail_json(msg='Connection error %s' % str(e))
- elif str(type(e)) == "":
- module.fail_json(msg='SSL Error %s' % str(e))
- else:
- module.fail_json(msg='Unexpected error during login %s' % str(e))
-
- readwrite_attrs = [
- 'name',
- 'targetlbvserver',
- 'targetvserverexpr',
- 'comment',
- ]
- readonly_attrs = [
- 'hits',
- 'referencecount',
- 'undefhits',
- 'builtin',
- ]
-
- immutable_attrs = [
- 'name',
- 'targetvserverexpr',
- ]
-
- transforms = {
- }
-
- # Instantiate config proxy
- csaction_proxy = ConfigProxy(
- actual=csaction(),
- client=client,
- attribute_values_dict=module.params,
- readwrite_attrs=readwrite_attrs,
- readonly_attrs=readonly_attrs,
- immutable_attrs=immutable_attrs,
- transforms=transforms,
- )
-
- try:
-
- ensure_feature_is_enabled(client, 'CS')
- # Apply appropriate state
- if module.params['state'] == 'present':
- log('Applying actions for state present')
- if not action_exists(client, module):
- if not module.check_mode:
- csaction_proxy.add()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- elif not action_identical(client, module, csaction_proxy):
-
- # Check if we try to change value of immutable attributes
- immutables_changed = get_immutables_intersection(csaction_proxy, diff_list(client, module, csaction_proxy).keys())
- if immutables_changed != []:
- module.fail_json(
- msg='Cannot update immutable attributes %s' % (immutables_changed,),
- diff=diff_list(client, module, csaction_proxy),
- **module_result
- )
-
- if not module.check_mode:
- csaction_proxy.update()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- else:
- module_result['changed'] = False
-
- # Sanity check for state
- log('Sanity checks for state present')
- if not module.check_mode:
- if not action_exists(client, module):
- module.fail_json(msg='Content switching action does not exist', **module_result)
- if not action_identical(client, module, csaction_proxy):
- module.fail_json(
- msg='Content switching action differs from configured',
- diff=diff_list(client, module, csaction_proxy),
- **module_result
- )
-
- elif module.params['state'] == 'absent':
- log('Applying actions for state absent')
- if action_exists(client, module):
- if not module.check_mode:
- csaction_proxy.delete()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- else:
- module_result['changed'] = False
-
- # Sanity check for state
- if not module.check_mode:
- log('Sanity checks for state absent')
- if action_exists(client, module):
- module.fail_json(msg='Content switching action still exists', **module_result)
-
- except nitro_exception as e:
- msg = "nitro exception errorcode=%s, message=%s" % (str(e.errorcode), e.message)
- module.fail_json(msg=msg, **module_result)
-
- client.logout()
- module.exit_json(**module_result)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/netscaler/netscaler_cs_policy.py b/plugins/modules/network/netscaler/netscaler_cs_policy.py
deleted file mode 100644
index f31452d11f..0000000000
--- a/plugins/modules/network/netscaler/netscaler_cs_policy.py
+++ /dev/null
@@ -1,288 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2017 Citrix Systems
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: netscaler_cs_policy
-short_description: Manage content switching policy
-description:
- - Manage content switching policy.
- - "This module is intended to run either on the ansible control node or a bastion (jumpserver) with access to the actual netscaler instance."
-
-
-author: George Nikolopoulos (@giorgos-nikolopoulos)
-
-options:
-
- policyname:
- description:
- - >-
- Name for the content switching policy. Must begin with an ASCII alphanumeric or underscore C(_)
- character, and must contain only ASCII alphanumeric, underscore, hash C(#), period C(.), space C( ), colon
- C(:), at sign C(@), equal sign C(=), and hyphen C(-) characters. Cannot be changed after a policy is
- created.
- - "The following requirement applies only to the NetScaler CLI:"
- - >-
- If the name includes one or more spaces, enclose the name in double or single quotation marks (for
- example, my policy or my policy).
- - "Minimum length = 1"
-
- url:
- description:
- - >-
- URL string that is matched with the URL of a request. Can contain a wildcard character. Specify the
- string value in the following format: C([[prefix] [*]] [.suffix]).
- - "Minimum length = 1"
- - "Maximum length = 208"
-
- rule:
- description:
- - >-
- Expression, or name of a named expression, against which traffic is evaluated. Written in the classic
- or default syntax.
- - "Note:"
- - >-
- Maximum length of a string literal in the expression is 255 characters. A longer string can be split
- into smaller strings of up to 255 characters each, and the smaller strings concatenated with the +
- operator. For example, you can create a 500-character string as follows: '"" + ""'
-
- domain:
- description:
- - "The domain name. The string value can range to 63 characters."
- - "Minimum length = 1"
-
- action:
- description:
- - >-
- Content switching action that names the target load balancing virtual server to which the traffic is
- switched.
-
-extends_documentation_fragment:
-- community.general.netscaler
-
-requirements:
- - nitro python sdk
-'''
-
-EXAMPLES = '''
-- name: Create url cs policy
- delegate_to: localhost
- netscaler_cs_policy:
- nsip: 172.18.0.2
- nitro_user: nsroot
- nitro_pass: nsroot
- validate_certs: no
-
- state: present
-
- policyname: policy_1
- url: /example/
-'''
-
-RETURN = '''
-loglines:
- description: list of logged messages by the module
- returned: always
- type: list
- sample: ['message 1', 'message 2']
-
-msg:
- description: Message detailing the failure reason
- returned: failure
- type: str
- sample: "Could not load nitro python sdk"
-
-diff:
- description: List of differences between the actual configured object and the configuration specified in the module
- returned: failure
- type: dict
- sample: { 'url': 'difference. ours: (str) example1 other: (str) /example1' }
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.netscaler.netscaler import (ConfigProxy, get_nitro_client, netscaler_common_arguments,
- log, loglines, ensure_feature_is_enabled)
-try:
- from nssrc.com.citrix.netscaler.nitro.resource.config.cs.cspolicy import cspolicy
- from nssrc.com.citrix.netscaler.nitro.exception.nitro_exception import nitro_exception
- PYTHON_SDK_IMPORTED = True
-except ImportError as e:
- PYTHON_SDK_IMPORTED = False
-
-
-def policy_exists(client, module):
- log('Checking if policy exists')
- if cspolicy.count_filtered(client, 'policyname:%s' % module.params['policyname']) > 0:
- return True
- else:
- return False
-
-
-def policy_identical(client, module, cspolicy_proxy):
- log('Checking if defined policy is identical to configured')
- if cspolicy.count_filtered(client, 'policyname:%s' % module.params['policyname']) == 0:
- return False
- policy_list = cspolicy.get_filtered(client, 'policyname:%s' % module.params['policyname'])
- diff_dict = cspolicy_proxy.diff_object(policy_list[0])
- if 'ip' in diff_dict:
- del diff_dict['ip']
- if len(diff_dict) == 0:
- return True
- else:
- return False
-
-
-def diff_list(client, module, cspolicy_proxy):
- policy_list = cspolicy.get_filtered(client, 'policyname:%s' % module.params['policyname'])
- return cspolicy_proxy.diff_object(policy_list[0])
-
-
-def main():
-
- module_specific_arguments = dict(
- policyname=dict(type='str'),
- url=dict(type='str'),
- rule=dict(type='str'),
- domain=dict(type='str'),
- action=dict(type='str'),
- )
-
- hand_inserted_arguments = dict(
- )
-
- argument_spec = dict()
-
- argument_spec.update(netscaler_common_arguments)
- argument_spec.update(module_specific_arguments)
- argument_spec.update(hand_inserted_arguments)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- )
- module_result = dict(
- changed=False,
- failed=False,
- loglines=loglines,
- )
-
- # Fail the module if imports failed
- if not PYTHON_SDK_IMPORTED:
- module.fail_json(msg='Could not load nitro python sdk')
-
- # Fallthrough to rest of execution
- client = get_nitro_client(module)
-
- try:
- client.login()
- except nitro_exception as e:
- msg = "nitro exception during login. errorcode=%s, message=%s" % (str(e.errorcode), e.message)
- module.fail_json(msg=msg)
- except Exception as e:
- if str(type(e)) == "":
- module.fail_json(msg='Connection error %s' % str(e))
- elif str(type(e)) == "":
- module.fail_json(msg='SSL Error %s' % str(e))
- else:
- module.fail_json(msg='Unexpected error during login %s' % str(e))
-
- readwrite_attrs = [
- 'policyname',
- 'url',
- 'rule',
- 'domain',
- 'action',
- ]
- readonly_attrs = [
- 'vstype',
- 'hits',
- 'bindhits',
- 'labelname',
- 'labeltype',
- 'priority',
- 'activepolicy',
- 'cspolicytype',
- ]
-
- transforms = {
- }
-
- # Instantiate config proxy
- cspolicy_proxy = ConfigProxy(
- actual=cspolicy(),
- client=client,
- attribute_values_dict=module.params,
- readwrite_attrs=readwrite_attrs,
- readonly_attrs=readonly_attrs,
- transforms=transforms,
- )
-
- try:
- ensure_feature_is_enabled(client, 'CS')
-
- # Apply appropriate state
- if module.params['state'] == 'present':
- log('Sanity checks for state present')
- if not policy_exists(client, module):
- if not module.check_mode:
- cspolicy_proxy.add()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- elif not policy_identical(client, module, cspolicy_proxy):
- if not module.check_mode:
- cspolicy_proxy.update()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- else:
- module_result['changed'] = False
-
- # Sanity check for state
- if not module.check_mode:
- log('Sanity checks for state present')
- if not policy_exists(client, module):
- module.fail_json(msg='Policy does not exist', **module_result)
- if not policy_identical(client, module, cspolicy_proxy):
- module.fail_json(msg='Policy differs from configured', diff=diff_list(client, module, cspolicy_proxy), **module_result)
-
- elif module.params['state'] == 'absent':
- log('Applying actions for state absent')
- if policy_exists(client, module):
- if not module.check_mode:
- cspolicy_proxy.delete()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- else:
- module_result['changed'] = False
-
- # Sanity check for state
- if not module.check_mode:
- log('Sanity checks for state absent')
- if policy_exists(client, module):
- module.fail_json(msg='Policy still exists', **module_result)
-
- except nitro_exception as e:
- msg = "nitro exception errorcode=%s, message=%s" % (str(e.errorcode), e.message)
- module.fail_json(msg=msg, **module_result)
-
- client.logout()
- module.exit_json(**module_result)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/netscaler/netscaler_cs_vserver.py b/plugins/modules/network/netscaler/netscaler_cs_vserver.py
deleted file mode 100644
index 7fbc495cc0..0000000000
--- a/plugins/modules/network/netscaler/netscaler_cs_vserver.py
+++ /dev/null
@@ -1,1307 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2017 Citrix Systems
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: netscaler_cs_vserver
-short_description: Manage content switching vserver
-description:
- - Manage content switching vserver
- - This module is intended to run either on the ansible control node or a bastion (jumpserver) with access to the actual netscaler instance
-
-
-author: George Nikolopoulos (@giorgos-nikolopoulos)
-
-options:
-
- name:
- description:
- - >-
- Name for the content switching virtual server. Must begin with an ASCII alphanumeric or underscore
- C(_) character, and must contain only ASCII alphanumeric, underscore C(_), hash C(#), period C(.), space,
- colon C(:), at sign C(@), equal sign C(=), and hyphen C(-) characters.
- - "Cannot be changed after the CS virtual server is created."
- - "Minimum length = 1"
-
- td:
- description:
- - >-
- Integer value that uniquely identifies the traffic domain in which you want to configure the entity.
- If you do not specify an ID, the entity becomes part of the default traffic domain, which has an ID
- of 0.
- - "Minimum value = 0"
- - "Maximum value = 4094"
-
- servicetype:
- choices:
- - 'HTTP'
- - 'SSL'
- - 'TCP'
- - 'FTP'
- - 'RTSP'
- - 'SSL_TCP'
- - 'UDP'
- - 'DNS'
- - 'SIP_UDP'
- - 'SIP_TCP'
- - 'SIP_SSL'
- - 'ANY'
- - 'RADIUS'
- - 'RDP'
- - 'MYSQL'
- - 'MSSQL'
- - 'DIAMETER'
- - 'SSL_DIAMETER'
- - 'DNS_TCP'
- - 'ORACLE'
- - 'SMPP'
- description:
- - "Protocol used by the virtual server."
-
- ipv46:
- description:
- - "IP address of the content switching virtual server."
- - "Minimum length = 1"
-
- targettype:
- choices:
- - 'GSLB'
- description:
- - "Virtual server target type."
-
- ippattern:
- description:
- - >-
- IP address pattern, in dotted decimal notation, for identifying packets to be accepted by the virtual
- server. The IP Mask parameter specifies which part of the destination IP address is matched against
- the pattern. Mutually exclusive with the IP Address parameter.
- - >-
- For example, if the IP pattern assigned to the virtual server is C(198.51.100.0) and the IP mask is
- C(255.255.240.0) (a forward mask), the first 20 bits in the destination IP addresses are matched with
- the first 20 bits in the pattern. The virtual server accepts requests with IP addresses that range
- from 198.51.96.1 to 198.51.111.254. You can also use a pattern such as C(0.0.2.2) and a mask such as
- C(0.0.255.255) (a reverse mask).
- - >-
- If a destination IP address matches more than one IP pattern, the pattern with the longest match is
- selected, and the associated virtual server processes the request. For example, if the virtual
- servers, C(vs1) and C(vs2), have the same IP pattern, C(0.0.100.128), but different IP masks of C(0.0.255.255)
- and C(0.0.224.255), a destination IP address of 198.51.100.128 has the longest match with the IP pattern
- of C(vs1). If a destination IP address matches two or more virtual servers to the same extent, the
- request is processed by the virtual server whose port number matches the port number in the request.
-
- ipmask:
- description:
- - >-
- IP mask, in dotted decimal notation, for the IP Pattern parameter. Can have leading or trailing
- non-zero octets (for example, C(255.255.240.0) or C(0.0.255.255)). Accordingly, the mask specifies whether
- the first n bits or the last n bits of the destination IP address in a client request are to be
- matched with the corresponding bits in the IP pattern. The former is called a forward mask. The
- latter is called a reverse mask.
-
- range:
- description:
- - >-
- Number of consecutive IP addresses, starting with the address specified by the IP Address parameter,
- to include in a range of addresses assigned to this virtual server.
- - "Minimum value = C(1)"
- - "Maximum value = C(254)"
-
- port:
- description:
- - "Port number for content switching virtual server."
- - "Minimum value = 1"
- - "Range C(1) - C(65535)"
- - "* in CLI is represented as 65535 in NITRO API"
-
- stateupdate:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- Enable state updates for a specific content switching virtual server. By default, the Content
- Switching virtual server is always UP, regardless of the state of the Load Balancing virtual servers
- bound to it. This parameter interacts with the global setting as follows:
- - "Global Level | Vserver Level | Result"
- - "enabled enabled enabled"
- - "enabled disabled enabled"
- - "disabled enabled enabled"
- - "disabled disabled disabled"
- - >-
- If you want to enable state updates for only some content switching virtual servers, be sure to
- disable the state update parameter.
-
- cacheable:
- description:
- - >-
- Use this option to specify whether a virtual server, used for load balancing or content switching,
- routes requests to the cache redirection virtual server before sending it to the configured servers.
- type: bool
-
- redirecturl:
- description:
- - >-
- URL to which traffic is redirected if the virtual server becomes unavailable. The service type of the
- virtual server should be either C(HTTP) or C(SSL).
- - >-
- Caution: Make sure that the domain in the URL does not match the domain specified for a content
- switching policy. If it does, requests are continuously redirected to the unavailable virtual server.
- - "Minimum length = 1"
-
- clttimeout:
- description:
- - "Idle time, in seconds, after which the client connection is terminated. The default values are:"
- - "Minimum value = C(0)"
- - "Maximum value = C(31536000)"
-
- precedence:
- choices:
- - 'RULE'
- - 'URL'
- description:
- - >-
- Type of precedence to use for both RULE-based and URL-based policies on the content switching virtual
- server. With the default C(RULE) setting, incoming requests are evaluated against the rule-based
- content switching policies. If none of the rules match, the URL in the request is evaluated against
- the URL-based content switching policies.
-
- casesensitive:
- description:
- - >-
- Consider case in URLs (for policies that use URLs instead of RULES). For example, with the C(on)
- setting, the URLs /a/1.html and /A/1.HTML are treated differently and can have different targets (set
- by content switching policies). With the C(off) setting, /a/1.html and /A/1.HTML are switched to the
- same target.
- type: bool
-
- somethod:
- choices:
- - 'CONNECTION'
- - 'DYNAMICCONNECTION'
- - 'BANDWIDTH'
- - 'HEALTH'
- - 'NONE'
- description:
- - >-
- Type of spillover used to divert traffic to the backup virtual server when the primary virtual server
- reaches the spillover threshold. Connection spillover is based on the number of connections.
- Bandwidth spillover is based on the total Kbps of incoming and outgoing traffic.
-
- sopersistence:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - "Maintain source-IP based persistence on primary and backup virtual servers."
-
- sopersistencetimeout:
- description:
- - "Time-out value, in minutes, for spillover persistence."
- - "Minimum value = C(2)"
- - "Maximum value = C(1440)"
-
- sothreshold:
- description:
- - >-
- Depending on the spillover method, the maximum number of connections or the maximum total bandwidth
- (Kbps) that a virtual server can handle before spillover occurs.
- - "Minimum value = C(1)"
- - "Maximum value = C(4294967287)"
-
- sobackupaction:
- choices:
- - 'DROP'
- - 'ACCEPT'
- - 'REDIRECT'
- description:
- - >-
- Action to be performed if spillover is to take effect, but no backup chain to spillover is usable or
- exists.
-
- redirectportrewrite:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - "State of port rewrite while performing HTTP redirect."
-
- downstateflush:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- Flush all active transactions associated with a virtual server whose state transitions from UP to
- DOWN. Do not enable this option for applications that must complete their transactions.
-
- backupvserver:
- description:
- - >-
- Name of the backup virtual server that you are configuring. Must begin with an ASCII alphanumeric or
- underscore C(_) character, and must contain only ASCII alphanumeric, underscore C(_), hash C(#), period C(.),
- space C( ), colon C(:), at sign C(@), equal sign C(=), and hyphen C(-) characters. Can be changed after the
- backup virtual server is created. You can assign a different backup virtual server or rename the
- existing virtual server.
- - "Minimum length = 1"
-
- disableprimaryondown:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- Continue forwarding the traffic to backup virtual server even after the primary server comes UP from
- the DOWN state.
-
- insertvserveripport:
- choices:
- - 'OFF'
- - 'VIPADDR'
- - 'V6TOV4MAPPING'
- description:
- - >-
- Insert the virtual server's VIP address and port number in the request header. Available values
- function as follows:
- - "C(VIPADDR) - Header contains the vserver's IP address and port number without any translation."
- - "C(OFF) - The virtual IP and port header insertion option is disabled."
- - >-
- C(V6TOV4MAPPING) - Header contains the mapped IPv4 address corresponding to the IPv6 address of the
- vserver and the port number. An IPv6 address can be mapped to a user-specified IPv4 address using the
- set ns ip6 command.
-
- vipheader:
- description:
- - "Name of virtual server IP and port header, for use with the VServer IP Port Insertion parameter."
- - "Minimum length = 1"
-
- rtspnat:
- description:
- - "Enable network address translation (NAT) for real-time streaming protocol (RTSP) connections."
- type: bool
-
- authenticationhost:
- description:
- - >-
- FQDN of the authentication virtual server. The service type of the virtual server should be either
- C(HTTP) or C(SSL).
- - "Minimum length = 3"
- - "Maximum length = 252"
-
- authentication:
- description:
- - "Authenticate users who request a connection to the content switching virtual server."
- type: bool
-
- listenpolicy:
- description:
- - >-
- String specifying the listen policy for the content switching virtual server. Can be either the name
- of an existing expression or an in-line expression.
-
- authn401:
- description:
- - "Enable HTTP 401-response based authentication."
- type: bool
-
- authnvsname:
- description:
- - >-
- Name of authentication virtual server that authenticates the incoming user requests to this content
- switching virtual server. .
- - "Minimum length = 1"
- - "Maximum length = 252"
-
- push:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- Process traffic with the push virtual server that is bound to this content switching virtual server
- (specified by the Push VServer parameter). The service type of the push virtual server should be
- either C(HTTP) or C(SSL).
-
- pushvserver:
- description:
- - >-
- Name of the load balancing virtual server, of type C(PUSH) or C(SSL_PUSH), to which the server pushes
- updates received on the client-facing load balancing virtual server.
- - "Minimum length = 1"
-
- pushlabel:
- description:
- - >-
- Expression for extracting the label from the response received from server. This string can be either
- an existing rule name or an inline expression. The service type of the virtual server should be
- either C(HTTP) or C(SSL).
-
- pushmulticlients:
- description:
- - >-
- Allow multiple Web 2.0 connections from the same client to connect to the virtual server and expect
- updates.
- type: bool
-
- tcpprofilename:
- description:
- - "Name of the TCP profile containing TCP configuration settings for the virtual server."
- - "Minimum length = 1"
- - "Maximum length = 127"
-
- httpprofilename:
- description:
- - >-
- Name of the HTTP profile containing HTTP configuration settings for the virtual server. The service
- type of the virtual server should be either C(HTTP) or C(SSL).
- - "Minimum length = 1"
- - "Maximum length = 127"
-
- dbprofilename:
- description:
- - "Name of the DB profile."
- - "Minimum length = 1"
- - "Maximum length = 127"
-
- oracleserverversion:
- choices:
- - '10G'
- - '11G'
- description:
- - "Oracle server version."
-
- comment:
- description:
- - "Information about this virtual server."
-
- mssqlserverversion:
- choices:
- - '70'
- - '2000'
- - '2000SP1'
- - '2005'
- - '2008'
- - '2008R2'
- - '2012'
- - '2014'
- description:
- - "The version of the MSSQL server."
-
- l2conn:
- description:
- - "Use L2 Parameters to identify a connection."
- type: bool
-
- mysqlprotocolversion:
- description:
- - "The protocol version returned by the mysql vserver."
-
- mysqlserverversion:
- description:
- - "The server version string returned by the mysql vserver."
- - "Minimum length = 1"
- - "Maximum length = 31"
-
- mysqlcharacterset:
- description:
- - "The character set returned by the mysql vserver."
-
- mysqlservercapabilities:
- description:
- - "The server capabilities returned by the mysql vserver."
-
- appflowlog:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - "Enable logging appflow flow information."
-
- netprofile:
- description:
- - "The name of the network profile."
- - "Minimum length = 1"
- - "Maximum length = 127"
-
- icmpvsrresponse:
- choices:
- - 'PASSIVE'
- - 'ACTIVE'
- description:
- - "Can be active or passive."
-
- rhistate:
- choices:
- - 'PASSIVE'
- - 'ACTIVE'
- description:
- - "A host route is injected according to the setting on the virtual servers"
- - >-
- * If set to C(PASSIVE) on all the virtual servers that share the IP address, the appliance always
- injects the hostroute.
- - >-
- * If set to C(ACTIVE) on all the virtual servers that share the IP address, the appliance injects even
- if one virtual server is UP.
- - >-
- * If set to C(ACTIVE) on some virtual servers and C(PASSIVE) on the others, the appliance, injects even if
- one virtual server set to C(ACTIVE) is UP.
-
- authnprofile:
- description:
- - "Name of the authentication profile to be used when authentication is turned on."
-
- dnsprofilename:
- description:
- - >-
- Name of the DNS profile to be associated with the VServer. DNS profile properties will applied to the
- transactions processed by a VServer. This parameter is valid only for DNS and DNS-TCP VServers.
- - "Minimum length = 1"
- - "Maximum length = 127"
-
- domainname:
- description:
- - "Domain name for which to change the time to live (TTL) and/or backup service IP address."
- - "Minimum length = 1"
-
- ttl:
- description:
- - "."
- - "Minimum value = C(1)"
-
- backupip:
- description:
- - "."
- - "Minimum length = 1"
-
- cookiedomain:
- description:
- - "."
- - "Minimum length = 1"
-
- cookietimeout:
- description:
- - "."
- - "Minimum value = C(0)"
- - "Maximum value = C(1440)"
-
- sitedomainttl:
- description:
- - "."
- - "Minimum value = C(1)"
-
- lbvserver:
- description:
- - The default Load Balancing virtual server.
-
- ssl_certkey:
- description:
- - The name of the ssl certificate that is bound to this service.
- - The ssl certificate must already exist.
- - Creating the certificate can be done with the M(netscaler_ssl_certkey) module.
- - This option is only applicable only when C(servicetype) is C(SSL).
-
- disabled:
- description:
- - When set to C(yes) the cs vserver will be disabled.
- - When set to C(no) the cs vserver will be enabled.
- - >-
- Note that due to limitations of the underlying NITRO API a C(disabled) state change alone
- does not cause the module result to report a changed status.
- type: bool
- default: 'no'
-
-extends_documentation_fragment:
-- community.general.netscaler
-
-requirements:
- - nitro python sdk
-'''
-
-EXAMPLES = '''
-# policy_1 must have been already created with the netscaler_cs_policy module
-# lbvserver_1 must have been already created with the netscaler_lb_vserver module
-
-- name: Setup content switching vserver
- delegate_to: localhost
- netscaler_cs_vserver:
- nsip: 172.18.0.2
- nitro_user: nsroot
- nitro_pass: nsroot
-
- state: present
-
- name: cs_vserver_1
- ipv46: 192.168.1.1
- port: 80
- servicetype: HTTP
-
- policybindings:
- - policyname: policy_1
- targetlbvserver: lbvserver_1
-'''
-
-RETURN = '''
-loglines:
- description: list of logged messages by the module
- returned: always
- type: list
- sample: ['message 1', 'message 2']
-
-msg:
- description: Message detailing the failure reason
- returned: failure
- type: str
- sample: "Action does not exist"
-
-diff:
- description: List of differences between the actual configured object and the configuration specified in the module
- returned: failure
- type: dict
- sample: { 'clttimeout': 'difference. ours: (float) 100.0 other: (float) 60.0' }
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.netscaler.netscaler import (
- ConfigProxy,
- get_nitro_client,
- netscaler_common_arguments,
- log,
- loglines,
- ensure_feature_is_enabled,
- get_immutables_intersection
-)
-try:
- from nssrc.com.citrix.netscaler.nitro.resource.config.cs.csvserver import csvserver
- from nssrc.com.citrix.netscaler.nitro.resource.config.cs.csvserver_lbvserver_binding import csvserver_lbvserver_binding
- from nssrc.com.citrix.netscaler.nitro.resource.config.cs.csvserver_cspolicy_binding import csvserver_cspolicy_binding
- from nssrc.com.citrix.netscaler.nitro.resource.config.ssl.sslvserver_sslcertkey_binding import sslvserver_sslcertkey_binding
- from nssrc.com.citrix.netscaler.nitro.exception.nitro_exception import nitro_exception
- PYTHON_SDK_IMPORTED = True
-except ImportError as e:
- PYTHON_SDK_IMPORTED = False
-
-
-def cs_vserver_exists(client, module):
- if csvserver.count_filtered(client, 'name:%s' % module.params['name']) > 0:
- return True
- else:
- return False
-
-
-def cs_vserver_identical(client, module, csvserver_proxy):
- csvserver_list = csvserver.get_filtered(client, 'name:%s' % module.params['name'])
- diff_dict = csvserver_proxy.diff_object(csvserver_list[0])
- if len(diff_dict) == 0:
- return True
- else:
- return False
-
-
-def get_configured_policybindings(client, module):
- log('Getting configured policy bindigs')
- bindings = {}
- if module.params['policybindings'] is None:
- return bindings
-
- for binding in module.params['policybindings']:
- binding['name'] = module.params['name']
- key = binding['policyname']
- binding_proxy = ConfigProxy(
- actual=csvserver_cspolicy_binding(),
- client=client,
- readwrite_attrs=[
- 'priority',
- 'bindpoint',
- 'policyname',
- 'labelname',
- 'gotopriorityexpression',
- 'targetlbvserver',
- 'name',
- 'invoke',
- 'labeltype',
- ],
- readonly_attrs=[],
- attribute_values_dict=binding
- )
- bindings[key] = binding_proxy
- return bindings
-
-
-def get_default_lb_vserver(client, module):
- try:
- default_lb_vserver = csvserver_lbvserver_binding.get(client, module.params['name'])
- return default_lb_vserver[0]
- except nitro_exception as e:
- if e.errorcode == 258:
- return csvserver_lbvserver_binding()
- else:
- raise
-
-
-def default_lb_vserver_identical(client, module):
- d = get_default_lb_vserver(client, module)
- configured = ConfigProxy(
- actual=csvserver_lbvserver_binding(),
- client=client,
- readwrite_attrs=[
- 'name',
- 'lbvserver',
- ],
- attribute_values_dict={
- 'name': module.params['name'],
- 'lbvserver': module.params['lbvserver'],
- }
- )
- log('default lb vserver %s' % ((d.name, d.lbvserver),))
- if d.name is None and module.params['lbvserver'] is None:
- log('Default lb vserver identical missing')
- return True
- elif d.name is not None and module.params['lbvserver'] is None:
- log('Default lb vserver needs removing')
- return False
- elif configured.has_equal_attributes(d):
- log('Default lb vserver identical')
- return True
- else:
- log('Default lb vserver not identical')
- return False
-
-
-def sync_default_lb_vserver(client, module):
- d = get_default_lb_vserver(client, module)
-
- if module.params['lbvserver'] is not None:
- configured = ConfigProxy(
- actual=csvserver_lbvserver_binding(),
- client=client,
- readwrite_attrs=[
- 'name',
- 'lbvserver',
- ],
- attribute_values_dict={
- 'name': module.params['name'],
- 'lbvserver': module.params['lbvserver'],
- }
- )
-
- if not configured.has_equal_attributes(d):
- if d.name is not None:
- log('Deleting default lb vserver %s' % d.lbvserver)
- csvserver_lbvserver_binding.delete(client, d)
- log('Adding default lb vserver %s' % configured.lbvserver)
- configured.add()
- else:
- if d.name is not None:
- log('Deleting default lb vserver %s' % d.lbvserver)
- csvserver_lbvserver_binding.delete(client, d)
-
-
-def get_actual_policybindings(client, module):
- log('Getting actual policy bindigs')
- bindings = {}
- try:
- count = csvserver_cspolicy_binding.count(client, name=module.params['name'])
- if count == 0:
- return bindings
- except nitro_exception as e:
- if e.errorcode == 258:
- return bindings
- else:
- raise
-
- for binding in csvserver_cspolicy_binding.get(client, name=module.params['name']):
- key = binding.policyname
- bindings[key] = binding
-
- return bindings
-
-
-def cs_policybindings_identical(client, module):
- log('Checking policy bindings identical')
- actual_bindings = get_actual_policybindings(client, module)
- configured_bindings = get_configured_policybindings(client, module)
-
- actual_keyset = set(actual_bindings.keys())
- configured_keyset = set(configured_bindings.keys())
- if len(actual_keyset ^ configured_keyset) > 0:
- return False
-
- # Compare item to item
- for key in actual_bindings.keys():
- configured_binding_proxy = configured_bindings[key]
- actual_binding_object = actual_bindings[key]
- if not configured_binding_proxy.has_equal_attributes(actual_binding_object):
- return False
-
- # Fallthrough to success
- return True
-
-
-def sync_cs_policybindings(client, module):
- log('Syncing cs policybindings')
- actual_bindings = get_actual_policybindings(client, module)
- configured_bindings = get_configured_policybindings(client, module)
-
- # Delete actual bindings not in configured
- delete_keys = list(set(actual_bindings.keys()) - set(configured_bindings.keys()))
- for key in delete_keys:
- log('Deleting binding for policy %s' % key)
- csvserver_cspolicy_binding.delete(client, actual_bindings[key])
-
- # Add configured bindings not in actual
- add_keys = list(set(configured_bindings.keys()) - set(actual_bindings.keys()))
- for key in add_keys:
- log('Adding binding for policy %s' % key)
- configured_bindings[key].add()
-
- # Update existing if changed
- modify_keys = list(set(configured_bindings.keys()) & set(actual_bindings.keys()))
- for key in modify_keys:
- if not configured_bindings[key].has_equal_attributes(actual_bindings[key]):
- log('Updating binding for policy %s' % key)
- csvserver_cspolicy_binding.delete(client, actual_bindings[key])
- configured_bindings[key].add()
-
-
-def ssl_certkey_bindings_identical(client, module):
- log('Checking if ssl cert key bindings are identical')
- vservername = module.params['name']
- if sslvserver_sslcertkey_binding.count(client, vservername) == 0:
- bindings = []
- else:
- bindings = sslvserver_sslcertkey_binding.get(client, vservername)
-
- if module.params['ssl_certkey'] is None:
- if len(bindings) == 0:
- return True
- else:
- return False
- else:
- certificate_list = [item.certkeyname for item in bindings]
- if certificate_list == [module.params['ssl_certkey']]:
- return True
- else:
- return False
-
-
-def ssl_certkey_bindings_sync(client, module):
- log('Syncing certkey bindings')
- vservername = module.params['name']
- if sslvserver_sslcertkey_binding.count(client, vservername) == 0:
- bindings = []
- else:
- bindings = sslvserver_sslcertkey_binding.get(client, vservername)
-
- # Delete existing bindings
- for binding in bindings:
- log('Deleting existing binding for certkey %s' % binding.certkeyname)
- sslvserver_sslcertkey_binding.delete(client, binding)
-
- # Add binding if appropriate
- if module.params['ssl_certkey'] is not None:
- log('Adding binding for certkey %s' % module.params['ssl_certkey'])
- binding = sslvserver_sslcertkey_binding()
- binding.vservername = module.params['name']
- binding.certkeyname = module.params['ssl_certkey']
- sslvserver_sslcertkey_binding.add(client, binding)
-
-
-def diff_list(client, module, csvserver_proxy):
- csvserver_list = csvserver.get_filtered(client, 'name:%s' % module.params['name'])
- return csvserver_proxy.diff_object(csvserver_list[0])
-
-
-def do_state_change(client, module, csvserver_proxy):
- if module.params['disabled']:
- log('Disabling cs vserver')
- result = csvserver.disable(client, csvserver_proxy.actual)
- else:
- log('Enabling cs vserver')
- result = csvserver.enable(client, csvserver_proxy.actual)
- return result
-
-
-def main():
-
- module_specific_arguments = dict(
-
- name=dict(type='str'),
- td=dict(type='float'),
- servicetype=dict(
- type='str',
- choices=[
- 'HTTP',
- 'SSL',
- 'TCP',
- 'FTP',
- 'RTSP',
- 'SSL_TCP',
- 'UDP',
- 'DNS',
- 'SIP_UDP',
- 'SIP_TCP',
- 'SIP_SSL',
- 'ANY',
- 'RADIUS',
- 'RDP',
- 'MYSQL',
- 'MSSQL',
- 'DIAMETER',
- 'SSL_DIAMETER',
- 'DNS_TCP',
- 'ORACLE',
- 'SMPP'
- ]
- ),
-
- ipv46=dict(type='str'),
- dnsrecordtype=dict(
- type='str',
- choices=[
- 'A',
- 'AAAA',
- 'CNAME',
- 'NAPTR',
- ]
- ),
- ippattern=dict(type='str'),
- ipmask=dict(type='str'),
- range=dict(type='float'),
- port=dict(type='int'),
- stateupdate=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- cacheable=dict(type='bool'),
- redirecturl=dict(type='str'),
- clttimeout=dict(type='float'),
- precedence=dict(
- type='str',
- choices=[
- 'RULE',
- 'URL',
- ]
- ),
- casesensitive=dict(type='bool'),
- somethod=dict(
- type='str',
- choices=[
- 'CONNECTION',
- 'DYNAMICCONNECTION',
- 'BANDWIDTH',
- 'HEALTH',
- 'NONE',
- ]
- ),
- sopersistence=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- sopersistencetimeout=dict(type='float'),
- sothreshold=dict(type='float'),
- sobackupaction=dict(
- type='str',
- choices=[
- 'DROP',
- 'ACCEPT',
- 'REDIRECT',
- ]
- ),
- redirectportrewrite=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- downstateflush=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- disableprimaryondown=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- insertvserveripport=dict(
- type='str',
- choices=[
- 'OFF',
- 'VIPADDR',
- 'V6TOV4MAPPING',
- ]
- ),
- vipheader=dict(type='str'),
- rtspnat=dict(type='bool'),
- authenticationhost=dict(type='str'),
- authentication=dict(type='bool'),
- listenpolicy=dict(type='str'),
- authn401=dict(type='bool'),
- authnvsname=dict(type='str'),
- push=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- pushvserver=dict(type='str'),
- pushlabel=dict(type='str'),
- pushmulticlients=dict(type='bool'),
- tcpprofilename=dict(type='str'),
- httpprofilename=dict(type='str'),
- dbprofilename=dict(type='str'),
- oracleserverversion=dict(
- type='str',
- choices=[
- '10G',
- '11G',
- ]
- ),
- comment=dict(type='str'),
- mssqlserverversion=dict(
- type='str',
- choices=[
- '70',
- '2000',
- '2000SP1',
- '2005',
- '2008',
- '2008R2',
- '2012',
- '2014',
- ]
- ),
- l2conn=dict(type='bool'),
- mysqlprotocolversion=dict(type='float'),
- mysqlserverversion=dict(type='str'),
- mysqlcharacterset=dict(type='float'),
- mysqlservercapabilities=dict(type='float'),
- appflowlog=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- netprofile=dict(type='str'),
- icmpvsrresponse=dict(
- type='str',
- choices=[
- 'PASSIVE',
- 'ACTIVE',
- ]
- ),
- rhistate=dict(
- type='str',
- choices=[
- 'PASSIVE',
- 'ACTIVE',
- ]
- ),
- authnprofile=dict(type='str'),
- dnsprofilename=dict(type='str'),
- )
-
- hand_inserted_arguments = dict(
- policybindings=dict(type='list'),
- ssl_certkey=dict(type='str'),
- disabled=dict(
- type='bool',
- default=False
- ),
- lbvserver=dict(type='str'),
- )
-
- argument_spec = dict()
-
- argument_spec.update(netscaler_common_arguments)
-
- argument_spec.update(module_specific_arguments)
- argument_spec.update(hand_inserted_arguments)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- )
- module_result = dict(
- changed=False,
- failed=False,
- loglines=loglines,
- )
-
- # Fail the module if imports failed
- if not PYTHON_SDK_IMPORTED:
- module.fail_json(msg='Could not load nitro python sdk')
-
- # Fallthrough to rest of execution
- client = get_nitro_client(module)
-
- try:
- client.login()
- except nitro_exception as e:
- msg = "nitro exception during login. errorcode=%s, message=%s" % (str(e.errorcode), e.message)
- module.fail_json(msg=msg)
- except Exception as e:
- if str(type(e)) == "":
- module.fail_json(msg='Connection error %s' % str(e))
- elif str(type(e)) == "":
- module.fail_json(msg='SSL Error %s' % str(e))
- else:
- module.fail_json(msg='Unexpected error during login %s' % str(e))
-
- readwrite_attrs = [
- 'name',
- 'td',
- 'servicetype',
- 'ipv46',
- 'dnsrecordtype',
- 'ippattern',
- 'ipmask',
- 'range',
- 'port',
- 'stateupdate',
- 'cacheable',
- 'redirecturl',
- 'clttimeout',
- 'precedence',
- 'casesensitive',
- 'somethod',
- 'sopersistence',
- 'sopersistencetimeout',
- 'sothreshold',
- 'sobackupaction',
- 'redirectportrewrite',
- 'downstateflush',
- 'disableprimaryondown',
- 'insertvserveripport',
- 'vipheader',
- 'rtspnat',
- 'authenticationhost',
- 'authentication',
- 'listenpolicy',
- 'authn401',
- 'authnvsname',
- 'push',
- 'pushvserver',
- 'pushlabel',
- 'pushmulticlients',
- 'tcpprofilename',
- 'httpprofilename',
- 'dbprofilename',
- 'oracleserverversion',
- 'comment',
- 'mssqlserverversion',
- 'l2conn',
- 'mysqlprotocolversion',
- 'mysqlserverversion',
- 'mysqlcharacterset',
- 'mysqlservercapabilities',
- 'appflowlog',
- 'netprofile',
- 'icmpvsrresponse',
- 'rhistate',
- 'authnprofile',
- 'dnsprofilename',
- ]
-
- readonly_attrs = [
- 'ip',
- 'value',
- 'ngname',
- 'type',
- 'curstate',
- 'sc',
- 'status',
- 'cachetype',
- 'redirect',
- 'homepage',
- 'dnsvservername',
- 'domain',
- 'policyname',
- 'servicename',
- 'weight',
- 'cachevserver',
- 'targetvserver',
- 'priority',
- 'url',
- 'gotopriorityexpression',
- 'bindpoint',
- 'invoke',
- 'labeltype',
- 'labelname',
- 'gt2gb',
- 'statechangetimesec',
- 'statechangetimemsec',
- 'tickssincelaststatechange',
- 'ruletype',
- 'lbvserver',
- 'targetlbvserver',
- ]
-
- immutable_attrs = [
- 'name',
- 'td',
- 'servicetype',
- 'ipv46',
- 'targettype',
- 'range',
- 'port',
- 'state',
- 'vipheader',
- 'newname',
- ]
-
- transforms = {
- 'cacheable': ['bool_yes_no'],
- 'rtspnat': ['bool_on_off'],
- 'authn401': ['bool_on_off'],
- 'casesensitive': ['bool_on_off'],
- 'authentication': ['bool_on_off'],
- 'l2conn': ['bool_on_off'],
- 'pushmulticlients': ['bool_yes_no'],
- 'stateupdate': [lambda v: v.upper()],
- 'sopersistence': [lambda v: v.upper()],
- 'redirectportrewrite': [lambda v: v.upper()],
- 'downstateflush': [lambda v: v.upper()],
- 'disableprimaryondown': [lambda v: v.upper()],
- 'push': [lambda v: v.upper()],
- 'appflowlog': [lambda v: v.upper()],
- }
-
- # Instantiate config proxy
- csvserver_proxy = ConfigProxy(
- actual=csvserver(),
- client=client,
- attribute_values_dict=module.params,
- readwrite_attrs=readwrite_attrs,
- readonly_attrs=readonly_attrs,
- immutable_attrs=immutable_attrs,
- transforms=transforms,
- )
-
- try:
- ensure_feature_is_enabled(client, 'CS')
-
- # Apply appropriate state
- if module.params['state'] == 'present':
- log('Applying actions for state present')
- if not cs_vserver_exists(client, module):
- if not module.check_mode:
- csvserver_proxy.add()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- elif not cs_vserver_identical(client, module, csvserver_proxy):
-
- # Check if we try to change value of immutable attributes
- immutables_changed = get_immutables_intersection(csvserver_proxy, diff_list(client, module, csvserver_proxy).keys())
- if immutables_changed != []:
- module.fail_json(
- msg='Cannot update immutable attributes %s' % (immutables_changed,),
- diff=diff_list(client, module, csvserver_proxy),
- **module_result
- )
-
- if not module.check_mode:
- csvserver_proxy.update()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- else:
- module_result['changed'] = False
-
- # Check policybindings
- if not cs_policybindings_identical(client, module):
- if not module.check_mode:
- sync_cs_policybindings(client, module)
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
-
- if module.params['servicetype'] != 'SSL' and module.params['ssl_certkey'] is not None:
- module.fail_json(msg='ssl_certkey is applicable only to SSL vservers', **module_result)
-
- # Check ssl certkey bindings
- if module.params['servicetype'] == 'SSL':
- if not ssl_certkey_bindings_identical(client, module):
- if not module.check_mode:
- ssl_certkey_bindings_sync(client, module)
-
- module_result['changed'] = True
-
- # Check default lb vserver
- if not default_lb_vserver_identical(client, module):
- if not module.check_mode:
- sync_default_lb_vserver(client, module)
- module_result['changed'] = True
-
- if not module.check_mode:
- res = do_state_change(client, module, csvserver_proxy)
- if res.errorcode != 0:
- msg = 'Error when setting disabled state. errorcode: %s message: %s' % (res.errorcode, res.message)
- module.fail_json(msg=msg, **module_result)
-
- # Sanity check for state
- if not module.check_mode:
- log('Sanity checks for state present')
- if not cs_vserver_exists(client, module):
- module.fail_json(msg='CS vserver does not exist', **module_result)
- if not cs_vserver_identical(client, module, csvserver_proxy):
- module.fail_json(msg='CS vserver differs from configured', diff=diff_list(client, module, csvserver_proxy), **module_result)
- if not cs_policybindings_identical(client, module):
- module.fail_json(msg='Policy bindings differ')
-
- if module.params['servicetype'] == 'SSL':
- if not ssl_certkey_bindings_identical(client, module):
- module.fail_json(msg='sll certkey bindings not identical', **module_result)
-
- elif module.params['state'] == 'absent':
- log('Applying actions for state absent')
- if cs_vserver_exists(client, module):
- if not module.check_mode:
- csvserver_proxy.delete()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- else:
- module_result['changed'] = False
-
- # Sanity check for state
- if not module.check_mode:
- log('Sanity checks for state absent')
- if cs_vserver_exists(client, module):
- module.fail_json(msg='CS vserver still exists', **module_result)
-
- except nitro_exception as e:
- msg = "nitro exception errorcode=%s, message=%s" % (str(e.errorcode), e.message)
- module.fail_json(msg=msg, **module_result)
-
- client.logout()
- module.exit_json(**module_result)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/netscaler/netscaler_gslb_service.py b/plugins/modules/network/netscaler/netscaler_gslb_service.py
deleted file mode 100644
index 2d2e0f8296..0000000000
--- a/plugins/modules/network/netscaler/netscaler_gslb_service.py
+++ /dev/null
@@ -1,696 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2017 Citrix Systems
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: netscaler_gslb_service
-short_description: Manage gslb service entities in Netscaler.
-description:
- - Manage gslb service entities in Netscaler.
-
-
-author: George Nikolopoulos (@giorgos-nikolopoulos)
-
-options:
-
- servicename:
- description:
- - >-
- Name for the GSLB service. Must begin with an ASCII alphanumeric or underscore C(_) character, and
- must contain only ASCII alphanumeric, underscore C(_), hash C(#), period C(.), space, colon C(:), at C(@),
- equals C(=), and hyphen C(-) characters. Can be changed after the GSLB service is created.
- - >-
- - "Minimum length = 1"
-
- cnameentry:
- description:
- - "Canonical name of the GSLB service. Used in CNAME-based GSLB."
- - "Minimum length = 1"
-
-
- servername:
- description:
- - "Name of the server hosting the GSLB service."
- - "Minimum length = 1"
-
- servicetype:
- choices:
- - 'HTTP'
- - 'FTP'
- - 'TCP'
- - 'UDP'
- - 'SSL'
- - 'SSL_BRIDGE'
- - 'SSL_TCP'
- - 'NNTP'
- - 'ANY'
- - 'SIP_UDP'
- - 'SIP_TCP'
- - 'SIP_SSL'
- - 'RADIUS'
- - 'RDP'
- - 'RTSP'
- - 'MYSQL'
- - 'MSSQL'
- - 'ORACLE'
- description:
- - "Type of service to create."
-
- port:
- description:
- - "Port on which the load balancing entity represented by this GSLB service listens."
- - "Minimum value = 1"
- - "Range 1 - 65535"
- - "* in CLI is represented as 65535 in NITRO API"
-
- publicip:
- description:
- - >-
- The public IP address that a NAT device translates to the GSLB service's private IP address.
- Optional.
-
- publicport:
- description:
- - >-
- The public port associated with the GSLB service's public IP address. The port is mapped to the
- service's private port number. Applicable to the local GSLB service. Optional.
-
- maxclient:
- description:
- - >-
- The maximum number of open connections that the service can support at any given time. A GSLB service
- whose connection count reaches the maximum is not considered when a GSLB decision is made, until the
- connection count drops below the maximum.
- - "Minimum value = C(0)"
- - "Maximum value = C(4294967294)"
-
- healthmonitor:
- description:
- - "Monitor the health of the GSLB service."
- type: bool
-
- sitename:
- description:
- - "Name of the GSLB site to which the service belongs."
- - "Minimum length = 1"
-
- cip:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- In the request that is forwarded to the GSLB service, insert a header that stores the client's IP
- address. Client IP header insertion is used in connection-proxy based site persistence.
-
- cipheader:
- description:
- - >-
- Name for the HTTP header that stores the client's IP address. Used with the Client IP option. If
- client IP header insertion is enabled on the service and a name is not specified for the header, the
- NetScaler appliance uses the name specified by the cipHeader parameter in the set ns param command
- or, in the GUI, the Client IP Header parameter in the Configure HTTP Parameters dialog box.
- - "Minimum length = 1"
-
- sitepersistence:
- choices:
- - 'ConnectionProxy'
- - 'HTTPRedirect'
- - 'NONE'
- description:
- - "Use cookie-based site persistence. Applicable only to C(HTTP) and C(SSL) GSLB services."
-
- siteprefix:
- description:
- - >-
- The site's prefix string. When the service is bound to a GSLB virtual server, a GSLB site domain is
- generated internally for each bound service-domain pair by concatenating the site prefix of the
- service and the name of the domain. If the special string NONE is specified, the site-prefix string
- is unset. When implementing HTTP redirect site persistence, the NetScaler appliance redirects GSLB
- requests to GSLB services by using their site domains.
-
- clttimeout:
- description:
- - >-
- Idle time, in seconds, after which a client connection is terminated. Applicable if connection proxy
- based site persistence is used.
- - "Minimum value = 0"
- - "Maximum value = 31536000"
-
- maxbandwidth:
- description:
- - >-
- Integer specifying the maximum bandwidth allowed for the service. A GSLB service whose bandwidth
- reaches the maximum is not considered when a GSLB decision is made, until its bandwidth consumption
- drops below the maximum.
-
- downstateflush:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- Flush all active transactions associated with the GSLB service when its state transitions from UP to
- DOWN. Do not enable this option for services that must complete their transactions. Applicable if
- connection proxy based site persistence is used.
-
- maxaaausers:
- description:
- - >-
- Maximum number of SSL VPN users that can be logged on concurrently to the VPN virtual server that is
- represented by this GSLB service. A GSLB service whose user count reaches the maximum is not
- considered when a GSLB decision is made, until the count drops below the maximum.
- - "Minimum value = C(0)"
- - "Maximum value = C(65535)"
-
- monthreshold:
- description:
- - >-
- Monitoring threshold value for the GSLB service. If the sum of the weights of the monitors that are
- bound to this GSLB service and are in the UP state is not equal to or greater than this threshold
- value, the service is marked as DOWN.
- - "Minimum value = C(0)"
- - "Maximum value = C(65535)"
-
- hashid:
- description:
- - "Unique hash identifier for the GSLB service, used by hash based load balancing methods."
- - "Minimum value = C(1)"
-
- comment:
- description:
- - "Any comments that you might want to associate with the GSLB service."
-
- appflowlog:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - "Enable logging appflow flow information."
-
- ipaddress:
- description:
- - >-
- IP address for the GSLB service. Should represent a load balancing, content switching, or VPN virtual
- server on the NetScaler appliance, or the IP address of another load balancing device.
-
- monitor_bindings:
- description:
- - Bind monitors to this gslb service
- suboptions:
-
- weight:
- description:
- - Weight to assign to the monitor-service binding.
- - A larger number specifies a greater weight.
- - Contributes to the monitoring threshold, which determines the state of the service.
- - Minimum value = C(1)
- - Maximum value = C(100)
-
- monitor_name:
- description:
- - Monitor name.
-
-extends_documentation_fragment:
-- community.general.netscaler
-
-requirements:
- - nitro python sdk
-'''
-
-EXAMPLES = '''
-- name: Setup gslb service 2
-
- delegate_to: localhost
- register: result
- check_mode: "{{ check_mode }}"
-
- netscaler_gslb_service:
- operation: present
-
- servicename: gslb-service-2
- cnameentry: example.com
- sitename: gslb-site-1
-'''
-
-RETURN = '''
-loglines:
- description: list of logged messages by the module
- returned: always
- type: list
- sample: "['message 1', 'message 2']"
-
-msg:
- description: Message detailing the failure reason
- returned: failure
- type: str
- sample: "Action does not exist"
-
-diff:
- description: List of differences between the actual configured object and the configuration specified in the module
- returned: failure
- type: dict
- sample: "{ 'targetlbvserver': 'difference. ours: (str) server1 other: (str) server2' }"
-'''
-
-import copy
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.netscaler.netscaler import (
- ConfigProxy,
- get_nitro_client,
- netscaler_common_arguments,
- log,
- loglines,
- ensure_feature_is_enabled,
- monkey_patch_nitro_api,
- get_immutables_intersection,
-)
-
-try:
- monkey_patch_nitro_api()
- from nssrc.com.citrix.netscaler.nitro.resource.config.gslb.gslbservice import gslbservice
- from nssrc.com.citrix.netscaler.nitro.resource.config.gslb.gslbservice_lbmonitor_binding import gslbservice_lbmonitor_binding
- from nssrc.com.citrix.netscaler.nitro.exception.nitro_exception import nitro_exception
- PYTHON_SDK_IMPORTED = True
-except ImportError as e:
- PYTHON_SDK_IMPORTED = False
-
-
-def gslb_service_exists(client, module):
- if gslbservice.count_filtered(client, 'servicename:%s' % module.params['servicename']) > 0:
- return True
- else:
- return False
-
-
-def gslb_service_identical(client, module, gslb_service_proxy):
- gslb_service_list = gslbservice.get_filtered(client, 'servicename:%s' % module.params['servicename'])
- diff_dict = gslb_service_proxy.diff_object(gslb_service_list[0])
- # Ignore ip attribute missing
- if 'ip' in diff_dict:
- del diff_dict['ip']
- if len(diff_dict) == 0:
- return True
- else:
- return False
-
-
-def get_actual_monitor_bindings(client, module):
- log('get_actual_monitor_bindings')
- # Get actual monitor bindings and index them by monitor_name
- actual_monitor_bindings = {}
- if gslbservice_lbmonitor_binding.count(client, servicename=module.params['servicename']) != 0:
- # Get all monitor bindings associated with the named gslb vserver
- fetched_bindings = gslbservice_lbmonitor_binding.get(client, servicename=module.params['servicename'])
- # index by monitor name
- for binding in fetched_bindings:
- # complete_missing_attributes(binding, gslbservice_lbmonitor_binding_rw_attrs, fill_value=None)
- actual_monitor_bindings[binding.monitor_name] = binding
- return actual_monitor_bindings
-
-
-def get_configured_monitor_bindings(client, module):
- log('get_configured_monitor_bindings')
- configured_monitor_proxys = {}
- gslbservice_lbmonitor_binding_rw_attrs = [
- 'weight',
- 'servicename',
- 'monitor_name',
- ]
- # Get configured monitor bindings and index them by monitor_name
- if module.params['monitor_bindings'] is not None:
- for configured_monitor_bindings in module.params['monitor_bindings']:
- binding_values = copy.deepcopy(configured_monitor_bindings)
- binding_values['servicename'] = module.params['servicename']
- proxy = ConfigProxy(
- actual=gslbservice_lbmonitor_binding(),
- client=client,
- attribute_values_dict=binding_values,
- readwrite_attrs=gslbservice_lbmonitor_binding_rw_attrs,
- readonly_attrs=[],
- )
- configured_monitor_proxys[configured_monitor_bindings['monitor_name']] = proxy
- return configured_monitor_proxys
-
-
-def monitor_bindings_identical(client, module):
- log('monitor_bindings_identical')
- actual_bindings = get_actual_monitor_bindings(client, module)
- configured_proxys = get_configured_monitor_bindings(client, module)
-
- actual_keyset = set(actual_bindings.keys())
- configured_keyset = set(configured_proxys.keys())
-
- symmetric_difference = actual_keyset ^ configured_keyset
- if len(symmetric_difference) != 0:
- log('Symmetric difference %s' % symmetric_difference)
- return False
-
- # Item for item equality test
- for key, proxy in configured_proxys.items():
- if not proxy.has_equal_attributes(actual_bindings[key]):
- log('monitor binding difference %s' % proxy.diff_object(actual_bindings[key]))
- return False
-
- # Fallthrough to True result
- return True
-
-
-def sync_monitor_bindings(client, module):
- log('sync_monitor_bindings')
-
- actual_monitor_bindings = get_actual_monitor_bindings(client, module)
- configured_monitor_proxys = get_configured_monitor_bindings(client, module)
-
- # Delete actual bindings not in configured bindings
- for monitor_name, actual_binding in actual_monitor_bindings.items():
- if monitor_name not in configured_monitor_proxys.keys():
- log('Deleting absent binding for monitor %s' % monitor_name)
- log('dir is %s' % dir(actual_binding))
- gslbservice_lbmonitor_binding.delete(client, actual_binding)
-
- # Delete and re-add actual bindings that differ from configured
- for proxy_key, binding_proxy in configured_monitor_proxys.items():
- if proxy_key in actual_monitor_bindings:
- actual_binding = actual_monitor_bindings[proxy_key]
- if not binding_proxy.has_equal_attributes(actual_binding):
- log('Deleting differing binding for monitor %s' % actual_binding.monitor_name)
- log('dir %s' % dir(actual_binding))
- log('attribute monitor_name %s' % getattr(actual_binding, 'monitor_name'))
- log('attribute monitorname %s' % getattr(actual_binding, 'monitorname', None))
- gslbservice_lbmonitor_binding.delete(client, actual_binding)
- log('Adding anew binding for monitor %s' % binding_proxy.monitor_name)
- binding_proxy.add()
-
- # Add configured monitors that are missing from actual
- for proxy_key, binding_proxy in configured_monitor_proxys.items():
- if proxy_key not in actual_monitor_bindings.keys():
- log('Adding monitor binding for monitor %s' % binding_proxy.monitor_name)
- binding_proxy.add()
-
-
-def diff_list(client, module, gslb_service_proxy):
- gslb_service_list = gslbservice.get_filtered(client, 'servicename:%s' % module.params['servicename'])
- diff_list = gslb_service_proxy.diff_object(gslb_service_list[0])
- if 'ip' in diff_list:
- del diff_list['ip']
- return diff_list
-
-
-def all_identical(client, module, gslb_service_proxy):
- return gslb_service_identical(client, module, gslb_service_proxy) and monitor_bindings_identical(client, module)
-
-
-def main():
-
- module_specific_arguments = dict(
- servicename=dict(type='str'),
- cnameentry=dict(type='str'),
- servername=dict(type='str'),
- servicetype=dict(
- type='str',
- choices=[
- 'HTTP',
- 'FTP',
- 'TCP',
- 'UDP',
- 'SSL',
- 'SSL_BRIDGE',
- 'SSL_TCP',
- 'NNTP',
- 'ANY',
- 'SIP_UDP',
- 'SIP_TCP',
- 'SIP_SSL',
- 'RADIUS',
- 'RDP',
- 'RTSP',
- 'MYSQL',
- 'MSSQL',
- 'ORACLE',
- ]
- ),
- port=dict(type='int'),
- publicip=dict(type='str'),
- publicport=dict(type='int'),
- maxclient=dict(type='float'),
- healthmonitor=dict(type='bool'),
- sitename=dict(type='str'),
- cip=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- cipheader=dict(type='str'),
- sitepersistence=dict(
- type='str',
- choices=[
- 'ConnectionProxy',
- 'HTTPRedirect',
- 'NONE',
- ]
- ),
- siteprefix=dict(type='str'),
- clttimeout=dict(type='float'),
- maxbandwidth=dict(type='float'),
- downstateflush=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- maxaaausers=dict(type='float'),
- monthreshold=dict(type='float'),
- hashid=dict(type='float'),
- comment=dict(type='str'),
- appflowlog=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- ipaddress=dict(type='str'),
- )
-
- hand_inserted_arguments = dict(
- monitor_bindings=dict(type='list'),
- )
-
- argument_spec = dict()
-
- argument_spec.update(netscaler_common_arguments)
- argument_spec.update(module_specific_arguments)
- argument_spec.update(hand_inserted_arguments)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- )
- module_result = dict(
- changed=False,
- failed=False,
- loglines=loglines,
- )
-
- # Fail the module if imports failed
- if not PYTHON_SDK_IMPORTED:
- module.fail_json(msg='Could not load nitro python sdk')
-
- # Fallthrough to rest of execution
- client = get_nitro_client(module)
-
- try:
- client.login()
- except nitro_exception as e:
- msg = "nitro exception during login. errorcode=%s, message=%s" % (str(e.errorcode), e.message)
- module.fail_json(msg=msg)
- except Exception as e:
- if str(type(e)) == "":
- module.fail_json(msg='Connection error %s' % str(e))
- elif str(type(e)) == "":
- module.fail_json(msg='SSL Error %s' % str(e))
- else:
- module.fail_json(msg='Unexpected error during login %s' % str(e))
-
- readwrite_attrs = [
- 'servicename',
- 'cnameentry',
- 'ip',
- 'servername',
- 'servicetype',
- 'port',
- 'publicip',
- 'publicport',
- 'maxclient',
- 'healthmonitor',
- 'sitename',
- 'cip',
- 'cipheader',
- 'sitepersistence',
- 'siteprefix',
- 'clttimeout',
- 'maxbandwidth',
- 'downstateflush',
- 'maxaaausers',
- 'monthreshold',
- 'hashid',
- 'comment',
- 'appflowlog',
- 'ipaddress',
- ]
-
- readonly_attrs = [
- 'gslb',
- 'svrstate',
- 'svreffgslbstate',
- 'gslbthreshold',
- 'gslbsvcstats',
- 'monstate',
- 'preferredlocation',
- 'monitor_state',
- 'statechangetimesec',
- 'tickssincelaststatechange',
- 'threshold',
- 'clmonowner',
- 'clmonview',
- '__count',
- ]
-
- immutable_attrs = [
- 'servicename',
- 'cnameentry',
- 'ip',
- 'servername',
- 'servicetype',
- 'port',
- 'sitename',
- 'state',
- 'cipheader',
- 'cookietimeout',
- 'clttimeout',
- 'svrtimeout',
- 'viewip',
- 'monitor_name_svc',
- 'newname',
- ]
-
- transforms = {
- 'healthmonitor': ['bool_yes_no'],
- 'cip': [lambda v: v.upper()],
- 'downstateflush': [lambda v: v.upper()],
- 'appflowlog': [lambda v: v.upper()],
- }
-
- # params = copy.deepcopy(module.params)
- module.params['ip'] = module.params['ipaddress']
-
- # Instantiate config proxy
- gslb_service_proxy = ConfigProxy(
- actual=gslbservice(),
- client=client,
- attribute_values_dict=module.params,
- transforms=transforms,
- readwrite_attrs=readwrite_attrs,
- readonly_attrs=readonly_attrs,
- immutable_attrs=immutable_attrs,
- )
-
- try:
- ensure_feature_is_enabled(client, 'GSLB')
- # Apply appropriate state
- if module.params['state'] == 'present':
- if not gslb_service_exists(client, module):
- if not module.check_mode:
- gslb_service_proxy.add()
- sync_monitor_bindings(client, module)
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- elif not all_identical(client, module, gslb_service_proxy):
-
- # Check if we try to change value of immutable attributes
- immutables_changed = get_immutables_intersection(gslb_service_proxy, diff_list(client, module, gslb_service_proxy).keys())
- if immutables_changed != []:
- module.fail_json(
- msg='Cannot update immutable attributes %s' % (immutables_changed,),
- diff=diff_list(client, module, gslb_service_proxy),
- **module_result
- )
-
- # Update main configuration object
- if not gslb_service_identical(client, module, gslb_service_proxy):
- if not module.check_mode:
- gslb_service_proxy.update()
-
- # Update monitor bindigns
- if not monitor_bindings_identical(client, module):
- if not module.check_mode:
- sync_monitor_bindings(client, module)
-
- # Fallthrough to save and change status update
- module_result['changed'] = True
- if module.params['save_config']:
- client.save_config()
- else:
- module_result['changed'] = False
-
- # Sanity check for state
- if not module.check_mode:
- if not gslb_service_exists(client, module):
- module.fail_json(msg='GSLB service does not exist', **module_result)
- if not gslb_service_identical(client, module, gslb_service_proxy):
- module.fail_json(
- msg='GSLB service differs from configured',
- diff=diff_list(client, module, gslb_service_proxy),
- **module_result
- )
- if not monitor_bindings_identical(client, module):
- module.fail_json(
- msg='Monitor bindings differ from configured',
- diff=diff_list(client, module, gslb_service_proxy),
- **module_result
- )
-
- elif module.params['state'] == 'absent':
- if gslb_service_exists(client, module):
- if not module.check_mode:
- gslb_service_proxy.delete()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- else:
- module_result['changed'] = False
-
- # Sanity check for state
- if not module.check_mode:
- if gslb_service_exists(client, module):
- module.fail_json(msg='GSLB service still exists', **module_result)
-
- except nitro_exception as e:
- msg = "nitro exception errorcode=%s, message=%s" % (str(e.errorcode), e.message)
- module.fail_json(msg=msg, **module_result)
-
- client.logout()
- module.exit_json(**module_result)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/netscaler/netscaler_gslb_site.py b/plugins/modules/network/netscaler/netscaler_gslb_site.py
deleted file mode 100644
index a84ac1c781..0000000000
--- a/plugins/modules/network/netscaler/netscaler_gslb_site.py
+++ /dev/null
@@ -1,424 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2017 Citrix Systems
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: netscaler_gslb_site
-short_description: Manage gslb site entities in Netscaler.
-description:
- - Manage gslb site entities in Netscaler.
-
-
-author: George Nikolopoulos (@giorgos-nikolopoulos)
-
-options:
-
- sitename:
- description:
- - >-
- Name for the GSLB site. Must begin with an ASCII alphanumeric or underscore C(_) character, and must
- contain only ASCII alphanumeric, underscore C(_), hash C(#), period C(.), space C( ), colon C(:), at C(@), equals
- C(=), and hyphen C(-) characters. Cannot be changed after the virtual server is created.
- - "Minimum length = 1"
-
- sitetype:
- choices:
- - 'REMOTE'
- - 'LOCAL'
- description:
- - >-
- Type of site to create. If the type is not specified, the appliance automatically detects and sets
- the type on the basis of the IP address being assigned to the site. If the specified site IP address
- is owned by the appliance (for example, a MIP address or SNIP address), the site is a local site.
- Otherwise, it is a remote site.
-
- siteipaddress:
- description:
- - >-
- IP address for the GSLB site. The GSLB site uses this IP address to communicate with other GSLB
- sites. For a local site, use any IP address that is owned by the appliance (for example, a SNIP or
- MIP address, or the IP address of the ADNS service).
- - "Minimum length = 1"
-
- publicip:
- description:
- - >-
- Public IP address for the local site. Required only if the appliance is deployed in a private address
- space and the site has a public IP address hosted on an external firewall or a NAT device.
- - "Minimum length = 1"
-
- metricexchange:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- Exchange metrics with other sites. Metrics are exchanged by using Metric Exchange Protocol (MEP). The
- appliances in the GSLB setup exchange health information once every second.
- - >-
- If you disable metrics exchange, you can use only static load balancing methods (such as round robin,
- static proximity, or the hash-based methods), and if you disable metrics exchange when a dynamic load
- balancing method (such as least connection) is in operation, the appliance falls back to round robin.
- Also, if you disable metrics exchange, you must use a monitor to determine the state of GSLB
- services. Otherwise, the service is marked as DOWN.
-
- nwmetricexchange:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- Exchange, with other GSLB sites, network metrics such as round-trip time (RTT), learned from
- communications with various local DNS (LDNS) servers used by clients. RTT information is used in the
- dynamic RTT load balancing method, and is exchanged every 5 seconds.
-
- sessionexchange:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - "Exchange persistent session entries with other GSLB sites every five seconds."
-
- triggermonitor:
- choices:
- - 'ALWAYS'
- - 'MEPDOWN'
- - 'MEPDOWN_SVCDOWN'
- description:
- - >-
- Specify the conditions under which the GSLB service must be monitored by a monitor, if one is bound.
- Available settings function as follows:
- - "* C(ALWAYS) - Monitor the GSLB service at all times."
- - >-
- * C(MEPDOWN) - Monitor the GSLB service only when the exchange of metrics through the Metrics Exchange
- Protocol (MEP) is disabled.
- - "C(MEPDOWN_SVCDOWN) - Monitor the service in either of the following situations:"
- - "* The exchange of metrics through MEP is disabled."
- - >-
- * The exchange of metrics through MEP is enabled but the status of the service, learned through
- metrics exchange, is DOWN.
-
- parentsite:
- description:
- - "Parent site of the GSLB site, in a parent-child topology."
-
- clip:
- description:
- - >-
- Cluster IP address. Specify this parameter to connect to the remote cluster site for GSLB auto-sync.
- Note: The cluster IP address is defined when creating the cluster.
-
- publicclip:
- description:
- - >-
- IP address to be used to globally access the remote cluster when it is deployed behind a NAT. It can
- be same as the normal cluster IP address.
-
- naptrreplacementsuffix:
- description:
- - >-
- The naptr replacement suffix configured here will be used to construct the naptr replacement field in
- NAPTR record.
- - "Minimum length = 1"
-
-
-extends_documentation_fragment:
-- community.general.netscaler
-
-requirements:
- - nitro python sdk
-'''
-
-EXAMPLES = '''
-- name: Setup gslb site
- delegate_to: localhost
- netscaler_gslb_site:
- nsip: 172.18.0.2
- nitro_user: nsroot
- nitro_pass: nsroot
-
- sitename: gslb-site-1
- siteipaddress: 192.168.1.1
- sitetype: LOCAL
- publicip: 192.168.1.1
- metricexchange: enabled
- nwmetricexchange: enabled
- sessionexchange: enabled
- triggermonitor: ALWAYS
-
-'''
-
-RETURN = '''
-loglines:
- description: list of logged messages by the module
- returned: always
- type: list
- sample: "['message 1', 'message 2']"
-
-msg:
- description: Message detailing the failure reason
- returned: failure
- type: str
- sample: "Action does not exist"
-
-diff:
- description: List of differences between the actual configured object and the configuration specified in the module
- returned: failure
- type: dict
- sample: "{ 'targetlbvserver': 'difference. ours: (str) server1 other: (str) server2' }"
-'''
-
-try:
- from nssrc.com.citrix.netscaler.nitro.resource.config.gslb.gslbsite import gslbsite
- from nssrc.com.citrix.netscaler.nitro.exception.nitro_exception import nitro_exception
- PYTHON_SDK_IMPORTED = True
-except ImportError as e:
- PYTHON_SDK_IMPORTED = False
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.netscaler.netscaler import (
- ConfigProxy,
- get_nitro_client,
- netscaler_common_arguments,
- log,
- loglines,
- ensure_feature_is_enabled,
- get_immutables_intersection,
-)
-
-
-def gslb_site_exists(client, module):
- if gslbsite.count_filtered(client, 'sitename:%s' % module.params['sitename']) > 0:
- return True
- else:
- return False
-
-
-def gslb_site_identical(client, module, gslb_site_proxy):
- gslb_site_list = gslbsite.get_filtered(client, 'sitename:%s' % module.params['sitename'])
- diff_dict = gslb_site_proxy.diff_object(gslb_site_list[0])
- if len(diff_dict) == 0:
- return True
- else:
- return False
-
-
-def diff_list(client, module, gslb_site_proxy):
- gslb_site_list = gslbsite.get_filtered(client, 'sitename:%s' % module.params['sitename'])
- return gslb_site_proxy.diff_object(gslb_site_list[0])
-
-
-def main():
-
- module_specific_arguments = dict(
- sitename=dict(type='str'),
- sitetype=dict(
- type='str',
- choices=[
- 'REMOTE',
- 'LOCAL',
- ]
- ),
- siteipaddress=dict(type='str'),
- publicip=dict(type='str'),
- metricexchange=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- nwmetricexchange=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- sessionexchange=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- triggermonitor=dict(
- type='str',
- choices=[
- 'ALWAYS',
- 'MEPDOWN',
- 'MEPDOWN_SVCDOWN',
- ]
- ),
- parentsite=dict(type='str'),
- clip=dict(type='str'),
- publicclip=dict(type='str'),
- naptrreplacementsuffix=dict(type='str'),
- )
-
- hand_inserted_arguments = dict(
- )
-
- argument_spec = dict()
-
- argument_spec.update(netscaler_common_arguments)
- argument_spec.update(module_specific_arguments)
- argument_spec.update(hand_inserted_arguments)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- )
- module_result = dict(
- changed=False,
- failed=False,
- loglines=loglines,
- )
-
- # Fail the module if imports failed
- if not PYTHON_SDK_IMPORTED:
- module.fail_json(msg='Could not load nitro python sdk')
-
- # Fallthrough to rest of execution
- client = get_nitro_client(module)
-
- try:
- client.login()
- except nitro_exception as e:
- msg = "nitro exception during login. errorcode=%s, message=%s" % (str(e.errorcode), e.message)
- module.fail_json(msg=msg)
- except Exception as e:
- if str(type(e)) == "":
- module.fail_json(msg='Connection error %s' % str(e))
- elif str(type(e)) == "":
- module.fail_json(msg='SSL Error %s' % str(e))
- else:
- module.fail_json(msg='Unexpected error during login %s' % str(e))
-
- readwrite_attrs = [
- 'sitename',
- 'sitetype',
- 'siteipaddress',
- 'publicip',
- 'metricexchange',
- 'nwmetricexchange',
- 'sessionexchange',
- 'triggermonitor',
- 'parentsite',
- 'clip',
- 'publicclip',
- 'naptrreplacementsuffix',
- ]
-
- readonly_attrs = [
- 'status',
- 'persistencemepstatus',
- 'version',
- '__count',
- ]
-
- immutable_attrs = [
- 'sitename',
- 'sitetype',
- 'siteipaddress',
- 'publicip',
- 'parentsite',
- 'clip',
- 'publicclip',
- ]
-
- transforms = {
- 'metricexchange': [lambda v: v.upper()],
- 'nwmetricexchange': [lambda v: v.upper()],
- 'sessionexchange': [lambda v: v.upper()],
- }
-
- # Instantiate config proxy
- gslb_site_proxy = ConfigProxy(
- actual=gslbsite(),
- client=client,
- attribute_values_dict=module.params,
- readwrite_attrs=readwrite_attrs,
- readonly_attrs=readonly_attrs,
- immutable_attrs=immutable_attrs,
- transforms=transforms,
- )
-
- try:
- ensure_feature_is_enabled(client, 'GSLB')
-
- # Apply appropriate state
- if module.params['state'] == 'present':
- log('Applying actions for state present')
- if not gslb_site_exists(client, module):
- if not module.check_mode:
- gslb_site_proxy.add()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- elif not gslb_site_identical(client, module, gslb_site_proxy):
-
- # Check if we try to change value of immutable attributes
- immutables_changed = get_immutables_intersection(gslb_site_proxy, diff_list(client, module, gslb_site_proxy).keys())
- if immutables_changed != []:
- module.fail_json(
- msg='Cannot update immutable attributes %s' % (immutables_changed,),
- diff=diff_list(client, module, gslb_site_proxy),
- **module_result
- )
-
- if not module.check_mode:
- gslb_site_proxy.update()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- else:
- module_result['changed'] = False
-
- # Sanity check for state
- if not module.check_mode:
- log('Sanity checks for state present')
- if not gslb_site_exists(client, module):
- module.fail_json(msg='GSLB site does not exist', **module_result)
- if not gslb_site_identical(client, module, gslb_site_proxy):
- module.fail_json(msg='GSLB site differs from configured', diff=diff_list(client, module, gslb_site_proxy), **module_result)
-
- elif module.params['state'] == 'absent':
- log('Applying actions for state absent')
- if gslb_site_exists(client, module):
- if not module.check_mode:
- gslb_site_proxy.delete()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- else:
- module_result['changed'] = False
-
- # Sanity check for state
- if not module.check_mode:
- log('Sanity checks for state absent')
- if gslb_site_exists(client, module):
- module.fail_json(msg='GSLB site still exists', **module_result)
-
- except nitro_exception as e:
- msg = "nitro exception errorcode=%s, message=%s" % (str(e.errorcode), e.message)
- module.fail_json(msg=msg, **module_result)
-
- client.logout()
- module.exit_json(**module_result)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/netscaler/netscaler_gslb_vserver.py b/plugins/modules/network/netscaler/netscaler_gslb_vserver.py
deleted file mode 100644
index ee0c8390a7..0000000000
--- a/plugins/modules/network/netscaler/netscaler_gslb_vserver.py
+++ /dev/null
@@ -1,955 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2017 Citrix Systems
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: netscaler_gslb_vserver
-short_description: Configure gslb vserver entities in Netscaler.
-description:
- - Configure gslb vserver entities in Netscaler.
-
-
-author: George Nikolopoulos (@giorgos-nikolopoulos)
-
-options:
-
- name:
- description:
- - >-
- Name for the GSLB virtual server. Must begin with an ASCII alphanumeric or underscore C(_) character,
- and must contain only ASCII alphanumeric, underscore C(_), hash C(#), period C(.), space, colon C(:), at C(@),
- equals C(=), and hyphen C(-) characters. Can be changed after the virtual server is created.
- - "Minimum length = 1"
-
- servicetype:
- choices:
- - 'HTTP'
- - 'FTP'
- - 'TCP'
- - 'UDP'
- - 'SSL'
- - 'SSL_BRIDGE'
- - 'SSL_TCP'
- - 'NNTP'
- - 'ANY'
- - 'SIP_UDP'
- - 'SIP_TCP'
- - 'SIP_SSL'
- - 'RADIUS'
- - 'RDP'
- - 'RTSP'
- - 'MYSQL'
- - 'MSSQL'
- - 'ORACLE'
- description:
- - "Protocol used by services bound to the virtual server."
- - >-
-
- dnsrecordtype:
- choices:
- - 'A'
- - 'AAAA'
- - 'CNAME'
- - 'NAPTR'
- description:
- - "DNS record type to associate with the GSLB virtual server's domain name."
- - "Default value: A"
- - "Possible values = A, AAAA, CNAME, NAPTR"
-
- lbmethod:
- choices:
- - 'ROUNDROBIN'
- - 'LEASTCONNECTION'
- - 'LEASTRESPONSETIME'
- - 'SOURCEIPHASH'
- - 'LEASTBANDWIDTH'
- - 'LEASTPACKETS'
- - 'STATICPROXIMITY'
- - 'RTT'
- - 'CUSTOMLOAD'
- description:
- - "Load balancing method for the GSLB virtual server."
- - "Default value: LEASTCONNECTION"
- - >-
- Possible values = ROUNDROBIN, LEASTCONNECTION, LEASTRESPONSETIME, SOURCEIPHASH, LEASTBANDWIDTH,
- LEASTPACKETS, STATICPROXIMITY, RTT, CUSTOMLOAD
-
- backuplbmethod:
- choices:
- - 'ROUNDROBIN'
- - 'LEASTCONNECTION'
- - 'LEASTRESPONSETIME'
- - 'SOURCEIPHASH'
- - 'LEASTBANDWIDTH'
- - 'LEASTPACKETS'
- - 'STATICPROXIMITY'
- - 'RTT'
- - 'CUSTOMLOAD'
- description:
- - >-
- Backup load balancing method. Becomes operational if the primary load balancing method fails or
- cannot be used. Valid only if the primary method is based on either round-trip time (RTT) or static
- proximity.
-
- netmask:
- description:
- - "IPv4 network mask for use in the SOURCEIPHASH load balancing method."
- - "Minimum length = 1"
-
- v6netmasklen:
- description:
- - >-
- Number of bits to consider, in an IPv6 source IP address, for creating the hash that is required by
- the C(SOURCEIPHASH) load balancing method.
- - "Default value: C(128)"
- - "Minimum value = C(1)"
- - "Maximum value = C(128)"
-
- tolerance:
- description:
- - >-
- Site selection tolerance, in milliseconds, for implementing the RTT load balancing method. If a
- site's RTT deviates from the lowest RTT by more than the specified tolerance, the site is not
- considered when the NetScaler appliance makes a GSLB decision. The appliance implements the round
- robin method of global server load balancing between sites whose RTT values are within the specified
- tolerance. If the tolerance is 0 (zero), the appliance always sends clients the IP address of the
- site with the lowest RTT.
- - "Minimum value = C(0)"
- - "Maximum value = C(100)"
-
- persistencetype:
- choices:
- - 'SOURCEIP'
- - 'NONE'
- description:
- - "Use source IP address based persistence for the virtual server."
- - >-
- After the load balancing method selects a service for the first packet, the IP address received in
- response to the DNS query is used for subsequent requests from the same client.
-
- persistenceid:
- description:
- - >-
- The persistence ID for the GSLB virtual server. The ID is a positive integer that enables GSLB sites
- to identify the GSLB virtual server, and is required if source IP address based or spill over based
- persistence is enabled on the virtual server.
- - "Minimum value = C(0)"
- - "Maximum value = C(65535)"
-
- persistmask:
- description:
- - >-
- The optional IPv4 network mask applied to IPv4 addresses to establish source IP address based
- persistence.
- - "Minimum length = 1"
-
- v6persistmasklen:
- description:
- - >-
- Number of bits to consider in an IPv6 source IP address when creating source IP address based
- persistence sessions.
- - "Default value: C(128)"
- - "Minimum value = C(1)"
- - "Maximum value = C(128)"
-
- timeout:
- description:
- - "Idle time, in minutes, after which a persistence entry is cleared."
- - "Default value: C(2)"
- - "Minimum value = C(2)"
- - "Maximum value = C(1440)"
-
- mir:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - "Include multiple IP addresses in the DNS responses sent to clients."
-
- disableprimaryondown:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- Continue to direct traffic to the backup chain even after the primary GSLB virtual server returns to
- the UP state. Used when spillover is configured for the virtual server.
-
- dynamicweight:
- choices:
- - 'SERVICECOUNT'
- - 'SERVICEWEIGHT'
- - 'DISABLED'
- description:
- - >-
- Specify if the appliance should consider the service count, service weights, or ignore both when
- using weight-based load balancing methods. The state of the number of services bound to the virtual
- server help the appliance to select the service.
-
- considereffectivestate:
- choices:
- - 'NONE'
- - 'STATE_ONLY'
- description:
- - >-
- If the primary state of all bound GSLB services is DOWN, consider the effective states of all the
- GSLB services, obtained through the Metrics Exchange Protocol (MEP), when determining the state of
- the GSLB virtual server. To consider the effective state, set the parameter to STATE_ONLY. To
- disregard the effective state, set the parameter to NONE.
- - >-
- The effective state of a GSLB service is the ability of the corresponding virtual server to serve
- traffic. The effective state of the load balancing virtual server, which is transferred to the GSLB
- service, is UP even if only one virtual server in the backup chain of virtual servers is in the UP
- state.
-
- comment:
- description:
- - "Any comments that you might want to associate with the GSLB virtual server."
-
- somethod:
- choices:
- - 'CONNECTION'
- - 'DYNAMICCONNECTION'
- - 'BANDWIDTH'
- - 'HEALTH'
- - 'NONE'
- description:
- - "Type of threshold that, when exceeded, triggers spillover. Available settings function as follows:"
- - "* C(CONNECTION) - Spillover occurs when the number of client connections exceeds the threshold."
- - >-
- * C(DYNAMICCONNECTION) - Spillover occurs when the number of client connections at the GSLB virtual
- server exceeds the sum of the maximum client (Max Clients) settings for bound GSLB services. Do not
- specify a spillover threshold for this setting, because the threshold is implied by the Max Clients
- settings of the bound GSLB services.
- - >-
- * C(BANDWIDTH) - Spillover occurs when the bandwidth consumed by the GSLB virtual server's incoming and
- outgoing traffic exceeds the threshold.
- - >-
- * C(HEALTH) - Spillover occurs when the percentage of weights of the GSLB services that are UP drops
- below the threshold. For example, if services gslbSvc1, gslbSvc2, and gslbSvc3 are bound to a virtual
- server, with weights 1, 2, and 3, and the spillover threshold is 50%, spillover occurs if gslbSvc1
- and gslbSvc3 or gslbSvc2 and gslbSvc3 transition to DOWN.
- - "* C(NONE) - Spillover does not occur."
-
- sopersistence:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- If spillover occurs, maintain source IP address based persistence for both primary and backup GSLB
- virtual servers.
-
- sopersistencetimeout:
- description:
- - "Timeout for spillover persistence, in minutes."
- - "Default value: C(2)"
- - "Minimum value = C(2)"
- - "Maximum value = C(1440)"
-
- sothreshold:
- description:
- - >-
- Threshold at which spillover occurs. Specify an integer for the CONNECTION spillover method, a
- bandwidth value in kilobits per second for the BANDWIDTH method (do not enter the units), or a
- percentage for the HEALTH method (do not enter the percentage symbol).
- - "Minimum value = C(1)"
- - "Maximum value = C(4294967287)"
-
- sobackupaction:
- choices:
- - 'DROP'
- - 'ACCEPT'
- - 'REDIRECT'
- description:
- - >-
- Action to be performed if spillover is to take effect, but no backup chain to spillover is usable or
- exists.
-
- appflowlog:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - "Enable logging appflow flow information."
-
- domain_bindings:
- description:
- - >-
- List of bindings for domains for this glsb vserver.
- suboptions:
- cookietimeout:
- description:
- - Timeout, in minutes, for the GSLB site cookie.
-
- domainname:
- description:
- - Domain name for which to change the time to live (TTL) and/or backup service IP address.
-
- ttl:
- description:
- - Time to live (TTL) for the domain.
-
- sitedomainttl:
- description:
- - >-
- TTL, in seconds, for all internally created site domains (created when a site prefix is
- configured on a GSLB service) that are associated with this virtual server.
- - Minimum value = C(1)
-
- service_bindings:
- description:
- - List of bindings for gslb services bound to this gslb virtual server.
- suboptions:
- servicename:
- description:
- - Name of the GSLB service for which to change the weight.
- weight:
- description:
- - Weight to assign to the GSLB service.
-
- disabled:
- description:
- - When set to C(yes) the GSLB Vserver state will be set to C(disabled).
- - When set to C(no) the GSLB Vserver state will be set to C(enabled).
- - >-
- Note that due to limitations of the underlying NITRO API a C(disabled) state change alone
- does not cause the module result to report a changed status.
- type: bool
- default: false
-
-
-
-
-extends_documentation_fragment:
-- community.general.netscaler
-
-requirements:
- - nitro python sdk
-'''
-
-EXAMPLES = '''
-'''
-
-RETURN = '''
-'''
-
-
-import copy
-
-try:
- from nssrc.com.citrix.netscaler.nitro.resource.config.gslb.gslbvserver import gslbvserver
- from nssrc.com.citrix.netscaler.nitro.resource.config.gslb.gslbvserver_gslbservice_binding import gslbvserver_gslbservice_binding
- from nssrc.com.citrix.netscaler.nitro.resource.config.gslb.gslbvserver_domain_binding import gslbvserver_domain_binding
- from nssrc.com.citrix.netscaler.nitro.exception.nitro_exception import nitro_exception
- PYTHON_SDK_IMPORTED = True
-except ImportError as e:
- PYTHON_SDK_IMPORTED = False
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.community.general.plugins.module_utils.network.netscaler.netscaler import (
- ConfigProxy,
- get_nitro_client,
- netscaler_common_arguments,
- log,
- loglines,
- ensure_feature_is_enabled,
- get_immutables_intersection,
- complete_missing_attributes
-)
-
-
-gslbvserver_domain_binding_rw_attrs = [
- 'name',
- 'domainname',
- 'backupipflag',
- 'cookietimeout',
- 'backupip',
- 'ttl',
- 'sitedomainttl',
- 'cookie_domainflag',
-]
-
-gslbvserver_gslbservice_binding_rw_attrs = [
- 'name',
- 'servicename',
- 'weight',
-]
-
-
-def get_actual_domain_bindings(client, module):
- log('get_actual_domain_bindings')
- # Get actual domain bindings and index them by domainname
- actual_domain_bindings = {}
- if gslbvserver_domain_binding.count(client, name=module.params['name']) != 0:
- # Get all domain bindings associated with the named gslb vserver
- fetched_domain_bindings = gslbvserver_domain_binding.get(client, name=module.params['name'])
- # index by domainname
- for binding in fetched_domain_bindings:
- complete_missing_attributes(binding, gslbvserver_domain_binding_rw_attrs, fill_value=None)
- actual_domain_bindings[binding.domainname] = binding
- return actual_domain_bindings
-
-
-def get_configured_domain_bindings_proxys(client, module):
- log('get_configured_domain_bindings_proxys')
- configured_domain_proxys = {}
- # Get configured domain bindings and index them by domainname
- if module.params['domain_bindings'] is not None:
- for configured_domain_binding in module.params['domain_bindings']:
- binding_values = copy.deepcopy(configured_domain_binding)
- binding_values['name'] = module.params['name']
- gslbvserver_domain_binding_proxy = ConfigProxy(
- actual=gslbvserver_domain_binding(),
- client=client,
- attribute_values_dict=binding_values,
- readwrite_attrs=gslbvserver_domain_binding_rw_attrs,
- readonly_attrs=[],
- )
- configured_domain_proxys[configured_domain_binding['domainname']] = gslbvserver_domain_binding_proxy
- return configured_domain_proxys
-
-
-def sync_domain_bindings(client, module):
- log('sync_domain_bindings')
-
- actual_domain_bindings = get_actual_domain_bindings(client, module)
- configured_domain_proxys = get_configured_domain_bindings_proxys(client, module)
-
- # Delete actual bindings not in configured bindings
- for domainname, actual_domain_binding in actual_domain_bindings.items():
- if domainname not in configured_domain_proxys.keys():
- log('Deleting absent binding for domain %s' % domainname)
- gslbvserver_domain_binding.delete(client, actual_domain_binding)
-
- # Delete actual bindings that differ from configured
- for proxy_key, binding_proxy in configured_domain_proxys.items():
- if proxy_key in actual_domain_bindings:
- actual_binding = actual_domain_bindings[proxy_key]
- if not binding_proxy.has_equal_attributes(actual_binding):
- log('Deleting differing binding for domain %s' % binding_proxy.domainname)
- gslbvserver_domain_binding.delete(client, actual_binding)
- log('Adding anew binding for domain %s' % binding_proxy.domainname)
- binding_proxy.add()
-
- # Add configured domains that are missing from actual
- for proxy_key, binding_proxy in configured_domain_proxys.items():
- if proxy_key not in actual_domain_bindings.keys():
- log('Adding domain binding for domain %s' % binding_proxy.domainname)
- binding_proxy.add()
-
-
-def domain_bindings_identical(client, module):
- log('domain_bindings_identical')
- actual_domain_bindings = get_actual_domain_bindings(client, module)
- configured_domain_proxys = get_configured_domain_bindings_proxys(client, module)
-
- actual_keyset = set(actual_domain_bindings.keys())
- configured_keyset = set(configured_domain_proxys.keys())
-
- symmetric_difference = actual_keyset ^ configured_keyset
-
- log('symmetric difference %s' % symmetric_difference)
- if len(symmetric_difference) != 0:
- return False
-
- # Item for item equality test
- for key, proxy in configured_domain_proxys.items():
- diff = proxy.diff_object(actual_domain_bindings[key])
- if 'backupipflag' in diff:
- del diff['backupipflag']
- if not len(diff) == 0:
- return False
- # Fallthrough to True result
- return True
-
-
-def get_actual_service_bindings(client, module):
- log('get_actual_service_bindings')
- # Get actual domain bindings and index them by domainname
- actual_bindings = {}
- if gslbvserver_gslbservice_binding.count(client, name=module.params['name']) != 0:
- # Get all service bindings associated with the named gslb vserver
- fetched_bindings = gslbvserver_gslbservice_binding.get(client, name=module.params['name'])
- # index by servicename
- for binding in fetched_bindings:
- complete_missing_attributes(binding, gslbvserver_gslbservice_binding_rw_attrs, fill_value=None)
- actual_bindings[binding.servicename] = binding
-
- return actual_bindings
-
-
-def get_configured_service_bindings(client, module):
- log('get_configured_service_bindings_proxys')
- configured_proxys = {}
- # Get configured domain bindings and index them by domainname
- if module.params['service_bindings'] is not None:
- for configured_binding in module.params['service_bindings']:
- binding_values = copy.deepcopy(configured_binding)
- binding_values['name'] = module.params['name']
- gslbvserver_service_binding_proxy = ConfigProxy(
- actual=gslbvserver_gslbservice_binding(),
- client=client,
- attribute_values_dict=binding_values,
- readwrite_attrs=gslbvserver_gslbservice_binding_rw_attrs,
- readonly_attrs=[],
- )
- configured_proxys[configured_binding['servicename']] = gslbvserver_service_binding_proxy
- return configured_proxys
-
-
-def sync_service_bindings(client, module):
- actual = get_actual_service_bindings(client, module)
- configured = get_configured_service_bindings(client, module)
-
- # Delete extraneous
- extraneous_service_bindings = list(set(actual.keys()) - set(configured.keys()))
- for servicename in extraneous_service_bindings:
- log('Deleting missing binding from service %s' % servicename)
- binding = actual[servicename]
- binding.name = module.params['name']
- gslbvserver_gslbservice_binding.delete(client, binding)
-
- # Recreate different
- common_service_bindings = list(set(actual.keys()) & set(configured.keys()))
- for servicename in common_service_bindings:
- proxy = configured[servicename]
- binding = actual[servicename]
- if not proxy.has_equal_attributes(actual):
- log('Recreating differing service binding %s' % servicename)
- gslbvserver_gslbservice_binding.delete(client, binding)
- proxy.add()
-
- # Add missing
- missing_service_bindings = list(set(configured.keys()) - set(actual.keys()))
- for servicename in missing_service_bindings:
- proxy = configured[servicename]
- log('Adding missing service binding %s' % servicename)
- proxy.add()
-
-
-def service_bindings_identical(client, module):
- actual_bindings = get_actual_service_bindings(client, module)
- configured_proxys = get_configured_service_bindings(client, module)
-
- actual_keyset = set(actual_bindings.keys())
- configured_keyset = set(configured_proxys.keys())
-
- symmetric_difference = actual_keyset ^ configured_keyset
- if len(symmetric_difference) != 0:
- return False
-
- # Item for item equality test
- for key, proxy in configured_proxys.items():
- if key in actual_bindings.keys():
- if not proxy.has_equal_attributes(actual_bindings[key]):
- return False
-
- # Fallthrough to True result
- return True
-
-
-def gslb_vserver_exists(client, module):
- if gslbvserver.count_filtered(client, 'name:%s' % module.params['name']) > 0:
- return True
- else:
- return False
-
-
-def gslb_vserver_identical(client, module, gslb_vserver_proxy):
- gslb_vserver_list = gslbvserver.get_filtered(client, 'name:%s' % module.params['name'])
- diff_dict = gslb_vserver_proxy.diff_object(gslb_vserver_list[0])
- if len(diff_dict) != 0:
- return False
- else:
- return True
-
-
-def all_identical(client, module, gslb_vserver_proxy):
- return (
- gslb_vserver_identical(client, module, gslb_vserver_proxy) and
- domain_bindings_identical(client, module) and
- service_bindings_identical(client, module)
- )
-
-
-def diff_list(client, module, gslb_vserver_proxy):
- gslb_vserver_list = gslbvserver.get_filtered(client, 'name:%s' % module.params['name'])
- return gslb_vserver_proxy.diff_object(gslb_vserver_list[0])
-
-
-def do_state_change(client, module, gslb_vserver_proxy):
- if module.params['disabled']:
- log('Disabling glsb_vserver')
- result = gslbvserver.disable(client, gslb_vserver_proxy.actual)
- else:
- log('Enabling gslbvserver')
- result = gslbvserver.enable(client, gslb_vserver_proxy.actual)
- return result
-
-
-def main():
-
- module_specific_arguments = dict(
- name=dict(type='str'),
- servicetype=dict(
- type='str',
- choices=[
- 'HTTP',
- 'FTP',
- 'TCP',
- 'UDP',
- 'SSL',
- 'SSL_BRIDGE',
- 'SSL_TCP',
- 'NNTP',
- 'ANY',
- 'SIP_UDP',
- 'SIP_TCP',
- 'SIP_SSL',
- 'RADIUS',
- 'RDP',
- 'RTSP',
- 'MYSQL',
- 'MSSQL',
- 'ORACLE',
- ]
- ),
- dnsrecordtype=dict(
- type='str',
- choices=[
- 'A',
- 'AAAA',
- 'CNAME',
- 'NAPTR',
- ]
- ),
- lbmethod=dict(
- type='str',
- choices=[
- 'ROUNDROBIN',
- 'LEASTCONNECTION',
- 'LEASTRESPONSETIME',
- 'SOURCEIPHASH',
- 'LEASTBANDWIDTH',
- 'LEASTPACKETS',
- 'STATICPROXIMITY',
- 'RTT',
- 'CUSTOMLOAD',
- ]
- ),
- backuplbmethod=dict(
- type='str',
- choices=[
- 'ROUNDROBIN',
- 'LEASTCONNECTION',
- 'LEASTRESPONSETIME',
- 'SOURCEIPHASH',
- 'LEASTBANDWIDTH',
- 'LEASTPACKETS',
- 'STATICPROXIMITY',
- 'RTT',
- 'CUSTOMLOAD',
- ]
- ),
- netmask=dict(type='str'),
- v6netmasklen=dict(type='float'),
- tolerance=dict(type='float'),
- persistencetype=dict(
- type='str',
- choices=[
- 'SOURCEIP',
- 'NONE',
- ]
- ),
- persistenceid=dict(type='float'),
- persistmask=dict(type='str'),
- v6persistmasklen=dict(type='float'),
- timeout=dict(type='float'),
- mir=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- disableprimaryondown=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- dynamicweight=dict(
- type='str',
- choices=[
- 'SERVICECOUNT',
- 'SERVICEWEIGHT',
- 'DISABLED',
- ]
- ),
- considereffectivestate=dict(
- type='str',
- choices=[
- 'NONE',
- 'STATE_ONLY',
- ]
- ),
- comment=dict(type='str'),
- somethod=dict(
- type='str',
- choices=[
- 'CONNECTION',
- 'DYNAMICCONNECTION',
- 'BANDWIDTH',
- 'HEALTH',
- 'NONE',
- ]
- ),
- sopersistence=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- sopersistencetimeout=dict(type='float'),
- sothreshold=dict(type='float'),
- sobackupaction=dict(
- type='str',
- choices=[
- 'DROP',
- 'ACCEPT',
- 'REDIRECT',
- ]
- ),
- appflowlog=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- domainname=dict(type='str'),
- cookie_domain=dict(type='str'),
- )
-
- hand_inserted_arguments = dict(
- domain_bindings=dict(type='list'),
- service_bindings=dict(type='list'),
- disabled=dict(
- type='bool',
- default=False,
- ),
- )
-
- argument_spec = dict()
-
- argument_spec.update(netscaler_common_arguments)
- argument_spec.update(module_specific_arguments)
- argument_spec.update(hand_inserted_arguments)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- )
- module_result = dict(
- changed=False,
- failed=False,
- loglines=loglines,
- )
-
- # Fail the module if imports failed
- if not PYTHON_SDK_IMPORTED:
- module.fail_json(msg='Could not load nitro python sdk')
-
- # Fallthrough to rest of execution
- client = get_nitro_client(module)
-
- try:
- client.login()
- except nitro_exception as e:
- msg = "nitro exception during login. errorcode=%s, message=%s" % (str(e.errorcode), e.message)
- module.fail_json(msg=msg)
- except Exception as e:
- if str(type(e)) == "":
- module.fail_json(msg='Connection error %s' % str(e))
- elif str(type(e)) == "":
- module.fail_json(msg='SSL Error %s' % str(e))
- else:
- module.fail_json(msg='Unexpected error during login %s' % str(e))
-
- readwrite_attrs = [
- 'name',
- 'servicetype',
- 'dnsrecordtype',
- 'lbmethod',
- 'backuplbmethod',
- 'netmask',
- 'v6netmasklen',
- 'tolerance',
- 'persistencetype',
- 'persistenceid',
- 'persistmask',
- 'v6persistmasklen',
- 'timeout',
- 'mir',
- 'disableprimaryondown',
- 'dynamicweight',
- 'considereffectivestate',
- 'comment',
- 'somethod',
- 'sopersistence',
- 'sopersistencetimeout',
- 'sothreshold',
- 'sobackupaction',
- 'appflowlog',
- 'cookie_domain',
- ]
-
- readonly_attrs = [
- 'curstate',
- 'status',
- 'lbrrreason',
- 'iscname',
- 'sitepersistence',
- 'totalservices',
- 'activeservices',
- 'statechangetimesec',
- 'statechangetimemsec',
- 'tickssincelaststatechange',
- 'health',
- 'policyname',
- 'priority',
- 'gotopriorityexpression',
- 'type',
- 'vsvrbindsvcip',
- 'vsvrbindsvcport',
- '__count',
- ]
-
- immutable_attrs = [
- 'name',
- 'servicetype',
- ]
-
- transforms = {
- 'mir': [lambda v: v.upper()],
- 'disableprimaryondown': [lambda v: v.upper()],
- 'sopersistence': [lambda v: v.upper()],
- 'appflowlog': [lambda v: v.upper()],
- }
-
- # Instantiate config proxy
- gslb_vserver_proxy = ConfigProxy(
- actual=gslbvserver(),
- client=client,
- attribute_values_dict=module.params,
- readwrite_attrs=readwrite_attrs,
- readonly_attrs=readonly_attrs,
- immutable_attrs=immutable_attrs,
- transforms=transforms,
- )
-
- try:
- ensure_feature_is_enabled(client, 'GSLB')
- # Apply appropriate state
- if module.params['state'] == 'present':
- log('Applying state present')
- if not gslb_vserver_exists(client, module):
- log('Creating object')
- if not module.check_mode:
- gslb_vserver_proxy.add()
- sync_domain_bindings(client, module)
- sync_service_bindings(client, module)
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- elif not all_identical(client, module, gslb_vserver_proxy):
- log('Entering update actions')
-
- # Check if we try to change value of immutable attributes
- if not gslb_vserver_identical(client, module, gslb_vserver_proxy):
- log('Updating gslb vserver')
- immutables_changed = get_immutables_intersection(gslb_vserver_proxy, diff_list(client, module, gslb_vserver_proxy).keys())
- if immutables_changed != []:
- module.fail_json(
- msg='Cannot update immutable attributes %s' % (immutables_changed,),
- diff=diff_list(client, module, gslb_vserver_proxy),
- **module_result
- )
- if not module.check_mode:
- gslb_vserver_proxy.update()
-
- # Update domain bindings
- if not domain_bindings_identical(client, module):
- if not module.check_mode:
- sync_domain_bindings(client, module)
-
- # Update service bindings
- if not service_bindings_identical(client, module):
- if not module.check_mode:
- sync_service_bindings(client, module)
-
- module_result['changed'] = True
- if not module.check_mode:
- if module.params['save_config']:
- client.save_config()
- else:
- module_result['changed'] = False
-
- if not module.check_mode:
- res = do_state_change(client, module, gslb_vserver_proxy)
- if res.errorcode != 0:
- msg = 'Error when setting disabled state. errorcode: %s message: %s' % (res.errorcode, res.message)
- module.fail_json(msg=msg, **module_result)
-
- # Sanity check for state
- if not module.check_mode:
- if not gslb_vserver_exists(client, module):
- module.fail_json(msg='GSLB Vserver does not exist', **module_result)
- if not gslb_vserver_identical(client, module, gslb_vserver_proxy):
- module.fail_json(msg='GSLB Vserver differs from configured', diff=diff_list(client, module, gslb_vserver_proxy), **module_result)
- if not domain_bindings_identical(client, module):
- module.fail_json(msg='Domain bindings differ from configured', diff=diff_list(client, module, gslb_vserver_proxy), **module_result)
- if not service_bindings_identical(client, module):
- module.fail_json(msg='Service bindings differ from configured', diff=diff_list(client, module, gslb_vserver_proxy), **module_result)
-
- elif module.params['state'] == 'absent':
-
- if gslb_vserver_exists(client, module):
- if not module.check_mode:
- gslb_vserver_proxy.delete()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- else:
- module_result['changed'] = False
-
- # Sanity check for state
- if not module.check_mode:
- if gslb_vserver_exists(client, module):
- module.fail_json(msg='GSLB Vserver still exists', **module_result)
-
- except nitro_exception as e:
- msg = "nitro exception errorcode=%s, message=%s" % (str(e.errorcode), e.message)
- module.fail_json(msg=msg, **module_result)
-
- client.logout()
- module.exit_json(**module_result)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/netscaler/netscaler_lb_monitor.py b/plugins/modules/network/netscaler/netscaler_lb_monitor.py
deleted file mode 100644
index f2f5ad126a..0000000000
--- a/plugins/modules/network/netscaler/netscaler_lb_monitor.py
+++ /dev/null
@@ -1,1381 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2017 Citrix Systems
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
-module: netscaler_lb_monitor
-short_description: Manage load balancing monitors
-description:
- - Manage load balancing monitors.
- - This module is intended to run either on the ansible control node or a bastion (jumpserver) with access to the actual netscaler instance.
-
-
-author: George Nikolopoulos (@giorgos-nikolopoulos)
-
-options:
-
- monitorname:
- description:
- - >-
- Name for the monitor. Must begin with an ASCII alphanumeric or underscore C(_) character, and must
- contain only ASCII alphanumeric, underscore, hash C(#), period C(.), space C( ), colon C(:), at C(@), equals
- C(=), and hyphen C(-) characters.
- - "Minimum length = 1"
-
- type:
- choices:
- - 'PING'
- - 'TCP'
- - 'HTTP'
- - 'TCP-ECV'
- - 'HTTP-ECV'
- - 'UDP-ECV'
- - 'DNS'
- - 'FTP'
- - 'LDNS-PING'
- - 'LDNS-TCP'
- - 'LDNS-DNS'
- - 'RADIUS'
- - 'USER'
- - 'HTTP-INLINE'
- - 'SIP-UDP'
- - 'SIP-TCP'
- - 'LOAD'
- - 'FTP-EXTENDED'
- - 'SMTP'
- - 'SNMP'
- - 'NNTP'
- - 'MYSQL'
- - 'MYSQL-ECV'
- - 'MSSQL-ECV'
- - 'ORACLE-ECV'
- - 'LDAP'
- - 'POP3'
- - 'CITRIX-XML-SERVICE'
- - 'CITRIX-WEB-INTERFACE'
- - 'DNS-TCP'
- - 'RTSP'
- - 'ARP'
- - 'CITRIX-AG'
- - 'CITRIX-AAC-LOGINPAGE'
- - 'CITRIX-AAC-LAS'
- - 'CITRIX-XD-DDC'
- - 'ND6'
- - 'CITRIX-WI-EXTENDED'
- - 'DIAMETER'
- - 'RADIUS_ACCOUNTING'
- - 'STOREFRONT'
- - 'APPC'
- - 'SMPP'
- - 'CITRIX-XNC-ECV'
- - 'CITRIX-XDM'
- - 'CITRIX-STA-SERVICE'
- - 'CITRIX-STA-SERVICE-NHOP'
- description:
- - "Type of monitor that you want to create."
-
- action:
- choices:
- - 'NONE'
- - 'LOG'
- - 'DOWN'
- description:
- - >-
- Action to perform when the response to an inline monitor (a monitor of type C(HTTP-INLINE)) indicates
- that the service is down. A service monitored by an inline monitor is considered C(DOWN) if the response
- code is not one of the codes that have been specified for the Response Code parameter.
- - "Available settings function as follows:"
- - >-
- * C(NONE) - Do not take any action. However, the show service command and the show lb monitor command
- indicate the total number of responses that were checked and the number of consecutive error
- responses received after the last successful probe.
- - "* C(LOG) - Log the event in NSLOG or SYSLOG."
- - >-
- * C(DOWN) - Mark the service as being down, and then do not direct any traffic to the service until the
- configured down time has expired. Persistent connections to the service are terminated as soon as the
- service is marked as C(DOWN). Also, log the event in NSLOG or SYSLOG.
-
- respcode:
- description:
- - >-
- Response codes for which to mark the service as UP. For any other response code, the action performed
- depends on the monitor type. C(HTTP) monitors and C(RADIUS) monitors mark the service as C(DOWN), while
- C(HTTP-INLINE) monitors perform the action indicated by the Action parameter.
-
- httprequest:
- description:
- - 'HTTP request to send to the server (for example, C("HEAD /file.html")).'
-
- rtsprequest:
- description:
- - 'RTSP request to send to the server (for example, C("OPTIONS *")).'
-
- customheaders:
- description:
- - "Custom header string to include in the monitoring probes."
-
- maxforwards:
- description:
- - >-
- Maximum number of hops that the SIP request used for monitoring can traverse to reach the server.
- Applicable only to monitors of type C(SIP-UDP).
- - "Minimum value = C(0)"
- - "Maximum value = C(255)"
-
- sipmethod:
- choices:
- - 'OPTIONS'
- - 'INVITE'
- - 'REGISTER'
- description:
- - "SIP method to use for the query. Applicable only to monitors of type C(SIP-UDP)."
-
- sipuri:
- description:
- - >-
- SIP URI string to send to the service (for example, C(sip:sip.test)). Applicable only to monitors of
- type C(SIP-UDP).
- - "Minimum length = 1"
-
- sipreguri:
- description:
- - >-
- SIP user to be registered. Applicable only if the monitor is of type C(SIP-UDP) and the SIP Method
- parameter is set to C(REGISTER).
- - "Minimum length = 1"
-
- send:
- description:
- - "String to send to the service. Applicable to C(TCP-ECV), C(HTTP-ECV), and C(UDP-ECV) monitors."
-
- recv:
- description:
- - >-
- String expected from the server for the service to be marked as UP. Applicable to C(TCP-ECV), C(HTTP-ECV),
- and C(UDP-ECV) monitors.
-
- query:
- description:
- - "Domain name to resolve as part of monitoring the DNS service (for example, C(example.com))."
-
- querytype:
- choices:
- - 'Address'
- - 'Zone'
- - 'AAAA'
- description:
- - >-
- Type of DNS record for which to send monitoring queries. Set to C(Address) for querying A records, C(AAAA)
- for querying AAAA records, and C(Zone) for querying the SOA record.
-
- scriptname:
- description:
- - >-
- Path and name of the script to execute. The script must be available on the NetScaler appliance, in
- the /nsconfig/monitors/ directory.
- - "Minimum length = 1"
-
- scriptargs:
- description:
- - "String of arguments for the script. The string is copied verbatim into the request."
-
- dispatcherip:
- description:
- - "IP address of the dispatcher to which to send the probe."
-
- dispatcherport:
- description:
- - "Port number on which the dispatcher listens for the monitoring probe."
-
- username:
- description:
- - >-
- User name with which to probe the C(RADIUS), C(NNTP), C(FTP), C(FTP-EXTENDED), C(MYSQL), C(MSSQL), C(POP3), C(CITRIX-AG),
- C(CITRIX-XD-DDC), C(CITRIX-WI-EXTENDED), C(CITRIX-XNC) or C(CITRIX-XDM) server.
- - "Minimum length = 1"
-
- password:
- description:
- - >-
- Password that is required for logging on to the C(RADIUS), C(NNTP), C(FTP), C(FTP-EXTENDED), C(MYSQL), C(MSSQL), C(POP3),
- C(CITRIX-AG), C(CITRIX-XD-DDC), C(CITRIX-WI-EXTENDED), C(CITRIX-XNC-ECV) or C(CITRIX-XDM) server. Used in
- conjunction with the user name specified for the C(username) parameter.
- - "Minimum length = 1"
-
- secondarypassword:
- description:
- - >-
- Secondary password that users might have to provide to log on to the Access Gateway server.
- Applicable to C(CITRIX-AG) monitors.
-
- logonpointname:
- description:
- - >-
- Name of the logon point that is configured for the Citrix Access Gateway Advanced Access Control
- software. Required if you want to monitor the associated login page or Logon Agent. Applicable to
- C(CITRIX-AAC-LAS) and C(CITRIX-AAC-LOGINPAGE) monitors.
-
- lasversion:
- description:
- - >-
- Version number of the Citrix Advanced Access Control Logon Agent. Required by the C(CITRIX-AAC-LAS)
- monitor.
-
- radkey:
- description:
- - >-
- Authentication key (shared secret text string) for RADIUS clients and servers to exchange. Applicable
- to monitors of type C(RADIUS) and C(RADIUS_ACCOUNTING).
- - "Minimum length = 1"
-
- radnasid:
- description:
- - "NAS-Identifier to send in the Access-Request packet. Applicable to monitors of type C(RADIUS)."
- - "Minimum length = 1"
-
- radnasip:
- description:
- - >-
- Network Access Server (NAS) IP address to use as the source IP address when monitoring a RADIUS
- server. Applicable to monitors of type C(RADIUS) and C(RADIUS_ACCOUNTING).
-
- radaccounttype:
- description:
- - "Account Type to be used in Account Request Packet. Applicable to monitors of type C(RADIUS_ACCOUNTING)."
- - "Minimum value = 0"
- - "Maximum value = 15"
-
- radframedip:
- description:
- - "Source ip with which the packet will go out . Applicable to monitors of type C(RADIUS_ACCOUNTING)."
-
- radapn:
- description:
- - >-
- Called Station Id to be used in Account Request Packet. Applicable to monitors of type
- C(RADIUS_ACCOUNTING).
- - "Minimum length = 1"
-
- radmsisdn:
- description:
- - >-
- Calling Stations Id to be used in Account Request Packet. Applicable to monitors of type
- C(RADIUS_ACCOUNTING).
- - "Minimum length = 1"
-
- radaccountsession:
- description:
- - >-
- Account Session ID to be used in Account Request Packet. Applicable to monitors of type
- C(RADIUS_ACCOUNTING).
- - "Minimum length = 1"
-
- lrtm:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- Calculate the least response times for bound services. If this parameter is not enabled, the
- appliance does not learn the response times of the bound services. Also used for LRTM load balancing.
-
- deviation:
- description:
- - >-
- Time value added to the learned average response time in dynamic response time monitoring (DRTM).
- When a deviation is specified, the appliance learns the average response time of bound services and
- adds the deviation to the average. The final value is then continually adjusted to accommodate
- response time variations over time. Specified in milliseconds, seconds, or minutes.
- - "Minimum value = C(0)"
- - "Maximum value = C(20939)"
-
- units1:
- choices:
- - 'SEC'
- - 'MSEC'
- - 'MIN'
- description:
- - "Unit of measurement for the Deviation parameter. Cannot be changed after the monitor is created."
-
- interval:
- description:
- - "Time interval between two successive probes. Must be greater than the value of Response Time-out."
- - "Minimum value = C(1)"
- - "Maximum value = C(20940)"
-
- units3:
- choices:
- - 'SEC'
- - 'MSEC'
- - 'MIN'
- description:
- - "monitor interval units."
-
- resptimeout:
- description:
- - >-
- Amount of time for which the appliance must wait before it marks a probe as FAILED. Must be less than
- the value specified for the Interval parameter.
- - >-
- Note: For C(UDP-ECV) monitors for which a receive string is not configured, response timeout does not
- apply. For C(UDP-ECV) monitors with no receive string, probe failure is indicated by an ICMP port
- unreachable error received from the service.
- - "Minimum value = C(1)"
- - "Maximum value = C(20939)"
-
- units4:
- choices:
- - 'SEC'
- - 'MSEC'
- - 'MIN'
- description:
- - "monitor response timeout units."
-
- resptimeoutthresh:
- description:
- - >-
- Response time threshold, specified as a percentage of the Response Time-out parameter. If the
- response to a monitor probe has not arrived when the threshold is reached, the appliance generates an
- SNMP trap called monRespTimeoutAboveThresh. After the response time returns to a value below the
- threshold, the appliance generates a monRespTimeoutBelowThresh SNMP trap. For the traps to be
- generated, the "MONITOR-RTO-THRESHOLD" alarm must also be enabled.
- - "Minimum value = C(0)"
- - "Maximum value = C(100)"
-
- retries:
- description:
- - >-
- Maximum number of probes to send to establish the state of a service for which a monitoring probe
- failed.
- - "Minimum value = C(1)"
- - "Maximum value = C(127)"
-
- failureretries:
- description:
- - >-
- Number of retries that must fail, out of the number specified for the Retries parameter, for a
- service to be marked as DOWN. For example, if the Retries parameter is set to 10 and the Failure
- Retries parameter is set to 6, out of the ten probes sent, at least six probes must fail if the
- service is to be marked as DOWN. The default value of 0 means that all the retries must fail if the
- service is to be marked as DOWN.
- - "Minimum value = C(0)"
- - "Maximum value = C(32)"
-
- alertretries:
- description:
- - >-
- Number of consecutive probe failures after which the appliance generates an SNMP trap called
- monProbeFailed.
- - "Minimum value = C(0)"
- - "Maximum value = C(32)"
-
- successretries:
- description:
- - "Number of consecutive successful probes required to transition a service's state from DOWN to UP."
- - "Minimum value = C(1)"
- - "Maximum value = C(32)"
-
- downtime:
- description:
- - >-
- Time duration for which to wait before probing a service that has been marked as DOWN. Expressed in
- milliseconds, seconds, or minutes.
- - "Minimum value = C(1)"
- - "Maximum value = C(20939)"
-
- units2:
- choices:
- - 'SEC'
- - 'MSEC'
- - 'MIN'
- description:
- - "Unit of measurement for the Down Time parameter. Cannot be changed after the monitor is created."
-
- destip:
- description:
- - >-
- IP address of the service to which to send probes. If the parameter is set to 0, the IP address of
- the server to which the monitor is bound is considered the destination IP address.
-
- destport:
- description:
- - >-
- TCP or UDP port to which to send the probe. If the parameter is set to 0, the port number of the
- service to which the monitor is bound is considered the destination port. For a monitor of type C(USER),
- however, the destination port is the port number that is included in the HTTP request sent to the
- dispatcher. Does not apply to monitors of type C(PING).
-
- state:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- State of the monitor. The C(disabled) setting disables not only the monitor being configured, but all
- monitors of the same type, until the parameter is set to C(enabled). If the monitor is bound to a
- service, the state of the monitor is not taken into account when the state of the service is
- determined.
-
- reverse:
- description:
- - >-
- Mark a service as DOWN, instead of UP, when probe criteria are satisfied, and as UP instead of DOWN
- when probe criteria are not satisfied.
- type: bool
-
- transparent:
- description:
- - >-
- The monitor is bound to a transparent device such as a firewall or router. The state of a transparent
- device depends on the responsiveness of the services behind it. If a transparent device is being
- monitored, a destination IP address must be specified. The probe is sent to the specified IP address
- by using the MAC address of the transparent device.
- type: bool
-
- iptunnel:
- description:
- - >-
- Send the monitoring probe to the service through an IP tunnel. A destination IP address must be
- specified.
- type: bool
-
- tos:
- description:
- - "Probe the service by encoding the destination IP address in the IP TOS (6) bits."
- type: bool
-
- tosid:
- description:
- - "The TOS ID of the specified destination IP. Applicable only when the TOS parameter is set."
- - "Minimum value = C(1)"
- - "Maximum value = C(63)"
-
- secure:
- description:
- - >-
- Use a secure SSL connection when monitoring a service. Applicable only to TCP based monitors. The
- secure option cannot be used with a C(CITRIX-AG) monitor, because a CITRIX-AG monitor uses a secure
- connection by default.
- type: bool
-
- validatecred:
- description:
- - >-
- Validate the credentials of the Xen Desktop DDC server user. Applicable to monitors of type
- C(CITRIX-XD-DDC).
- type: bool
-
- domain:
- description:
- - >-
- Domain in which the XenDesktop Desktop Delivery Controller (DDC) servers or Web Interface servers are
- present. Required by C(CITRIX-XD-DDC) and C(CITRIX-WI-EXTENDED) monitors for logging on to the DDC servers
- and Web Interface servers, respectively.
-
- ipaddress:
- description:
- - >-
- Set of IP addresses expected in the monitoring response from the DNS server, if the record type is A
- or AAAA. Applicable to C(DNS) monitors.
- - "Minimum length = 1"
-
- group:
- description:
- - >-
- Name of a newsgroup available on the NNTP service that is to be monitored. The appliance periodically
- generates an NNTP query for the name of the newsgroup and evaluates the response. If the newsgroup is
- found on the server, the service is marked as UP. If the newsgroup does not exist or if the search
- fails, the service is marked as DOWN. Applicable to NNTP monitors.
- - "Minimum length = 1"
-
- filename:
- description:
- - >-
- Name of a file on the FTP server. The appliance monitors the FTP service by periodically checking the
- existence of the file on the server. Applicable to C(FTP-EXTENDED) monitors.
- - "Minimum length = 1"
-
- basedn:
- description:
- - >-
- The base distinguished name of the LDAP service, from where the LDAP server can begin the search for
- the attributes in the monitoring query. Required for C(LDAP) service monitoring.
- - "Minimum length = 1"
-
- binddn:
- description:
- - >-
- The distinguished name with which an LDAP monitor can perform the Bind operation on the LDAP server.
- Optional. Applicable to C(LDAP) monitors.
- - "Minimum length = 1"
-
- filter:
- description:
- - "Filter criteria for the LDAP query. Optional."
- - "Minimum length = 1"
-
- attribute:
- description:
- - >-
- Attribute to evaluate when the LDAP server responds to the query. Success or failure of the
- monitoring probe depends on whether the attribute exists in the response. Optional.
- - "Minimum length = 1"
-
- database:
- description:
- - "Name of the database to connect to during authentication."
- - "Minimum length = 1"
-
- oraclesid:
- description:
- - "Name of the service identifier that is used to connect to the Oracle database during authentication."
- - "Minimum length = 1"
-
- sqlquery:
- description:
- - >-
- SQL query for a C(MYSQL-ECV) or C(MSSQL-ECV) monitor. Sent to the database server after the server
- authenticates the connection.
- - "Minimum length = 1"
-
- evalrule:
- description:
- - >-
- Default syntax expression that evaluates the database server's response to a MYSQL-ECV or MSSQL-ECV
- monitoring query. Must produce a Boolean result. The result determines the state of the server. If
- the expression returns TRUE, the probe succeeds.
- - >-
- For example, if you want the appliance to evaluate the error message to determine the state of the
- server, use the rule C(MYSQL.RES.ROW(10) .TEXT_ELEM(2).EQ("MySQL")).
-
- mssqlprotocolversion:
- choices:
- - '70'
- - '2000'
- - '2000SP1'
- - '2005'
- - '2008'
- - '2008R2'
- - '2012'
- - '2014'
- description:
- - "Version of MSSQL server that is to be monitored."
-
- Snmpoid:
- description:
- - "SNMP OID for C(SNMP) monitors."
- - "Minimum length = 1"
-
- snmpcommunity:
- description:
- - "Community name for C(SNMP) monitors."
- - "Minimum length = 1"
-
- snmpthreshold:
- description:
- - "Threshold for C(SNMP) monitors."
- - "Minimum length = 1"
-
- snmpversion:
- choices:
- - 'V1'
- - 'V2'
- description:
- - "SNMP version to be used for C(SNMP) monitors."
-
- metrictable:
- description:
- - "Metric table to which to bind metrics."
- - "Minimum length = 1"
- - "Maximum length = 99"
-
- application:
- description:
- - >-
- Name of the application used to determine the state of the service. Applicable to monitors of type
- C(CITRIX-XML-SERVICE).
- - "Minimum length = 1"
-
- sitepath:
- description:
- - >-
- URL of the logon page. For monitors of type C(CITRIX-WEB-INTERFACE), to monitor a dynamic page under the
- site path, terminate the site path with a slash C(/). Applicable to C(CITRIX-WEB-INTERFACE),
- C(CITRIX-WI-EXTENDED) and C(CITRIX-XDM) monitors.
- - "Minimum length = 1"
-
- storename:
- description:
- - >-
- Store Name. For monitors of type C(STOREFRONT), C(storename) is an optional argument defining storefront
- service store name. Applicable to C(STOREFRONT) monitors.
- - "Minimum length = 1"
-
- storefrontacctservice:
- description:
- - >-
- Enable/Disable probing for Account Service. Applicable only to Store Front monitors. For
- multi-tenancy configuration users my skip account service.
- type: bool
-
- hostname:
- description:
- - "Hostname in the FQDN format (Example: C(porche.cars.org)). Applicable to C(STOREFRONT) monitors."
- - "Minimum length = 1"
-
- netprofile:
- description:
- - "Name of the network profile."
- - "Minimum length = 1"
- - "Maximum length = 127"
-
- originhost:
- description:
- - >-
- Origin-Host value for the Capabilities-Exchange-Request (CER) message to use for monitoring Diameter
- servers.
- - "Minimum length = 1"
-
- originrealm:
- description:
- - >-
- Origin-Realm value for the Capabilities-Exchange-Request (CER) message to use for monitoring Diameter
- servers.
- - "Minimum length = 1"
-
- hostipaddress:
- description:
- - >-
- Host-IP-Address value for the Capabilities-Exchange-Request (CER) message to use for monitoring
- Diameter servers. If Host-IP-Address is not specified, the appliance inserts the mapped IP (MIP)
- address or subnet IP (SNIP) address from which the CER request (the monitoring probe) is sent.
- - "Minimum length = 1"
-
- vendorid:
- description:
- - >-
- Vendor-Id value for the Capabilities-Exchange-Request (CER) message to use for monitoring Diameter
- servers.
-
- productname:
- description:
- - >-
- Product-Name value for the Capabilities-Exchange-Request (CER) message to use for monitoring Diameter
- servers.
- - "Minimum length = 1"
-
- firmwarerevision:
- description:
- - >-
- Firmware-Revision value for the Capabilities-Exchange-Request (CER) message to use for monitoring
- Diameter servers.
-
- authapplicationid:
- description:
- - >-
- List of Auth-Application-Id attribute value pairs (AVPs) for the Capabilities-Exchange-Request (CER)
- message to use for monitoring Diameter servers. A maximum of eight of these AVPs are supported in a
- monitoring CER message.
- - "Minimum value = C(0)"
- - "Maximum value = C(4294967295)"
-
- acctapplicationid:
- description:
- - >-
- List of Acct-Application-Id attribute value pairs (AVPs) for the Capabilities-Exchange-Request (CER)
- message to use for monitoring Diameter servers. A maximum of eight of these AVPs are supported in a
- monitoring message.
- - "Minimum value = C(0)"
- - "Maximum value = C(4294967295)"
-
- inbandsecurityid:
- choices:
- - 'NO_INBAND_SECURITY'
- - 'TLS'
- description:
- - >-
- Inband-Security-Id for the Capabilities-Exchange-Request (CER) message to use for monitoring Diameter
- servers.
-
- supportedvendorids:
- description:
- - >-
- List of Supported-Vendor-Id attribute value pairs (AVPs) for the Capabilities-Exchange-Request (CER)
- message to use for monitoring Diameter servers. A maximum eight of these AVPs are supported in a
- monitoring message.
- - "Minimum value = C(1)"
- - "Maximum value = C(4294967295)"
-
- vendorspecificvendorid:
- description:
- - >-
- Vendor-Id to use in the Vendor-Specific-Application-Id grouped attribute-value pair (AVP) in the
- monitoring CER message. To specify Auth-Application-Id or Acct-Application-Id in
- Vendor-Specific-Application-Id, use vendorSpecificAuthApplicationIds or
- vendorSpecificAcctApplicationIds, respectively. Only one Vendor-Id is supported for all the
- Vendor-Specific-Application-Id AVPs in a CER monitoring message.
- - "Minimum value = 1"
-
- vendorspecificauthapplicationids:
- description:
- - >-
- List of Vendor-Specific-Auth-Application-Id attribute value pairs (AVPs) for the
- Capabilities-Exchange-Request (CER) message to use for monitoring Diameter servers. A maximum of
- eight of these AVPs are supported in a monitoring message. The specified value is combined with the
- value of vendorSpecificVendorId to obtain the Vendor-Specific-Application-Id AVP in the CER
- monitoring message.
- - "Minimum value = C(0)"
- - "Maximum value = C(4294967295)"
-
- vendorspecificacctapplicationids:
- description:
- - >-
- List of Vendor-Specific-Acct-Application-Id attribute value pairs (AVPs) to use for monitoring
- Diameter servers. A maximum of eight of these AVPs are supported in a monitoring message. The
- specified value is combined with the value of vendorSpecificVendorId to obtain the
- Vendor-Specific-Application-Id AVP in the CER monitoring message.
- - "Minimum value = C(0)"
- - "Maximum value = C(4294967295)"
-
- kcdaccount:
- description:
- - "KCD Account used by C(MSSQL) monitor."
- - "Minimum length = 1"
- - "Maximum length = 32"
-
- storedb:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- Store the database list populated with the responses to monitor probes. Used in database specific
- load balancing if C(MSSQL-ECV)/C(MYSQL-ECV) monitor is configured.
-
- storefrontcheckbackendservices:
- description:
- - >-
- This option will enable monitoring of services running on storefront server. Storefront services are
- monitored by probing to a Windows service that runs on the Storefront server and exposes details of
- which storefront services are running.
- type: bool
-
- trofscode:
- description:
- - "Code expected when the server is under maintenance."
-
- trofsstring:
- description:
- - >-
- String expected from the server for the service to be marked as trofs. Applicable to HTTP-ECV/TCP-ECV
- monitors.
-
-extends_documentation_fragment:
-- community.general.netscaler
-
-requirements:
- - nitro python sdk
-'''
-
-EXAMPLES = '''
-- name: Set lb monitor
- local_action:
- nsip: 172.18.0.2
- nitro_user: nsroot
- nitro_pass: nsroot
- validate_certs: no
-
-
- module: netscaler_lb_monitor
- state: present
-
- monitorname: monitor_1
- type: HTTP-INLINE
- action: DOWN
- respcode: ['400']
-'''
-
-RETURN = '''
-loglines:
- description: list of logged messages by the module
- returned: always
- type: list
- sample: ['message 1', 'message 2']
-
-msg:
- description: Message detailing the failure reason
- returned: failure
- type: str
- sample: "Action does not exist"
-
-diff:
- description: List of differences between the actual configured object and the configuration specified in the module
- returned: failure
- type: dict
- sample: { 'targetlbvserver': 'difference. ours: (str) server1 other: (str) server2' }
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-
-from ansible_collections.community.general.plugins.module_utils.network.netscaler.netscaler import (
- ConfigProxy,
- get_nitro_client,
- netscaler_common_arguments,
- log,
- loglines,
- ensure_feature_is_enabled,
- get_immutables_intersection
-)
-
-try:
- from nssrc.com.citrix.netscaler.nitro.resource.config.lb.lbmonitor import lbmonitor
- from nssrc.com.citrix.netscaler.nitro.exception.nitro_exception import nitro_exception
- PYTHON_SDK_IMPORTED = True
-except ImportError as e:
- PYTHON_SDK_IMPORTED = False
-
-
-def lbmonitor_exists(client, module):
- log('Checking if monitor exists')
- if lbmonitor.count_filtered(client, 'monitorname:%s' % module.params['monitorname']) > 0:
- return True
- else:
- return False
-
-
-def lbmonitor_identical(client, module, lbmonitor_proxy):
- log('Checking if monitor is identical')
-
- count = lbmonitor.count_filtered(client, 'monitorname:%s' % module.params['monitorname'])
- if count == 0:
- return False
-
- lbmonitor_list = lbmonitor.get_filtered(client, 'monitorname:%s' % module.params['monitorname'])
- diff_dict = lbmonitor_proxy.diff_object(lbmonitor_list[0])
-
- # Skipping hashed fields since the cannot be compared directly
- hashed_fields = [
- 'password',
- 'secondarypassword',
- 'radkey',
- ]
- for key in hashed_fields:
- if key in diff_dict:
- del diff_dict[key]
-
- if diff_dict == {}:
- return True
- else:
- return False
-
-
-def diff_list(client, module, lbmonitor_proxy):
- monitor_list = lbmonitor.get_filtered(client, 'monitorname:%s' % module.params['monitorname'])
- return lbmonitor_proxy.diff_object(monitor_list[0])
-
-
-def main():
-
- module_specific_arguments = dict(
-
- monitorname=dict(type='str'),
-
- type=dict(
- type='str',
- choices=[
- 'PING',
- 'TCP',
- 'HTTP',
- 'TCP-ECV',
- 'HTTP-ECV',
- 'UDP-ECV',
- 'DNS',
- 'FTP',
- 'LDNS-PING',
- 'LDNS-TCP',
- 'LDNS-DNS',
- 'RADIUS',
- 'USER',
- 'HTTP-INLINE',
- 'SIP-UDP',
- 'SIP-TCP',
- 'LOAD',
- 'FTP-EXTENDED',
- 'SMTP',
- 'SNMP',
- 'NNTP',
- 'MYSQL',
- 'MYSQL-ECV',
- 'MSSQL-ECV',
- 'ORACLE-ECV',
- 'LDAP',
- 'POP3',
- 'CITRIX-XML-SERVICE',
- 'CITRIX-WEB-INTERFACE',
- 'DNS-TCP',
- 'RTSP',
- 'ARP',
- 'CITRIX-AG',
- 'CITRIX-AAC-LOGINPAGE',
- 'CITRIX-AAC-LAS',
- 'CITRIX-XD-DDC',
- 'ND6',
- 'CITRIX-WI-EXTENDED',
- 'DIAMETER',
- 'RADIUS_ACCOUNTING',
- 'STOREFRONT',
- 'APPC',
- 'SMPP',
- 'CITRIX-XNC-ECV',
- 'CITRIX-XDM',
- 'CITRIX-STA-SERVICE',
- 'CITRIX-STA-SERVICE-NHOP',
- ]
- ),
-
- action=dict(
- type='str',
- choices=[
- 'NONE',
- 'LOG',
- 'DOWN',
- ]
- ),
- respcode=dict(type='list'),
- httprequest=dict(type='str'),
- rtsprequest=dict(type='str'),
- customheaders=dict(type='str'),
- maxforwards=dict(type='float'),
- sipmethod=dict(
- type='str',
- choices=[
- 'OPTIONS',
- 'INVITE',
- 'REGISTER',
- ]
- ),
- sipuri=dict(type='str'),
- sipreguri=dict(type='str'),
- send=dict(type='str'),
- recv=dict(type='str'),
- query=dict(type='str'),
- querytype=dict(
- type='str',
- choices=[
- 'Address',
- 'Zone',
- 'AAAA',
- ]
- ),
- scriptname=dict(type='str'),
- scriptargs=dict(type='str'),
- dispatcherip=dict(type='str'),
- dispatcherport=dict(type='int'),
- username=dict(type='str'),
- password=dict(type='str'),
- secondarypassword=dict(type='str'),
- logonpointname=dict(type='str'),
- lasversion=dict(type='str'),
- radkey=dict(type='str'),
- radnasid=dict(type='str'),
- radnasip=dict(type='str'),
- radaccounttype=dict(type='float'),
- radframedip=dict(type='str'),
- radapn=dict(type='str'),
- radmsisdn=dict(type='str'),
- radaccountsession=dict(type='str'),
- lrtm=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- deviation=dict(type='float'),
- units1=dict(
- type='str',
- choices=[
- 'SEC',
- 'MSEC',
- 'MIN',
- ]
- ),
- interval=dict(type='int'),
- units3=dict(
- type='str',
- choices=[
- 'SEC',
- 'MSEC',
- 'MIN',
- ]
- ),
- resptimeout=dict(type='int'),
- units4=dict(
- type='str',
- choices=[
- 'SEC',
- 'MSEC',
- 'MIN',
- ]
- ),
- resptimeoutthresh=dict(type='float'),
- retries=dict(type='int'),
- failureretries=dict(type='int'),
- alertretries=dict(type='int'),
- successretries=dict(type='int'),
- downtime=dict(type='int'),
- units2=dict(
- type='str',
- choices=[
- 'SEC',
- 'MSEC',
- 'MIN',
- ]
- ),
- destip=dict(type='str'),
- destport=dict(type='int'),
- reverse=dict(type='bool'),
- transparent=dict(type='bool'),
- iptunnel=dict(type='bool'),
- tos=dict(type='bool'),
- tosid=dict(type='float'),
- secure=dict(type='bool'),
- validatecred=dict(type='bool'),
- domain=dict(type='str'),
- ipaddress=dict(type='list'),
- group=dict(type='str'),
- filename=dict(type='str'),
- basedn=dict(type='str'),
- binddn=dict(type='str'),
- filter=dict(type='str'),
- attribute=dict(type='str'),
- database=dict(type='str'),
- oraclesid=dict(type='str'),
- sqlquery=dict(type='str'),
- evalrule=dict(type='str'),
- mssqlprotocolversion=dict(
- type='str',
- choices=[
- '70',
- '2000',
- '2000SP1',
- '2005',
- '2008',
- '2008R2',
- '2012',
- '2014',
- ]
- ),
- Snmpoid=dict(type='str'),
- snmpcommunity=dict(type='str'),
- snmpthreshold=dict(type='str'),
- snmpversion=dict(
- type='str',
- choices=[
- 'V1',
- 'V2',
- ]
- ),
- application=dict(type='str'),
- sitepath=dict(type='str'),
- storename=dict(type='str'),
- storefrontacctservice=dict(type='bool'),
- hostname=dict(type='str'),
- netprofile=dict(type='str'),
- originhost=dict(type='str'),
- originrealm=dict(type='str'),
- hostipaddress=dict(type='str'),
- vendorid=dict(type='float'),
- productname=dict(type='str'),
- firmwarerevision=dict(type='float'),
- authapplicationid=dict(type='list'),
- acctapplicationid=dict(type='list'),
- inbandsecurityid=dict(
- type='str',
- choices=[
- 'NO_INBAND_SECURITY',
- 'TLS',
- ]
- ),
- supportedvendorids=dict(type='list'),
- vendorspecificvendorid=dict(type='float'),
- vendorspecificauthapplicationids=dict(type='list'),
- vendorspecificacctapplicationids=dict(type='list'),
- storedb=dict(
- type='str',
- choices=[
- 'enabled',
- 'disabled',
- ]
- ),
- storefrontcheckbackendservices=dict(type='bool'),
- trofscode=dict(type='float'),
- trofsstring=dict(type='str'),
- )
-
- hand_inserted_arguments = dict()
-
- argument_spec = dict()
- argument_spec.update(module_specific_arguments)
- argument_spec.update(netscaler_common_arguments)
- argument_spec.update(hand_inserted_arguments)
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- )
-
- module_result = dict(
- changed=False,
- failed=False,
- loglines=loglines,
- )
-
- # Fail the module if imports failed
- if not PYTHON_SDK_IMPORTED:
- module.fail_json(msg='Could not load nitro python sdk', **module_result)
-
- # Fallthrough to rest of execution
- client = get_nitro_client(module)
-
- try:
- client.login()
- except nitro_exception as e:
- msg = "nitro exception during login. errorcode=%s, message=%s" % (str(e.errorcode), e.message)
- module.fail_json(msg=msg)
- except Exception as e:
- if str(type(e)) == "":
- module.fail_json(msg='Connection error %s' % str(e))
- elif str(type(e)) == "":
- module.fail_json(msg='SSL Error %s' % str(e))
- else:
- module.fail_json(msg='Unexpected error during login %s' % str(e))
-
- # Instantiate lb monitor object
- readwrite_attrs = [
- 'monitorname',
- 'type',
- 'action',
- 'respcode',
- 'httprequest',
- 'rtsprequest',
- 'customheaders',
- 'maxforwards',
- 'sipmethod',
- 'sipuri',
- 'sipreguri',
- 'send',
- 'recv',
- 'query',
- 'querytype',
- 'scriptname',
- 'scriptargs',
- 'dispatcherip',
- 'dispatcherport',
- 'username',
- 'password',
- 'secondarypassword',
- 'logonpointname',
- 'lasversion',
- 'radkey',
- 'radnasid',
- 'radnasip',
- 'radaccounttype',
- 'radframedip',
- 'radapn',
- 'radmsisdn',
- 'radaccountsession',
- 'lrtm',
- 'deviation',
- 'units1',
- 'interval',
- 'units3',
- 'resptimeout',
- 'units4',
- 'resptimeoutthresh',
- 'retries',
- 'failureretries',
- 'alertretries',
- 'successretries',
- 'downtime',
- 'units2',
- 'destip',
- 'destport',
- 'reverse',
- 'transparent',
- 'iptunnel',
- 'tos',
- 'tosid',
- 'secure',
- 'validatecred',
- 'domain',
- 'ipaddress',
- 'group',
- 'filename',
- 'basedn',
- 'binddn',
- 'filter',
- 'attribute',
- 'database',
- 'oraclesid',
- 'sqlquery',
- 'evalrule',
- 'mssqlprotocolversion',
- 'Snmpoid',
- 'snmpcommunity',
- 'snmpthreshold',
- 'snmpversion',
- 'application',
- 'sitepath',
- 'storename',
- 'storefrontacctservice',
- 'netprofile',
- 'originhost',
- 'originrealm',
- 'hostipaddress',
- 'vendorid',
- 'productname',
- 'firmwarerevision',
- 'authapplicationid',
- 'acctapplicationid',
- 'inbandsecurityid',
- 'supportedvendorids',
- 'vendorspecificvendorid',
- 'vendorspecificauthapplicationids',
- 'vendorspecificacctapplicationids',
- 'storedb',
- 'storefrontcheckbackendservices',
- 'trofscode',
- 'trofsstring',
- ]
-
- readonly_attrs = [
- 'lrtmconf',
- 'lrtmconfstr',
- 'dynamicresponsetimeout',
- 'dynamicinterval',
- 'multimetrictable',
- 'dup_state',
- 'dup_weight',
- 'weight',
- ]
-
- immutable_attrs = [
- 'monitorname',
- 'type',
- 'units1',
- 'units3',
- 'units4',
- 'units2',
- 'Snmpoid',
- 'hostname',
- 'servicename',
- 'servicegroupname',
- ]
-
- transforms = {
- 'storefrontcheckbackendservices': ['bool_yes_no'],
- 'secure': ['bool_yes_no'],
- 'tos': ['bool_yes_no'],
- 'validatecred': ['bool_yes_no'],
- 'storefrontacctservice': ['bool_yes_no'],
- 'iptunnel': ['bool_yes_no'],
- 'transparent': ['bool_yes_no'],
- 'reverse': ['bool_yes_no'],
- 'lrtm': [lambda v: v.upper()],
- 'storedb': [lambda v: v.upper()],
- }
-
- lbmonitor_proxy = ConfigProxy(
- actual=lbmonitor(),
- client=client,
- attribute_values_dict=module.params,
- readwrite_attrs=readwrite_attrs,
- readonly_attrs=readonly_attrs,
- immutable_attrs=immutable_attrs,
- transforms=transforms,
- )
-
- try:
- ensure_feature_is_enabled(client, 'LB')
-
- if module.params['state'] == 'present':
- log('Applying actions for state present')
- if not lbmonitor_exists(client, module):
- if not module.check_mode:
- log('Adding monitor')
- lbmonitor_proxy.add()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- elif not lbmonitor_identical(client, module, lbmonitor_proxy):
-
- # Check if we try to change value of immutable attributes
- immutables_changed = get_immutables_intersection(lbmonitor_proxy, diff_list(client, module, lbmonitor_proxy).keys())
- if immutables_changed != []:
- diff = diff_list(client, module, lbmonitor_proxy)
- msg = 'Cannot update immutable attributes %s' % (immutables_changed,)
- module.fail_json(msg=msg, diff=diff, **module_result)
-
- if not module.check_mode:
- log('Updating monitor')
- lbmonitor_proxy.update()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- else:
- log('Doing nothing for monitor')
- module_result['changed'] = False
-
- # Sanity check for result
- log('Sanity checks for state present')
- if not module.check_mode:
- if not lbmonitor_exists(client, module):
- module.fail_json(msg='lb monitor does not exist', **module_result)
- if not lbmonitor_identical(client, module, lbmonitor_proxy):
- module.fail_json(
- msg='lb monitor is not configured correctly',
- diff=diff_list(client, module, lbmonitor_proxy),
- **module_result
- )
-
- elif module.params['state'] == 'absent':
- log('Applying actions for state absent')
- if lbmonitor_exists(client, module):
- if not module.check_mode:
- lbmonitor_proxy.delete()
- if module.params['save_config']:
- client.save_config()
- module_result['changed'] = True
- else:
- module_result['changed'] = False
-
- # Sanity check for result
- log('Sanity checks for state absent')
- if not module.check_mode:
- if lbmonitor_exists(client, module):
- module.fail_json(msg='lb monitor still exists', **module_result)
-
- module_result['actual_attributes'] = lbmonitor_proxy.get_actual_rw_attributes(filter='monitorname')
- except nitro_exception as e:
- msg = "nitro exception errorcode=%s, message=%s" % (str(e.errorcode), e.message)
- module.fail_json(msg=msg, **module_result)
-
- client.logout()
-
- module.exit_json(**module_result)
-
-
-if __name__ == "__main__":
- main()
diff --git a/plugins/modules/network/netscaler/netscaler_lb_vserver.py b/plugins/modules/network/netscaler/netscaler_lb_vserver.py
deleted file mode 100644
index 087edd42c5..0000000000
--- a/plugins/modules/network/netscaler/netscaler_lb_vserver.py
+++ /dev/null
@@ -1,1941 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2017 Citrix Systems
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: netscaler_lb_vserver
-short_description: Manage load balancing vserver configuration
-description:
- - Manage load balancing vserver configuration
- - This module is intended to run either on the ansible control node or a bastion (jumpserver) with access to the actual netscaler instance
-
-
-author: George Nikolopoulos (@giorgos-nikolopoulos)
-
-options:
-
- name:
- description:
- - >-
- Name for the virtual server. Must begin with an ASCII alphanumeric or underscore C(_) character, and
- must contain only ASCII alphanumeric, underscore, hash C(#), period C(.), space C( ), colon C(:), at sign
- C(@), equal sign C(=), and hyphen C(-) characters. Can be changed after the virtual server is created.
- - "Minimum length = 1"
-
- servicetype:
- choices:
- - 'HTTP'
- - 'FTP'
- - 'TCP'
- - 'UDP'
- - 'SSL'
- - 'SSL_BRIDGE'
- - 'SSL_TCP'
- - 'DTLS'
- - 'NNTP'
- - 'DNS'
- - 'DHCPRA'
- - 'ANY'
- - 'SIP_UDP'
- - 'SIP_TCP'
- - 'SIP_SSL'
- - 'DNS_TCP'
- - 'RTSP'
- - 'PUSH'
- - 'SSL_PUSH'
- - 'RADIUS'
- - 'RDP'
- - 'MYSQL'
- - 'MSSQL'
- - 'DIAMETER'
- - 'SSL_DIAMETER'
- - 'TFTP'
- - 'ORACLE'
- - 'SMPP'
- - 'SYSLOGTCP'
- - 'SYSLOGUDP'
- - 'FIX'
- - 'SSL_FIX'
- description:
- - "Protocol used by the service (also called the service type)."
-
- ipv46:
- description:
- - "IPv4 or IPv6 address to assign to the virtual server."
-
- ippattern:
- description:
- - >-
- IP address pattern, in dotted decimal notation, for identifying packets to be accepted by the virtual
- server. The IP Mask parameter specifies which part of the destination IP address is matched against
- the pattern. Mutually exclusive with the IP Address parameter.
- - >-
- For example, if the IP pattern assigned to the virtual server is C(198.51.100.0) and the IP mask is
- C(255.255.240.0) (a forward mask), the first 20 bits in the destination IP addresses are matched with
- the first 20 bits in the pattern. The virtual server accepts requests with IP addresses that range
- from C(198.51.96.1) to C(198.51.111.254). You can also use a pattern such as C(0.0.2.2) and a mask such as
- C(0.0.255.255) (a reverse mask).
- - >-
- If a destination IP address matches more than one IP pattern, the pattern with the longest match is
- selected, and the associated virtual server processes the request. For example, if virtual servers
- C(vs1) and C(vs2) have the same IP pattern, C(0.0.100.128), but different IP masks of C(0.0.255.255) and
- C(0.0.224.255), a destination IP address of C(198.51.100.128) has the longest match with the IP pattern of
- vs1. If a destination IP address matches two or more virtual servers to the same extent, the request
- is processed by the virtual server whose port number matches the port number in the request.
-
- ipmask:
- description:
- - >-
- IP mask, in dotted decimal notation, for the IP Pattern parameter. Can have leading or trailing
- non-zero octets (for example, C(255.255.240.0) or C(0.0.255.255)). Accordingly, the mask specifies whether
- the first n bits or the last n bits of the destination IP address in a client request are to be
- matched with the corresponding bits in the IP pattern. The former is called a forward mask. The
- latter is called a reverse mask.
-
- port:
- description:
- - "Port number for the virtual server."
- - "Range C(1) - C(65535)"
- - "* in CLI is represented as C(65535) in NITRO API"
-
- range:
- description:
- - >-
- Number of IP addresses that the appliance must generate and assign to the virtual server. The virtual
- server then functions as a network virtual server, accepting traffic on any of the generated IP
- addresses. The IP addresses are generated automatically, as follows:
- - >-
- * For a range of n, the last octet of the address specified by the IP Address parameter increments
- n-1 times.
- - "* If the last octet exceeds 255, it rolls over to 0 and the third octet increments by 1."
- - >-
- Note: The Range parameter assigns multiple IP addresses to one virtual server. To generate an array
- of virtual servers, each of which owns only one IP address, use brackets in the IP Address and Name
- parameters to specify the range. For example:
- - "add lb vserver my_vserver[1-3] HTTP 192.0.2.[1-3] 80."
- - "Minimum value = C(1)"
- - "Maximum value = C(254)"
-
- persistencetype:
- choices:
- - 'SOURCEIP'
- - 'COOKIEINSERT'
- - 'SSLSESSION'
- - 'RULE'
- - 'URLPASSIVE'
- - 'CUSTOMSERVERID'
- - 'DESTIP'
- - 'SRCIPDESTIP'
- - 'CALLID'
- - 'RTSPSID'
- - 'DIAMETER'
- - 'FIXSESSION'
- - 'NONE'
- description:
- - "Type of persistence for the virtual server. Available settings function as follows:"
- - "* C(SOURCEIP) - Connections from the same client IP address belong to the same persistence session."
- - >-
- * C(COOKIEINSERT) - Connections that have the same HTTP Cookie, inserted by a Set-Cookie directive from
- a server, belong to the same persistence session.
- - "* C(SSLSESSION) - Connections that have the same SSL Session ID belong to the same persistence session."
- - >-
- * C(CUSTOMSERVERID) - Connections with the same server ID form part of the same session. For this
- persistence type, set the Server ID (CustomServerID) parameter for each service and configure the
- Rule parameter to identify the server ID in a request.
- - "* C(RULE) - All connections that match a user defined rule belong to the same persistence session."
- - >-
- * C(URLPASSIVE) - Requests that have the same server ID in the URL query belong to the same persistence
- session. The server ID is the hexadecimal representation of the IP address and port of the service to
- which the request must be forwarded. This persistence type requires a rule to identify the server ID
- in the request.
- - "* C(DESTIP) - Connections to the same destination IP address belong to the same persistence session."
- - >-
- * C(SRCIPDESTIP) - Connections that have the same source IP address and destination IP address belong to
- the same persistence session.
- - "* C(CALLID) - Connections that have the same CALL-ID SIP header belong to the same persistence session."
- - "* C(RTSPSID) - Connections that have the same RTSP Session ID belong to the same persistence session."
- - >-
- * FIXSESSION - Connections that have the same SenderCompID and TargetCompID values belong to the same
- persistence session.
-
- timeout:
- description:
- - "Time period for which a persistence session is in effect."
- - "Minimum value = C(0)"
- - "Maximum value = C(1440)"
-
- persistencebackup:
- choices:
- - 'SOURCEIP'
- - 'NONE'
- description:
- - >-
- Backup persistence type for the virtual server. Becomes operational if the primary persistence
- mechanism fails.
-
- backuppersistencetimeout:
- description:
- - "Time period for which backup persistence is in effect."
- - "Minimum value = C(2)"
- - "Maximum value = C(1440)"
-
- lbmethod:
- choices:
- - 'ROUNDROBIN'
- - 'LEASTCONNECTION'
- - 'LEASTRESPONSETIME'
- - 'URLHASH'
- - 'DOMAINHASH'
- - 'DESTINATIONIPHASH'
- - 'SOURCEIPHASH'
- - 'SRCIPDESTIPHASH'
- - 'LEASTBANDWIDTH'
- - 'LEASTPACKETS'
- - 'TOKEN'
- - 'SRCIPSRCPORTHASH'
- - 'LRTM'
- - 'CALLIDHASH'
- - 'CUSTOMLOAD'
- - 'LEASTREQUEST'
- - 'AUDITLOGHASH'
- - 'STATICPROXIMITY'
- description:
- - "Load balancing method. The available settings function as follows:"
- - >-
- * C(ROUNDROBIN) - Distribute requests in rotation, regardless of the load. Weights can be assigned to
- services to enforce weighted round robin distribution.
- - "* C(LEASTCONNECTION) (default) - Select the service with the fewest connections."
- - "* C(LEASTRESPONSETIME) - Select the service with the lowest average response time."
- - "* C(LEASTBANDWIDTH) - Select the service currently handling the least traffic."
- - "* C(LEASTPACKETS) - Select the service currently serving the lowest number of packets per second."
- - "* C(CUSTOMLOAD) - Base service selection on the SNMP metrics obtained by custom load monitors."
- - >-
- * C(LRTM) - Select the service with the lowest response time. Response times are learned through
- monitoring probes. This method also takes the number of active connections into account.
- - >-
- Also available are a number of hashing methods, in which the appliance extracts a predetermined
- portion of the request, creates a hash of the portion, and then checks whether any previous requests
- had the same hash value. If it finds a match, it forwards the request to the service that served
- those previous requests. Following are the hashing methods:
- - "* C(URLHASH) - Create a hash of the request URL (or part of the URL)."
- - >-
- * C(DOMAINHASH) - Create a hash of the domain name in the request (or part of the domain name). The
- domain name is taken from either the URL or the Host header. If the domain name appears in both
- locations, the URL is preferred. If the request does not contain a domain name, the load balancing
- method defaults to C(LEASTCONNECTION).
- - "* C(DESTINATIONIPHASH) - Create a hash of the destination IP address in the IP header."
- - "* C(SOURCEIPHASH) - Create a hash of the source IP address in the IP header."
- - >-
- * C(TOKEN) - Extract a token from the request, create a hash of the token, and then select the service
- to which any previous requests with the same token hash value were sent.
- - >-
- * C(SRCIPDESTIPHASH) - Create a hash of the string obtained by concatenating the source IP address and
- destination IP address in the IP header.
- - "* C(SRCIPSRCPORTHASH) - Create a hash of the source IP address and source port in the IP header."
- - "* C(CALLIDHASH) - Create a hash of the SIP Call-ID header."
-
- hashlength:
- description:
- - >-
- Number of bytes to consider for the hash value used in the URLHASH and DOMAINHASH load balancing
- methods.
- - "Minimum value = C(1)"
- - "Maximum value = C(4096)"
-
- netmask:
- description:
- - >-
- IPv4 subnet mask to apply to the destination IP address or source IP address when the load balancing
- method is C(DESTINATIONIPHASH) or C(SOURCEIPHASH).
- - "Minimum length = 1"
-
- v6netmasklen:
- description:
- - >-
- Number of bits to consider in an IPv6 destination or source IP address, for creating the hash that is
- required by the C(DESTINATIONIPHASH) and C(SOURCEIPHASH) load balancing methods.
- - "Minimum value = C(1)"
- - "Maximum value = C(128)"
-
- backuplbmethod:
- choices:
- - 'ROUNDROBIN'
- - 'LEASTCONNECTION'
- - 'LEASTRESPONSETIME'
- - 'SOURCEIPHASH'
- - 'LEASTBANDWIDTH'
- - 'LEASTPACKETS'
- - 'CUSTOMLOAD'
- description:
- - "Backup load balancing method. Becomes operational if the primary load balancing me"
- - "thod fails or cannot be used."
- - "Valid only if the primary method is based on static proximity."
-
- cookiename:
- description:
- - >-
- Use this parameter to specify the cookie name for C(COOKIE) persistence type. It specifies the name of
- cookie with a maximum of 32 characters. If not specified, cookie name is internally generated.
-
-
- listenpolicy:
- description:
- - >-
- Default syntax expression identifying traffic accepted by the virtual server. Can be either an
- expression (for example, C(CLIENT.IP.DST.IN_SUBNET(192.0.2.0/24)) or the name of a named expression. In
- the above example, the virtual server accepts all requests whose destination IP address is in the
- 192.0.2.0/24 subnet.
-
- listenpriority:
- description:
- - >-
- Integer specifying the priority of the listen policy. A higher number specifies a lower priority. If
- a request matches the listen policies of more than one virtual server the virtual server whose listen
- policy has the highest priority (the lowest priority number) accepts the request.
- - "Minimum value = C(0)"
- - "Maximum value = C(101)"
-
- resrule:
- description:
- - >-
- Default syntax expression specifying which part of a server's response to use for creating rule based
- persistence sessions (persistence type RULE). Can be either an expression or the name of a named
- expression.
- - "Example:"
- - 'C(HTTP.RES.HEADER("setcookie").VALUE(0).TYPECAST_NVLIST_T("=",";").VALUE("server1")).'
-
- persistmask:
- description:
- - "Persistence mask for IP based persistence types, for IPv4 virtual servers."
- - "Minimum length = 1"
-
- v6persistmasklen:
- description:
- - "Persistence mask for IP based persistence types, for IPv6 virtual servers."
- - "Minimum value = C(1)"
- - "Maximum value = C(128)"
-
- rtspnat:
- description:
- - "Use network address translation (NAT) for RTSP data connections."
- type: bool
-
- m:
- choices:
- - 'IP'
- - 'MAC'
- - 'IPTUNNEL'
- - 'TOS'
- description:
- - "Redirection mode for load balancing. Available settings function as follows:"
- - >-
- * C(IP) - Before forwarding a request to a server, change the destination IP address to the server's IP
- address.
- - >-
- * C(MAC) - Before forwarding a request to a server, change the destination MAC address to the server's
- MAC address. The destination IP address is not changed. MAC-based redirection mode is used mostly in
- firewall load balancing deployments.
- - >-
- * C(IPTUNNEL) - Perform IP-in-IP encapsulation for client IP packets. In the outer IP headers, set the
- destination IP address to the IP address of the server and the source IP address to the subnet IP
- (SNIP). The client IP packets are not modified. Applicable to both IPv4 and IPv6 packets.
- - "* C(TOS) - Encode the virtual server's TOS ID in the TOS field of the IP header."
- - "You can use either the C(IPTUNNEL) or the C(TOS) option to implement Direct Server Return (DSR)."
-
- tosid:
- description:
- - >-
- TOS ID of the virtual server. Applicable only when the load balancing redirection mode is set to TOS.
- - "Minimum value = C(1)"
- - "Maximum value = C(63)"
-
- datalength:
- description:
- - >-
- Length of the token to be extracted from the data segment of an incoming packet, for use in the token
- method of load balancing. The length of the token, specified in bytes, must not be greater than 24
- KB. Applicable to virtual servers of type TCP.
- - "Minimum value = C(1)"
- - "Maximum value = C(100)"
-
- dataoffset:
- description:
- - >-
- Offset to be considered when extracting a token from the TCP payload. Applicable to virtual servers,
- of type TCP, using the token method of load balancing. Must be within the first 24 KB of the TCP
- payload.
- - "Minimum value = C(0)"
- - "Maximum value = C(25400)"
-
- sessionless:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- Perform load balancing on a per-packet basis, without establishing sessions. Recommended for load
- balancing of intrusion detection system (IDS) servers and scenarios involving direct server return
- (DSR), where session information is unnecessary.
-
- connfailover:
- choices:
- - 'DISABLED'
- - 'STATEFUL'
- - 'STATELESS'
- description:
- - >-
- Mode in which the connection failover feature must operate for the virtual server. After a failover,
- established TCP connections and UDP packet flows are kept active and resumed on the secondary
- appliance. Clients remain connected to the same servers. Available settings function as follows:
- - >-
- * C(STATEFUL) - The primary appliance shares state information with the secondary appliance, in real
- time, resulting in some runtime processing overhead.
- - >-
- * C(STATELESS) - State information is not shared, and the new primary appliance tries to re-create the
- packet flow on the basis of the information contained in the packets it receives.
- - "* C(DISABLED) - Connection failover does not occur."
-
- redirurl:
- description:
- - "URL to which to redirect traffic if the virtual server becomes unavailable."
- - >-
- WARNING! Make sure that the domain in the URL does not match the domain specified for a content
- switching policy. If it does, requests are continuously redirected to the unavailable virtual server.
- - "Minimum length = 1"
-
- cacheable:
- description:
- - >-
- Route cacheable requests to a cache redirection virtual server. The load balancing virtual server can
- forward requests only to a transparent cache redirection virtual server that has an IP address and
- port combination of *:80, so such a cache redirection virtual server must be configured on the
- appliance.
- type: bool
-
- clttimeout:
- description:
- - "Idle time, in seconds, after which a client connection is terminated."
- - "Minimum value = C(0)"
- - "Maximum value = C(31536000)"
-
- somethod:
- choices:
- - 'CONNECTION'
- - 'DYNAMICCONNECTION'
- - 'BANDWIDTH'
- - 'HEALTH'
- - 'NONE'
- description:
- - "Type of threshold that, when exceeded, triggers spillover. Available settings function as follows:"
- - "* C(CONNECTION) - Spillover occurs when the number of client connections exceeds the threshold."
- - >-
- * DYNAMICCONNECTION - Spillover occurs when the number of client connections at the virtual server
- exceeds the sum of the maximum client (Max Clients) settings for bound services. Do not specify a
- spillover threshold for this setting, because the threshold is implied by the Max Clients settings of
- bound services.
- - >-
- * C(BANDWIDTH) - Spillover occurs when the bandwidth consumed by the virtual server's incoming and
- outgoing traffic exceeds the threshold.
- - >-
- * C(HEALTH) - Spillover occurs when the percentage of weights of the services that are UP drops below
- the threshold. For example, if services svc1, svc2, and svc3 are bound to a virtual server, with
- weights 1, 2, and 3, and the spillover threshold is 50%, spillover occurs if svc1 and svc3 or svc2
- and svc3 transition to DOWN.
- - "* C(NONE) - Spillover does not occur."
-
- sopersistence:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- If spillover occurs, maintain source IP address based persistence for both primary and backup virtual
- servers.
-
- sopersistencetimeout:
- description:
- - "Timeout for spillover persistence, in minutes."
- - "Minimum value = C(2)"
- - "Maximum value = C(1440)"
-
- healththreshold:
- description:
- - >-
- Threshold in percent of active services below which vserver state is made down. If this threshold is
- 0, vserver state will be up even if one bound service is up.
- - "Minimum value = C(0)"
- - "Maximum value = C(100)"
-
- sothreshold:
- description:
- - >-
- Threshold at which spillover occurs. Specify an integer for the C(CONNECTION) spillover method, a
- bandwidth value in kilobits per second for the C(BANDWIDTH) method (do not enter the units), or a
- percentage for the C(HEALTH) method (do not enter the percentage symbol).
- - "Minimum value = C(1)"
- - "Maximum value = C(4294967287)"
-
- sobackupaction:
- choices:
- - 'DROP'
- - 'ACCEPT'
- - 'REDIRECT'
- description:
- - >-
- Action to be performed if spillover is to take effect, but no backup chain to spillover is usable or
- exists.
-
- redirectportrewrite:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - "Rewrite the port and change the protocol to ensure successful HTTP redirects from services."
-
- downstateflush:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- Flush all active transactions associated with a virtual server whose state transitions from UP to
- DOWN. Do not enable this option for applications that must complete their transactions.
-
- disableprimaryondown:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - >-
- If the primary virtual server goes down, do not allow it to return to primary status until manually
- enabled.
-
- insertvserveripport:
- choices:
- - 'OFF'
- - 'VIPADDR'
- - 'V6TOV4MAPPING'
- description:
- - >-
- Insert an HTTP header, whose value is the IP address and port number of the virtual server, before
- forwarding a request to the server. The format of the header is : _, where vipHeader is the name that you specify for the header. If the virtual
- server has an IPv6 address, the address in the header is enclosed in brackets ([ and ]) to separate
- it from the port number. If you have mapped an IPv4 address to a virtual server's IPv6 address, the
- value of this parameter determines which IP address is inserted in the header, as follows:
- - >-
- * C(VIPADDR) - Insert the IP address of the virtual server in the HTTP header regardless of whether the
- virtual server has an IPv4 address or an IPv6 address. A mapped IPv4 address, if configured, is
- ignored.
- - >-
- * C(V6TOV4MAPPING) - Insert the IPv4 address that is mapped to the virtual server's IPv6 address. If a
- mapped IPv4 address is not configured, insert the IPv6 address.
- - "* C(OFF) - Disable header insertion."
-
- vipheader:
- description:
- - "Name for the inserted header. The default name is vip-header."
- - "Minimum length = 1"
-
- authenticationhost:
- description:
- - >-
- Fully qualified domain name (FQDN) of the authentication virtual server to which the user must be
- redirected for authentication. Make sure that the Authentication parameter is set to C(yes).
- - "Minimum length = 3"
- - "Maximum length = 252"
-
- authentication:
- description:
- - "Enable or disable user authentication."
- type: bool
-
- authn401:
- description:
- - "Enable or disable user authentication with HTTP 401 responses."
- type: bool
-
- authnvsname:
- description:
- - "Name of an authentication virtual server with which to authenticate users."
- - "Minimum length = 1"
- - "Maximum length = 252"
-
- push:
- choices:
- - 'enabled'
- - 'disabled'
- description:
- - "Process traffic with the push virtual server that is bound to this load balancing virtual server."
-
- pushvserver:
- description:
- - >-
- Name of the load balancing virtual server, of type PUSH or SSL_PUSH, to which the server pushes
- updates received on the load balancing virtual server that you are configuring.
- - "Minimum length = 1"
-
- pushlabel:
- description:
- - >-
- Expression for extracting a label from the server's response. Can be either an expression or the name
- of a named expression.
-
- pushmulticlients:
- description:
- - >-
- Allow multiple Web 2.0 connections from the same client to connect to the virtual server and expect
- updates.
- type: bool
-
- tcpprofilename:
- description:
- - "Name of the TCP profile whose settings are to be applied to the virtual server."
- - "Minimum length = 1"
- - "Maximum length = 127"
-
- httpprofilename:
- description:
- - "Name of the HTTP profile whose settings are to be applied to the virtual server."
- - "Minimum length = 1"
- - "Maximum length = 127"
-
- dbprofilename:
- description:
- - "Name of the DB profile whose settings are to be applied to the virtual server."
- - "Minimum length = 1"
- - "Maximum length = 127"
-
- comment:
- description:
- - "Any comments that you might want to associate with the virtual server."
-
- l2conn:
- description:
- - >-
- Use Layer 2 parameters (channel number, MAC address, and VLAN ID) in addition to the 4-tuple (