summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQijunPan <panqijun@huawei.com>2017-05-26 00:33:57 +0800
committerJohn R Barker <john@johnrbarker.com>2017-05-25 17:33:57 +0100
commite86279cee4a500d13ceaf577ec587232b1745f88 (patch)
treeb0214972603d5b1c2d28f30dc759df6ac4467909
parente9f2c080f4e2c093c2cc140abf15d7ebe8f03dd8 (diff)
downloadansible-e86279cee4a500d13ceaf577ec587232b1745f88.tar.gz
Contributing new /lib/ansible/plugins/action/ce.py module to manage HUAWEI data center CloudEngine switch (#21645)
* commit plugins action ce module commit plugins action ce module * update plugins/action/ce.py update plugins/action/ce.py * update action ce.py update action ce.py * fix CI issues * update ce.py * add ce action
-rw-r--r--lib/ansible/constants.py4
-rw-r--r--lib/ansible/plugins/action/ce.py134
2 files changed, 136 insertions, 2 deletions
diff --git a/lib/ansible/constants.py b/lib/ansible/constants.py
index eb7f12284b..b914959541 100644
--- a/lib/ansible/constants.py
+++ b/lib/ansible/constants.py
@@ -343,7 +343,7 @@ DEFAULT_TEST_PLUGIN_PATH = get_config(p, DEFAULTS, 'test_plugins', 'ANSIBLE_TEST
DEFAULT_STRATEGY_PLUGIN_PATH = get_config(p, DEFAULTS, 'strategy_plugins', 'ANSIBLE_STRATEGY_PLUGINS',
'~/.ansible/plugins/strategy:/usr/share/ansible/plugins/strategy', value_type='pathlist')
-NETWORK_GROUP_MODULES = get_config(p, DEFAULTS, 'network_group_modules', 'NETWORK_GROUP_MODULES', ['eos', 'nxos', 'ios', 'iosxr', 'junos',
+NETWORK_GROUP_MODULES = get_config(p, DEFAULTS, 'network_group_modules', 'NETWORK_GROUP_MODULES', ['eos', 'nxos', 'ios', 'iosxr', 'junos', 'ce',
'vyos', 'sros', 'dellos9', 'dellos10', 'dellos6'],
value_type='list')
DEFAULT_STRATEGY = get_config(p, DEFAULTS, 'strategy', 'ANSIBLE_STRATEGY', 'linear')
@@ -373,7 +373,7 @@ RETRY_FILES_ENABLED = get_config(p, DEFAULTS, 'retry_files_enabled', 'ANSIBLE_RE
RETRY_FILES_SAVE_PATH = get_config(p, DEFAULTS, 'retry_files_save_path', 'ANSIBLE_RETRY_FILES_SAVE_PATH', None, value_type='path')
DEFAULT_NULL_REPRESENTATION = get_config(p, DEFAULTS, 'null_representation', 'ANSIBLE_NULL_REPRESENTATION', None, value_type='none')
DISPLAY_ARGS_TO_STDOUT = get_config(p, DEFAULTS, 'display_args_to_stdout', 'ANSIBLE_DISPLAY_ARGS_TO_STDOUT', False, value_type='boolean')
-MAX_FILE_SIZE_FOR_DIFF = get_config(p, DEFAULTS, 'max_diff_size', 'ANSIBLE_MAX_DIFF_SIZE', 1024 * 1024, value_type='integer')
+MAAX_FILE_SIZE_FOR_DIFF = get_config(p, DEFAULTS, 'max_diff_size', 'ANSIBLE_MAX_DIFF_SIZE', 1024 * 1024, value_type='integer')
# CONNECTION RELATED
USE_PERSISTENT_CONNECTIONS = get_config(p, DEFAULTS, 'use_persistent_connections', 'ANSIBLE_USE_PERSISTENT_CONNECTIONS', False, value_type='boolean')
diff --git a/lib/ansible/plugins/action/ce.py b/lib/ansible/plugins/action/ce.py
new file mode 100644
index 0000000000..f10ff293d7
--- /dev/null
+++ b/lib/ansible/plugins/action/ce.py
@@ -0,0 +1,134 @@
+#
+# (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 <http://www.gnu.org/licenses/>.
+#
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import sys
+import copy
+
+from ansible.plugins.action.normal import ActionModule as _ActionModule
+from ansible.utils.path import unfrackpath
+from ansible.plugins import connection_loader
+from ansible.module_utils.six import iteritems
+from ansible.module_utils.ce import ce_argument_spec
+from ansible.module_utils.basic import AnsibleFallbackNotFound
+from ansible.module_utils._text import to_bytes
+
+try:
+ from __main__ import display
+except ImportError:
+ from ansible.utils.display import Display
+ display = Display()
+
+
+class ActionModule(_ActionModule):
+
+ def run(self, tmp=None, task_vars=None):
+ if self._play_context.connection != 'local':
+ return dict(
+ failed=True,
+ msg='invalid connection specified, expected connection=local, '
+ 'got %s' % self._play_context.connection
+ )
+
+ provider = self.load_provider()
+ 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 int(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.timeout = provider['timeout'] or self._play_context.timeout
+ self._task.args['provider'] = provider.update(
+ host=pc.remote_addr,
+ port=pc.port,
+ username=pc.remote_user,
+ password=pc.password,
+ ssh_keyfile=pc.private_key_file
+ )
+ display.vvv('using connection plugin %s' % pc.connection, pc.remote_addr)
+ connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)
+ socket_path = self._get_socket_path(pc)
+ display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)
+
+ if not os.path.exists(socket_path):
+ # start the connection if it isn't started
+ rc, out, err = connection.exec_command('open_shell()')
+ display.vvvv('open_shell() returned %s %s %s' % (rc, out, err))
+ if rc != 0:
+ return {'failed': True,
+ 'msg': 'unable to open shell. Please see: ' +
+ 'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell',
+ 'rc': rc}
+ else:
+ # make sure we are in the right cli context which should be
+ # enable mode and not config module
+ rc, out, err = connection.exec_command('prompt()')
+ while str(out).strip().endswith(']'):
+ display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
+ connection.exec_command('return')
+ rc, out, err = connection.exec_command('prompt()')
+
+ task_vars['ansible_socket'] = socket_path
+
+ # make sure a transport value is set in args
+ self._task.args['transport'] = transport
+
+ result = super(ActionModule, self).run(tmp, task_vars)
+ return result
+
+ def _get_socket_path(self, play_context):
+ ssh = connection_loader.get('ssh', class_only=True)
+ cp = ssh._create_control_path(play_context.remote_addr, play_context.port, play_context.remote_user)
+ path = unfrackpath("$HOME/.ansible/pc")
+ return cp % dict(directory=path)
+
+ def load_provider(self):
+ provider = self._task.args.get('provider', {})
+ for key, value in iteritems(ce_argument_spec):
+ if key != 'provider' and key not in provider:
+ if key in self._task.args:
+ provider[key] = self._task.args[key]
+ elif 'fallback' in value:
+ provider[key] = self._fallback(value['fallback'])
+ elif key not in provider:
+ provider[key] = None
+ return provider
+
+ def _fallback(self, fallback):
+ strategy = fallback[0]
+ args = []
+ kwargs = {}
+
+ for item in fallback[1:]:
+ if isinstance(item, dict):
+ kwargs = item
+ else:
+ args = item
+ try:
+ return strategy(*args, **kwargs)
+ except AnsibleFallbackNotFound:
+ pass