Repository: ansible/ansible

Issue:
[WIP] Make network plugins PY3 complaint
<!---

-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report


##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
asa
dellos6
dellos9
dellos10
eos
ios
iosxr
junos
nxos
sros
vyos

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
2.4
```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->

##### SUMMARY
<!--- Explain the problem briefly -->
Issue to track py3 compliance for network modules
##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml

```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```

```



Discussion:
@ganeshrn Let me know if you need any help in this ? I would like to help here.

Resolving patch:
diff --git a/lib/ansible/module_utils/dellos9.py b/lib/ansible/module_utils/dellos9.py
--- a/lib/ansible/module_utils/dellos9.py
+++ b/lib/ansible/module_utils/dellos9.py
@@ -31,6 +31,7 @@
 #
 import re
 
+from ansible.module_utils._text import to_text
 from ansible.module_utils.basic import env_fallback, return_values
 from ansible.module_utils.network_common import to_list, ComplexList
 from ansible.module_utils.connection import exec_command
@@ -80,8 +81,8 @@ def get_config(module, flags=[]):
     except KeyError:
         rc, out, err = exec_command(module, cmd)
         if rc != 0:
-            module.fail_json(msg='unable to retrieve current config', stderr=err)
-        cfg = str(out).strip()
+            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
 
@@ -103,15 +104,15 @@ def run_commands(module, commands, check_rc=True):
         cmd = module.jsonify(cmd)
         rc, out, err = exec_command(module, cmd)
         if check_rc and rc != 0:
-            module.fail_json(msg=err, rc=rc)
-        responses.append(out)
+            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):
     rc, out, err = exec_command(module, 'configure terminal')
     if rc != 0:
-        module.fail_json(msg='unable to enter configuration mode', err=err)
+        module.fail_json(msg='unable to enter configuration mode', err=to_text(err, errors='surrogate_or_strict'))
 
     for command in to_list(commands):
         if command == 'end':
@@ -119,7 +120,7 @@ def load_config(module, commands):
         cmd = {'command': command, 'prompt': WARNING_PROMPTS_RE, 'answer': 'yes'}
         rc, out, err = exec_command(module, module.jsonify(cmd))
         if rc != 0:
-            module.fail_json(msg=err, command=command, rc=rc)
+            module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), command=command, rc=rc)
 
     exec_command(module, 'end')
 
diff --git a/lib/ansible/plugins/terminal/dellos9.py b/lib/ansible/plugins/terminal/dellos9.py
--- a/lib/ansible/plugins/terminal/dellos9.py
+++ b/lib/ansible/plugins/terminal/dellos9.py
@@ -24,6 +24,7 @@
 import re
 import json
 
+from ansible.module_utils._text import to_text, to_bytes
 from ansible.plugins.terminal import TerminalBase
 from ansible.errors import AnsibleConnectionFailure
 
@@ -31,36 +32,36 @@
 class TerminalModule(TerminalBase):
 
     terminal_stdout_re = [
-        re.compile(r"[\r\n]?[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$"),
-        re.compile(r"\[\w+\@[\w\-\.]+(?: [^\]])\] ?[>#\$] ?$")
+        re.compile(br"[\r\n]?[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$"),
+        re.compile(br"\[\w+\@[\w\-\.]+(?: [^\]])\] ?[>#\$] ?$")
     ]
 
     terminal_stderr_re = [
-        re.compile(r"% ?Error: (?:(?!\bdoes not exist\b)(?!\balready exists\b)(?!\bHost not found\b)(?!\bnot active\b).)*$"),
-        re.compile(r"% ?Bad secret"),
-        re.compile(r"invalid input", re.I),
-        re.compile(r"(?:incomplete|ambiguous) command", re.I),
-        re.compile(r"connection timed out", re.I),
-        re.compile(r"'[^']' +returned error code: ?\d+"),
+        re.compile(br"% ?Error: (?:(?!\bdoes not exist\b)(?!\balready exists\b)(?!\bHost not found\b)(?!\bnot active\b).)*$"),
+        re.compile(br"% ?Bad secret"),
+        re.compile(br"invalid input", re.I),
+        re.compile(br"(?:incomplete|ambiguous) command", re.I),
+        re.compile(br"connection timed out", re.I),
+        re.compile(br"'[^']' +returned error code: ?\d+"),
     ]
 
     def on_open_shell(self):
         try:
-            self._exec_cli_command('terminal length 0')
+            self._exec_cli_command(b'terminal length 0')
         except AnsibleConnectionFailure:
             raise AnsibleConnectionFailure('unable to set terminal parameters')
 
     def on_authorize(self, passwd=None):
-        if self._get_prompt().endswith('#'):
+        if self._get_prompt().endswith(b'#'):
             return
 
-        cmd = {'command': 'enable'}
+        cmd = {u'command': u'enable'}
         if passwd:
-            cmd['prompt'] = r"[\r\n]?password: $"
-            cmd['answer'] = passwd
+            cmd[u'prompt'] = to_text(r"[\r\n]?password: $", errors='surrogate_or_strict')
+            cmd[u'answer'] = passwd
 
         try:
-            self._exec_cli_command(json.dumps(cmd))
+            self._exec_cli_command(to_bytes(json.dumps(cmd), errors='surrogate_or_strict'))
         except AnsibleConnectionFailure:
             raise AnsibleConnectionFailure('unable to elevate privilege to enable mode')
 
@@ -70,9 +71,9 @@ def on_deauthorize(self):
             # if prompt is None most likely the terminal is hung up at a prompt
             return
 
-        if prompt.strip().endswith(')#'):
-            self._exec_cli_command('end')
-            self._exec_cli_command('disable')
+        if prompt.strip().endswith(b')#'):
+            self._exec_cli_command(b'end')
+            self._exec_cli_command(b'disable')
 
-        elif prompt.endswith('#'):
-            self._exec_cli_command('disable')
+        elif prompt.endswith(b'#'):
+            self._exec_cli_command(b'disable')


Test patch: