We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
junos_config fails if config format is xml
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
junos_config

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
2.3
```

##### 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 -->

##### STEPS TO REPRODUCE
```
Create a file with junos config in xml format
$ cat junos_config.xml
<interfaces>
    <interface>
        <name>ae11</name>
        <unit>
            <name>0</name>
            <description>Test</description>
        </unit>
    </interface>
</interfaces>
```
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
  - name: Run junos_config
    junos_config:
      src:  junos_config.xml
      comment: update config
      host: "{{ ansible_ssh_host }}"
      username: "{{ juniper_user }}"
      password: "{{ juniper_passwd }}"
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Run should configure interface on device
##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
Fails with error message.
<!--- Paste verbatim command output between quotes below -->
```
 "msg": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><rpc-error xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" xmlns:junos=\"http://xml.juniper.net/junos/15.1X49/junos\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n<error-type>protocol</error-type>\n<error-tag>operation-failed</error-tag>\n<error-severity>error</error-severity>\n<error-message>syntax error, expecting &lt;/configuration&gt;</error-message>\n<error-info>\n<bad-element>&lt;interfaces&gt;\n    &lt;interface&gt;\n        &lt;name&gt;ae11&lt;/name&gt;\n        &lt;unit&gt;\n            &lt;name&gt;0&lt;/name&gt;\n            &lt;description&gt;Test&lt;/description&gt;\n        &lt;/unit&gt;\n    &lt;/interface&gt;\n&lt;/interfaces&gt;</bad-element>\n</error-info>\n</rpc-error>\n"
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lib/ansible/module_utils/junos.py`
Content:
```
1 #
2 # (c) 2017 Red Hat, Inc.
3 #
4 # This file is part of Ansible
5 #
6 # Ansible is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # Ansible is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
18 #
19 from contextlib import contextmanager
20 
21 from xml.etree.ElementTree import Element, SubElement
22 
23 from ansible.module_utils.basic import env_fallback, return_values
24 from ansible.module_utils.netconf import send_request, children
25 from ansible.module_utils.netconf import discard_changes, validate
26 from ansible.module_utils.six import string_types
27 
28 ACTIONS = frozenset(['merge', 'override', 'replace', 'update', 'set'])
29 JSON_ACTIONS = frozenset(['merge', 'override', 'update'])
30 FORMATS = frozenset(['xml', 'text', 'json'])
31 CONFIG_FORMATS = frozenset(['xml', 'text', 'json', 'set'])
32 
33 junos_argument_spec = {
34     'host': dict(),
35     'port': dict(type='int'),
36     'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
37     'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True),
38     'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
39     'timeout': dict(type='int'),
40     'provider': dict(type='dict'),
41     'transport': dict()
42 }
43 
44 # Add argument's default value here
45 ARGS_DEFAULT_VALUE = {
46     'timeout': 10
47 }
48 
49 def check_args(module, warnings):
50     provider = module.params['provider'] or {}
51     for key in junos_argument_spec:
52         if key not in ('provider',) and module.params[key]:
53             warnings.append('argument %s has been deprecated and will be '
54                     'removed in a future version' % key)
55 
56     # set argument's default value if not provided in input
57     # This is done to avoid unwanted argument deprecation warning
58     # in case argument is not given as input (outside provider).
59     for key in ARGS_DEFAULT_VALUE:
60         if not module.params.get(key, None):
61             module.params[key] = ARGS_DEFAULT_VALUE[key]
62 
63     if provider:
64         for param in ('password',):
65             if provider.get(param):
66                 module.no_log_values.update(return_values(provider[param]))
67 
68 def _validate_rollback_id(module, value):
69     try:
70         if not 0 <= int(value) <= 49:
71             raise ValueError
72     except ValueError:
73         module.fail_json(msg='rollback must be between 0 and 49')
74 
75 def load_configuration(module, candidate=None, action='merge', rollback=None, format='xml'):
76 
77     if all((candidate is None, rollback is None)):
78         module.fail_json(msg='one of candidate or rollback must be specified')
79 
80     elif all((candidate is not None, rollback is not None)):
81         module.fail_json(msg='candidate and rollback are mutually exclusive')
82 
83     if format not in FORMATS:
84         module.fail_json(msg='invalid format specified')
85 
86     if format == 'json' and action not in JSON_ACTIONS:
87         module.fail_json(msg='invalid action for format json')
88     elif format in ('text', 'xml') and action not in ACTIONS:
89         module.fail_json(msg='invalid action format %s' % format)
90     if action == 'set' and not format == 'text':
91         module.fail_json(msg='format must be text when action is set')
92 
93     if rollback is not None:
94         _validate_rollback_id(module, rollback)
95         xattrs = {'rollback': str(rollback)}
96     else:
97         xattrs = {'action': action, 'format': format}
98 
99     obj = Element('load-configuration', xattrs)
100 
101     if candidate is not None:
102         lookup = {'xml': 'configuration', 'text': 'configuration-text',
103                   'set': 'configuration-set', 'json': 'configuration-json'}
104 
105         if action == 'set':
106             cfg = SubElement(obj, 'configuration-set')
107         else:
108             cfg = SubElement(obj, lookup[format])
109 
110         if isinstance(candidate, string_types):
111             cfg.text = candidate
112         else:
113             cfg.append(candidate)
114 
115     return send_request(module, obj)
116 
117 def get_configuration(module, compare=False, format='xml', rollback='0'):
118     if format not in CONFIG_FORMATS:
119         module.fail_json(msg='invalid config format specified')
120     xattrs = {'format': format}
121     if compare:
122         _validate_rollback_id(module, rollback)
123         xattrs['compare'] = 'rollback'
124         xattrs['rollback'] = str(rollback)
125     return send_request(module, Element('get-configuration', xattrs))
126 
127 def commit_configuration(module, confirm=False, check=False, comment=None, confirm_timeout=None):
128     obj = Element('commit-configuration')
129     if confirm:
130         SubElement(obj, 'confirmed')
131     if check:
132         SubElement(obj, 'check')
133     if comment:
134         subele = SubElement(obj, 'log')
135         subele.text = str(comment)
136     if confirm_timeout:
137         subele = SubElement(obj, 'confirm-timeout')
138         subele.text = int(confirm_timeout)
139     return send_request(module, obj)
140 
141 def command(module, command, format='text', rpc_only=False):
142     xattrs = {'format': format}
143     if rpc_only:
144         command += ' | display xml rpc'
145         xattrs['format'] = 'text'
146     return send_request(module, Element('command', xattrs, text=command))
147 
148 lock_configuration = lambda x: send_request(x, Element('lock-configuration'))
149 unlock_configuration = lambda x: send_request(x, Element('unlock-configuration'))
150 
151 @contextmanager
152 def locked_config(module):
153     try:
154         lock_configuration(module)
155         yield
156     finally:
157         unlock_configuration(module)
158 
159 def get_diff(module):
160 
161     reply = get_configuration(module, compare=True, format='text')
162     output = reply.find('.//configuration-output')
163     if output is not None:
164         return output.text
165 
166 def load_config(module, candidate, warnings, action='merge', commit=False, format='xml',
167                 comment=None, confirm=False, confirm_timeout=None):
168 
169     with locked_config(module):
170         if isinstance(candidate, list):
171             candidate = '\n'.join(candidate)
172 
173         reply = load_configuration(module, candidate, action=action, format=format)
174         if isinstance(reply, list):
175             warnings.extend(reply)
176 
177         validate(module)
178         diff = get_diff(module)
179 
180         if diff:
181             diff = str(diff).strip()
182             if commit:
183                 commit_configuration(module, confirm=confirm, comment=comment,
184                                      confirm_timeout=confirm_timeout)
185             else:
186                 discard_changes(module)
187 
188         return diff
189
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/lib/ansible/module_utils/junos.py b/lib/ansible/module_utils/junos.py
--- a/lib/ansible/module_utils/junos.py
+++ b/lib/ansible/module_utils/junos.py
@@ -18,7 +18,7 @@
 #
 from contextlib import contextmanager
 
