1# 2017 Red Hat Inc.
2# (c) 2017 Ansible Project
3# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
4
5from __future__ import (absolute_import, division, print_function)
6__metaclass__ = type
7
8DOCUMENTATION = """
9author: Ansible Core Team
10connection: persistent
11short_description: Use a persistent unix socket for connection
12description:
13  - This is a helper plugin to allow making other connections persistent.
14version_added: "2.3"
15options:
16  persistent_command_timeout:
17    type: int
18    description:
19      - Configures, in seconds, the amount of time to wait for a command to
20        return from the remote device.  If this timer is exceeded before the
21        command returns, the connection plugin will raise an exception and
22        close
23    default: 10
24    ini:
25      - section: persistent_connection
26        key: command_timeout
27    env:
28      - name: ANSIBLE_PERSISTENT_COMMAND_TIMEOUT
29    vars:
30      - name: ansible_command_timeout
31"""
32from ansible.executor.task_executor import start_connection
33from ansible.plugins.connection import ConnectionBase
34from ansible.module_utils._text import to_text
35from ansible.module_utils.connection import Connection as SocketConnection
36from ansible.utils.display import Display
37
38display = Display()
39
40
41class Connection(ConnectionBase):
42    ''' Local based connections '''
43
44    transport = 'persistent'
45    has_pipelining = False
46
47    def __init__(self, play_context, new_stdin, *args, **kwargs):
48        super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
49        self._task_uuid = to_text(kwargs.get('task_uuid', ''))
50
51    def _connect(self):
52        self._connected = True
53        return self
54
55    def exec_command(self, cmd, in_data=None, sudoable=True):
56        display.vvvv('exec_command(), socket_path=%s' % self.socket_path, host=self._play_context.remote_addr)
57        connection = SocketConnection(self.socket_path)
58        out = connection.exec_command(cmd, in_data=in_data, sudoable=sudoable)
59        return 0, out, ''
60
61    def put_file(self, in_path, out_path):
62        pass
63
64    def fetch_file(self, in_path, out_path):
65        pass
66
67    def close(self):
68        self._connected = False
69
70    def run(self):
71        """Returns the path of the persistent connection socket.
72
73        Attempts to ensure (within playcontext.timeout seconds) that the
74        socket path exists. If the path exists (or the timeout has expired),
75        returns the socket path.
76        """
77        display.vvvv('starting connection from persistent connection plugin', host=self._play_context.remote_addr)
78        variables = {'ansible_command_timeout': self.get_option('persistent_command_timeout')}
79        socket_path = start_connection(self._play_context, variables, self._task_uuid)
80        display.vvvv('local domain socket path is %s' % socket_path, host=self._play_context.remote_addr)
81        setattr(self, '_socket_path', socket_path)
82        return socket_path
83