'Executes the cmd on in the shell and returns the output
The method accepts three forms of cmd.  The first form is as a byte
string that represents the command to be executed in the shell.  The
second form is as a utf8 JSON byte string with additional keywords.
The third form is a json-rpc (2.0)
Keywords supported for cmd:
:command: the command string to execute
:prompt: the expected prompt generated by executing command.
This can be a string or a list of strings
:answer: the string to respond to the prompt with
:sendonly: bool to disable waiting for response
:arg cmd: the byte string that represents the command to be executed
which can be a single command or a json encoded string.
:returns: a tuple of (return code, stdout, stderr).  The return
code is an integer and stdout and stderr are byte strings'

def exec_command(self, cmd):

    try:
        obj = json.loads(to_text(cmd, errors='surrogate_or_strict'))
    except (ValueError, TypeError):
        obj = {'command': to_bytes(cmd.strip(), errors='surrogate_or_strict')}
    obj = dict(((k, to_bytes(v, errors='surrogate_or_strict', nonstring='passthru')) for (k, v) in obj.items()))
    if ('prompt' in obj):
        if isinstance(obj['prompt'], binary_type):
            obj['prompt'] = [obj['prompt']]
        elif (not isinstance(obj['prompt'], Sequence)):
            if (obj['prompt'] is not None):
                obj['prompt'] = [to_bytes(obj['prompt'], errors='surrogate_or_strict')]
        else:
            obj['prompt'] = [to_bytes(p, errors='surrogate_or_strict') for p in obj['prompt'] if (p is not None)]
    if ('jsonrpc' in obj):
        if self._cliconf:
            out = self._exec_rpc(obj)
        else:
            out = self.internal_error(('cliconf    is    not    supported    for    network_os    %s' % self._play_context.network_os))
        return (0, to_bytes(out, errors='surrogate_or_strict'), '')
    if (obj['command'] == 'prompt()'):
        return (0, self._matched_prompt, '')
    try:
        if (not signal.getsignal(signal.SIGALRM)):
            signal.signal(signal.SIGALRM, self.alarm_handler)
        signal.alarm(self._play_context.timeout)
        out = self.send(obj['command'], obj.get('prompt'), obj.get('answer'), obj.get('sendonly'))
        signal.alarm(0)
        return (0, out, '')
    except (AnsibleConnectionFailure, ValueError) as exc:
        return (1, '', to_bytes(exc))