-from xml.etree.ElementTree import Element, SubElement
+from xml.etree.ElementTree import Element, SubElement, fromstring
 
 from ansible.module_utils.basic import env_fallback, return_values
 from ansible.module_utils.netconf import send_request, children
@@ -108,10 +108,12 @@
             cfg = SubElement(obj, lookup[format])
 
         if isinstance(candidate, string_types):
-            cfg.text = candidate
+            if format == 'xml':
+                cfg.append(fromstring(candidate))
+            else:
+                cfg.text = candidate
         else:
             cfg.append(candidate)
-
     return send_request(module, obj)
 
 def get_configuration(module, compare=False, format='xml', rollback='0'):

{"golden_diff": "diff --git a/lib/ansible/module_utils/junos.py b/lib/ansible/module_utils/junos.py\n--- a/lib/ansible/module_utils/junos.py\n+++ b/lib/ansible/module_utils/junos.py\n@@ -18,7 +18,7 @@\n #\n from contextlib import contextmanager\n \n-from xml.etree.ElementTree import Element, SubElement\n+from xml.etree.ElementTree import Element, SubElement, fromstring\n \n from ansible.module_utils.basic import env_fallback, return_values\n from ansible.module_utils.netconf import send_request, children\n@@ -108,10 +108,12 @@\n             cfg = SubElement(obj, lookup[format])\n \n         if isinstance(candidate, string_types):\n-            cfg.text = candidate\n+            if format == 'xml':\n+                cfg.append(fromstring(candidate))\n+            else:\n+                cfg.text = candidate\n         else:\n             cfg.append(candidate)\n-\n     return send_request(module, obj)\n \n def get_configuration(module, compare=False, format='xml', rollback='0'):\n", "issue": "junos_config fails if config format is xml\n<!---\r\nVerify first that your issue/request is not already reported on GitHub.\r\nAlso test if the latest release, and master branch are affected too.\r\n-->\r\n\r\n##### ISSUE TYPE\r\n<!--- Pick one below and delete the rest: -->\r\n - Bug Report\r\n\r\n##### COMPONENT NAME\r\n<!--- Name of the module/plugin/task/feature -->\r\njunos_config\r\n\r\n##### ANSIBLE VERSION\r\n<!--- Paste verbatim output from \u201cansible --version\u201d between quotes below -->\r\n```\r\n2.3\r\n```\r\n\r\n##### CONFIGURATION\r\n<!---\r\nMention any settings you have changed/added/removed in ansible.cfg\r\n(or using the ANSIBLE_* environment variables).\r\n-->\r\n\r\n##### OS / ENVIRONMENT\r\n<!---\r\nMention the OS you are running Ansible from, and the OS you are\r\nmanaging, or say \u201cN/A\u201d for anything that is not platform-specific.\r\n-->\r\n\r\n##### SUMMARY\r\n<!--- Explain the problem briefly -->\r\n\r\n##### STEPS TO REPRODUCE\r\n```\r\nCreate a file with junos config in xml format\r\n$ cat junos_config.xml\r\n<interfaces>\r\n    <interface>\r\n        <name>ae11</name>\r\n        <unit>\r\n            <name>0</name>\r\n            <description>Test</description>\r\n        </unit>\r\n    </interface>\r\n</interfaces>\r\n```\r\n-->\r\n\r\n<!--- Paste example playbooks or commands between quotes below -->\r\n```yaml\r\n  - name: Run junos_config\r\n    junos_config:\r\n      src:  junos_config.xml\r\n      comment: update config\r\n      host: \"{{ ansible_ssh_host }}\"\r\n      username: \"{{ juniper_user }}\"\r\n      password: \"{{ juniper_passwd }}\"\r\n```\r\n\r\n<!--- You can also paste gist.github.com links for larger files -->\r\n\r\n##### EXPECTED RESULTS\r\n<!--- What did you expect to happen when running the steps above? -->\r\nRun should configure interface on device\r\n##### ACTUAL RESULTS\r\n<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->\r\nFails with error message.\r\n<!--- Paste verbatim command output between quotes below -->\r\n```\r\n \"msg\": \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?><rpc-error xmlns=\\\"urn:ietf:params:xml:ns:netconf:base:1.0\\\" xmlns:junos=\\\"http://xml.juniper.net/junos/15.1X49/junos\\\" xmlns:nc=\\\"urn:ietf:params:xml:ns:netconf:base:1.0\\\">\\n<error-type>protocol</error-type>\\n<error-tag>operation-failed</error-tag>\\n<error-severity>error</error-severity>\\n<error-message>syntax error, expecting &lt;/configuration&gt;</error-message>\\n<error-info>\\n<bad-element>&lt;interfaces&gt;\\n    &lt;interface&gt;\\n        &lt;name&gt;ae11&lt;/name&gt;\\n        &lt;unit&gt;\\n            &lt;name&gt;0&lt;/name&gt;\\n            &lt;description&gt;Test&lt;/description&gt;\\n        &lt;/unit&gt;\\n    &lt;/interface&gt;\\n&lt;/interfaces&gt;</bad-element>\\n</error-info>\\n</rpc-error>\\n\"\r\n```\r\n\n", "before_files": [{"content": "#\n# (c) 2017 Red Hat, Inc.\n#\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n#\nfrom contextlib import contextmanager\n\nfrom xml.etree.ElementTree import Element, SubElement\n\nfrom ansible.module_utils.basic import env_fallback, return_values\nfrom ansible.module_utils.netconf import send_request, children\nfrom ansible.module_utils.netconf import discard_changes, validate\nfrom ansible.module_utils.six import string_types\n\nACTIONS = frozenset(['merge', 'override', 'replace', 'update', 'set'])\nJSON_ACTIONS = frozenset(['merge', 'override', 'update'])\nFORMATS = frozenset(['xml', 'text', 'json'])\nCONFIG_FORMATS = frozenset(['xml', 'text', 'json', 'set'])\n\njunos_argument_spec = {\n    'host': dict(),\n    'port': dict(type='int'),\n    'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),\n    'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True),\n    'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),\n    'timeout': dict(type='int'),\n    'provider': dict(type='dict'),\n    'transport': dict()\n}\n\n# Add argument's default value here\nARGS_DEFAULT_VALUE = {\n    'timeout': 10\n}\n\ndef check_args(module, warnings):\n    provider = module.params['provider'] or {}\n    for key in junos_argument_spec:\n        if key not in ('provider',) and module.params[key]:\n            warnings.append('argument %s has been deprecated and will be '\n                    'removed in a future version' % key)\n\n    # set argument's default value if not provided in input\n    # This is done to avoid unwanted argument deprecation warning\n    # in case argument is not given as input (outside provider).\n    for key in ARGS_DEFAULT_VALUE:\n        if not module.params.get(key, None):\n            module.params[key] = ARGS_DEFAULT_VALUE[key]\n\n    if provider:\n        for param in ('password',):\n            if provider.get(param):\n                module.no_log_values.update(return_values(provider[param]))\n\ndef _validate_rollback_id(module, value):\n    try:\n        if not 0 <= int(value) <= 49:\n            raise ValueError\n    except ValueError:\n        module.fail_json(msg='rollback must be between 0 and 49')\n\ndef load_configuration(module, candidate=None, action='merge', rollback=None, format='xml'):\n\n    if all((candidate is None, rollback is None)):\n        module.fail_json(msg='one of candidate or rollback must be specified')\n\n    elif all((candidate is not None, rollback is not None)):\n        module.fail_json(msg='candidate and rollback are mutually exclusive')\n\n    if format not in FORMATS:\n        module.fail_json(msg='invalid format specified')\n\n    if format == 'json' and action not in JSON_ACTIONS:\n        module.fail_json(msg='invalid action for format json')\n    elif format in ('text', 'xml') and action not in ACTIONS:\n        module.fail_json(msg='invalid action format %s' % format)\n    if action == 'set' and not format == 'text':\n        module.fail_json(msg='format must be text when action is set')\n\n    if rollback is not None:\n        _validate_rollback_id(module, rollback)\n        xattrs = {'rollback': str(rollback)}\n    else:\n        xattrs = {'action': action, 'format': format}\n\n    obj = Element('load-configuration', xattrs)\n\n    if candidate is not None:\n        lookup = {'xml': 'configuration', 'text': 'configuration-text',\n                  'set': 'configuration-set', 'json': 'configuration-json'}\n\n        if action == 'set':\n            cfg = SubElement(obj, 'configuration-set')\n        else:\n            cfg = SubElement(obj, lookup[format])\n\n        if isinstance(candidate, string_types):\n            cfg.text = candidate\n        else:\n            cfg.append(candidate)\n\n    return send_request(module, obj)\n\ndef get_configuration(module, compare=False, format='xml', rollback='0'):\n    if format not in CONFIG_FORMATS:\n        module.fail_json(msg='invalid config format specified')\n    xattrs = {'format': format}\n    if compare:\n        _validate_rollback_id(module, rollback)\n        xattrs['compare'] = 'rollback'\n        xattrs['rollback'] = str(rollback)\n    return send_request(module, Element('get-configuration', xattrs))\n\ndef commit_configuration(module, confirm=False, check=False, comment=None, confirm_timeout=None):\n    obj = Element('commit-configuration')\n    if confirm:\n        SubElement(obj, 'confirmed')\n    if check:\n        SubElement(obj, 'check')\n    if comment:\n        subele = SubElement(obj, 'log')\n        subele.text = str(comment)\n    if confirm_timeout:\n        subele = SubElement(obj, 'confirm-timeout')\n        subele.text = int(confirm_timeout)\n    return send_request(module, obj)\n\ndef command(module, command, format='text', rpc_only=False):\n    xattrs = {'format': format}\n    if rpc_only:\n        command += ' | display xml rpc'\n        xattrs['format'] = 'text'\n    return send_request(module, Element('command', xattrs, text=command))\n\nlock_configuration = lambda x: send_request(x, Element('lock-configuration'))\nunlock_configuration = lambda x: send_request(x, Element('unlock-configuration'))\n\n@contextmanager\ndef locked_config(module):\n    try:\n        lock_configuration(module)\n        yield\n    finally:\n        unlock_configuration(module)\n\ndef get_diff(module):\n\n    reply = get_configuration(module, compare=True, format='text')\n    output = reply.find('.//configuration-output')\n    if output is not None:\n        return output.text\n\ndef load_config(module, candidate, warnings, action='merge', commit=False, format='xml',\n                comment=None, confirm=False, confirm_timeout=None):\n\n    with locked_config(module):\n        if isinstance(candidate, list):\n            candidate = '\\n'.join(candidate)\n\n        reply = load_configuration(module, candidate, action=action, format=format)\n        if isinstance(reply, list):\n            warnings.extend(reply)\n\n        validate(module)\n        diff = get_diff(module)\n\n        if diff:\n            diff = str(diff).strip()\n            if commit:\n                commit_configuration(module, confirm=confirm, comment=comment,\n                                     confirm_timeout=confirm_timeout)\n            else:\n                discard_changes(module)\n\n        return diff\n", "path": "lib/ansible/module_utils/junos.py"}], "after_files": [{"content": "#\n# (c) 2017 Red Hat, Inc.\n#\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n#\nfrom contextlib import contextmanager\n\nfrom xml.etree.ElementTree import Element, SubElement, fromstring\n\nfrom ansible.module_utils.basic import env_fallback, return_values\nfrom ansible.module_utils.netconf import send_request, children\nfrom ansible.module_utils.netconf import discard_changes, validate\nfrom ansible.module_utils.six import string_types\n\nACTIONS = frozenset(['merge', 'override', 'replace', 'update', 'set'])\nJSON_ACTIONS = frozenset(['merge', 'override', 'update'])\nFORMATS = frozenset(['xml', 'text', 'json'])\nCONFIG_FORMATS = frozenset(['xml', 'text', 'json', 'set'])\n\njunos_argument_spec = {\n    'host': dict(),\n    'port': dict(type='int'),\n    'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),\n    'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True),\n    'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),\n    'timeout': dict(type='int'),\n    'provider': dict(type='dict'),\n    'transport': dict()\n}\n\n# Add argument's default value here\nARGS_DEFAULT_VALUE = {\n    'timeout': 10\n}\n\ndef check_args(module, warnings):\n    provider = module.params['provider'] or {}\n    for key in junos_argument_spec:\n        if key not in ('provider',) and module.params[key]:\n            warnings.append('argument %s has been deprecated and will be '\n                    'removed in a future version' % key)\n\n    # set argument's default value if not provided in input\n    # This is done to avoid unwanted argument deprecation warning\n    # in case argument is not given as input (outside provider).\n    for key in ARGS_DEFAULT_VALUE:\n        if not module.params.get(key, None):\n            module.params[key] = ARGS_DEFAULT_VALUE[key]\n\n    if provider:\n        for param in ('password',):\n            if provider.get(param):\n                module.no_log_values.update(return_values(provider[param]))\n\ndef _validate_rollback_id(module, value):\n    try:\n        if not 0 <= int(value) <= 49:\n            raise ValueError\n    except ValueError:\n        module.fail_json(msg='rollback must be between 0 and 49')\n\ndef load_configuration(module, candidate=None, action='merge', rollback=None, format='xml'):\n\n    if all((candidate is None, rollback is None)):\n        module.fail_json(msg='one of candidate or rollback must be specified')\n\n    elif all((candidate is not None, rollback is not None)):\n        module.fail_json(msg='candidate and rollback are mutually exclusive')\n\n    if format not in FORMATS:\n        module.fail_json(msg='invalid format specified')\n\n    if format == 'json' and action not in JSON_ACTIONS:\n        module.fail_json(msg='invalid action for format json')\n    elif format in ('text', 'xml') and action not in ACTIONS:\n        module.fail_json(msg='invalid action format %s' % format)\n    if action == 'set' and not format == 'text':\n        module.fail_json(msg='format must be text when action is set')\n\n    if rollback is not None:\n        _validate_rollback_id(module, rollback)\n        xattrs = {'rollback': str(rollback)}\n    else:\n        xattrs = {'action': action, 'format': format}\n\n    obj = Element('load-configuration', xattrs)\n\n    if candidate is not None:\n        lookup = {'xml': 'configuration', 'text': 'configuration-text',\n                  'set': 'configuration-set', 'json': 'configuration-json'}\n\n        if action == 'set':\n            cfg = SubElement(obj, 'configuration-set')\n        else:\n            cfg = SubElement(obj, lookup[format])\n\n        if isinstance(candidate, string_types):\n            if format == 'xml':\n                cfg.append(fromstring(candidate))\n            else:\n                cfg.text = candidate\n        else:\n            cfg.append(candidate)\n    return send_request(module, obj)\n\ndef get_configuration(module, compare=False, format='xml', rollback='0'):\n    if format not in CONFIG_FORMATS:\n        module.fail_json(msg='invalid config format specified')\n    xattrs = {'format': format}\n    if compare:\n        _validate_rollback_id(module, rollback)\n        xattrs['compare'] = 'rollback'\n        xattrs['rollback'] = str(rollback)\n    return send_request(module, Element('get-configuration', xattrs))\n\ndef commit_configuration(module, confirm=False, check=False, comment=None, confirm_timeout=None):\n    obj = Element('commit-configuration')\n    if confirm:\n        SubElement(obj, 'confirmed')\n    if check:\n        SubElement(obj, 'check')\n    if comment:\n        subele = SubElement(obj, 'log')\n        subele.text = str(comment)\n    if confirm_timeout:\n        subele = SubElement(obj, 'confirm-timeout')\n        subele.text = int(confirm_timeout)\n    return send_request(module, obj)\n\ndef command(module, command, format='text', rpc_only=False):\n    xattrs = {'format': format}\n    if rpc_only:\n        command += ' | display xml rpc'\n        xattrs['format'] = 'text'\n    return send_request(module, Element('command', xattrs, text=command))\n\nlock_configuration = lambda x: send_request(x, Element('lock-configuration'))\nunlock_configuration = lambda x: send_request(x, Element('unlock-configuration'))\n\n@contextmanager\ndef locked_config(module):\n    try:\n        lock_configuration(module)\n        yield\n    finally:\n        unlock_configuration(module)\n\ndef get_diff(module):\n\n    reply = get_configuration(module, compare=True, format='text')\n    output = reply.find('.//configuration-output')\n    if output is not None:\n        return output.text\n\ndef load_config(module, candidate, warnings, action='merge', commit=False, format='xml',\n                comment=None, confirm=False, confirm_timeout=None):\n\n    with locked_config(module):\n        if isinstance(candidate, list):\n            candidate = '\\n'.join(candidate)\n\n        reply = load_configuration(module, candidate, action=action, format=format)\n        if isinstance(reply, list):\n            warnings.extend(reply)\n\n        validate(module)\n        diff = get_diff(module)\n\n        if diff:\n            diff = str(diff).strip()\n            if commit:\n                commit_configuration(module, confirm=confirm, comment=comment,\n                                     confirm_timeout=confirm_timeout)\n            else:\n                discard_changes(module)\n\n        return diff\n", "path": "lib/ansible/module_utils/junos.py"}]}