junos_config: Remove reliance on ability to output configuration in `set` format (#23225)

* Remove reliance on ability to output configuration in `set` format
* Support multiple warnings per rpc-reply
pull/23270/head
Nathaniel Case 8 years ago committed by GitHub
parent 01e27b1083
commit 597bca3129

@ -147,7 +147,7 @@ def get_diff(module):
if output is not None: if output is not None:
return output.text return output.text
def load_config(module, candidate, action='merge', commit=False, format='xml', def load_config(module, candidate, warnings, action='merge', commit=False, format='xml',
comment=None, confirm=False, confirm_timeout=None): comment=None, confirm=False, confirm_timeout=None):
with locked_config(module): with locked_config(module):
@ -155,6 +155,8 @@ def load_config(module, candidate, action='merge', commit=False, format='xml',
candidate = '\n'.join(candidate) candidate = '\n'.join(candidate)
reply = load_configuration(module, candidate, action=action, format=format) reply = load_configuration(module, candidate, action=action, format=format)
if isinstance(reply, list):
warnings.extend(reply)
validate(module) validate(module)
diff = get_diff(module) diff = get_diff(module)
@ -168,4 +170,3 @@ def load_config(module, candidate, action='merge', commit=False, format='xml',
discard_changes(module) discard_changes(module)
return diff return diff

@ -31,13 +31,31 @@ from xml.etree.ElementTree import tostring, fromstring
from ansible.module_utils.connection import exec_command from ansible.module_utils.connection import exec_command
NS_MAP = {'nc': "urn:ietf:params:xml:ns:netconf:base:1.0"}
def send_request(module, obj, check_rc=True): def send_request(module, obj, check_rc=True):
request = tostring(obj) request = tostring(obj)
rc, out, err = exec_command(module, request) rc, out, err = exec_command(module, request)
if rc != 0: if rc != 0 and check_rc:
if check_rc: error_root = fromstring(err)
fake_parent = Element('root')
fake_parent.append(error_root)
error_list = fake_parent.findall('.//nc:rpc-error', NS_MAP)
if not error_list:
module.fail_json(msg=str(err)) module.fail_json(msg=str(err))
return fromstring(out)
warnings = []
for rpc_error in error_list:
message = rpc_error.find('./nc:error-message', NS_MAP).text
severity = rpc_error.find('./nc:error-severity', NS_MAP).text
if severity == 'warning':
warnings.append(message)
else:
module.fail_json(msg=str(err))
return warnings
return fromstring(out) return fromstring(out)
def children(root, iterable): def children(root, iterable):

@ -157,7 +157,7 @@ def main():
module.fail_json(msg='unable to retrieve device configuration') module.fail_json(msg='unable to retrieve device configuration')
result['__backup__'] = str(match.text).strip() result['__backup__'] = str(match.text).strip()
diff = load_config(module, src, action=action, commit=commit, format=fmt) diff = load_config(module, src, warnings, action=action, commit=commit, format=fmt)
if diff: if diff:
result['changed'] = True result['changed'] = True
if module._diff: if module._diff:

@ -219,12 +219,10 @@ def filter_delete_statements(module, candidate):
reply = get_configuration(module, format='set') reply = get_configuration(module, format='set')
match = reply.find('.//configuration-set') match = reply.find('.//configuration-set')
if match is None: if match is None:
module.fail_json(msg='unable to retrieve device configuration') # Could not find configuration-set in reply, perhaps device does not support it?
return candidate
config = str(match.text) config = str(match.text)
#if 'delete interfaces lo0' in candidate:
# raise ValueError(config)
modified_candidate = candidate[:] modified_candidate = candidate[:]
for index, line in enumerate(candidate): for index, line in enumerate(candidate):
if line.startswith('delete'): if line.startswith('delete'):
@ -234,7 +232,7 @@ def filter_delete_statements(module, candidate):
return modified_candidate return modified_candidate
def configure_device(module): def configure_device(module, warnings):
candidate = module.params['lines'] or module.params['src'] candidate = module.params['lines'] or module.params['src']
if isinstance(candidate, string_types): if isinstance(candidate, string_types):
candidate = candidate.split('\n') candidate = candidate.split('\n')
@ -266,7 +264,7 @@ def configure_device(module):
kwargs['format'] = 'text' kwargs['format'] = 'text'
kwargs['action'] = 'set' kwargs['action'] = 'set'
return load_config(module, candidate, **kwargs) return load_config(module, candidate, warnings, **kwargs)
def main(): def main():
""" main entry point for module execution """ main entry point for module execution
@ -307,10 +305,14 @@ def main():
result = {'changed': False, 'warnings': warnings} result = {'changed': False, 'warnings': warnings}
if module.params['backup']: if module.params['backup']:
reply = get_configuration(module, format='set') for conf_format in ['set', 'text']:
match = reply.find('.//configuration-set') reply = get_configuration(module, format=conf_format)
if match is None: match = reply.find('.//configuration-%s' % conf_format)
if match is not None:
break
else:
module.fail_json(msg='unable to retrieve device configuration') module.fail_json(msg='unable to retrieve device configuration')
result['__backup__'] = str(match.text).strip() result['__backup__'] = str(match.text).strip()
if module.params['rollback']: if module.params['rollback']:
@ -326,7 +328,7 @@ def main():
result['changed'] = True result['changed'] = True
else: else:
diff = configure_device(module) diff = configure_device(module, warnings)
if diff: if diff:
if module._diff: if module._diff:
result['diff'] = {'prepared': diff} result['diff'] = {'prepared': diff}

Loading…
Cancel
Save