Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stable-2.7] Move missing library abort to use rather than import #55648

Merged
merged 3 commits into from
Apr 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelogs/fragments/55384-netconf-import.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bugfixes:
- Move netconf import errors from import to use.
19 changes: 16 additions & 3 deletions lib/ansible/plugins/netconf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@

from ansible.errors import AnsibleError
from ansible.plugins import AnsiblePlugin

from ansible.module_utils._text import to_native

try:
from ncclient.operations import RPCError
from ncclient.xml_ import to_xml, to_ele
except ImportError:
raise AnsibleError("ncclient is not installed")
HAS_NCCLIENT = True
NCCLIENT_IMP_ERR = None
except (ImportError, AttributeError) as err: # paramiko and gssapi are incompatible and raise AttributeError not ImportError
HAS_NCCLIENT = False
NCCLIENT_IMP_ERR = err

try:
from lxml.etree import Element, SubElement, tostring, fromstring
Expand All @@ -47,6 +50,15 @@ def wrapped(self, *args, **kwargs):
return wrapped


def ensure_ncclient(func):
@wraps(func)
def wrapped(self, *args, **kwargs):
if not HAS_NCCLIENT:
raise AnsibleError("Package ncclient is not installed: %s. Please install it with `pip install ncclient`" % to_native(NCCLIENT_IMP_ERR))
return func(self, *args, **kwargs)
return wrapped


class NetconfBase(AnsiblePlugin):
"""
A base class for implementing Netconf connections
Expand Down Expand Up @@ -104,6 +116,7 @@ def __init__(self, connection):
self._connection = connection
self.m = self._connection._manager

@ensure_ncclient
@ensure_connected
def rpc(self, name):
"""
Expand Down
32 changes: 15 additions & 17 deletions lib/ansible/plugins/netconf/ce.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@
import json
import re

from ansible import constants as C
from ansible.module_utils._text import to_text, to_bytes
from ansible.errors import AnsibleConnectionFailure, AnsibleError
from ansible.errors import AnsibleConnectionFailure
from ansible.plugins.netconf import NetconfBase
from ansible.plugins.netconf import ensure_connected
from ansible.plugins.netconf import ensure_connected, ensure_ncclient

try:
from ncclient import manager
from ncclient.operations import RPCError
from ncclient.transport.errors import SSHUnknownHostError
from ncclient.xml_ import to_ele, to_xml, new_ele
except ImportError:
raise AnsibleError("ncclient is not installed")
HAS_NCCLIENT = True
except (ImportError, AttributeError): # paramiko and gssapi are incompatible and raise AttributeError not ImportError
HAS_NCCLIENT = False

try:
from __main__ import display
Expand All @@ -45,12 +45,14 @@

class Netconf(NetconfBase):

@ensure_ncclient
def get_text(self, ele, tag):
try:
return to_text(ele.find(tag).text, errors='surrogate_then_replace').strip()
except AttributeError:
pass

@ensure_ncclient
def get_device_info(self):
device_info = dict()
device_info['network_os'] = 'ce'
Expand All @@ -71,6 +73,7 @@ def execute_rpc(self, name):
:name: Name of rpc in string format"""
return self.rpc(name)

@ensure_ncclient
@ensure_connected
def load_configuration(self, *args, **kwargs):
"""Loads given configuration on device
Expand Down Expand Up @@ -101,8 +104,8 @@ def get_capabilities(self):
return json.dumps(result)

@staticmethod
@ensure_ncclient
def guess_network_os(obj):

