Clarify exception handling in net modules (#15507)

* Clarify exception handling in EOS

Also modify to EOS to standardize modules. It makes vimdiff a lot less angry

* Move IOS exception handling into Cli

* Move IOS-XR exception handling into Cli

* Move JUNOS exception handling into Cli

* Move NXOS exception handling into Cli

And reorganize to make it match the other modules

* Move OpenSwitch exception handling into Cli

More speculative restructuring here
This commit is contained in:
Nathaniel Case 2016-04-25 16:04:19 -04:00
commit 250b975704
6 changed files with 150 additions and 129 deletions

View file

@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
import re
import time
import json
@ -29,22 +30,22 @@ try:
except ImportError:
HAS_OPS = False
from ansible.module_utils.basic import AnsibleModule, env_fallback
from ansible.module_utils.urls import fetch_url
from ansible.module_utils.shell import Shell, HAS_PARAMIKO
from ansible.module_utils.basic import AnsibleModule, env_fallback, get_exception
from ansible.module_utils.shell import Shell, ShellError, HAS_PARAMIKO
from ansible.module_utils.netcfg import parse
from ansible.module_utils.urls import fetch_url
NET_PASSWD_RE = re.compile(r"[\r\n]?password: $", re.I)
NET_COMMON_ARGS = dict(
host=dict(),
host=dict(required=True),
port=dict(type='int'),
username=dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
password=dict(no_log=True, fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD'])),
ssh_keyfile=dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
use_ssl=dict(default=True, type='bool'),
validate_certs=dict(default=True, type='bool'),
transport=dict(default='ssh', choices=['ssh', 'cli', 'rest']),
use_ssl=dict(default=True, type='bool'),
provider=dict(type='dict')
)
@ -159,12 +160,21 @@ class Cli(object):
password = self.module.params['password']
key_filename = self.module.params['ssh_keyfile']
self.shell = Shell()
self.shell.open(host, port=port, username=username, password=password,
key_filename=key_filename)
try:
self.shell = Shell()
self.shell.open(host, port=port, username=username, password=password, key_filename=key_filename)
except ShellError:
e = get_exception()
msg = 'failed to connect to %s:%s - %s' % (host, port, str(e))
self.module.fail_json(msg=msg)
def send(self, commands, encoding='text'):
try:
return self.shell.send(commands)
except ShellError:
e = get_exception()
self.module.fail_json(msg=e.message, commands=commands)
def send(self, commands):
return self.shell.send(commands)
class NetworkModule(AnsibleModule):
@ -185,38 +195,37 @@ class NetworkModule(AnsibleModule):
super(NetworkModule, self)._load_params()
provider = self.params.get('provider') or dict()
for key, value in provider.items():
if key in NET_COMMON_ARGS.keys():
if key in NET_COMMON_ARGS:
if self.params.get(key) is None and value is not None:
self.params[key] = value
def connect(self):
if self.params['transport'] == 'rest':
self.connection = Rest(self)
elif self.params['transport'] == 'cli':
self.connection = Cli(self)
cls = globals().get(str(self.params['transport']).capitalize())
try:
self.connection = cls(self)
except TypeError:
e = get_exception()
self.fail_json(msg=e.message)
self.connection.connect()
def configure(self, config):
def configure(self, commands):
if self.params['transport'] == 'cli':
commands = to_list(config)
commands = to_list(commands)
commands.insert(0, 'configure terminal')
responses = self.execute(commands)
responses.pop(0)
return responses
elif self.params['transport'] == 'rest':
path = '/system/full-configuration'
return self.connection.put(path, data=config)
return self.connection.put(path, data=commands)
else:
if not self._opsidl:
(self._extschema, self._opsidl) = get_opsidl()
ops.dc.write(config, self._extschema, self._opsidl)
ops.dc.write(commands, self._extschema, self._opsidl)
def execute(self, commands, **kwargs):
try:
return self.connection.send(commands, **kwargs)
except Exception, exc:
self.fail_json(msg=exc.message, commands=commands)
return self.connection.send(commands, **kwargs)
def disconnect(self):
self.connection.close()
@ -251,7 +260,6 @@ def get_module(**kwargs):
if not HAS_OPS and module.params['transport'] == 'ssh':
module.fail_json(msg='could not import ops library')
# HAS_PARAMIKO is set by module_utils/shell.py
if module.params['transport'] == 'cli' and not HAS_PARAMIKO:
module.fail_json(msg='paramiko is required but does not appear to be installed')
@ -259,4 +267,3 @@ def get_module(**kwargs):
module.connect()
return module