From 5fdb39c4d147f5ef2a70353a48af68269c66ab78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claes=20N=C3=A4st=C3=A9n?= Date: Fri, 15 Dec 2017 14:43:07 +0100 Subject: [PATCH] nso_verify for Cisco NSO (#33945) Module for verifying that configuration is as expected in Cisco NSO. --- lib/ansible/modules/network/nso/nso_verify.py | 188 ++++++++++++++++++ .../network/nso/fixtures/device_schema.json | 1 + .../network/nso/fixtures/devices_schema.json | 1 + .../nso/fixtures/verify_violation_data.json | 10 + .../modules/network/nso/test_nso_verify.py | 104 ++++++++++ 5 files changed, 304 insertions(+) create mode 100644 lib/ansible/modules/network/nso/nso_verify.py create mode 100644 test/units/modules/network/nso/fixtures/device_schema.json create mode 100644 test/units/modules/network/nso/fixtures/devices_schema.json create mode 100644 test/units/modules/network/nso/fixtures/verify_violation_data.json create mode 100644 test/units/modules/network/nso/test_nso_verify.py diff --git a/lib/ansible/modules/network/nso/nso_verify.py b/lib/ansible/modules/network/nso/nso_verify.py new file mode 100644 index 00000000000..95a57bffceb --- /dev/null +++ b/lib/ansible/modules/network/nso/nso_verify.py @@ -0,0 +1,188 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2017 Cisco and/or its affiliates. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +# + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +ANSIBLE_METADATA = { + 'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community' +} + +DOCUMENTATION = ''' +--- +module: nso_verify +extends_documentation_fragment: nso +short_description: Verifies Cisco NSO configuration. +description: + - This module provides support for verifying Cisco NSO configuration is in + compliance with specified values. +author: "Claes Nästén (@cnasten)" +options: + data: + description: > + NSO data in format as C(| display json) converted to YAML. List entries can + be annotated with a C(__state) entry. Set to in-sync/deep-in-sync for + services to verify service is in sync with the network. Set to absent in + list entries to ensure they are deleted if they exist in NSO. + required: true +version_added: "2.5" +''' + +EXAMPLES = ''' +- name: Verify interface is up + nso_config: + url: http://localhost:8080/jsonrpc + username: username + password: password + data: + ncs:devices: + device: + - name: ce0 + live-status: + interfaces: + interface: + - name: GigabitEthernet0/12 + - state: Up +''' + +RETURN = ''' +violations: + description: List of value violations + returned: failed + type: complex + sample: + - path: /ncs:devices/device{ce0}/description + expected-value: CE0 example + value: null + contains: + path: + description: Path to the value in violation + returned: always + type: string + expected-value: + description: Expected value of path + returned: always + type: string + value: + description: Current value of path + returned: always + type: string +''' + +from ansible.module_utils.network.nso.nso import connect, verify_version, nso_argument_spec +from ansible.module_utils.network.nso.nso import normalize_value +from ansible.module_utils.network.nso.nso import State, ValueBuilder +from ansible.module_utils.network.nso.nso import ModuleFailException, NsoException +from ansible.module_utils.basic import AnsibleModule + + +class NsoVerify(object): + def __init__(self, client, data): + self._client = client + self._data = data + + def main(self): + violations = [] + + # build list of values from configured data + value_builder = ValueBuilder(self._client) + for key, value in self._data.items(): + value_builder.build('', key, value) + + for expected_value in value_builder.values: + if expected_value.state == State.PRESENT: + violations.append({ + 'path': expected_value.path, + 'expected-value': 'present', + 'value': 'absent' + }) + elif expected_value.state == State.ABSENT: + violations.append({ + 'path': expected_value.path, + 'expected-value': 'absent', + 'value': 'present' + }) + elif expected_value.state == State.SET: + try: + value = self._client.get_value(expected_value.path)['value'] + except NsoException as ex: + if ex.error.get('type', '') == 'data.not_found': + value = None + else: + raise + + # handle different types properly + n_value = normalize_value( + expected_value.value, value, expected_value.path) + if n_value != expected_value.value: + violations.append({ + 'path': expected_value.path, + 'expected-value': expected_value.value, + 'value': n_value + }) + else: + raise ModuleFailException( + 'value state {0} not supported at {1}'.format( + expected_value.state, expected_value.path)) + + return violations + + +def main(): + argument_spec = dict( + data=dict(required=True, type='dict') + ) + argument_spec.update(nso_argument_spec) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True + ) + p = module.params + + client = connect(p) + nso_verify = NsoVerify(client, p['data']) + try: + verify_version(client) + + violations = nso_verify.main() + client.logout() + + num_violations = len(violations) + if num_violations > 0: + msg = '{0} value{1} differ'.format( + num_violations, num_violations > 1 and 's' or '') + module.fail_json(msg=msg, violations=violations) + else: + module.exit_json(changed=False) + + except NsoException as ex: + client.logout() + module.fail_json(msg=ex.message) + except ModuleFailException as ex: + client.logout() + module.fail_json(msg=ex.message) + + +if __name__ == '__main__': + main() diff --git a/test/units/modules/network/nso/fixtures/device_schema.json b/test/units/modules/network/nso/fixtures/device_schema.json new file mode 100644 index 00000000000..d3bd2ac3639 --- /dev/null +++ b/test/units/modules/network/nso/fixtures/device_schema.json @@ -0,0 +1 @@ +{"meta": {"prefix": "ncs", "namespace": "http://tail-f.com/ns/ncs", "types": {"http://tail-f.com/ns/ncs:t85": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t85"}], "leaf_type": [{"name": "string"}]}], "urn:ietf:params:xml:ns:yang:ietf-inet-types:port-number": [{"range": {"value": [["0", "65535"]]}, "name": "urn:ietf:params:xml:ns:yang:ietf-inet-types:port-number"}, {"name": "uint16"}], "http://tail-f.com/ns/ncs:t83": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t83"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:node-name": [{"name": "http://tail-f.com/ns/ncs:node-name"}, {"max-length": {"value": 253}, "min-length": {"value": 1}, "name": "urn:ietf:params:xml:ns:yang:ietf-inet-types:domain-name", "pattern": {"value": "((([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.)*([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.?)|\\."}}, {"name": "string"}], "http://tail-f.com/ns/ncs:t29": [{"range": {"value": [["1", "4294967"]]}, "name": "http://tail-f.com/ns/ncs:t29"}, {"name": "uint32"}], "http://tail-f.com/ns/ncs:t101": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t101"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:t43": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t43"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:t27": [{"range": {"value": [["1", "4294967"]]}, "name": "http://tail-f.com/ns/ncs:t27"}, {"name": "uint32"}], "http://tail-f.com/ns/ncs:t40": [{"name": "http://tail-f.com/ns/ncs:t40", "enumeration": [{"label": "reject"}, {"label": "accept"}]}, {"name": "string"}], "http://tail-f.com/ns/ncs:t47": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t47"}], "leaf_type": [{"name": "string"}]}], "urn:ietf:params:xml:ns:yang:ietf-inet-types:host": [{"union": [[{"name": "urn:ietf:params:xml:ns:yang:ietf-inet-types:ip-address"}, {"name": "ip-address"}], [{"max-length": {"value": 253}, "min-length": {"value": 1}, "name": "urn:ietf:params:xml:ns:yang:ietf-inet-types:domain-name", "pattern": {"value": "((([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.)*([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.?)|\\."}}, {"name": "string"}]]}], "http://tail-f.com/ns/ncs:t45": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t45"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:t49": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t49"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:trace-flag": [{"name": "http://tail-f.com/ns/ncs:trace-flag", "enumeration": [{"info": "Trace is disabled", "label": "false"}, {"info": "Raw, unformatted data", "label": "raw"}, {"info": "Pretty-printed data", "label": "pretty"}]}, {"name": "string"}], "http://tail-f.com/ns/ncs:t28": [{"range": {"value": [["1", "4294967"]]}, "name": "http://tail-f.com/ns/ncs:t28"}, {"name": "uint32"}]}, "keypath": "/ncs:devices/device"}, "data": {"info": {"string": "The list of managed devices"}, "kind": "list", "leafref_groups": [["remote-node"], ["authgroup"], ["device-profile"]], "mandatory": true, "name": "device", "max_elements": "unbounded", "contains_when_statement": true, "qname": "ncs:device", "children": [{"info": {"string": "A string uniquely identifying the managed device"}, "kind": "key", "mandatory": true, "name": "name", "qname": "ncs:name", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "type": {"primitive": true, "name": "string"}}, {"info": {"string": "IP address or host name for the management interface"}, "kind": "leaf", "name": "address", "qname": "ncs:address", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"namespace": "urn:ietf:params:xml:ns:yang:ietf-inet-types", "name": "host"}}, {"info": {"string": "Port for the management interface"}, "kind": "leaf", "name": "port", "qname": "ncs:port", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"namespace": "urn:ietf:params:xml:ns:yang:ietf-inet-types", "name": "port-number"}}, {"info": {"string": "Name of remote node which connects to device"}, "kind": "leaf", "name": "remote-node", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "node-name"}, "qname": "ncs:remote-node", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "leafref_target": "/ncs:cluster/remote-node/name", "is_leafref": true}, {"info": {"string": "SSH connection configuration"}, "kind": "container", "mandatory": true, "name": "ssh", "qname": "ncs:ssh", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Free form textual description"}, "kind": "leaf", "name": "description", "qname": "ncs:description", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"primitive": true, "name": "string"}}, {"info": {"string": "Physical location of devices in the group"}, "kind": "container", "mandatory": true, "name": "location", "qname": "ncs:location", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Authentication credentials for the device"}, "kind": "leaf", "name": "authgroup", "type": {"primitive": true, "name": "string"}, "qname": "ncs:authgroup", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "leafref_target": "/ncs:devices/authgroups/group/name", "is_leafref": true}, {"info": {"string": "Management protocol for the device"}, "kind": "container", "mandatory": true, "name": "device-type", "qname": "ncs:device-type", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"kind": "leaf", "name": "device-profile", "type": {"primitive": true, "name": "string"}, "qname": "ncs:device-profile", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "leafref_target": "/ncs:devices/profiles/profile/name", "is_leafref": true}, {"info": {"string": "Timeout in seconds for new connections"}, "kind": "leaf", "name": "connect-timeout", "qname": "ncs:connect-timeout", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "units": "seconds", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t27"}}, {"info": {"string": "Timeout in seconds used when reading data"}, "kind": "leaf", "name": "read-timeout", "qname": "ncs:read-timeout", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "units": "seconds", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t28"}}, {"info": {"string": "Timeout in seconds used when writing data"}, "kind": "leaf", "name": "write-timeout", "qname": "ncs:write-timeout", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "units": "seconds", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t29"}}, {"info": {"string": "Controls SSH keep alive settings"}, "kind": "container", "mandatory": true, "name": "ssh-keep-alive", "qname": "ncs:ssh-keep-alive", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Trace the southbound communication to devices"}, "kind": "leaf", "name": "trace", "qname": "ncs:trace", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "trace-flag"}}, {"info": {"string": "Control which device capabilities NCS uses"}, "kind": "container", "mandatory": true, "name": "ned-settings", "qname": "ncs:ned-settings", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Control settings for the commit-queue"}, "kind": "container", "mandatory": true, "name": "commit-queue", "qname": "ncs:commit-queue", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Control how sessions to related devices can be pooled."}, "kind": "container", "mandatory": true, "name": "session-pool", "qname": "ncs:session-pool", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Control settings for no-overwrite sync check"}, "kind": "container", "mandatory": true, "name": "no-overwrite", "qname": "ncs:no-overwrite", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Specifies the behaviour of a commit operation involving a\ndevice that is out of sync with NCS. Value accept assumes that\nthe device's sync state is unknown and it is cleared on commit.\nThe default behaviour is to reject such commits."}, "kind": "leaf", "name": "out-of-sync-commit-behaviour", "qname": "ncs:out-of-sync-commit-behaviour", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t40"}}, {"default": "use-lsa", "kind": "choice", "cases": [{"kind": "case", "name": "use-lsa", "children": [{"info": {"string": "Handle the LSA nodes as such. This is the default"}, "kind": "leaf", "name": "use-lsa", "qname": "ncs:use-lsa", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"primitive": true, "name": "empty"}}]}, {"kind": "case", "name": "no-lsa", "children": [{"info": {"string": "Do not handle any of the LSA nodes as such. These nodes\nwill be handled as any other device. This has the same\nresult as adding the commit flag 'no-lsa' to every commit."}, "kind": "leaf", "name": "no-lsa", "qname": "ncs:no-lsa", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"primitive": true, "name": "empty"}}]}], "name": "choice-lsa"}, {"info": {"string": "Show all active settings for the device"}, "kind": "container", "mandatory": true, "name": "active-settings", "qname": "ncs:active-settings", "is_config_false_callpoint": true, "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "Additional protocols for the live-tree (read-only)"}, "kind": "list", "leafref_groups": [["authgroup"]], "min_elements": 0, "name": "live-status-protocol", "max_elements": "unbounded", "qname": "ncs:live-status-protocol", "children": [{"kind": "key", "mandatory": true, "name": "name", "qname": "ncs:name", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "type": {"primitive": true, "name": "string"}}, {"info": {"string": "IP Address for the management interface"}, "kind": "leaf", "name": "address", "qname": "ncs:address", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"namespace": "urn:ietf:params:xml:ns:yang:ietf-inet-types", "name": "host"}}, {"info": {"string": "Port for the management interface"}, "kind": "leaf", "name": "port", "qname": "ncs:port", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"namespace": "urn:ietf:params:xml:ns:yang:ietf-inet-types", "name": "port-number"}}, {"info": {"string": "SSH host key configuration"}, "kind": "container", "name": "ssh", "presence": true, "qname": "ncs:ssh", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}}, {"info": {"string": "Authentication credentials for the device"}, "kind": "leaf", "name": "authgroup", "type": {"primitive": true, "name": "string"}, "qname": "ncs:authgroup", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "leafref_target": "/ncs:devices/authgroups/group/name", "is_leafref": true}, {"info": {"string": "Management protocol for the device"}, "kind": "container", "mandatory": true, "name": "device-type", "qname": "ncs:device-type", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Operational State for the live protocol"}, "kind": "container", "mandatory": true, "name": "state", "qname": "ncs:state", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "List of capabillities supported by the device"}, "kind": "list", "min_elements": 0, "name": "capability", "max_elements": "unbounded", "qname": "ncs:capability", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "key": ["uri"], "mandatory": true, "config": false, "children": [{"info": {"string": "Capability URI"}, "kind": "key", "mandatory": true, "name": "uri", "type": {"primitive": true, "name": "string"}, "qname": "ncs:uri", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "Capability revision"}, "kind": "leaf", "name": "revision", "type": {"primitive": true, "name": "string"}, "qname": "ncs:revision", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "config": false}, {"info": {"string": "Capability module"}, "kind": "leaf", "name": "module", "type": {"primitive": true, "name": "string"}, "qname": "ncs:module", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "config": false}, {"info": {"string": "Capability features"}, "kind": "leaf-list", "name": "feature", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t83"}, "qname": "ncs:feature", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "config": false}, {"info": {"string": "Capability deviations"}, "kind": "leaf-list", "name": "deviation", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t85"}, "qname": "ncs:deviation", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "config": false}]}], "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "key": ["name"], "mandatory": true, "leafrefGroups": [["authgroup"]]}, {"info": {"string": "Show states for the device"}, "kind": "container", "mandatory": true, "name": "state", "qname": "ncs:state", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "How the device was added to NCS"}, "kind": "container", "mandatory": true, "name": "source", "qname": "ncs:source", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "A list of capabilities supported by the device"}, "kind": "list", "min_elements": 0, "name": "capability", "max_elements": "unbounded", "qname": "ncs:capability", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "key": ["uri"], "mandatory": true, "config": false, "children": [{"kind": "key", "mandatory": true, "name": "uri", "type": {"primitive": true, "name": "string"}, "qname": "ncs:uri", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"kind": "leaf", "name": "revision", "config": false, "qname": "ncs:revision", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "type": {"primitive": true, "name": "string"}}, {"kind": "leaf", "name": "module", "config": false, "qname": "ncs:module", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "type": {"primitive": true, "name": "string"}}, {"kind": "leaf-list", "name": "feature", "config": false, "qname": "ncs:feature", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t43"}}, {"kind": "leaf-list", "name": "deviation", "config": false, "qname": "ncs:deviation", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t45"}}, {"info": {"string": "This action removes a capability from the list of capabilities.\nIf leaf module is set then corresponding module is attempted to\nbe removed from the list of modules for this device. This action\nis only intended to be used for pre-provisioning: it is not\npossible to override capabilities and modules provided by the\nNED implementation using this action."}, "kind": "action", "mandatory": true, "name": "remove", "qname": "ncs:remove", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}]}, {"info": {"string": "This is a list of the YANG modules supported by the device.\n\nThis list is populated the first time NCS connects to the\ndevice."}, "kind": "list", "min_elements": 0, "name": "module", "max_elements": "unbounded", "qname": "ncs:module", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "key": ["name"], "mandatory": true, "config": false, "children": [{"kind": "key", "mandatory": true, "name": "name", "type": {"primitive": true, "name": "string"}, "qname": "ncs:name", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"kind": "leaf", "name": "revision", "config": false, "qname": "ncs:revision", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "type": {"primitive": true, "name": "string"}}, {"kind": "leaf-list", "name": "feature", "config": false, "qname": "ncs:feature", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t47"}}, {"kind": "leaf-list", "name": "deviation", "config": false, "qname": "ncs:deviation", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t49"}}]}, {"info": {"string": "Contains vendor-specific information for\nidentifying the system platform.\n\nNEDs MAY augment this container with more device-specific\nnodes."}, "kind": "container", "mandatory": true, "name": "platform", "qname": "ncs:platform", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "NCS copy of the device configuration"}, "kind": "container", "mandatory": true, "name": "config", "qname": "ncs:config", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Status data fetched from the device"}, "kind": "container", "mandatory": true, "name": "live-status", "qname": "ncs:live-status", "is_config_false_callpoint": true, "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "RPCs from the device"}, "kind": "container", "mandatory": true, "name": "rpc", "qname": "ncs:rpc", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "NETCONF notifications from the device"}, "kind": "container", "mandatory": true, "name": "netconf-notifications", "qname": "ncs:netconf-notifications", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Show services that use this device"}, "kind": "leaf-list", "name": "service-list", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t101"}, "qname": "ncs:service-list", "is_config_false_callpoint": true, "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "config": false}, {"info": {"string": "Notification address if different from device address"}, "kind": "leaf", "name": "snmp-notification-address", "qname": "ncs:snmp-notification-address", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"namespace": "urn:ietf:params:xml:ns:yang:ietf-inet-types", "name": "host"}}, {"info": {"string": "Device specific information"}, "kind": "container", "name": "platform", "presence": true, "when_targets": ["/ncs:devices/device/device-type/cli/ned-id"], "qname": "alu-meta:platform", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}}, {"info": {"string": "A summary of all active alarms per device."}, "kind": "container", "mandatory": true, "name": "alarm-summary", "qname": "al:alarm-summary", "is_config_false_callpoint": true, "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "Note: this action overwrites existing list of capabilities.\n\nThis action copies the list of capabilities and the list of modules\nfrom another device or profile. When used on a device, this action\nis only intended to be used for pre-provisioning: it is not possible\nto override capabilities and modules provided by the\nNED implementation using this action."}, "kind": "action", "mandatory": true, "name": "copy-capabilities", "qname": "ncs:copy-capabilities", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Note: this action overwrites existing list of capabilities.\n\nThis action populates the list of capabilities based on the\nconfigured ned-id for this device, if possible. NCS will look up\nthe package corresponding to the ned-id and add all the modules\nfrom this packages to the list of this device's capabilities and\nlist of modules. It is the responsibility of the caller to verify\nthat the automatically populated list of capabilities matches actual\ndevice's capabilities. The list of capabilities can then be\nfine-tuned using add-capability and capability/remove actions.\nCurrently this approach will only work for CLI and generic devices.\nThis action is only intended to be used for pre-provisioning:\nit is not possible to override capabilities and modules provided\nby the NED implementation using this action."}, "kind": "action", "mandatory": true, "name": "find-capabilities", "qname": "ncs:find-capabilities", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "This action adds a capability to the list of capabilities.\nIf uri is specified, then it is parsed as YANG capability string\nand module, revision, feature and deviation parameters are derived\nfrom the string. If module is specified, then the namespace is\nlooked up in the list of loaded namespaces and capability string\nconstructed automatically. If the module is specified and the\nattempt to look it up failed, then the action does nothing.\nIf module is specified or can be derived from capability string,\nthen the module is also added/replaced in the list of modules. This\naction is only intended to be used for pre-provisioning: it is not\npossible to override capabilities and modules provided by the NED\nimplementation using this action."}, "kind": "action", "mandatory": true, "name": "add-capability", "qname": "ncs:add-capability", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Take a named template and copy it here"}, "kind": "action", "mandatory": true, "name": "apply-template", "leafrefGroups": [["template-name"]], "qname": "ncs:apply-template", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}, "leafref_groups": [["template-name"]]}, {"info": {"string": "Instantiate the config for the device from existing device"}, "kind": "action", "mandatory": true, "name": "instantiate-from-other-device", "leafrefGroups": [["device-name"]], "qname": "ncs:instantiate-from-other-device", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}, "leafref_groups": [["device-name"]]}, {"info": {"string": "Compare the actual device config with the NCS copy"}, "kind": "action", "mandatory": true, "name": "compare-config", "qname": "ncs:compare-config", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Synchronize the config by pulling from the device"}, "kind": "action", "mandatory": true, "name": "sync-from", "qname": "ncs:sync-from", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Synchronize the config by pushing to the device"}, "kind": "action", "mandatory": true, "name": "sync-to", "qname": "ncs:sync-to", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Check if the NCS config is in sync with the device"}, "kind": "action", "mandatory": true, "name": "check-sync", "qname": "ncs:check-sync", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Check if NCS and the device have compatible YANG modules"}, "kind": "action", "mandatory": true, "name": "check-yang-modules", "qname": "ncs:check-yang-modules", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Connect to the device"}, "kind": "action", "mandatory": true, "name": "connect", "qname": "ncs:connect", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Close all sessions to the device"}, "kind": "action", "mandatory": true, "name": "disconnect", "qname": "ncs:disconnect", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "ICMP ping the device"}, "kind": "action", "mandatory": true, "name": "ping", "qname": "ncs:ping", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Delete the config in NCS without deleting it in the device"}, "kind": "action", "mandatory": true, "name": "delete-config", "qname": "ncs:delete-config", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Secure copy file to the device"}, "kind": "action", "mandatory": true, "name": "scp-to", "qname": "ncs:scp-to", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Secure copy file to the device"}, "kind": "action", "mandatory": true, "name": "scp-from", "qname": "ncs:scp-from", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}], "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "key": ["name"], "min_elements": 0, "leafrefGroups": [["remote-node"], ["authgroup"], ["device-profile"]]}} diff --git a/test/units/modules/network/nso/fixtures/devices_schema.json b/test/units/modules/network/nso/fixtures/devices_schema.json new file mode 100644 index 00000000000..541ba01067a --- /dev/null +++ b/test/units/modules/network/nso/fixtures/devices_schema.json @@ -0,0 +1 @@ +{"meta": {"prefix": "ncs", "namespace": "http://tail-f.com/ns/ncs", "types": {"http://tail-f.com/ns/ncs:t68": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t68"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:t85": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t85"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:t83": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t83"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:t60": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t60"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:t101": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t101"}], "leaf_type": [{"name": "string"}]}], "urn:ietf:params:xml:ns:yang:ietf-inet-types:host": [{"union": [[{"name": "urn:ietf:params:xml:ns:yang:ietf-inet-types:ip-address"}, {"name": "ip-address"}], [{"max-length": {"value": 253}, "min-length": {"value": 1}, "name": "urn:ietf:params:xml:ns:yang:ietf-inet-types:domain-name", "pattern": {"value": "((([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.)*([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.?)|\\."}}, {"name": "string"}]]}], "http://tail-f.com/ns/ncs:trace-flag": [{"name": "http://tail-f.com/ns/ncs:trace-flag", "enumeration": [{"info": "Trace is disabled", "label": "false"}, {"info": "Raw, unformatted data", "label": "raw"}, {"info": "Pretty-printed data", "label": "pretty"}]}, {"name": "string"}], "http://tail-f.com/ns/ncs:t43": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t43"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:t27": [{"range": {"value": [["1", "4294967"]]}, "name": "http://tail-f.com/ns/ncs:t27"}, {"name": "uint32"}], "http://tail-f.com/ns/ncs:t40": [{"name": "http://tail-f.com/ns/ncs:t40", "enumeration": [{"label": "reject"}, {"label": "accept"}]}, {"name": "string"}], "http://tail-f.com/ns/ncs:t47": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t47"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:t45": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t45"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:t49": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t49"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:t29": [{"range": {"value": [["1", "4294967"]]}, "name": "http://tail-f.com/ns/ncs:t29"}, {"name": "uint32"}], "http://tail-f.com/ns/ncs:t28": [{"range": {"value": [["1", "4294967"]]}, "name": "http://tail-f.com/ns/ncs:t28"}, {"name": "uint32"}], "http://tail-f.com/ns/ncs:node-name": [{"name": "http://tail-f.com/ns/ncs:node-name"}, {"max-length": {"value": 253}, "min-length": {"value": 1}, "name": "urn:ietf:params:xml:ns:yang:ietf-inet-types:domain-name", "pattern": {"value": "((([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.)*([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.?)|\\."}}, {"name": "string"}], "http://tail-f.com/ns/ncs:t74": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t74"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:t72": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t72"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:t70": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t70"}], "leaf_type": [{"name": "string"}]}], "urn:ietf:params:xml:ns:yang:ietf-inet-types:port-number": [{"range": {"value": [["0", "65535"]]}, "name": "urn:ietf:params:xml:ns:yang:ietf-inet-types:port-number"}, {"name": "uint16"}], "http://tail-f.com/ns/ncs:t56": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t56"}], "leaf_type": [{"name": "string"}]}], "http://tail-f.com/ns/ncs:t58": [{"list_type": [{"leaf-list": true, "name": "http://tail-f.com/ns/ncs:t58"}], "leaf_type": [{"name": "string"}]}]}, "keypath": "/ncs:devices"}, "data": {"info": {"string": "The managed devices and device communication settings"}, "kind": "container", "mandatory": true, "name": "devices", "contains_when_statement": true, "qname": "ncs:devices", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "children": [{"info": {"string": "Global settings for all managed devices."}, "kind": "container", "mandatory": true, "name": "global-settings", "qname": "ncs:global-settings", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Device profile parameters"}, "kind": "container", "mandatory": true, "name": "profiles", "qname": "ncs:profiles", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Authentication for managed devices"}, "kind": "container", "mandatory": true, "name": "authgroups", "qname": "ncs:authgroups", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Named configuration templates for devices"}, "kind": "list", "min_elements": 0, "name": "template", "max_elements": "unbounded", "qname": "ncs:template", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "key": ["name"], "mandatory": true, "children": [{"info": {"string": "The name of a specific template configuration."}, "kind": "key", "mandatory": true, "name": "name", "qname": "ncs:name", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "type": {"primitive": true, "name": "string"}}, {"info": {"string": "This container is augmented with data models from the devices."}, "kind": "container", "mandatory": true, "name": "config", "qname": "ncs:config", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}]}, {"info": {"string": "Groups of devices"}, "kind": "list", "leafref_groups": [["device-name"], ["device-group"], ["member"]], "min_elements": 0, "name": "device-group", "max_elements": "unbounded", "qname": "ncs:device-group", "children": [{"kind": "key", "mandatory": true, "name": "name", "qname": "ncs:name", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "type": {"primitive": true, "name": "string"}}, {"info": {"string": "Physical location of devices in the group"}, "kind": "container", "mandatory": true, "name": "location", "qname": "ncs:location", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Device within group"}, "kind": "leaf-list", "name": "device-name", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t56"}, "qname": "ncs:device-name", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "leafref_target": "/ncs:devices/device/name", "is_leafref": true}, {"info": {"string": "Group within group"}, "kind": "leaf-list", "name": "device-group", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t58"}, "qname": "ncs:device-group", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "leafref_target": "/ncs:devices/device-group/name", "is_leafref": true}, {"info": {"string": "Flattened list of all members"}, "kind": "leaf-list", "name": "member", "is_leafref": true, "qname": "ncs:member", "is_config_false_callpoint": true, "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "leafref_target": "/ncs:devices/device/name", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t60"}, "config": false}, {"info": {"string": "RPCs from the device's"}, "kind": "container", "mandatory": true, "name": "rpc", "qname": "ncs:rpc", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "A summary of all active alarms per device group."}, "kind": "container", "mandatory": true, "name": "alarm-summary", "qname": "al:alarm-summary", "is_config_false_callpoint": true, "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "Set up sessions to all unlocked devices"}, "kind": "action", "mandatory": true, "name": "connect", "qname": "ncs:connect", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Synchronize the config by pushing to the devices"}, "kind": "action", "mandatory": true, "name": "sync-to", "qname": "ncs:sync-to", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Synchronize the config by pulling from the devices"}, "kind": "action", "mandatory": true, "name": "sync-from", "qname": "ncs:sync-from", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Check if the NCS config is in sync with the device"}, "kind": "action", "mandatory": true, "name": "check-sync", "qname": "ncs:check-sync", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Check if NCS and the devices have compatible YANG modules"}, "kind": "action", "mandatory": true, "name": "check-yang-modules", "qname": "ncs:check-yang-modules", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Retrieve SSH host keys from all devices"}, "kind": "action", "mandatory": true, "name": "fetch-ssh-host-keys", "qname": "ncs:fetch-ssh-host-keys", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Take a named template and copy it here"}, "kind": "action", "mandatory": true, "name": "apply-template", "leafrefGroups": [["template-name"]], "qname": "ncs:apply-template", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}, "leafref_groups": [["template-name"]]}], "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "key": ["name"], "mandatory": true, "leafrefGroups": [["device-name"], ["device-group"], ["member"]]}, {"info": {"string": "A list of named groups of MIBs"}, "kind": "list", "leafref_groups": [["mib-group"]], "min_elements": 0, "name": "mib-group", "max_elements": "unbounded", "qname": "ncs:mib-group", "children": [{"info": {"string": "An arbitrary name of the MIB group."}, "kind": "key", "mandatory": true, "name": "name", "qname": "ncs:name", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "type": {"primitive": true, "name": "string"}}, {"info": {"string": "MIB module names or name prefixes"}, "kind": "leaf-list", "name": "mib-module", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t68"}, "qname": "ncs:mib-module", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "leafref_target": "/ncs:devices/device-module/mib-module", "is_leafref": true}, {"info": {"string": "A list of MIB groups contained in this MIB group"}, "kind": "leaf-list", "name": "mib-group", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t70"}, "qname": "ncs:mib-group", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "leafref_target": "/ncs:devices/mib-group/name", "is_leafref": true}], "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "key": ["name"], "mandatory": true, "leafrefGroups": [["mib-group"]]}, {"info": {"string": "List the devices and supported modules"}, "kind": "list", "min_elements": 0, "name": "device-module", "max_elements": "unbounded", "qname": "ncs:device-module", "is_config_false_callpoint": true, "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "key": ["name"], "mandatory": true, "config": false, "children": [{"info": {"string": "The module name"}, "kind": "key", "mandatory": true, "name": "name", "type": {"primitive": true, "name": "string"}, "qname": "ncs:name", "is_config_false_callpoint": true, "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "The module revision"}, "kind": "leaf-list", "name": "revision", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t72"}, "qname": "ncs:revision", "is_config_false_callpoint": true, "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "config": false}, {"info": {"string": "The XML namespace uri for the module"}, "kind": "leaf", "name": "uri", "type": {"primitive": true, "name": "string"}, "qname": "ncs:uri", "is_config_false_callpoint": true, "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "config": false}, {"info": {"string": "The names of the devices that support this module"}, "kind": "leaf-list", "name": "devices", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t74"}, "qname": "ncs:devices", "is_config_false_callpoint": true, "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "config": false}]}, {"info": {"string": "The list of managed devices"}, "kind": "list", "leafref_groups": [["remote-node"], ["authgroup"], ["device-profile"]], "min_elements": 0, "name": "device", "max_elements": "unbounded", "qname": "ncs:device", "children": [{"info": {"string": "A string uniquely identifying the managed device"}, "kind": "key", "mandatory": true, "name": "name", "qname": "ncs:name", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "type": {"primitive": true, "name": "string"}}, {"info": {"string": "IP address or host name for the management interface"}, "kind": "leaf", "name": "address", "qname": "ncs:address", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"namespace": "urn:ietf:params:xml:ns:yang:ietf-inet-types", "name": "host"}}, {"info": {"string": "Port for the management interface"}, "kind": "leaf", "name": "port", "qname": "ncs:port", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"namespace": "urn:ietf:params:xml:ns:yang:ietf-inet-types", "name": "port-number"}}, {"info": {"string": "Name of remote node which connects to device"}, "kind": "leaf", "name": "remote-node", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "node-name"}, "qname": "ncs:remote-node", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "leafref_target": "/ncs:cluster/remote-node/name", "is_leafref": true}, {"info": {"string": "SSH connection configuration"}, "kind": "container", "mandatory": true, "name": "ssh", "qname": "ncs:ssh", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Free form textual description"}, "kind": "leaf", "name": "description", "qname": "ncs:description", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"primitive": true, "name": "string"}}, {"info": {"string": "Physical location of devices in the group"}, "kind": "container", "mandatory": true, "name": "location", "qname": "ncs:location", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Authentication credentials for the device"}, "kind": "leaf", "name": "authgroup", "type": {"primitive": true, "name": "string"}, "qname": "ncs:authgroup", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "leafref_target": "/ncs:devices/authgroups/group/name", "is_leafref": true}, {"info": {"string": "Management protocol for the device"}, "kind": "container", "mandatory": true, "name": "device-type", "qname": "ncs:device-type", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"kind": "leaf", "name": "device-profile", "type": {"primitive": true, "name": "string"}, "qname": "ncs:device-profile", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "leafref_target": "/ncs:devices/profiles/profile/name", "is_leafref": true}, {"info": {"string": "Timeout in seconds for new connections"}, "kind": "leaf", "name": "connect-timeout", "qname": "ncs:connect-timeout", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "units": "seconds", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t27"}}, {"info": {"string": "Timeout in seconds used when reading data"}, "kind": "leaf", "name": "read-timeout", "qname": "ncs:read-timeout", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "units": "seconds", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t28"}}, {"info": {"string": "Timeout in seconds used when writing data"}, "kind": "leaf", "name": "write-timeout", "qname": "ncs:write-timeout", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "units": "seconds", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t29"}}, {"info": {"string": "Controls SSH keep alive settings"}, "kind": "container", "mandatory": true, "name": "ssh-keep-alive", "qname": "ncs:ssh-keep-alive", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Trace the southbound communication to devices"}, "kind": "leaf", "name": "trace", "qname": "ncs:trace", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "trace-flag"}}, {"info": {"string": "Control which device capabilities NCS uses"}, "kind": "container", "mandatory": true, "name": "ned-settings", "qname": "ncs:ned-settings", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Control settings for the commit-queue"}, "kind": "container", "mandatory": true, "name": "commit-queue", "qname": "ncs:commit-queue", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Control how sessions to related devices can be pooled."}, "kind": "container", "mandatory": true, "name": "session-pool", "qname": "ncs:session-pool", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Control settings for no-overwrite sync check"}, "kind": "container", "mandatory": true, "name": "no-overwrite", "qname": "ncs:no-overwrite", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Specifies the behaviour of a commit operation involving a\ndevice that is out of sync with NCS. Value accept assumes that\nthe device's sync state is unknown and it is cleared on commit.\nThe default behaviour is to reject such commits."}, "kind": "leaf", "name": "out-of-sync-commit-behaviour", "qname": "ncs:out-of-sync-commit-behaviour", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t40"}}, {"default": "use-lsa", "kind": "choice", "cases": [{"kind": "case", "name": "use-lsa", "children": [{"info": {"string": "Handle the LSA nodes as such. This is the default"}, "kind": "leaf", "name": "use-lsa", "qname": "ncs:use-lsa", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"primitive": true, "name": "empty"}}]}, {"kind": "case", "name": "no-lsa", "children": [{"info": {"string": "Do not handle any of the LSA nodes as such. These nodes\nwill be handled as any other device. This has the same\nresult as adding the commit flag 'no-lsa' to every commit."}, "kind": "leaf", "name": "no-lsa", "qname": "ncs:no-lsa", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"primitive": true, "name": "empty"}}]}], "name": "choice-lsa"}, {"info": {"string": "Show all active settings for the device"}, "kind": "container", "mandatory": true, "name": "active-settings", "qname": "ncs:active-settings", "is_config_false_callpoint": true, "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "Additional protocols for the live-tree (read-only)"}, "kind": "list", "leafref_groups": [["authgroup"]], "min_elements": 0, "name": "live-status-protocol", "max_elements": "unbounded", "qname": "ncs:live-status-protocol", "children": [{"kind": "key", "mandatory": true, "name": "name", "qname": "ncs:name", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "type": {"primitive": true, "name": "string"}}, {"info": {"string": "IP Address for the management interface"}, "kind": "leaf", "name": "address", "qname": "ncs:address", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"namespace": "urn:ietf:params:xml:ns:yang:ietf-inet-types", "name": "host"}}, {"info": {"string": "Port for the management interface"}, "kind": "leaf", "name": "port", "qname": "ncs:port", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"namespace": "urn:ietf:params:xml:ns:yang:ietf-inet-types", "name": "port-number"}}, {"info": {"string": "SSH host key configuration"}, "kind": "container", "name": "ssh", "presence": true, "qname": "ncs:ssh", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}}, {"info": {"string": "Authentication credentials for the device"}, "kind": "leaf", "name": "authgroup", "type": {"primitive": true, "name": "string"}, "qname": "ncs:authgroup", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "leafref_target": "/ncs:devices/authgroups/group/name", "is_leafref": true}, {"info": {"string": "Management protocol for the device"}, "kind": "container", "mandatory": true, "name": "device-type", "qname": "ncs:device-type", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Operational State for the live protocol"}, "kind": "container", "mandatory": true, "name": "state", "qname": "ncs:state", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "List of capabillities supported by the device"}, "kind": "list", "min_elements": 0, "name": "capability", "max_elements": "unbounded", "qname": "ncs:capability", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "key": ["uri"], "mandatory": true, "config": false, "children": [{"info": {"string": "Capability URI"}, "kind": "key", "mandatory": true, "name": "uri", "type": {"primitive": true, "name": "string"}, "qname": "ncs:uri", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "Capability revision"}, "kind": "leaf", "name": "revision", "type": {"primitive": true, "name": "string"}, "qname": "ncs:revision", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "config": false}, {"info": {"string": "Capability module"}, "kind": "leaf", "name": "module", "type": {"primitive": true, "name": "string"}, "qname": "ncs:module", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "config": false}, {"info": {"string": "Capability features"}, "kind": "leaf-list", "name": "feature", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t83"}, "qname": "ncs:feature", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "config": false}, {"info": {"string": "Capability deviations"}, "kind": "leaf-list", "name": "deviation", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t85"}, "qname": "ncs:deviation", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "config": false}]}], "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "key": ["name"], "mandatory": true, "leafrefGroups": [["authgroup"]]}, {"info": {"string": "Show states for the device"}, "kind": "container", "mandatory": true, "name": "state", "qname": "ncs:state", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "How the device was added to NCS"}, "kind": "container", "mandatory": true, "name": "source", "qname": "ncs:source", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "A list of capabilities supported by the device"}, "kind": "list", "min_elements": 0, "name": "capability", "max_elements": "unbounded", "qname": "ncs:capability", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "key": ["uri"], "mandatory": true, "config": false, "children": [{"kind": "key", "mandatory": true, "name": "uri", "type": {"primitive": true, "name": "string"}, "qname": "ncs:uri", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"kind": "leaf", "name": "revision", "config": false, "qname": "ncs:revision", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "type": {"primitive": true, "name": "string"}}, {"kind": "leaf", "name": "module", "config": false, "qname": "ncs:module", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "type": {"primitive": true, "name": "string"}}, {"kind": "leaf-list", "name": "feature", "config": false, "qname": "ncs:feature", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t43"}}, {"kind": "leaf-list", "name": "deviation", "config": false, "qname": "ncs:deviation", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t45"}}, {"info": {"string": "This action removes a capability from the list of capabilities.\nIf leaf module is set then corresponding module is attempted to\nbe removed from the list of modules for this device. This action\nis only intended to be used for pre-provisioning: it is not\npossible to override capabilities and modules provided by the\nNED implementation using this action."}, "kind": "action", "mandatory": true, "name": "remove", "qname": "ncs:remove", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}]}, {"info": {"string": "This is a list of the YANG modules supported by the device.\n\nThis list is populated the first time NCS connects to the\ndevice."}, "kind": "list", "min_elements": 0, "name": "module", "max_elements": "unbounded", "qname": "ncs:module", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "key": ["name"], "mandatory": true, "config": false, "children": [{"kind": "key", "mandatory": true, "name": "name", "type": {"primitive": true, "name": "string"}, "qname": "ncs:name", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"kind": "leaf", "name": "revision", "config": false, "qname": "ncs:revision", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "type": {"primitive": true, "name": "string"}}, {"kind": "leaf-list", "name": "feature", "config": false, "qname": "ncs:feature", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t47"}}, {"kind": "leaf-list", "name": "deviation", "config": false, "qname": "ncs:deviation", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t49"}}]}, {"info": {"string": "Contains vendor-specific information for\nidentifying the system platform.\n\nNEDs MAY augment this container with more device-specific\nnodes."}, "kind": "container", "mandatory": true, "name": "platform", "qname": "ncs:platform", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "NCS copy of the device configuration"}, "kind": "container", "mandatory": true, "name": "config", "qname": "ncs:config", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Status data fetched from the device"}, "kind": "container", "mandatory": true, "name": "live-status", "qname": "ncs:live-status", "is_config_false_callpoint": true, "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "RPCs from the device"}, "kind": "container", "mandatory": true, "name": "rpc", "qname": "ncs:rpc", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "NETCONF notifications from the device"}, "kind": "container", "mandatory": true, "name": "netconf-notifications", "qname": "ncs:netconf-notifications", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}}, {"info": {"string": "Show services that use this device"}, "kind": "leaf-list", "name": "service-list", "type": {"namespace": "http://tail-f.com/ns/ncs", "name": "t101"}, "qname": "ncs:service-list", "is_config_false_callpoint": true, "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "readonly": true, "config": false}, {"info": {"string": "Notification address if different from device address"}, "kind": "leaf", "name": "snmp-notification-address", "qname": "ncs:snmp-notification-address", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "type": {"namespace": "urn:ietf:params:xml:ns:yang:ietf-inet-types", "name": "host"}}, {"info": {"string": "Device specific information"}, "kind": "container", "name": "platform", "presence": true, "when_targets": ["/ncs:devices/device/device-type/cli/ned-id"], "qname": "alu-meta:platform", "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}}, {"info": {"string": "A summary of all active alarms per device."}, "kind": "container", "mandatory": true, "name": "alarm-summary", "qname": "al:alarm-summary", "is_config_false_callpoint": true, "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "Note: this action overwrites existing list of capabilities.\n\nThis action copies the list of capabilities and the list of modules\nfrom another device or profile. When used on a device, this action\nis only intended to be used for pre-provisioning: it is not possible\nto override capabilities and modules provided by the\nNED implementation using this action."}, "kind": "action", "mandatory": true, "name": "copy-capabilities", "qname": "ncs:copy-capabilities", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Note: this action overwrites existing list of capabilities.\n\nThis action populates the list of capabilities based on the\nconfigured ned-id for this device, if possible. NCS will look up\nthe package corresponding to the ned-id and add all the modules\nfrom this packages to the list of this device's capabilities and\nlist of modules. It is the responsibility of the caller to verify\nthat the automatically populated list of capabilities matches actual\ndevice's capabilities. The list of capabilities can then be\nfine-tuned using add-capability and capability/remove actions.\nCurrently this approach will only work for CLI and generic devices.\nThis action is only intended to be used for pre-provisioning:\nit is not possible to override capabilities and modules provided\nby the NED implementation using this action."}, "kind": "action", "mandatory": true, "name": "find-capabilities", "qname": "ncs:find-capabilities", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "This action adds a capability to the list of capabilities.\nIf uri is specified, then it is parsed as YANG capability string\nand module, revision, feature and deviation parameters are derived\nfrom the string. If module is specified, then the namespace is\nlooked up in the list of loaded namespaces and capability string\nconstructed automatically. If the module is specified and the\nattempt to look it up failed, then the action does nothing.\nIf module is specified or can be derived from capability string,\nthen the module is also added/replaced in the list of modules. This\naction is only intended to be used for pre-provisioning: it is not\npossible to override capabilities and modules provided by the NED\nimplementation using this action."}, "kind": "action", "mandatory": true, "name": "add-capability", "qname": "ncs:add-capability", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Take a named template and copy it here"}, "kind": "action", "mandatory": true, "name": "apply-template", "leafrefGroups": [["template-name"]], "qname": "ncs:apply-template", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}, "leafref_groups": [["template-name"]]}, {"info": {"string": "Instantiate the config for the device from existing device"}, "kind": "action", "mandatory": true, "name": "instantiate-from-other-device", "leafrefGroups": [["device-name"]], "qname": "ncs:instantiate-from-other-device", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}, "leafref_groups": [["device-name"]]}, {"info": {"string": "Compare the actual device config with the NCS copy"}, "kind": "action", "mandatory": true, "name": "compare-config", "qname": "ncs:compare-config", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Synchronize the config by pulling from the device"}, "kind": "action", "mandatory": true, "name": "sync-from", "qname": "ncs:sync-from", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Synchronize the config by pushing to the device"}, "kind": "action", "mandatory": true, "name": "sync-to", "qname": "ncs:sync-to", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Check if the NCS config is in sync with the device"}, "kind": "action", "mandatory": true, "name": "check-sync", "qname": "ncs:check-sync", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Check if NCS and the device have compatible YANG modules"}, "kind": "action", "mandatory": true, "name": "check-yang-modules", "qname": "ncs:check-yang-modules", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Connect to the device"}, "kind": "action", "mandatory": true, "name": "connect", "qname": "ncs:connect", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Close all sessions to the device"}, "kind": "action", "mandatory": true, "name": "disconnect", "qname": "ncs:disconnect", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "ICMP ping the device"}, "kind": "action", "mandatory": true, "name": "ping", "qname": "ncs:ping", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Delete the config in NCS without deleting it in the device"}, "kind": "action", "mandatory": true, "name": "delete-config", "qname": "ncs:delete-config", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Secure copy file to the device"}, "kind": "action", "mandatory": true, "name": "scp-to", "qname": "ncs:scp-to", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Secure copy file to the device"}, "kind": "action", "mandatory": true, "name": "scp-from", "qname": "ncs:scp-from", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}], "access": {"read": true, "create": true, "execute": false, "update": true, "delete": true}, "key": ["name"], "mandatory": true, "leafrefGroups": [["remote-node"], ["authgroup"], ["device-profile"]]}, {"info": {"string": "List of queued and completed commits"}, "kind": "container", "mandatory": true, "name": "commit-queue", "qname": "ncs:commit-queue", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "List of pooled NED sessions"}, "kind": "container", "mandatory": true, "name": "session-pool", "qname": "ncs:session-pool", "access": {"read": true, "create": false, "execute": false, "update": true, "delete": false}, "readonly": true, "config": false}, {"info": {"string": "Set up sessions to all unlocked devices"}, "kind": "action", "mandatory": true, "name": "connect", "leafrefGroups": [["device"]], "qname": "ncs:connect", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}, "leafref_groups": [["device"]]}, {"info": {"string": "Synchronize the config by pushing to the devices"}, "kind": "action", "mandatory": true, "name": "sync-to", "leafrefGroups": [["device"]], "qname": "ncs:sync-to", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}, "leafref_groups": [["device"]]}, {"info": {"string": "Synchronize the config by pulling from the devices"}, "kind": "action", "mandatory": true, "name": "sync-from", "leafrefGroups": [["device"]], "qname": "ncs:sync-from", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}, "leafref_groups": [["device"]]}, {"info": {"string": "Close all sessions to all devices"}, "kind": "action", "mandatory": true, "name": "disconnect", "qname": "ncs:disconnect", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Check if the NCS config is in sync with the device"}, "kind": "action", "mandatory": true, "name": "check-sync", "leafrefGroups": [["device"]], "qname": "ncs:check-sync", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}, "leafref_groups": [["device"]]}, {"info": {"string": "Check if NCS and the devices have compatible YANG modules"}, "kind": "action", "mandatory": true, "name": "check-yang-modules", "leafrefGroups": [["device"]], "qname": "ncs:check-yang-modules", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}, "leafref_groups": [["device"]]}, {"info": {"string": "Retrieve SSH host keys from all devices"}, "kind": "action", "mandatory": true, "name": "fetch-ssh-host-keys", "leafrefGroups": [["device"]], "qname": "ncs:fetch-ssh-host-keys", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}, "leafref_groups": [["device"]]}, {"info": {"string": "Clear all trace files"}, "kind": "action", "mandatory": true, "name": "clear-trace", "qname": "ncs:clear-trace", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}, {"info": {"string": "Synchronize parts of the devices' configuration by pulling from\nthe network."}, "kind": "action", "mandatory": true, "name": "partial-sync-from", "qname": "ncs:partial-sync-from", "access": {"read": false, "create": false, "execute": true, "update": false, "delete": false}}]}} diff --git a/test/units/modules/network/nso/fixtures/verify_violation_data.json b/test/units/modules/network/nso/fixtures/verify_violation_data.json new file mode 100644 index 00000000000..05742c11d75 --- /dev/null +++ b/test/units/modules/network/nso/fixtures/verify_violation_data.json @@ -0,0 +1,10 @@ +{ + "tailf-ncs:devices": { + "device": [ + { + "name": "ce0", + "description": "Example Device" + } + ] + } +} diff --git a/test/units/modules/network/nso/test_nso_verify.py b/test/units/modules/network/nso/test_nso_verify.py new file mode 100644 index 00000000000..06ee5284afe --- /dev/null +++ b/test/units/modules/network/nso/test_nso_verify.py @@ -0,0 +1,104 @@ +# +# Copyright (c) 2017 Cisco and/or its affiliates. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +from __future__ import (absolute_import, division, print_function) + +import json + +from ansible.compat.tests.mock import patch +from ansible.modules.network.nso import nso_verify +from . import nso_module +from .nso_module import MockResponse + + +class TestNsoVerify(nso_module.TestNsoModule): + module = nso_verify + + @patch('ansible.module_utils.network.nso.nso.open_url') + def test_nso_verify_empty_data(self, open_url_mock): + calls = [ + MockResponse('login', {}, 200, '{}', {'set-cookie': 'id'}), + MockResponse('get_system_setting', {'operation': 'version'}, 200, '{"result": "4.4.3"}'), + MockResponse('logout', {}, 200, '{"result": {}}'), + ] + open_url_mock.side_effect = lambda *args, **kwargs: nso_module.mock_call(calls, *args, **kwargs) + + data = {} + nso_module.set_module_args({ + 'username': 'user', 'password': 'password', + 'url': 'http://localhost:8080/jsonrpc', 'data': data + }) + self.execute_module(changed=False) + + self.assertEqual(0, len(calls)) + + @patch('ansible.module_utils.network.nso.nso.open_url') + def test_nso_verify_violation(self, open_url_mock): + devices_schema = nso_module.load_fixture('devices_schema.json') + device_schema = nso_module.load_fixture('device_schema.json') + + calls = [ + MockResponse('login', {}, 200, '{}', {'set-cookie': 'id'}), + MockResponse('get_system_setting', {'operation': 'version'}, 200, '{"result": "4.5.0"}'), + MockResponse('get_module_prefix_map', {}, 200, '{"result": {"tailf-ncs": "ncs"}}'), + MockResponse('new_trans', {'mode': 'read'}, 200, '{"result": {"th": 1}}'), + MockResponse('get_schema', {'path': '/ncs:devices'}, 200, '{"result": %s}' % (json.dumps(devices_schema, ))), + MockResponse('get_schema', {'path': '/ncs:devices/device'}, 200, '{"result": %s}' % (json.dumps(device_schema, ))), + MockResponse('exists', {'path': '/ncs:devices/device{ce0}'}, 200, '{"result": {"exists": true}}'), + MockResponse('get_value', {'path': '/ncs:devices/device{ce0}/description'}, 200, '{"result": {"value": "In Violation"}}'), + MockResponse('logout', {}, 200, '{"result": {}}'), + ] + open_url_mock.side_effect = lambda *args, **kwargs: nso_module.mock_call(calls, *args, **kwargs) + + data = nso_module.load_fixture('verify_violation_data.json') + nso_module.set_module_args({ + 'username': 'user', 'password': 'password', + 'url': 'http://localhost:8080/jsonrpc', 'data': data + }) + self.execute_module(failed=True, violations=[ + {'path': '/ncs:devices/device{ce0}/description', 'expected-value': 'Example Device', 'value': 'In Violation'}, + ]) + + self.assertEqual(0, len(calls)) + + @patch('ansible.module_utils.network.nso.nso.open_url') + def test_nso_verify_ok(self, open_url_mock): + devices_schema = nso_module.load_fixture('devices_schema.json') + device_schema = nso_module.load_fixture('device_schema.json') + + calls = [ + MockResponse('login', {}, 200, '{}', {'set-cookie': 'id'}), + MockResponse('get_system_setting', {'operation': 'version'}, 200, '{"result": "4.5.0"}'), + MockResponse('get_module_prefix_map', {}, 200, '{"result": {"tailf-ncs": "ncs"}}'), + MockResponse('new_trans', {'mode': 'read'}, 200, '{"result": {"th": 1}}'), + MockResponse('get_schema', {'path': '/ncs:devices'}, 200, '{"result": %s}' % (json.dumps(devices_schema, ))), + MockResponse('get_schema', {'path': '/ncs:devices/device'}, 200, '{"result": %s}' % (json.dumps(device_schema, ))), + MockResponse('exists', {'path': '/ncs:devices/device{ce0}'}, 200, '{"result": {"exists": true}}'), + MockResponse('get_value', {'path': '/ncs:devices/device{ce0}/description'}, 200, '{"result": {"value": "Example Device"}}'), + MockResponse('logout', {}, 200, '{"result": {}}'), + ] + open_url_mock.side_effect = lambda *args, **kwargs: nso_module.mock_call(calls, *args, **kwargs) + + data = nso_module.load_fixture('verify_violation_data.json') + nso_module.set_module_args({ + 'username': 'user', 'password': 'password', + 'url': 'http://localhost:8080/jsonrpc', 'data': data + }) + self.execute_module(changed=False) + + self.assertEqual(0, len(calls))