try:
m = manager.connect(
host=obj._play_context.remote_addr,
Expand Down Expand Up @@ -141,6 +144,7 @@ def compare_configuration(self, *args, **kwargs):
:rollback: rollback id"""
return self.m.compare_configuration(*args, **kwargs).data_xml

@ensure_ncclient
@ensure_connected
def execute_action(self, xml_str):
"""huawei execute-action"""
Expand All @@ -162,39 +166,39 @@ def reboot(self):
"""reboot the device"""
return self.m.reboot().data_xml

@ensure_connected
def halt(self):
"""reboot the device"""
return self.m.halt().data_xml

@ensure_ncclient
@ensure_connected
def get(self, *args, **kwargs):
try:
return self.m.get(*args, **kwargs).data_xml
except RPCError as exc:
raise Exception(to_xml(exc.xml))

@ensure_ncclient
@ensure_connected
def get_config(self, *args, **kwargs):
try:
return self.m.get_config(*args, **kwargs).data_xml
except RPCError as exc:
raise Exception(to_xml(exc.xml))

@ensure_ncclient
@ensure_connected
def edit_config(self, *args, **kwargs):
try:
return self.m.edit_config(*args, **kwargs).xml
except RPCError as exc:
raise Exception(to_xml(exc.xml))

@ensure_ncclient
@ensure_connected
def execute_nc_cli(self, *args, **kwargs):
try:
return self.m.cli(*args, **kwargs).xml
except RPCError as exc:
raise Exception(to_xml(exc.xml))

@ensure_ncclient
@ensure_connected
def commit(self, *args, **kwargs):
try:
Expand All @@ -209,9 +213,3 @@ def validate(self, *args, **kwargs):
@ensure_connected
def discard_changes(self, *args, **kwargs):
return self.m.discard_changes(*args, **kwargs).data_xml

@ensure_connected
def execute_rpc(self, name):
"""RPC to be execute on remote device
:name: Name of rpc in string format"""
return self.rpc(name)
25 changes: 13 additions & 12 deletions lib/ansible/plugins/netconf/iosxr.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,23 @@
import re
import collections

from ansible import constants as C
from ansible.module_utils.network.common.netconf import remove_namespaces
from ansible.module_utils.network.iosxr.iosxr import build_xml, etree_find
from ansible.errors import AnsibleConnectionFailure, AnsibleError
from ansible.errors import AnsibleConnectionFailure
from ansible.plugins.netconf import NetconfBase
from ansible.plugins.netconf import ensure_connected
from ansible.plugins.netconf import ensure_connected, ensure_ncclient

try:
from ncclient import manager
from ncclient.operations import RPCError
from ncclient.transport.errors import SSHUnknownHostError
from ncclient.xml_ import to_ele, to_xml, new_ele
except ImportError:
raise AnsibleError("ncclient is not installed")

try:
from lxml import etree
except ImportError:
raise AnsibleError("lxml is not installed")
from ncclient.xml_ import to_xml
HAS_NCCLIENT = True
except (ImportError, AttributeError): # paramiko and gssapi are incompatible and raise AttributeError not ImportError
HAS_NCCLIENT = False


class Netconf(NetconfBase):

@ensure_connected
def get_device_info(self):
device_info = {}
Expand Down Expand Up @@ -92,6 +86,7 @@ def get_capabilities(self):
return json.dumps(result)

@staticmethod
@ensure_ncclient
def guess_network_os(obj):
"""
Guess the remote network os name
Expand Down Expand Up @@ -123,6 +118,7 @@ def guess_network_os(obj):
return guessed_os

# TODO: change .xml to .data_xml, when ncclient supports data_xml on all platforms
@ensure_ncclient
@ensure_connected
def get(self, filter=None, remove_ns=False):
if isinstance(filter, list):
Expand All @@ -137,6 +133,7 @@ def get(self, filter=None, remove_ns=False):
except RPCError as exc:
raise Exception(to_xml(exc.xml))

@ensure_ncclient
@ensure_connected
def get_config(self, source=None, filter=None, remove_ns=False):
if isinstance(filter, list):
Expand All @@ -151,6 +148,7 @@ def get_config(self, source=None, filter=None, remove_ns=False):
except RPCError as exc:
raise Exception(to_xml(exc.xml))

@ensure_ncclient
@ensure_connected
def edit_config(self, config=None, format='xml', target='candidate', default_operation=None, test_option=None, error_option=None, remove_ns=False):
if config is None:
Expand All @@ -166,6 +164,7 @@ def edit_config(self, config=None, format='xml', target='candidate', default_ope
except RPCError as exc:
raise Exception(to_xml(exc.xml))

@ensure_ncclient
@ensure_connected
def commit(self, confirmed=False, timeout=None, persist=None, remove_ns=False):
try:
Expand All @@ -178,6 +177,7 @@ def commit(self, confirmed=False, timeout=None, persist=None, remove_ns=False):
except RPCError as exc:
raise Exception(to_xml(exc.xml))

@ensure_ncclient
@ensure_connected
def validate(self, source="candidate", remove_ns=False):
try:
Expand All @@ -190,6 +190,7 @@ def validate(self, source="candidate", remove_ns=False):
except RPCError as exc:
raise Exception(to_xml(exc.xml))

@ensure_ncclient
@ensure_connected
def discard_changes(self, remove_ns=False):
try:
Expand Down
17 changes: 10 additions & 7 deletions lib/ansible/plugins/netconf/junos.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,29 @@
import json
import re

from ansible import constants as C
from ansible.module_utils._text import to_text, to_bytes
from ansible.errors import AnsibleConnectionFailure, AnsibleError
from ansible.module_utils._text import to_text
from ansible.errors import AnsibleConnectionFailure
from ansible.plugins.netconf import NetconfBase
from ansible.plugins.netconf import ensure_connected
from ansible.plugins.netconf import ensure_connected, ensure_ncclient

try:
from ncclient import manager
from ncclient.operations import RPCError
from ncclient.transport.errors import SSHUnknownHostError
from ncclient.xml_ import to_ele, to_xml, new_ele, sub_ele
except ImportError:
raise AnsibleError("ncclient is not installed")
HAS_NCCLIENT = True
except (ImportError, AttributeError): # paramiko and gssapi are incompatible and raise AttributeError not ImportError
HAS_NCCLIENT = False


class Netconf(NetconfBase):

def get_text(self, ele, tag):
try:
return to_text(ele.find(tag).text, errors='surrogate_then_replace').strip()
except AttributeError:
pass

@ensure_ncclient
def get_device_info(self):
device_info = dict()
device_info['network_os'] = 'junos'
Expand All @@ -68,6 +68,7 @@ def execute_rpc(self, name):
"""
return self.rpc(name)

@ensure_ncclient
@ensure_connected
def load_configuration(self, format='xml', action='merge', target='candidate', config=None):
"""
Expand Down Expand Up @@ -101,6 +102,7 @@ def get_capabilities(self):
return json.dumps(result)

@staticmethod
@ensure_ncclient
def guess_network_os(obj):
"""
Guess the remote network os name
Expand Down Expand Up @@ -165,6 +167,7 @@ def reboot(self):
# below commit() is a workaround which build's raw `commit-configuration` xml with required tags and uses
# ncclient generic rpc() method to execute rpc on remote host.
# Remove below method after the issue in ncclient is fixed.
@ensure_ncclient
@ensure_connected
def commit(self, confirmed=False, check=False, timeout=None, comment=None, synchronize=False, at_time=None):
"""
Expand Down
22 changes: 9 additions & 13 deletions lib/ansible/plugins/netconf/sros.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,18 @@
import json
import re

from ansible import constants as C
from ansible.module_utils._text import to_text, to_bytes
from ansible.errors import AnsibleConnectionFailure, AnsibleError
from ansible.module_utils._text import to_text
from ansible.errors import AnsibleConnectionFailure
from ansible.plugins.netconf import NetconfBase
from ansible.plugins.netconf import ensure_connected
from ansible.plugins.netconf import ensure_ncclient

try:
from ncclient import manager
from ncclient.operations import RPCError
from ncclient.transport.errors import SSHUnknownHostError
from ncclient.xml_ import to_ele, to_xml, new_ele
except ImportError:
raise AnsibleError("ncclient is not installed")

try:
from lxml import etree
except ImportError:
raise AnsibleError("lxml is not installed")
from ncclient.xml_ import to_ele
HAS_NCCLIENT = True
except (ImportError, AttributeError): # paramiko and gssapi are incompatible and raise AttributeError not ImportError
HAS_NCCLIENT = False


class Netconf(NetconfBase):
Expand All @@ -49,6 +43,7 @@ def get_text(self, ele, tag):
except AttributeError:
pass

@ensure_ncclient
def get_device_info(self):
device_info = dict()
device_info['network_os'] = 'sros'
Expand All @@ -75,6 +70,7 @@ def get_capabilities(self):
return json.dumps(result)

@staticmethod
@ensure_ncclient
def guess_network_os(obj):
try:
m = manager.connect(
Expand Down