├── .gitignore ├── .vscode └── settings.json ├── README.md ├── _config.yml ├── bad-interfaces.yang ├── clixon ├── Makefile ├── interfaces.xml ├── interfaces_cli.cli ├── interfaces_fake_plugin.c └── startup_db ├── docs ├── clixon.md ├── example-yang-data-model.md ├── figures │ ├── clixon-architecture.jpg │ ├── mgsoft-netconf-browser-choose-yang-file.png │ ├── mgsoft-netconf-browser-config-tree.png │ ├── mgsoft-netconf-browser-config-xml.png │ ├── mgsoft-netconf-browser-connect-to-server.png │ ├── mgsoft-netconf-browser-connected.png │ ├── mgsoft-netconf-browser-edit-config-details.png │ ├── mgsoft-netconf-browser-edit-config.png │ ├── mgsoft-netconf-browser-expand-entire-subtree.png │ ├── mgsoft-netconf-browser-first-time.png │ ├── mgsoft-netconf-browser-get-config.png │ ├── mgsoft-netconf-browser-icon.png │ ├── mgsoft-netconf-browser-interfaces-subtree.png │ ├── mgsoft-netconf-browser-message-id.png │ ├── mgsoft-netconf-browser-module-in-panel.png │ ├── mgsoft-netconf-browser-startup.png │ ├── mgsoft-netconf-browser-validate.png │ ├── mgsoft-netconf-simulator-need-java.png │ ├── mgsoft-yang-designer-components-tab.png │ ├── mgsoft-yang-designer-create-new-project.png │ ├── mgsoft-yang-designer-edit-module.png │ ├── mgsoft-yang-designer-empty-module.png │ ├── mgsoft-yang-designer-errors.png │ ├── mgsoft-yang-designer-first-time.png │ ├── mgsoft-yang-designer-icon.png │ ├── mgsoft-yang-designer-module-details.png │ ├── mgsoft-yang-designer-new-module-button.png │ ├── mgsoft-yang-designer-project-details-2.png │ ├── mgsoft-yang-designer-project-details.png │ ├── mgsoft-yang-designer-source-code.png │ ├── mgsoft-yang-explorer-choose-yang-file.png │ ├── mgsoft-yang-explorer-dependencies.png │ ├── mgsoft-yang-explorer-find-nodes.png │ ├── mgsoft-yang-explorer-first-time.png │ ├── mgsoft-yang-explorer-icon.png │ ├── mgsoft-yang-explorer-interface-model-details.png │ ├── mgsoft-yang-explorer-interface-model-expanded-subtree.png │ ├── mgsoft-yang-explorer-interface-model-source.png │ ├── mgsoft-yang-explorer-interface-model-text-tree.png │ ├── mgsoft-yang-explorer-show-in-yang-tree.png │ ├── mgsoft-yang-explorer-startup.png │ ├── mgsoft-yang-explorer-uml-class-diagram.png │ ├── pyang-jstree-diagram.png │ ├── pyang-uml-diagram.png │ ├── yang-validator-home.png │ ├── yang-validator-validation-bad.png │ ├── yang-validator-validation-good.png │ ├── yuma-pro-client-execute-error-1.png │ ├── yuma-pro-client-execute-error-2.png │ ├── yuma-pro-client-execute-error-3.png │ ├── yuma-pro-client-execute-error-4.png │ ├── yuma-pro-html-file.png │ ├── yuma-pro-sdk-basic-components.png │ ├── yuma-pro-sdk-components.png │ ├── yuma-pro-sdk-feature-comparison.png │ ├── yumabench-add-2nd-interface.png │ ├── yumabench-add-device.png │ ├── yumabench-add-interface.png │ ├── yumabench-add-session.png │ ├── yumabench-add-user.png │ ├── yumabench-notifications.png │ ├── yumabench-operational-state.png │ ├── yumabench-select-devices.png │ ├── yumabench-session-window.png │ └── yumabench-startup.png ├── mg-soft-browser.md ├── mg-soft-designer.md ├── mg-soft-explorer.md ├── mg-soft-simulator.md ├── ncclient.md ├── netopeer2.md ├── pyang.md ├── references.md ├── tail-f-confd.md ├── tutorial-install.md ├── yang-validator.md ├── yanglint.md ├── yuma-pro-client.md ├── yuma-pro-sdk.md └── yumabench.md ├── interfaces.yang ├── ncclient ├── __pycache__ │ └── netconf_server_info.cpython-39.pyc ├── demo_client.py ├── edit_config.py ├── netconf_server_info.py ├── show_capabilities.py └── show_config.py ├── requirements.txt └── yanglint ├── bad-data.xml └── data.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Python 2 | venv/ 3 | *.pyc 4 | 5 | # C 6 | *.o 7 | *.so 8 | .depend 9 | 10 | # Files created when the user follows tutorial instructions 11 | **/interfaces.html 12 | **/interfaces.uml 13 | **/img/ 14 | interfaces/ 15 | 16 | # Log files 17 | *.log 18 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorTheme": "Visual Studio Light", 3 | "editor.minimap.enabled": false, 4 | "editor.rename.enablePreview": false, 5 | "git.confirmSync": false, 6 | "workbench.editor.enablePreview": false, 7 | "diffEditor.ignoreTrimWhitespace": false, 8 | "files.trimTrailingWhitespace": true, 9 | "editor.renderWhitespace": "all", 10 | "editor.rulers": [ 11 | 100 12 | ], 13 | "window.zoomLevel": 1, 14 | "cSpell.words": [ 15 | "appcmn", 16 | "Bierman", 17 | "dpkg", 18 | "Ersue", 19 | "etag", 20 | "getbulk", 21 | "GETCB", 22 | "gnutls", 23 | "ianach", 24 | "inet", 25 | "intf", 26 | "libcurl", 27 | "libfcgi", 28 | "libncurses", 29 | "libssh", 30 | "Mehmet", 31 | "mgrload", 32 | "multitail", 33 | "nacm", 34 | "ncwd", 35 | "ncxserver", 36 | "ncxsock", 37 | "NETCONF", 38 | "netconfd", 39 | "parms", 40 | "randomart", 41 | "rcmon", 42 | "RESTCONF", 43 | "rpcs", 44 | "sget", 45 | "timefilter", 46 | "topsecret", 47 | "Wijnen", 48 | "Wireshark", 49 | "yangcli", 50 | "yanglib", 51 | "ybulk", 52 | "ypatch", 53 | "ysys", 54 | "ytemp", 55 | "yumapro", 56 | "yumaworks", 57 | "ywapp", 58 | "ywes" 59 | ], 60 | "python.linting.pylintEnabled": true, 61 | "python.formatting.provider": "black", 62 | "python.linting.pylintArgs": [ 63 | "--load-plugins=pylint_django", 64 | "--django-settings-module=settings.py" 65 | ], 66 | "[python]": { 67 | "editor.formatOnType": true, 68 | "editor.formatOnSave": true, 69 | }, 70 | "html.format.enable": false, 71 | "gitlens.currentLine.enabled": false, 72 | "gitlens.hovers.currentLine.over": "line", 73 | "gitlens.codeLens.enabled": false, 74 | } 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --== **A WORK IN PROGRESS** ==-- 2 | 3 | # A scenic tour through the YANG ecosystem 4 | 5 | # Introduction 6 | 7 | This is a hands-on tutorial for the YANG ecosystem. 8 | 9 | YANG is a data modeling language that is used for managing devices. 10 | It is quite popular for managing networking devices such as routers, switches, firewalls, 11 | load balancers, etc. 12 | But in principle, YANG could be used to manage any device such as 13 | washing machines, satellites, robots, storage arrays, whatever. 14 | 15 | A YANG data model describes what the configurable and operational attributes of the device are. 16 | A configuration attribute is an attribute that can be set by the operator, such as the temperature 17 | for a washing machine (hot, warm, cold). 18 | An operational attribute is an attribute that can only be read by the operator, such as the 19 | remaining time for the cycle of a washing machine. 20 | The YANG data model can also describe actions (e.g. start a washing cycle) and notifications 21 | (e.g. the washing cycle has been completed). 22 | 23 | The YANG data model is used to generate a management interface for the device. 24 | One example of such a management interface is the command line interface (CLI) which is a 25 | an interface intended for humans to configure and monitor the device. 26 | Other examples of management interfaces are NETCONF and RESTCONF. These are intended to be used 27 | by network management systems (NMSs) or software defined networking (SDN) controllers to configure 28 | and monitor the device. 29 | 30 | In this tutorial we won't spend much time on the theory of what YANG, CLI, NETCONF, or RESTCONF 31 | are. 32 | Instead, we will take a very hands-on approach and dive right in. We will define a toy YANG 33 | data model for a router; it models only the IPv4 addresses on a set of interfaces. 34 | 35 | Then, we will "take a tour through the YANG ecosystem". We will explore various open source and 36 | commercial tools that do something with our toy YANG data model. Some tools allow us to validate 37 | the correctness of the YANG data model. Other tools allow us to generate the code that would run 38 | on the managed network devices: the CLI/NETCONF/RESTCONF server code that actually reflects 39 | changes in the configuration onto the actual hardware. And other tools yet again allow us to 40 | generate the code that runs in the network management system, i.e. the NETCONF/RESTCONF client 41 | code. 42 | 43 | We take a very hands-on approach for each tool that we explore: we explain how to install the tool 44 | and how to use it to do something practically useful. 45 | 46 | For a list of links to standards and tutorials related to YANG, NETCONF, RESTCONF, etc. see the 47 | [references page](docs/references.md). 48 | 49 | # Getting started 50 | 51 | This tutorial is written in such a way that you can follow along and run each example yourself. 52 | For instructions on how to go to install the necessary software see the 53 | [setting up the environment for this tutorial](docs/tutorial-install.md) page. 54 | 55 | # A very simple example YANG data model: interfaces.yang 56 | 57 | Throughout this tutorial we will be using a simple example YANG data model called 58 | `interfaces.yang` which is described in detail in the 59 | [example YANG data model](docs/example-yang-data-model.md) page. 60 | 61 | # YANG data model visualization, validation and transformation tools 62 | 63 | These tools validate YANG data models for correctness and transform YANG data models into other 64 | formats such as a text summary, an HTML summary, a UML diagram, etc. 65 | 66 | Open source: 67 | * [Pyang](docs/pyang.md) 68 | * [Yanglint](docs/yanglint.md) 69 | 70 | Online: 71 | * [YANG Validator](docs/yang-validator.md) 72 | 73 | Commercial: 74 | * [MG-SOFT YANG Explorer Professional Edition](docs/mg-soft-explorer.md) 75 | * [YumaWorks YumaPro Client](docs/yuma-pro-client.md) 76 | 77 | TODO: Move some of the graphical YANG model browsers from down below to here. 78 | 79 | # NETCONF / RESTCONF servers 80 | 81 | NETCONF / RESTCONF servers are intended to implement the on-device management plane for 82 | hardware devices. They typically provide the following functionality: 83 | 84 | * They provide a north-bound (server-side) NETCONF and RESTCONF interface for clients. 85 | 86 | * They often also provide other north-bound (server-side) interface such as gNMI, SNMP, and/or 87 | a command-line interface (CLI). 88 | 89 | * They provide a software development kit (SDK) that allows the developers of the software on the 90 | device to map abstract YANG operations to concrete operations on the device hardware. 91 | Typically, the developers implement callback functions that get called when a configuration 92 | attribute needs to be validated, when a configuration attribute is set to a different value, when 93 | an operational attribute value is retrieved, when a transaction is committed, when an action is 94 | executed, when a notification needs to be generated, etc. etc. Different implementations support 95 | different programming languages. 96 | 97 | * They provide the backend implementation for the YANG data models that manage the NETCONF / 98 | RESTCONF server functionality itself, e.g. 99 | [RFC8525: YANG library](https://datatracker.ietf.org/doc/rfc8525/). 100 | 101 | Open source: 102 | * [Clixon](docs/clixon.md) (IN PROGRESS) 103 | * [Netopeer2](docs/netopeer2.md) (IN PROGRESS) 104 | * [Sysrepo](https://github.com/sysrepo/sysrepo) (TODO) 105 | 106 | Commercial: 107 | * [Cisco Tail-f ConfD](docs/confd.md) (TODO) 108 | * [MG-SOFT NETCONF Simulator](docs/mg-soft-simulator.md) 109 | * [YumaWorks YumaPro SDK](docs/yuma-pro-sdk.md) 110 | 111 | # NETCONF / RESTCONF clients 112 | 113 | NETCONF / RESTCONF clients are executable tools that allow a client-side user to manage devices 114 | that offer a server-side NETCONF / RESTCONF interface. 115 | They typically provide the following functionality: 116 | 117 | * They can dynamically discover which YANG modules the device supports and download the 118 | corresponding YANG data model from the device. (Or alternatively, you can manually load YANG 119 | data models into the client). 120 | 121 | * They can create, edit, and delete configuration attributes. 122 | 123 | * They can retrieve operational attributes. 124 | 125 | * They can invoke actions. 126 | 127 | * They can receive notifications. 128 | 129 | * Some tools offer a terminal-based command-line interface. 130 | Other tools offer a graphical user interface (GUI). 131 | 132 | Commercial: 133 | * [MG-SOFT NetConf Browser Professional Edition](docs/mg-soft-browser.md) (IN PROGRESS) 134 | * [YumaWorks YumaBench](docs/yumabench.md) 135 | 136 | # NETCONF / RESTCONF client libraries 137 | 138 | These tools are libraries or modules in a particular programming language (e.g. C, C++) 139 | that provide NETCONF and/or RESTCONF client functionality to software developers: 140 | 141 | Open source: 142 | * [Libyang](https://netopeer.liberouter.org/doc/libyang/devel/html/) (C) (TODO) 143 | * [Ncclient](docs/ncclient.md) (Python) 144 | * [Yangson](https://yangson.labs.nic.cz/) (Python) (TODO) 145 | 146 | Commercial: 147 | * [MG-SOFT NETCONF/YANG Python Scripting System](https://www.mg-soft.si/mgNetConfScripting.html) (TODO) 148 | 149 | # YANG authoring tools 150 | 151 | YANG authoring tools provide an integrated development environment (IDE) that help you author and 152 | manage YANG data models. 153 | 154 | Commercial: 155 | * [MG-SOFT Visual YANG Designer Professional Edition](docs/mg-soft-designer.md) 156 | 157 | # Other 158 | 159 | I still have to look at the following tools and classify them: 160 | 161 | * [YANG Development Kit](https://ydkgen.readthedocs.io/en/latest/index.html) (TODO) 162 | * [Cisco Tail-f YANG Suite](https://developer.cisco.com/yangsuite/) 163 | * [JetConf](https://github.com/CZ-NIC/jetconf) 164 | * https://github.com/choppsv1/netconf 165 | 166 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | title: A Scenic Tour Through the YANG Ecosystem 2 | name: Bruno Rijsman 3 | description: by Bruno Rijsman 4 | google_analytics: UA-31532124-6 5 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /bad-interfaces.yang: -------------------------------------------------------------------------------- 1 | module bad-interfaces { 2 | 3 | namespace "http://remoteautonomy.com/yang-schemas/bad-interfaces"; 4 | prefix intf; 5 | 6 | organisation 7 | "Remote Autonomy"; 8 | 9 | contact 10 | "Bruno Rijsman 11 | brunorijsman@remoteautonomy.com"; 12 | 13 | description 14 | "A simplistic tutorial data model for interfaces on a device."; 15 | 16 | revision 2022-03-12 { 17 | description 18 | "Initial revision."; 19 | } 20 | 21 | container interfaces { 22 | description 23 | "Interface parameters."; 24 | 25 | list interface { 26 | key "name"; 27 | description 28 | "The list of interfaces on the device."; 29 | 30 | leaf name { 31 | type string; 32 | description 33 | "The name of the interface."; 34 | } 35 | 36 | leaf ipv4-address { 37 | type string { 38 | pattern 39 | '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' 40 | + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; 41 | } 42 | description 43 | "The IPv4 address of the interface."; 44 | } 45 | 46 | leaf sent-packets { 47 | type uint46; 48 | config false; 49 | description 50 | "The number of IPv4 packets sent out over this interface"; 51 | } 52 | 53 | leaf received-packets { 54 | type uint64; 55 | config false; 56 | description 57 | "The number of IPv4 packets received over this interface"; 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /clixon/Makefile: -------------------------------------------------------------------------------- 1 | srcdir = . 2 | top_srcdir = ../.. 3 | prefix = /usr/local 4 | bindir = ${exec_prefix}/bin 5 | includedir = ${prefix}/include 6 | datarootdir = ${prefix}/share 7 | sysconfdir = ${prefix}/etc 8 | datarootdir = ${prefix}/share 9 | localstatedir = ${prefix}/var 10 | libdir = ${prefix}/lib 11 | 12 | APPNAME = interfaces 13 | 14 | CC = gcc 15 | CFLAGS = -O2 -Wall -fPIC 16 | INSTALLFLAGS = -s 17 | 18 | INCLUDES = 19 | CPPFLAGS = -DHAVE_CONFIG_H -fPIC 20 | 21 | YANG_INSTALLDIR = /usr/local/share/clixon 22 | 23 | YANGSPECS = ../interfaces.yang 24 | 25 | PLUGIN = $(APPNAME)_fake_plugin.so 26 | PLUGIN_SRC = $(APPNAME)_fake_plugin.c 27 | PLUGIN_OBJ = $(PLUGIN_SRC:%.c=%.o) 28 | 29 | .SUFFIXES: .c .o 30 | 31 | .c.o: 32 | $(CC) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) -c $< 33 | 34 | .PHONY: all clean depend install 35 | 36 | all: $(PLUGIN) 37 | 38 | $(PLUGIN): $(PLUGIN_OBJ) 39 | $(CC) -Wall -shared $(LDFLAGS) -o $@ -lc $< -lclixon -lclixon_backend 40 | 41 | CLISPECS = $(APPNAME)_cli.cli 42 | 43 | clean: 44 | 45 | distclean: clean 46 | rm -f Makefile *~ .depend 47 | 48 | install: $(CLISPECS) $(APPNAME).xml $(PLUGIN) 49 | install -d -m 0755 $(DESTDIR)$(sysconfdir) 50 | install -m 0644 $(APPNAME).xml $(DESTDIR)$(sysconfdir) 51 | install -d -m 0755 $(DESTDIR)$(libdir)/$(APPNAME) 52 | install -d -m 0755 $(DESTDIR)$(libdir)/$(APPNAME)/clispec 53 | install -d -m 0755 $(DESTDIR)$(libdir)/$(APPNAME)/backend 54 | install -m 0644 $(CLISPECS) $(DESTDIR)$(libdir)/$(APPNAME)/clispec 55 | install -d -m 0755 $(DESTDIR)$(localstatedir) 56 | install -d -m 0755 $(DESTDIR)$(localstatedir)/$(APPNAME) 57 | install -m 0644 startup_db $(DESTDIR)$(localstatedir)/$(APPNAME)/ 58 | install -d -m 0755 $(DESTDIR)$(YANG_INSTALLDIR) 59 | install -m 0644 $(YANGSPECS) $(DESTDIR)$(YANG_INSTALLDIR) 60 | install -m 0644 $(INSTALLFLAGS) $(PLUGIN) $(DESTDIR)$(libdir)/$(APPNAME)/backend 61 | 62 | uninstall: 63 | rm -rf $(DESTDIR)$(sysconfdir)/$(APPNAME).xml 64 | rm -rf $(DESTDIR)$(libdir)/$(APPNAME) 65 | rm -rf $(DESTDIR)$(localstatedir)/$(APPNAME) 66 | for i in $(YANGSPEC) ; \ 67 | do rm $(DESTDIR)$(YANG_INSTALLDIR)/$$i; done 68 | 69 | depend: 70 | $(CC) $(DEPENDFLAGS) $(INCLUDES) $(CFLAGS) -MM $(PLUGIN_SRC) > .depend 71 | 72 | #include .depend 73 | -------------------------------------------------------------------------------- /clixon/interfaces.xml: -------------------------------------------------------------------------------- 1 | 2 | /usr/local/etc/interfaces.xml 3 | ietf-netconf:startup 4 | clixon-restconf:allow-auth-none 5 | /usr/local/share/clixon 6 | interfaces 7 | interfaces 8 | /usr/local/lib/interfaces/clispec 9 | /usr/local/lib/interfaces/backend 10 | /usr/local/var/interfaces.sock 11 | /usr/local/var/interfaces.pidfile 12 | true 13 | /usr/local/var/interfaces 14 | init 15 | false 16 | false 17 | clicon 18 | www-data 19 | drop_perm 20 | 21 | true 22 | none 23 | false 24 | 0 25 | file 26 | 27 | default 28 |
0.0.0.0
29 | 80 30 | false 31 |
32 |
33 | 34 | false 35 | 36 | include interfaces yang 37 | enable 38 | interfaces* 39 | 40 | 41 | compress 42 | compress 43 | container 44 | list 45 | 46 | 47 |
48 | -------------------------------------------------------------------------------- /clixon/interfaces_cli.cli: -------------------------------------------------------------------------------- 1 | CLICON_MODE="interfaces"; 2 | CLICON_PROMPT="%W> "; 3 | 4 | edit("Edit a configuration subtree") @datamodel, cli_auto_edit("datamodel"); 5 | up("Move one level up in the configuration"), cli_auto_up("datamodel"); 6 | top("Move to the top level in the configuration"), cli_auto_top("datamodel"); 7 | set("Set a configuration item value") @datamodel, cli_auto_set(); 8 | merge("Merge configuration items") @datamodel, cli_auto_merge(); 9 | create("Create a configuration item") @datamodel, cli_auto_create(); 10 | delete("Delete a configuration item") { 11 | @datamodel, cli_auto_del(); 12 | all("Delete whole candidate configuration"), delete_all("candidate"); 13 | } 14 | validate("Validate changes"), cli_validate(); 15 | commit("Commit the changes"), cli_commit(); 16 | quit("Quit"), cli_quit(); 17 | 18 | startup("Store running as startup config"), db_copy("running", "startup"); 19 | no("Negate or remove") debug("Debugging parts of the system"), cli_debug_cli((int32)0); 20 | debug("Debugging parts of the system"), cli_debug_cli((int32)1);{ 21 | level("Set debug level: 1..n") ("Set debug level (0..n)"), cli_debug_backend(); 22 | } 23 | discard("Discard edits (rollback 0)"), discard_changes(); 24 | compare("Compare running and candidate"), compare_dbs((int32)1); 25 | 26 | show("Show a particular state of the system"){ 27 | xpath("Show configuration") ("XPATH expression") ("Namespace"), show_conf_xpath("candidate"); 28 | version("Show version"), cli_show_version("candidate", "text", "/"); 29 | options("Show CLI options"), cli_show_options(); 30 | compare("Compare candidate and running databases"), compare_dbs((int32)0);{ 31 | xml("Show comparison in xml"), compare_dbs((int32)0); 32 | text("Show comparison in text"), compare_dbs((int32)1); 33 | } 34 | configuration("Show configuration"), cli_show_config("candidate", "text", "/");{ 35 | xml("Show configuration as XML"), cli_show_config("candidate", "xml", "/");{ 36 | @datamodel, cli_show_auto("candidate", "xml"); 37 | } 38 | cli("Show configuration as CLI commands"), cli_show_config("candidate", "cli", "/");{ 39 | @datamodel, cli_show_auto("candidate", "cli"); 40 | } 41 | netconf("Show configuration as netconf edit-config operation"), cli_show_config("candidate", "netconf", "/");{ 42 | @datamodel, cli_show_auto("candidate", "netconf"); 43 | } 44 | text("Show configuration as text"), cli_show_config("candidate","text","/");{ 45 | @datamodel, cli_show_auto("candidate", "text"); 46 | } 47 | json("Show configuration as JSON"), cli_show_config("candidate", "json", "/");{ 48 | @datamodel, cli_show_auto("candidate", "json"); 49 | } 50 | } 51 | state("Show configuration and state"), cli_auto_show("datamodel", "running", "text", true, true); { 52 | xml("Show configuration and state as XML"), cli_auto_show("datamodel", "running", "xml", true, true); 53 | } 54 | } 55 | 56 | save("Save candidate configuration to XML file") ("Filename (local filename)"), save_config_file("candidate","filename"); 57 | load("Load configuration from XML file") ("Filename (local filename)"),load_config_file("filename", "replace");{ 58 | replace("Replace candidate with file contents"), load_config_file("filename", "replace"); 59 | merge("Merge file with existent candidate"), load_config_file("filename", "merge"); 60 | } 61 | -------------------------------------------------------------------------------- /clixon/interfaces_fake_plugin.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define LOG_TAG "interfaces_fake_plugin" 9 | #define MAX_INDENT 128 10 | 11 | char* indent_str(size_t indent) { 12 | static char str[MAX_INDENT + 1]; 13 | assert(indent <= MAX_INDENT); 14 | for (int i=0; i 2 | 3 | true 4 | none 5 | false 6 | 0 7 | file 8 | 9 | default 10 |
0.0.0.0
11 | 80 12 | false 13 |
14 |
15 | 16 | -------------------------------------------------------------------------------- /docs/clixon.md: -------------------------------------------------------------------------------- 1 | # Clixon 2 | 3 | ## Introduction 4 | 5 | [Clixon](https://github.com/clicon/clixon) can generate a server from a YANG data model. 6 | 7 | The generated server provides multiple north-bound interfaces based on the YANG data model: 8 | * A command line interface (CLI). 9 | * A NETCONF interface. 10 | * A RESTCONF interface. 11 | 12 | Clixon also provides a software development kit (SDK) that allows you to develop plugins 13 | that implement the backend of the YANG data model, such as: 14 | * Retrieve the values for operational attributes from the underlying hardware when a 15 | NETCONF get / RESTCONF get / CLI show operation is performed. 16 | * Make the values for configuration attributes take effect in the underlying hardware when a 17 | NETCONF set / RESTCONF put / CLI set operation is performed. 18 | 19 | The following figure shows the clixon architecture: 20 | 21 | ![Clixon architecture](figures/clixon-architecture.jpg) 22 | 23 | Clixon is an open source project implemented in C. 24 | You can think of Clixon as being the open source equivalent of the commercial 25 | [CONFD](https://www.tail-f.com/management-agent/) product from [Tail-F](https://www.tail-f.com/) 26 | or the YumaPro product suite from [YumaWorks](https://www.yumaworks.com/). 27 | 28 | ## Install clixon 29 | 30 | [Clixon](https://github.com/clicon/clixon) is an open source project written in C that offers a 31 | YANG-based configuration data store with plugin APIs for configuration consuming applications and 32 | with CLI, NETCONF, and RESTCONF frontend interfaces. 33 | 34 | Install the dependencies for `clixon`: 35 | 36 |
 37 | $ sudo apt-get install flex bison
 38 | 
39 | 40 | Add `clixon` and `clicon` user groups and add users to them 41 | (replace __ with your username): 42 | 43 |
 44 | $ sudo useradd -M -U clixon
 45 | $ sudo usermod -a -G clixon <your-user-name>
 46 | $ sudo usermod -a -G clixon www-data
 47 | $ sudo useradd -M -U clicon
 48 | $ sudo usermod -a -G clicon <your-user-name>
 49 | $ sudo usermod -a -G clicon www-data
 50 | 
51 | 52 | 53 | Log out and log in again, to make the new user group settings take effect. 54 | 55 | Clone, build, and install the `cligen` GitHub repository: 56 | 57 |
 58 | $ cd ~
 59 | $ git clone https://github.com/clicon/cligen.git
 60 | $ cd cligen
 61 | $ ./configure
 62 | $ make
 63 | $ sudo make install
 64 | 
65 | 66 | 67 | Clone, build, and install the `clixon` GitHub repository: 68 | 69 |
 70 | $ cd ~
 71 | $ git clone https://github.com/clicon/clixon.git
 72 | $ cd clixon
 73 | $ ./configure
 74 | $ make
 75 | $ sudo make install
 76 | 
77 | 78 | We will explain how to start the clixon backend server and the clixon frontend servers for the 79 | CLI, for NETCONF, and for RESTCONF in the main body of the tutorial. 80 | 81 | ## Build the clixon backend server 82 | 83 | We will now explain how to build the clixon backend server for the `interfaces.yang` data model 84 | that we introduced earlier in this tutorial. 85 | 86 | First install clixon following the 87 | [clixon installation instructions](#clixon-installation-instructions) 88 | at the end of this tutorial. 89 | 90 | Change the current directory to the `clixon` directory in this repository: 91 | 92 |
 93 | $ cd ~/yang-tutorial/clixon
 94 | 
95 | 96 | This directory contains the following: 97 | 98 |
 99 | $ ls -1
100 | interfaces_cli.cli
101 | interfaces.xml
102 | Makefile
103 | plugins/
104 | startup_db
105 | 
106 | 107 | These files have the following functions: 108 | * File `interfaces.xml` is the the configuration file for the Clixon backend daemon. 109 | * File `interfaces_cli.cli` is the configuration file for the Clixon CLI daemon. 110 | * File `startup_db` contains startup configuration datastore. 111 | * Directory `plugins` contains tutorial code for the backend plugins (we will get to this later). 112 | * File `Makefile` contains the rules for building and installing Clixon. 113 | 114 | We will first run clixon without any plugins. 115 | Since there are no plugins yet, we don't have to compile any code. 116 | For now, the only thing we have to do is to install the clixon configuration files in the proper 117 | directories. 118 | This is achieved by running `make install` as a super user: 119 | 120 |
121 | $ sudo make install
122 | install -d -m 0755 /usr/local/etc
123 | install -m 0644 interfaces.xml /usr/local/etc
124 | install -d -m 0755 /usr/local/lib/interfaces
125 | install -d -m 0755 /usr/local/lib/interfaces/clispec
126 | install -m 0644 interfaces_cli.cli /usr/local/lib/interfaces/clispec
127 | install -d -m 0755 /usr/local/var
128 | install -d -m 0755 /usr/local/var/interfaces
129 | install -m 0644 startup_db /usr/local/var/interfaces/
130 | install -d -m 0755 /usr/local/share/clixon
131 | install -m 0644 ../interfaces.yang /usr/local/share/clixon
132 | 
133 | 134 | ## Start the clixon backend server daemon 135 | 136 | Start the clixon backend daemon. The minimal command to start the clixon server is: 137 | 138 |
139 | $ sudo clixon_backend -f interfaces.xml
140 | 
141 | 142 | I typically set the debug level to one (`-D 1`) and write the output to a log file: 143 | 144 |
145 | $ sudo clixon_backend -f interfaces.xml -lf/var/log/clixon.log -D 1
146 | 
147 | 148 | And then I typically monitor the log file in a separate terminal window: 149 | 150 |
151 | $ tail -f /var/log/clixon.log
152 | 
153 | 154 | To verify that the clixon backend daemon is actually running: 155 | 156 |
157 | $ ps aux | grep clixon
158 | root       47277  0.0  0.0   4596  3388 ?        Ss   15:27   0:00 clixon_backend -f interfaces.xml
159 | paralle+   47504  0.0  0.0   9040   740 pts/0    S+   15:28   0:00 grep --color=auto clixon
160 | 
161 | 162 | If you ever want to restart the clixon backend daemon, you first have to stop the old daemon first 163 | using the `-z` command line option (don't do this now): 164 | 165 |
166 | $ sudo clixon_backend -f interfaces.xml -z
167 | Mar 16 15:50:42: Killing old daemon with pid: 47277
168 | 
169 | 170 | ## Start the clixon CLI frontend 171 | 172 | Start the clixon command line interface (CLI) frontend: 173 | 174 |
175 | $ clixon_cli -f interfaces.xml
176 | cli>
177 | 
178 | 179 | ## Use the clixon CLI 180 | 181 | The `cli>` prompt indicates that we are now in the clixon CLI that was automatically generated from 182 | `interfaces.yang` data model in combination with the `interfaces_cli.cli` configuration file. 183 | 184 | Type `?` to get a list of available CLI commands: 185 | 186 |
187 | cli> ?
188 |   commit                Commit the changes
189 |   compare               Compare running and candidate
190 |   create                Create a configuration item
191 |   debug                 Debugging parts of the system
192 |   delete                Delete a configuration item
193 |   discard               Discard edits (rollback 0)
194 |   load                  Load configuration from XML file
195 |   merge                 Merge configuration items
196 |   mode                  Enter a configuration mode
197 |   no                    Negate or remove
198 |   quit                  Quit
199 |   save                  Save candidate configuration to XML file
200 |   set                   Set a configuration item value
201 |   show                  Show a particular state of the system
202 |   startup               Store running as startup config
203 |   top                   Move to the top level in the configuration
204 |   up                    Move one level up in the configuration
205 |   validate              Validate changes
206 | cli>
207 | 
208 | 209 | If we do a `show configuration` at this point, we get no output because we have not yet configured 210 | any interfaces: 211 | 212 |
213 | cli> show configuration
214 | cli> 
215 | 
216 | 217 | Configure IPv4 address `10.0.0.99` on the loopback interface `lo`: 218 | 219 |
220 | cli> set interfaces interface lo ipv4-address 10.0.0.99
221 | cli> 
222 | 
223 | 224 | The configuration that we just added has not yet taken effect: 225 | at this point it is just a candidate configuration and not yet a running configuration. 226 | 227 | Use the commit command to make the configuration take effect, in other words to make the 228 | candidate configuration the running configuration 229 | (later, when we implement the backend plugin we will see that committing the configuration 230 | causes the IPv4 address on the real interface to change): 231 | 232 |
233 | cli> commit
234 | cli> 
235 | 
236 | 237 | If you try to configure some attribute that is not defined in the YANG data model 238 | (`ipv6-address` in this example), 239 | you get an error. This is the simplest example of configuration validation based on the YANG data model: 240 | 241 |
242 | cli> set interfaces interface lo ipv6-address ::10
243 | CLI syntax error: "set interfaces interface lo ipv6-address ::10": Unknown command
244 | 
245 | 246 | If you try to configure an invalid IPv4 address, you also get an error. 247 | 248 |
249 | cli> set interfaces interface lo ipv4-address ::10
250 | CLI syntax error: "set interfaces interface lo ipv4-address ::10": "::10" is invalid input for cli command: ipv4-address
251 | 
252 | 253 | This is more sophisticated example of configuration validation based on the YANG data model. 254 | In this example, the invalid IPv4 address `::10` is rejected by the CLI because it does not match 255 | the regular expression in the YANG data model: 256 | 257 |
258 | leaf ipv4-address {
259 |     type string {
260 |         pattern
261 |           '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
262 |         + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';
263 |     }
264 |     description
265 |       "The IPv4 address of the interface.";
266 | }
267 | 
268 | 269 | 270 | Now configure the IPv4 address of a second interface `eth0`. 271 | In this case, instead of specifying the full path of the configured attribute in the `set` command, 272 | we navigate to the desired attribute using the `mode` command: 273 | 274 |
275 | cli> mode interfaces
276 | cli> mode interface
277 | cli> mode eth0
278 | cli> set ipv4-address 10.0.0.98
279 | cli> 
280 | 
281 | 282 | In addition to the `mode` command, we can also use the `up` and `top` commands to navigate through 283 | the levels in the configuration hierarchy: 284 | 285 |
286 | cli> set ? 
287 |   ipv4-address          The IPv4 address of the interface.
288 | cli> up
289 | cli> set ?
290 |   interface             The list of interfaces on the device.
291 | cli> top
292 | cli> set ?
293 |   interfaces            Interface parameters.
294 | 
295 | 296 | Recall that we have only added this second interface to the candidate configuration; 297 | not yet to the running configuration. 298 | 299 | Before we commit, we can use the `compare` command to see what the difference is between the 300 | candidate configuration and the running configuration, in other words which configuration changes 301 | have not yet been committed: 302 | 303 |
304 | cli> compare
305 |      interface {
306 | +        name eth0;
307 | +        ipv4-address 10.0.0.98;
308 | +    }
309 | +    interface {
310 |          name lo;
311 | 
312 | 313 | Note that the comparison looks a bit strange, because the `diff` algorithm in clixon does a simple 314 | text comparison which doesn't understand whether the first `interface {` line or the second 315 | `interface {` line was added. 316 | 317 | Now commit the candidate configuration: 318 | 319 |
320 | cli> commit
321 | cli>
322 | 
323 | 324 | Now, when we do `show configuration` we see both configured interfaces: 325 | 326 |
327 | cli> show configuration
328 | interfaces {
329 |     interface {
330 |         name eth0;
331 |         ipv4-address 10.0.0.98;
332 |     }
333 |     interface {
334 |         name lo;
335 |         ipv4-address 10.0.0.99;
336 |     }
337 | }
338 | cli> 
339 | 
340 | 341 | We can also look at the configuration other formats such as XML or JSON: 342 | 343 |
344 | cli> show configuration xml
345 | <interfaces xmlns="http://remoteautonomy.com/yang-schemas/interfaces">
346 |    <interface>
347 |       <name>eth0</name>
348 |       <ipv4-address>10.0.0.98</ipv4-address>
349 |    </interface>
350 |    <interface>
351 |       <name>lo</name>
352 |       <ipv4-address>10.0.0.99</ipv4-address>
353 |    </interface>
354 | </interfaces>
355 | </pre>
356 | 
357 | 358 |
359 | cli> show configuration json
360 | {
361 |   "ietf-restconf:data": {
362 |     "interfaces:interfaces": {
363 |       "interface": [
364 |         {
365 |           "name": "eth0",
366 |           "ipv4-address": "10.0.0.98"
367 |         },
368 |         {
369 |           "name": "lo",
370 |           "ipv4-address": "10.0.0.99"
371 |         }
372 |       ]
373 |     }
374 |   }
375 | }
376 | 
377 | 378 | Use the `quit` command to exit the CLI and return to the Linux shell: 379 | 380 |
381 | cli> quit
382 | $
383 | 
384 | 385 | ## Implement a clixon plugin 386 | 387 | Clixon has the concept of plugins. The responsibilities of a plugin include: 388 | 389 | * Validate changes to the data store before they are committed. 390 | Many constraints can be expressed in the YANG data model and can be validated by the clixon 391 | backend server without having to manually write any code. 392 | For example, the `ipv4-address` attribute in our data model enforces that the IPv4 address has 393 | the correct format by using the `pattern` option and a regular expression. 394 | Other constraints cannot be expressed in YANG and those constraints are validated by the 395 | plugin. 396 | In this tutorial we will enforce the (silly) constraint that there cannot be more than two 397 | interfaces starting with the letter x. 398 | 399 | * After each commit that passed the validation phase, process all configuration changes and 400 | make them take effect on the underlying hardware platform. 401 | In our example, when the user adds a new interface with an IPv4 address, the plugin must 402 | interact with the TCP/IP stack to add the IPv4 address. Or when the user modifies the IPv4 403 | address of an existing interface in the data store, the plugin must correspondingly modify the 404 | IPv4 address of the corresponding interface in the TCP/IP stack. Or when the user deletes 405 | an interface from the data store, the plugin must interact with the TCP/IP stack to remove 406 | the IPv4 address from the corresponding interface. 407 | 408 | * When the user retrieves the value of an operational attribute (e.g. using a `show` command the 409 | CLI), the plugin must provide the requested value. For example, when the value of the 410 | `sent-packets` attribute in the YANG data model is requested, the plugin must retrieve the 411 | corresponding counter from the TCP/IP stack. 412 | 413 | We will now implemented a fake plugin. 414 | It is fake in the sense that it will just swallow any configured IPv4 address without applying 415 | it to a real interface, 416 | and it will just return random values for the packet counters instead of reading the real counters 417 | from the real interfaces. 418 | Later, we will convert the fake plugin with a real plugin that configures and reads the real 419 | interfaces. 420 | But for now, we start simple and focus on the APIs provided by clixon. 421 | 422 | TODO: Get rid of the 'fake' terminology. 423 | 424 | The file `interfaces_fake_plugin.c` contains the code for our fake plugin. 425 | We will now walk through the code to explain how it works. 426 | 427 | The first thing we have to do is to register our plugin and its callback functions: 428 | 429 | TODO: write code first 430 | 431 | We register callbacks for validation (`ca_trans_validate`) and for commit (`ca_trans_commit`). 432 | We also register callbacks for the beginning of a transaction (`ca_trans_begin`) and the end 433 | of a transaction (`ca_trans_end`). 434 | We don't do anything in these callbacks, but it is necessary to register for them anyway, 435 | otherwise the validation and commit callback won't get called. 436 | There are additional callbacks that one can register for 437 | including, `ca_trans_complete`, `ca_trans_commit_done`, `ca_trans_revert`, and `ca_trans_abort`. 438 | 439 | 440 | ## References 441 | 442 | * [The clixon GitHub repository](https://github.com/clicon/clixon) 443 | 444 | * [The clixon examples GitHub repository](https://github.com/clicon/clixon-examples) 445 | 446 | * [Clixon documentation](https://clixon-docs.readthedocs.io/en/latest/) 447 | 448 | -------------------------------------------------------------------------------- /docs/example-yang-data-model.md: -------------------------------------------------------------------------------- 1 | # An example YANG data model 2 | 3 | We are going to start by writing a simple YANG data model that we will use throughout 4 | the remainder of this tutorial. 5 | 6 | Our data model manages the interfaces on a device. It contains a list of interfaces, and each 7 | interface has a name, an IPv4 address, and counters for the number of sent and received 8 | packets. 9 | 10 | In real life, the data models for managing interfaces 11 | ([RFC 8343](https://www.rfc-editor.org/rfc/pdfrfc/rfc8343.txt.pdf)) 12 | and for managing IP addresses 13 | ([RFC 8344](https://www.rfc-editor.org/rfc/pdfrfc/rfc8344.txt.pdf)) 14 | are way more complex, but we are using a simplistic data model in this tutorial to keep the 15 | example code short and easy to understand. 16 | 17 | Here is our data model (you can find it in this repository in the file `interfaces.yang`): 18 | 19 | ```yang 20 | module interfaces { 21 | 22 | namespace "http://remoteautonomy.com/yang-schemas/interfaces"; 23 | prefix intf; 24 | 25 | organization 26 | "Remote Autonomy"; 27 | 28 | contact 29 | "Bruno Rijsman 30 | brunorijsman@remoteautonomy.com"; 31 | 32 | description 33 | "A simplistic tutorial data model for interfaces on a device."; 34 | 35 | revision 2022-03-12 { 36 | description 37 | "Initial revision."; 38 | } 39 | 40 | container interfaces { 41 | description 42 | "Interface parameters."; 43 | 44 | list interface { 45 | key "name"; 46 | description 47 | "The list of interfaces on the device."; 48 | 49 | leaf name { 50 | type string; 51 | description 52 | "The name of the interface."; 53 | } 54 | 55 | leaf ipv4-address { 56 | type string { 57 | pattern 58 | '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' 59 | + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; 60 | } 61 | description 62 | "The IPv4 address of the interface."; 63 | } 64 | 65 | leaf sent-packets { 66 | type uint64; 67 | config false; 68 | description 69 | "The number of IPv4 packets sent out over this interface"; 70 | } 71 | 72 | leaf received-packets { 73 | type uint64; 74 | config false; 75 | description 76 | "The number of IPv4 packets received over this interface"; 77 | } 78 | } 79 | } 80 | } 81 | ``` 82 | 83 | There is also a file called `bad-interfaces.yang` that contains some errors on purpose so that 84 | we can demonstrate the error messages produced by the various YANG validation tools. 85 | 86 | TODO: Add an RPC to the data model -------------------------------------------------------------------------------- /docs/figures/clixon-architecture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/clixon-architecture.jpg -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-choose-yang-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-choose-yang-file.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-config-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-config-tree.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-config-xml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-config-xml.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-connect-to-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-connect-to-server.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-connected.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-edit-config-details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-edit-config-details.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-edit-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-edit-config.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-expand-entire-subtree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-expand-entire-subtree.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-first-time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-first-time.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-get-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-get-config.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-icon.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-interfaces-subtree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-interfaces-subtree.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-message-id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-message-id.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-module-in-panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-module-in-panel.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-startup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-startup.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-browser-validate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-browser-validate.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-netconf-simulator-need-java.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-netconf-simulator-need-java.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-designer-components-tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-designer-components-tab.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-designer-create-new-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-designer-create-new-project.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-designer-edit-module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-designer-edit-module.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-designer-empty-module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-designer-empty-module.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-designer-errors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-designer-errors.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-designer-first-time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-designer-first-time.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-designer-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-designer-icon.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-designer-module-details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-designer-module-details.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-designer-new-module-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-designer-new-module-button.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-designer-project-details-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-designer-project-details-2.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-designer-project-details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-designer-project-details.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-designer-source-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-designer-source-code.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-explorer-choose-yang-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-explorer-choose-yang-file.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-explorer-dependencies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-explorer-dependencies.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-explorer-find-nodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-explorer-find-nodes.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-explorer-first-time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-explorer-first-time.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-explorer-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-explorer-icon.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-explorer-interface-model-details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-explorer-interface-model-details.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-explorer-interface-model-expanded-subtree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-explorer-interface-model-expanded-subtree.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-explorer-interface-model-source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-explorer-interface-model-source.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-explorer-interface-model-text-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-explorer-interface-model-text-tree.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-explorer-show-in-yang-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-explorer-show-in-yang-tree.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-explorer-startup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-explorer-startup.png -------------------------------------------------------------------------------- /docs/figures/mgsoft-yang-explorer-uml-class-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/mgsoft-yang-explorer-uml-class-diagram.png -------------------------------------------------------------------------------- /docs/figures/pyang-jstree-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/pyang-jstree-diagram.png -------------------------------------------------------------------------------- /docs/figures/pyang-uml-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/pyang-uml-diagram.png -------------------------------------------------------------------------------- /docs/figures/yang-validator-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yang-validator-home.png -------------------------------------------------------------------------------- /docs/figures/yang-validator-validation-bad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yang-validator-validation-bad.png -------------------------------------------------------------------------------- /docs/figures/yang-validator-validation-good.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yang-validator-validation-good.png -------------------------------------------------------------------------------- /docs/figures/yuma-pro-client-execute-error-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yuma-pro-client-execute-error-1.png -------------------------------------------------------------------------------- /docs/figures/yuma-pro-client-execute-error-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yuma-pro-client-execute-error-2.png -------------------------------------------------------------------------------- /docs/figures/yuma-pro-client-execute-error-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yuma-pro-client-execute-error-3.png -------------------------------------------------------------------------------- /docs/figures/yuma-pro-client-execute-error-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yuma-pro-client-execute-error-4.png -------------------------------------------------------------------------------- /docs/figures/yuma-pro-html-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yuma-pro-html-file.png -------------------------------------------------------------------------------- /docs/figures/yuma-pro-sdk-basic-components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yuma-pro-sdk-basic-components.png -------------------------------------------------------------------------------- /docs/figures/yuma-pro-sdk-components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yuma-pro-sdk-components.png -------------------------------------------------------------------------------- /docs/figures/yuma-pro-sdk-feature-comparison.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yuma-pro-sdk-feature-comparison.png -------------------------------------------------------------------------------- /docs/figures/yumabench-add-2nd-interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yumabench-add-2nd-interface.png -------------------------------------------------------------------------------- /docs/figures/yumabench-add-device.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yumabench-add-device.png -------------------------------------------------------------------------------- /docs/figures/yumabench-add-interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yumabench-add-interface.png -------------------------------------------------------------------------------- /docs/figures/yumabench-add-session.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yumabench-add-session.png -------------------------------------------------------------------------------- /docs/figures/yumabench-add-user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yumabench-add-user.png -------------------------------------------------------------------------------- /docs/figures/yumabench-notifications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yumabench-notifications.png -------------------------------------------------------------------------------- /docs/figures/yumabench-operational-state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yumabench-operational-state.png -------------------------------------------------------------------------------- /docs/figures/yumabench-select-devices.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yumabench-select-devices.png -------------------------------------------------------------------------------- /docs/figures/yumabench-session-window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yumabench-session-window.png -------------------------------------------------------------------------------- /docs/figures/yumabench-startup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/docs/figures/yumabench-startup.png -------------------------------------------------------------------------------- /docs/mg-soft-browser.md: -------------------------------------------------------------------------------- 1 | # MG-SOFT NetConf Browser Professional Edition 2 | 3 | ## Introduction 4 | 5 | [MG-SOFT](https://www.mg-soft.si/) is a company that offers a suite of network management related 6 | products. 7 | One of their products, the 8 | [MG-SOFT NetConf Browser Professional Edition](https://www.mg-soft.si/mgNetConfBrowser.html) 9 | is a client that can connect to a NETCONF or RESTCONF server and that offers a graphical user 10 | interface for exploring and editing the data store in the server. 11 | 12 | ## Download and install 13 | 14 | You can download the MG-SOFT NetConf Browser Professional Edition from the 15 | [download page](https://www.mg-soft.si/download.html?product=netconfbrowser) 16 | on the MG-SOFT website. 17 | 18 | MG-SOFT offers a version of the browser that runs natively on Linux, but I find it more 19 | convenient to run the macOS version of the browser and connect to the NETCONF server that 20 | runs inside my Ubuntu virtual machine over the bridge network. 21 | 22 | To do anything interesting with the MG-SOFT NetConf Browser, you will need to apply a license key. 23 | You can [purchase a license online](https://www.mg-soft.si/mgNetConfBrowser-ordering.html) 24 | or you can [request a 30-day evaluation license online](https://www.mg-soft.si/evalKeyReq.html). 25 | Note: I am not affiliated with MG-SOFT in any way and I don't get any commission. 26 | 27 | ## Start the clixon NETCONF server 28 | 29 | The MG-SOFT NetConf Browser is a NETCONF client, so we need a NETCONF server to be running. 30 | We will use clixon as the NETCONF server. 31 | Refer to the [clixon chapter in this tutorial](clixon.md) for instructions on how install clixon, 32 | how to build clixon, how the start the clixon backend daemon, and how to configure SSH to start 33 | the clixon NETCONF server. 34 | 35 | As a quick sanity check to make sure the NETCONF server is running properly, 36 | manually start an SSH session 37 | (replace username@<vm-ip-address> with the usenname and IP address of the virtual 38 | machine that runs the clixon NETCONF server). 39 | You should see a NETCONF `hello` message from the server: 40 | 41 |
 42 | $ ssh <username@vm-ip-address> -s netconf
 43 | username@localhost's password: ******
 44 | urn:ietf:params:netconf:base:1.1urn:ietf:params:netconf:base:1.0urn:ietf:params:netconf:capability:candidate:1.0urn:ietf:params:netconf:capability:validate:1.1urn:ietf:params:netconf:capability:startup:1.0urn:ietf:params:netconf:capability:xpath:1.0urn:ietf:params:netconf:capability:notification:1.04]]>]]>
 45 | 
46 | 47 | Type Control-D to exit the SSH session. 48 | 49 | # Start the MG-SOFT NetConf Browser 50 | 51 | Double click on the MG-SOFT NetConf Browser icon in the applications folder. 52 | 53 | ![MG-SOFT NetConf Browser icon](figures/mgsoft-netconf-browser-icon.png) 54 | 55 | When you start the MG-SOFT NetConf Browser for the first time, it will give you the opportunity 56 | to install the evaluation license 57 | (you can also do this later using the Help → Apply License Key... menu item.) 58 | 59 | ![MG-SOFT NetConf Browser first time startup screen](figures/mgsoft-netconf-browser-first-time.png) 60 | 61 | After installing the license key, you end up in the following screen: 62 | 63 | ![MG-SOFT NetConf Browser startup screen](figures/mgsoft-netconf-browser-startup.png) 64 | 65 | # Load the YANG data model 66 | 67 | The first thing we have to do is to load our `interfaces.yang` YANG data model into the 68 | MG-SOFT NetConf Browser. 69 | Select the Module → Load Module... menu item, and open the `interfaces.yang` file in this 70 | repository. 71 | 72 | ![MG-SOFT NetConf Browser - choose YANG module](figures/mgsoft-netconf-browser-choose-yang-file.png) 73 | 74 | The `interfaces` YANG module appears in the left pane of the MG-SOFT NetConf Browser. 75 | 76 | ![MG-SOFT NetConf Browser - YANG module in panel](figures/mgsoft-netconf-browser-module-in-panel.png) 77 | 78 | You can right-click on `interfaces` and choose menu item Expand Entire Subtree. 79 | 80 | ![MG-SOFT NetConf Browser - expand entire subtree](figures/mgsoft-netconf-browser-expand-entire-subtree.png) 81 | 82 | This shows an outline of the `interfaces` YANG module. 83 | 84 | ![MG-SOFT NetConf Browser - interfaces subtree](figures/mgsoft-netconf-browser-interfaces-subtree.png) 85 | 86 | # Connect to the NETCONF server 87 | 88 | To connect ot the clixon NETCONF server, select the File → Connect... menu item and enter the 89 | following information (replace 10.211.55.8 with the IP address of the virtual machine that runs 90 | your NETCONF server and replace parallels with the username on the virtual machine). 91 | 92 | ![MG-SOFT NetConf Browser - connect to server](figures/mgsoft-netconf-browser-connect-to-server.png) 93 | 94 | Note: until recently clixon had a bug that prevented it from interoperating with clients running 95 | NETCONF version 1.1 (see [clixon issue #314](https://github.com/clicon/clixon/issues/314)). 96 | The symptom is that the clixon server stops responding after the initial hello message. 97 | By the time you are reading this tutorial, that bug should already have been fixed, but if not, 98 | you can work around the issue by selecting NETCONF version → 1.0 in the connect screen. 99 | 100 | If you click on the Session History tab, you can see that the session is connected. 101 | 102 | ![MG-SOFT NetConf Browser - session connected](figures/mgsoft-netconf-browser-connected.png) 103 | 104 | # Retrieve the configuration 105 | 106 | To retrieve the current candidate configuration (for example), right-click on the interfaces 107 | module, and then select get config (execute) → candidate. 108 | 109 | ![MG-SOFT NetConf Browser - get config](figures/mgsoft-netconf-browser-get-config.png) 110 | 111 | The retrieved configuration is shown in XML format in the middle pane (which you can make 112 | bigger). Note: this screenshot assumes that two interfaces have been configured in the clixon CLI. 113 | 114 | ![MG-SOFT NetConf Browser - get config](figures/mgsoft-netconf-browser-config-xml.png) 115 | 116 | To display the same configuration in a more convenient graphical tree format, click 117 | on the Output Tree tab: 118 | 119 | ![MG-SOFT NetConf Browser - get config](figures/mgsoft-netconf-browser-config-tree.png) 120 | 121 | # Change the configuration 122 | 123 | To edit the candidate configuration, right-click on the interfaces 124 | module, and then select edit config (compose) → candidate. 125 | 126 | ![MG-SOFT NetConf Browser - get config](figures/mgsoft-netconf-browser-edit-config.png) 127 | 128 | The NETCONF Content Editor window will appear, in which you can change the configuration 129 | (here we changed the IP address for interface eth1 from 2.2.2.2 to 3.3.3.3). 130 | 131 | ![MG-SOFT NetConf Browser - config editor](figures/mgsoft-netconf-browser-edit-config-details.png) 132 | 133 | Note: the nixon NETCONF server does not accept an empty message identified, so you have to enter 134 | some value (any value) for the `message-id`. 135 | 136 | ![MG-SOFT NetConf Browser - message id](figures/mgsoft-netconf-browser-message-id.png) 137 | 138 | At this point you can validate the new configuration on the server by clicking on the 139 | Validate on Server button (yellow document with green checkmark): 140 | 141 | ![MG-SOFT NetConf Browser - validate ](figures/mgsoft-netconf-browser-validate.png) 142 | 143 | TODO: This does not work; MG-SOFT NetConf Browser reports an error: 144 | 145 | ```xml 146 | 147 | 148 | 149 | application 150 | operation-failed 151 | error 152 | open(/usr/local/var/interfaces/config_db) 153 | 154 | 155 | ``` 156 | 157 | For some reason, clixon tries to open `/usr/local/var/interfaces/config_db` which does not exist: 158 | 159 |
160 | $ ls -1 /usr/local/var/interfaces
161 | candidate_db
162 | running_db
163 | startup_db
164 | tmp_db
165 | 
166 | 167 | ## References 168 | 169 | * [The MG-SOFT company homepage](https://www.mg-soft.si/) 170 | 171 | * [The MG-SOFT NetConf Browser Professional Edition product page](https://www.mg-soft.si/mgNetConfBrowser.html) 172 | -------------------------------------------------------------------------------- /docs/mg-soft-designer.md: -------------------------------------------------------------------------------- 1 | # MG-SOFT Visual YANG Designer Professional Edition 2 | 3 | ## Introduction 4 | 5 | [MG-SOFT](https://www.mg-soft.si/) is a company that offers a suite of network management related 6 | products. 7 | One of their products, the 8 | [MG-SOFT Visual YANG Designer Professional Edition](https://www.mg-soft.si/mgYangDesigner.html) 9 | is a YANG authoring tool that allows you to edit YANG data models in an integrated development 10 | environment (IDE). 11 | 12 | ## Download and install 13 | 14 | You can download the MG-SOFT Visual YANG Designer Professional Edition from the 15 | [download page](https://www.mg-soft.si/download.html?product=yangdesigner&os=java) 16 | on the MG-SOFT website. 17 | The designer is available for Windows, macOS, and several flavors of Linux. 18 | In this tutorial I use the macOS version. 19 | 20 | To do anything interesting with the MG-SOFT Visual YANG Designer, you will need to apply a license key. 21 | You can [purchase a license online](https://www.mg-soft.si/mgYangDesigner-ordering.html) 22 | or you can [request a 30-day evaluation license online](https://www.mg-soft.si/evalKeyReq.html). 23 | The evaluation license does not allow you to save YANG files. 24 | Note: I am not affiliated with MG-SOFT in any way and I don't get any commission. 25 | 26 | ## Start 27 | 28 | Double click on the MG-SOFT Visual YANG Designer icon in the applications folder. 29 | 30 | ![MG-SOFT Visual YANG Designer icon](figures/mgsoft-yang-designer-icon.png) 31 | 32 | When you start the MG-SOFT Visual YANG Designer for the first time, it will give you the opportunity 33 | to install the evaluation license 34 | (you can also do this later using the Help → Apply License Key... menu item.) 35 | 36 | ![MG-SOFT Visual YANG Designer first time startup screen](figures/mgsoft-yang-designer-first-time.png) 37 | 38 | ## Create a new project 39 | 40 | After MG-SOFT Visual YANG Designer has been started, choose the Create a new project option: 41 | 42 | ![MG-SOFT Visual YANG Designer create a new project](figures/mgsoft-yang-designer-create-new-project.png) 43 | 44 | and enter the details for the newly created project: 45 | 46 | ![MG-SOFT Visual YANG Designer project details part one](figures/mgsoft-yang-designer-project-details.png) 47 | 48 | ![MG-SOFT Visual YANG Designer project details part two](figures/mgsoft-yang-designer-project-details-2.png) 49 | 50 | ## Create a new module 51 | 52 | Click on the new module button: 53 | 54 | ![MG-SOFT Visual YANG Designer new module button](figures/mgsoft-yang-designer-new-module-button.png) 55 | 56 | and enter the details for the newly created module: 57 | 58 | ![MG-SOFT Visual YANG Designer module details](figures/mgsoft-yang-designer-module-details.png) 59 | 60 | The newly created empty module is displayed: 61 | 62 | ![MG-SOFT Visual YANG Designer empty module](figures/mgsoft-yang-designer-empty-module.png) 63 | 64 | ## Add components to the module 65 | 66 | In the left Project panel click on the tab: 67 | 68 | ![MG-SOFT Visual YANG Designer components tab](figures/mgsoft-yang-designer-components-tab.png) 69 | 70 | Drag and drop components from the left Project panel to the middle YANG Tree Preview panel. 71 | As you are dropping the component into the middle YANG Tree Preview panel, 72 | you will see gray lines to indicate where the component is allowed to be dropped. 73 | After a component has been dropped in place, you can enter details for component in the top 74 | right Node Editor panel (in the screenshot below we are entering details for a newly added `burners` 75 | container). 76 | In the bottom right Source panel you can see and edit the source code for the YANG data model as 77 | it is being constructed. 78 | 79 | ![MG-SOFT Visual YANG Designer edit module](figures/mgsoft-yang-designer-edit-module.png) 80 | 81 | ## View the module source 82 | 83 | Click on the to see and edit the source code of the YANG data model in a 84 | larger Source panel in the top right: 85 | 86 | ![MG-SOFT Visual YANG Designer source code](figures/mgsoft-yang-designer-source-code.png) 87 | 88 | ## View errors 89 | 90 | If there are any errors in your YANG data models, you can see them in the 91 | tab in the bottom-right panel, and the offending lines 92 | are marked with a red exclamation mark in the source code: 93 | 94 | ![MG-SOFT Visual YANG Designer errors](figures/mgsoft-yang-designer-errors.png) 95 | 96 | ## References 97 | 98 | * [The MG-SOFT company homepage](https://www.mg-soft.si/) 99 | 100 | * [The MG-SOFT Visual YANG Designer Professional Edition product page](https://www.mg-soft.si/mgYangDesigner.html) 101 | -------------------------------------------------------------------------------- /docs/mg-soft-explorer.md: -------------------------------------------------------------------------------- 1 | # MG-SOFT YANG Explorer Professional Edition 2 | 3 | ## Introduction 4 | 5 | [MG-SOFT](https://www.mg-soft.si/) is a company that offers a suite of network management related 6 | products. 7 | One of their products, the 8 | [MG-SOFT YANG Explorer Professional Edition](https://www.mg-soft.si/mgYangExplorer.html) 9 | allows you to explore, validate, and convert YANG data models. 10 | 11 | ## Download and install 12 | 13 | You can download the MG-SOFT YANG Explorer Professional Edition from the 14 | [download page](https://www.mg-soft.si/download.html?product=yangexplorer&os=java) 15 | on the MG-SOFT website. 16 | The explorer is available for Windows, macOS, and several flavors of Linux. 17 | In this tutorial I use the macOS version. 18 | 19 | To do anything interesting with the MG-SOFT YANG Explorer, you will need to apply a license key. 20 | You can [purchase a license online](https://www.mg-soft.si/mgYangExplorer-ordering.html) 21 | or you can [request a 30-day evaluation license online](https://www.mg-soft.si/evalKeyReq.html). 22 | Note: I am not affiliated with MG-SOFT in any way and I don't get any commission. 23 | 24 | ## Start 25 | 26 | Double click on the MG-SOFT YANG Explorer icon in the applications folder. 27 | 28 | ![MG-SOFT YANG Explorer icon](figures/mgsoft-yang-explorer-icon.png) 29 | 30 | When you start the MG-SOFT YANG Explorer for the first time, it will give you the opportunity 31 | to install the evaluation license 32 | (you can also do this later using the Help → Apply License Key... menu item.) 33 | 34 | ![MG-SOFT YANG Explorer first time startup screen](figures/mgsoft-yang-explorer-first-time.png) 35 | 36 | After installing the license key, you end up in the following screen. 37 | On the left side you see a list of standard IETF YANG data models that come bundled with the 38 | MG-SOFT YANG Explorer. 39 | 40 | ![MG-SOFT YANG Explorer startup screen](figures/mgsoft-yang-explorer-startup.png) 41 | 42 | # Load a YANG data model 43 | 44 | The first thing we have to do is to load our `interfaces.yang` YANG data model into the 45 | MG-SOFT YANG Explorer. 46 | Select the Module → Load Module... menu item, and open the `interfaces.yang` file in this 47 | repository. 48 | 49 | ![MG-SOFT YANG Explorer - choose YANG module](figures/mgsoft-yang-explorer-choose-yang-file.png) 50 | 51 | # Explore a YANG data model 52 | 53 | The `interfaces` YANG module appears in the left pane; when you click on it, you get the details. 54 | 55 | ![MG-SOFT YANG Explorer - interfaces model details](figures/mgsoft-yang-explorer-interface-model-details.png) 56 | 57 | You can click on the triangle next to the `interfaces` YANG module to expand it one level, 58 | or you can right-click on the module and select Expand Entire Subtree: 59 | 60 | ![MG-SOFT YANG Explorer - interfaces model expanded subtree](figures/mgsoft-yang-explorer-interface-model-expanded-subtree.png) 61 | 62 | While in the tree pane, you can use menu item Edit → Find Nodes... (⌘F) to search for specific nodes. 63 | In the following screenshot we search for all leaf nodes that contain the word address: 64 | 65 | ![MG-SOFT YANG Explorer - find nodes](figures/mgsoft-yang-explorer-find-nodes.png) 66 | 67 | Clicking the tab displays the textual tree diagram: 68 | 69 | ![MG-SOFT YANG Explorer - interfaces model text tree](figures/mgsoft-yang-explorer-interface-model-text-tree.png) 70 | 71 | Clicking the tab displays the source code for the YANG data model: 72 | 73 | ![MG-SOFT YANG Explorer - interfaces model source](figures/mgsoft-yang-explorer-interface-model-source.png) 74 | 75 | Our `interfaces` example YANG module is very simple and doesn't import any other modules, 76 | but most real-life modules do. 77 | The following screenshot shows the standard IETF YANG module `ietf-ipv6-unicast-routing`. 78 | On line 15 it imports another YANG module `ietf-inet-types`. 79 | You can right-click on the `import` statement and select Show in YANG Tree to navigate to the 80 | imported module 81 | 82 | ![MG-SOFT YANG Explorer - show in YANG tree](figures/mgsoft-yang-explorer-show-in-yang-tree.png) 83 | 84 | ## View UML diagram 85 | 86 | Select menu item View → UML Class Diagram... and click on the 🔧 icon to select a YANG data model 87 | and displays its UML class diagram: 88 | 89 | ![MG-SOFT YANG Explorer - UML class diagram](figures/mgsoft-yang-explorer-uml-class-diagram.png) 90 | 91 | ## View dependencies 92 | 93 | Select menu item View → YANG Dependencies... and click on the 🔧 icon to select a YANG data model 94 | and displays its YANG dependencies: 95 | 96 | ![MG-SOFT YANG Explorer - dependencies](figures/mgsoft-yang-explorer-dependencies.png) 97 | 98 | ## References 99 | 100 | * [The MG-SOFT company homepage](https://www.mg-soft.si/) 101 | 102 | * [The MG-SOFT YANG Explorer Professional Edition product page](https://www.mg-soft.si/mgYangExplorer.html) 103 | -------------------------------------------------------------------------------- /docs/mg-soft-simulator.md: -------------------------------------------------------------------------------- 1 | # MG-SOFT NETCONF Simulator 2 | 3 | ## Introduction 4 | 5 | [MG-SOFT](https://www.mg-soft.si/) is a company that offers a suite of network management related 6 | products. 7 | One of their products, the 8 | [MG-SOFT NETCONF Simulator](https://www.mg-soft.si/mgNetConfSimulator.html) 9 | allows you to simulate network devices that act as NETCONF or RESTCONF servers. 10 | 11 | ## Download and install (attempt) 12 | 13 | You can download the MG-SOFT NETCONF Simulator Edition from the 14 | [download page](https://www.mg-soft.si/download.html?product=netconfsimulator) 15 | on the MG-SOFT website. 16 | The simulator is only available on Microsoft Windows. 17 | 18 | Unfortunately, I don't own any Windows computers. 19 | I tried using Microsoft Windows Server 2019 Base running in a t2.large instance on Amazon Web 20 | Services (AWS), but when I ran the MG-SOFT NETCONF Simulator installer, I got the following 21 | error message about needing a Java Run-time Environment (JRE): 22 | 23 | ![Foobar](figures/mgsoft-netconf-simulator-need-java.png) 24 | 25 | Downloading and installing "Java for Windows" from 26 | the [Oracle website](https://www.java.com/en/download/) did not solve the problem. 27 | I spent a half hour Googling how to download "64-bit JRE 1.8" but could not figure it out and 28 | eventually gave up. 29 | 30 | -------------------------------------------------------------------------------- /docs/ncclient.md: -------------------------------------------------------------------------------- 1 | # Ncclient 2 | 3 | ## Introduction 4 | 5 | [Ncclient](https://github.com/ncclient/ncclient) (short for NETCONF client) is an open source 6 | Python module that allows you to develop Python scripts that interact with a NETCONF server. 7 | 8 | One issue with this project is that the 9 | [documentation page](https://ncclient.readthedocs.io/en/latest/) 10 | appears to be broken for some time now (many pages contain lists of empty placeholders). 11 | So, you will have to be comfortable reading 12 | [the source code of `ncclient` on GitHub](https://github.com/ncclient/ncclient/tree/master/ncclient) 13 | as documentation of its API. 14 | 15 | ## Install ncclient 16 | 17 | If you followed the 18 | [instructions for setting up the environment for this tutorial](tutorial-install.md) 19 | then ncclient is already installed. 20 | 21 | Or, use `pip` if you want to install ncclient separately: 22 | 23 |
 24 | $ pip install ncclient
 25 | 
26 | 27 | ## Start the clixon NETCONF server 28 | 29 | The MG-SOFT NetConf browser is a NETCONF client, so we need a NETCONF server to be running. 30 | We will use clixon as the NETCONF server. 31 | Refer to the [clixon chapter in this tutorial](clixon.md) for instructions on how install clixon, 32 | how to build clixon, how the start the clixon backend daemon, and how to configure SSH to start 33 | the clixon NETCONF server. 34 | 35 | As a quick sanity check to make sure the NETCONF server is running properly, 36 | manually start an SSH session. You should see a NETCONF `hello` message from the server: 37 | 38 |
 39 | $ ssh localhost -s netconf
 40 | username@localhost's password: ******
 41 | urn:ietf:params:netconf:base:1.1urn:ietf:params:netconf:base:1.0urn:ietf:params:netconf:capability:candidate:1.0urn:ietf:params:netconf:capability:validate:1.1urn:ietf:params:netconf:capability:startup:1.0urn:ietf:params:netconf:capability:xpath:1.0urn:ietf:params:netconf:capability:notification:1.04]]>]]>
 42 | 
43 | 44 | Type Control-D to exit the SSH session. 45 | 46 | ## Example Python scripts 47 | 48 | This repository contains several example Python scripts that use the `ncclient` Python module. 49 | In the remainder of this chapter we will walk you through those examples. 50 | 51 |
 52 | $ cd ~/yang-tutorial/ncclient
 53 | 
 54 | $ ls -1
 55 | [TODO] output
 56 | 
57 | 58 | You may optionally set the following environment variables to configure the address, username, 59 | and password of the NETCONF server: 60 | 61 |
 62 | $ export NETCONF_SERVER_ADDRESS="10.0.0.99"       # Default: loopback address 127.0.0.1
 63 | $ export NETCONF_SERVER_USERNAME="jamesbond"      # Default: your current username
 64 | $ export NETCONF_SERVER_PASSWORD="topsecret"      # Default: none (certificate based authentication)
 65 | 
66 | 67 | 68 | TODO: Test certificate-based SSH authentication 69 | 70 | ## Show the running configuration 71 | 72 | TODO: Remove `device_params={'name': 'alu'}` from all examples; it should not be needed anymore 73 | now that the patch has been submitted to clixon. 74 | 75 | The first example script `show_config.py` shows the running configuration in prettified XML 76 | format: 77 | 78 | ```python 79 | from ncclient import manager 80 | from bs4 import BeautifulSoup 81 | import netconf_server_info 82 | 83 | with manager.connect(host=netconf_server_info.address(), 84 | port=830, 85 | username=netconf_server_info.username(), 86 | password=netconf_server_info.password(), 87 | hostkey_verify=False, 88 | device_params={'name': 'alu'}) as mgr: 89 | config_xml = mgr.get_config(source='running').data_xml 90 | print(BeautifulSoup(config_xml, 'xml').prettify()) 91 | ``` 92 | 93 | Module `netconf_server_info` is used to read the environment variables that contain the NETCONF 94 | server information: 95 | 96 | ```python 97 | import psutil 98 | import os 99 | 100 | def address(): 101 | address = os.getenv('NETCONF_SERVER_ADDRESS') 102 | if address is None: 103 | return '127.0.0.1' 104 | return address 105 | 106 | def username(): 107 | username = os.getenv('NETCONF_SERVER_USERNAME') 108 | if username is None: 109 | return psutil.Process().username() 110 | return username 111 | 112 | def password(): 113 | return os.getenv('NETCONF_SERVER_PASSWORD') 114 | ``` 115 | 116 | Running the `show_config.py` script produces the following out (this assumes we configured 117 | interface `eth0` using the clixon CLI): 118 | 119 | ```xml 120 | 121 | 122 | 123 | 124 | 125 | 126 | eth0 127 | 128 | 129 | 1.1.1.1 130 | 131 | 132 | 133 | 134 | 135 | ``` 136 | 137 | # Show the client and server capabilties 138 | 139 | The example script `show_capabilities.py` shows the NETCONF client (ncclient) and 140 | server (clixon) capabilities. 141 | 142 | ```python 143 | from ncclient import manager 144 | from bs4 import BeautifulSoup 145 | import netconf_server_info 146 | 147 | with manager.connect(host=netconf_server_info.address(), 148 | port=830, 149 | username=netconf_server_info.username(), 150 | password=netconf_server_info.password(), 151 | hostkey_verify=False, 152 | device_params={'name': 'alu'}) as mgr: 153 | print("Client capabilities:") 154 | for capability in mgr.client_capabilities: 155 | print(f" {capability}") 156 | print("Server capabilities:") 157 | for capability in mgr.server_capabilities: 158 | print(f" {capability}") 159 | ``` 160 | 161 | The output of this script is: 162 | 163 | ``` 164 | Client capabilities: 165 | urn:ietf:params:netconf:base:1.0 166 | Server capabilities: 167 | urn:ietf:params:netconf:base:1.1 168 | urn:ietf:params:netconf:base:1.0 169 | urn:ietf:params:netconf:capability:candidate:1.0 170 | urn:ietf:params:netconf:capability:validate:1.1 171 | urn:ietf:params:netconf:capability:startup:1.0 172 | urn:ietf:params:netconf:capability:xpath:1.0 173 | urn:ietf:params:netconf:capability:notification:1.0 174 | ``` 175 | 176 | # Edit the configuration 177 | 178 | The example script `edit_config.py` adds an interface to the configuration: 179 | 180 | ```python 181 | from ncclient import manager 182 | import netconf_server_info 183 | 184 | with manager.connect(host=netconf_server_info.address(), 185 | port=830, 186 | username=netconf_server_info.username(), 187 | password=netconf_server_info.password(), 188 | hostkey_verify=False, 189 | device_params={'name': 'alu'}) as mgr: 190 | 191 | cfg_interface = """ 192 | 193 | 194 | 195 | eth1 196 | 2.2.2.2 197 | 198 | 199 | 200 | """ 201 | reply = mgr.edit_config(config=cfg_interface) 202 | assert reply.xpath("/rpc-reply/ok") != [] 203 | reply = mgr.commit() 204 | assert reply.xpath("/rpc-reply/ok") != [] 205 | ``` 206 | 207 | After running this script, the clixon CLI shows interface `eth1` in the configuration: 208 | 209 |
210 | cli> show configuration
211 | interfaces {
212 |     interface {
213 |         name eth0;
214 |         ipv4-address 1.1.1.1;
215 |     }
216 |     interface {
217 |         name eth1;
218 |         ipv4-address 2.2.2.2;
219 |     }
220 | }
221 | 
222 | 223 | -------------------------------------------------------------------------------- /docs/netopeer2.md: -------------------------------------------------------------------------------- 1 | # Netopeer2 2 | 3 | ## Introduction 4 | 5 | [Netopeer2](https://github.com/CESNET/netopeer2) 6 | is an open source NETCONF server developed by 7 | [CESNET](https://www.cesnet.cz/cesnet/?lang=en), 8 | an association of universities of the Czech Republic and the Czech Academy of Sciences. 9 | 10 | ## Installation 11 | 12 | We use an AWS t2.medium instance with 8 GB of disk running Ubuntu server 22.04 LTS. 13 | 14 | Follow the netopeer2 installation instructions documented 15 | [here](https://github.com/CESNET/netopeer2#compilation-and-installation): 16 | 17 | Update `apt`: 18 | 19 |
 20 | $ sudo apt update
 21 | 
22 | 23 | If any of the following steps generates a popup window, use tab and enter to select Ok. 24 | 25 | Install `cmake`: 26 | 27 |
 28 | $ sudo apt install -y cmake
 29 | 
30 | 31 | Install `libpcre2-dev`: 32 | 33 |
 34 | $ sudo apt install -y libpcre2-dev
 35 | 
36 | 37 | Install `libssh-dev`: 38 | 39 |
 40 | $ sudo apt install -y libssh-dev
 41 | 
42 | 43 | Install `openssl`: 44 | 45 |
 46 | $ sudo apt install -y openssl
 47 | 
48 | 49 | Install `valgrind`: 50 | 51 |
 52 | $ sudo apt install -y valgrind
 53 | 
54 | 55 | Install `libcmocka-dev`: 56 | 57 |
 58 | $ sudo apt install -y libcmocka-dev
 59 | 
60 | 61 | Install `libsystemd-dev`: 62 | 63 |
 64 | $ sudo apt install -y libsystemd-dev
 65 | 
66 | 67 | Install `build-essential`: 68 | 69 |
 70 | $ sudo apt install -y build-essential
 71 | 
72 | 73 | Install `shunit2`: 74 | 75 |
 76 | $ sudo apt-get install -y shunit2
 77 | 
78 | 79 | Install `expect`: 80 | 81 |
 82 | $ sudo apt-get install -y expect
 83 | 
84 | 85 | Clone the `libyang` repo: 86 | 87 |
 88 | $ cd ~
 89 | $ git clone https://github.com/CESNET/libyang.git
 90 | 
91 | 92 | Build `libyang` from source code: 93 | 94 |
 95 | $ cd libyang
 96 | $ mkdir build
 97 | $ cd build
 98 | $ cmake ..
 99 | $ make
100 | $ sudo make install
101 | 
102 | 103 | Clone the `libnetconf2` repo: 104 | 105 |
106 | $ cd ~
107 | $ git clone https://github.com/CESNET/libnetconf2.git
108 | 
109 | 110 | Build `libnetconf2` from source code: 111 | 112 |
113 | $ cd libnetconf2
114 | $ mkdir build
115 | $ cd build
116 | $ cmake ..
117 | $ make
118 | $ sudo make install
119 | 
120 | 121 | Clone the `sysrepo` repo: 122 | 123 |
124 | $ cd ~
125 | $ git clone https://github.com/sysrepo/sysrepo
126 | 
127 | 128 | Build `sysrepo` from source code: 129 | 130 |
131 | $ cd sysrepo
132 | $ mkdir build
133 | $ cd build
134 | $ cmake ..
135 | $ make
136 | $ sudo make install
137 | 
138 | 139 | Clone the `netopeer2` repo: 140 | 141 |
142 | $ cd ~
143 | $ git clone https://github.com/CESNET/netopeer2.git
144 | 
145 | 146 | Build `netopeer2` from source code (note the extra `ldconfig` step): 147 | 148 |
149 | $ cd netopeer2
150 | $ mkdir build
151 | $ cd build
152 | $ cmake ..   
153 | $ make
154 | $ sudo ldconfig
155 | $ sudo make install
156 | 
157 | 158 | ## Verify installation 159 | 160 | Verify that `netopeer2-server` has been installed: 161 | 162 |
163 | $ netopeer2-server -V
164 | netopeer2-server 2.1.23
165 | 
166 | 167 | Verify that `netopeer2-cli` has been installed. Type `exit` to return to the shell. 168 | 169 |
170 | $ netopeer2-cli
171 | get_netconf_dir: Configuration directory "/home/ubuntu/.netopeer2-cli" did not exist, created.
172 | load_config: No saved history.
173 | load_config: No saved configuration.
174 | > exit
175 | $s
176 | 
177 | 178 | Note: manual pages are available for `netopeer2-server` and `netopeer2-cli`: 179 | 180 |
181 | $ man netopeer2-server
182 | $ man netopeer2-cli
183 | 
184 | 185 | Verify that `sysrepo` has been installed: 186 | 187 |
188 | $ sudo sysrepoctl -l
189 | Sysrepo repository: /home/ubuntu/sysrepo/build/repository
190 | 
191 | Module Name                   | Revision   | Flags | Owner         | Startup Perms | Submodules | Features                                                                                
192 | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
193 | iana-crypt-hash               | 2014-08-06 | i     |               |               |            |                                                                                         
194 | ietf-crypto-types             | 2019-07-02 | I     | ubuntu:ubuntu | 600           |            |                                                                                         
195 | ietf-datastores               | 2018-02-14 | I     | root:root     | 444           |            |                                                                                         
196 | ietf-inet-types               | 2013-07-15 | i     |               |               |            |                                                                                         
197 | ietf-interfaces               | 2018-02-20 | I     | ubuntu:ubuntu | 600           |            |                                                                                         
198 | ietf-ip                       | 2018-02-22 | I     | ubuntu:ubuntu | 600           |            |                                                                                         
199 | ietf-keystore                 | 2019-07-02 | I     | ubuntu:ubuntu | 600           |            | keystore-supported                                                                      
200 | ietf-netconf                  | 2013-09-29 | I     | ubuntu:ubuntu | 600           |            | writable-running candidate confirmed-commit rollback-on-error validate startup url xpath
201 | ietf-netconf-acm              | 2018-02-14 | I     | root:root     | 600           |            |         
202 | ...
203 | 
204 | 205 | ## Set a password for user `ubuntu` 206 | 207 | Set the password for user `ubuntu` to `secret` to allows `netopeer2-cli` 208 | (the NETCONF client) to use password authentication (for now) when connecting to 209 | `netopeer2-server` (the NETCONF server): 210 | 211 |
212 | $ sudo passwd ubuntu
213 | New password: secret
214 | Retype new password: secret
215 | 
216 | 217 | ## Start the NETCONF server 218 | 219 | Start the `netopeer2-server` NETCONF server as a daemon: 220 | 221 |
222 | $ cd ~
223 | $ sudo netopeer2-server
224 | $
225 | 
226 | 227 | Verify that the server is running: 228 | 229 |
230 | $ ps aux | grep netopeer2-server
231 | root       18132  0.1  0.1 337832  7372 ?        Ssl  10:54   0:00 netopeer2-server
232 | ubuntu     18144  0.0  0.0   7008  2120 pts/0    S+   10:55   0:00 grep --color=auto netopeer2-server
233 | 
234 | 235 | 236 | ## Start the NETCONF client 237 | 238 | Start the `netopeer2-cli` NETCONF client: 239 | 240 |
241 | $ cd ~
242 | $ netopeer2-client
243 | >
244 | 
245 | 246 | Enter `help` to see the list of client commands: 247 | 248 |
249 | > help
250 | Available commands:
251 |   auth            Manage SSH authentication options
252 |   knownhosts      Manage the user knownhosts file
253 |   ...
254 |   exit            Quit the program
255 | >
256 | 
257 | 258 | Connect the client to the server (running on the same host) 259 | 260 |
261 | > connect
262 | Interactive SSH Authentication
263 | Type your password:
264 | Password: secret
265 | >
266 | 
267 | 268 | Retrieve the running configuration: 269 | 270 |
271 | > get-config --source running
272 | 
273 | ``` 274 | DATA 275 | 276 | 277 | 278 | 279 | genkey 280 | rsa2048 281 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqIbDXmMsEeQKJhOP9gn4IIO/MwijcOpB9AxjYdMa/WEYjacNXOWAzFHsO8OuYi8gYGo69M+2XtdF4xid3hoE9HPlE3/tOnMA7UBbtbPoYSKei5wN8zobUmtbwJyRHJciyShDKUS8zxM+2P1FoqjIzg0Il3ELfUnxmWoCvDOz1ekkRISuKxDTz2PLnPEqr2HyuBxkMBBRudxfkSfFSQhB7rjPg0UolGOUP+ffOTJuWeodYNnX9NXPc/kKnTNhD2423pANGjFJbM56H6GUpBIDpzuTo6+ds+NcZgYJazk1OiIXpEqLadgVa4nxe/BtbUZYvIccMNbxP4nl6QukjU/74QIDAQAB 282 | 283 | 284 | 285 | 286 | 287 | 288 | default-ssh 289 | 290 | 291 | 0.0.0.0 292 | 293 | 1 294 | 10 295 | 5 296 | 297 | 298 | 299 | 300 | 301 | default-key 302 | 303 | genkey 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | interactive 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | ``` 321 | 322 | 323 | ## TODO 324 | 325 | * Certificate-based authentication 326 | 327 | * The fancier NETCONF command-line client 328 | 329 | * The NETCONF client GUI 330 | 331 | * Loading our own YANG data model 332 | 333 | * Implementing the back-end for our own YANG data model 334 | 335 | ## References 336 | 337 | * [Netopeer2 GitHub repo](https://github.com/CESNET/netopeer2) 338 | 339 | * [Libyang GitHub repo](https://github.com/CESNET/libyang.git) 340 | 341 | * [Libnetconf2 GitHub repo](https://github.com/CESNET/libnetconf2.git) 342 | 343 | * [Sysrepo homepage](https://www.sysrepo.org/) 344 | 345 | * [Sysrepo GitHub repo](https://github.com/sysrepo/sysrepo) 346 | -------------------------------------------------------------------------------- /docs/pyang.md: -------------------------------------------------------------------------------- 1 | # Pyang 2 | 3 | ## Introduction 4 | 5 | [Pyang](https://github.com/mbj4668/pyang) is an open source YANG validator, transformer, and 6 | code generator, written in Python. 7 | 8 | ## Install Pyang 9 | 10 | If you haven't already done so, follow the instructions for 11 | [setting up the environment for this tutorial](tutorial-install.md) page. 12 | 13 | Make sure your Python virtual environment is active: 14 | 15 |
 16 | $ cd ~/yang-tutorial
 17 | $ source venv/bin/activate
 18 | (env) $
 19 | 
20 | 21 | Install `pyang` into your virtual environment: 22 | 23 |
 24 | $ pip install pyang
 25 | 
26 | 27 | Verify that `pyang` is properly installed: 28 | 29 |
 30 | $ pyang --version
 31 | pyang 2.5.2
 32 | 
33 | 34 | One of the examples in the tutorial converts the YANG data model into a UML diagram. 35 | This requires [PlantUML](https://plantuml.com/) to be installed: 36 | 37 |
 38 | $ sudo apt install -y plantuml
 39 | 
40 | 41 | ## Pyang: Validating a YANG data model 42 | 43 | The simplest way of using pyang is to validate the correctness of a YANG data model: 44 | 45 |
 46 | $ pyang interfaces.yang
 47 | 
48 | 49 | The fact that we get no output means that the YANG file was correct. In addition, the program 50 | returns status code zero, so you can do something like this: 51 | 52 |
 53 | $ if pyang interfaces.yang; then echo "All good"; else "There are errors"; fi
 54 | All good
 55 | 
56 | 57 | Validate YANG data model `bad-interfaces.yang` to see an example of the error messages produced 58 | by `pyang`: 59 | 60 |
 61 | $ pyang bad-interfaces.yang
 62 | bad-interfaces.yang:7: error: unexpected keyword "organisation"
 63 | bad-interfaces.yang:47: error: type "uint46" not found in module "bad-interfaces"
 64 | 
65 | 66 | ## Pyang: Converting a YANG data model 67 | 68 | YANG data models tend to be very long and verbose. Pyang can produce a summary of the YANG data 69 | model in a tree format: 70 | 71 |
 72 | $ pyang -f tree interfaces.yang
 73 | module: interfaces
 74 |   +--rw interfaces
 75 |      +--rw interface* [name]
 76 |         +--rw name                string
 77 |         +--rw ipv4-address?       string
 78 |         +--ro sent-packets?       uint64
 79 |         +--ro received-packets?   uint64
 80 | 
81 | 82 | The command `pyang --tree-help` displays an explanation of the symbols in the tree diagram. 83 | 84 | In addition to producing a tree summary, Pyang can also convert the YANG data model to many other 85 | formats: 86 | 87 |
 88 | $ pyang --help
 89 | Usage: pyang [options] [<filename>...]
 90 | 
 91 | Validates the YANG module in <filename> (or stdin), and all its dependencies.
 92 | 
 93 | Options:
 94 |   -h, --help            Show this help message and exit
 95 | [...]
 96 |   -f FORMAT, --format=FORMAT
 97 |                         Convert to FORMAT.  Supported formats are: yang, yin,
 98 |                         dsdl, omni, tree, jstree, flatten, uml, identifiers,
 99 |                         sample-xml-skeleton, capability, jsonxsl, depend,
100 |                         jtox, name
101 | [...]
102 | 
103 | 104 | We will give just a couple of examples of interesting format conversions. 105 | 106 | Use the following command to produce an HTML file that describes the YANG data model 107 | (`jstree` stands for JavaScript tree): 108 | 109 |
110 | $ pyang -f jstree interfaces.yang > interfaces.html
111 | 
112 | 113 | Use any web browser to view the produced HTML file. Here we assume that you are running Ubuntu and 114 | that you can start `firefox` from command line (on macOS use `open interfaces.html`): 115 | 116 |
117 | $ firefox interfaces.html
118 | 
119 | 120 | ![Pyang jstree diagram](figures/pyang-jstree-diagram.png) 121 | 122 | Another interesting option is to convert the YANG data model into a UML diagram: 123 | 124 |
125 | $ pyang -f uml interfaces.yang > interfaces.uml
126 | 
127 | 128 | You need to have `plantuml` installed (see 129 | [pyang installation instructions](#pyang-installation-instructions) 130 | ) to convert the produced UML text file to a graphical PNG file: 131 | 132 |
133 | $ plantuml interfaces.uml
134 | 
135 | 136 | The PNG file can be viewed in a web browser: 137 | 138 |
139 | $ firefox img/interfaces.png
140 | 
141 | 142 | ![Pyang uml diagram](figures/pyang-uml-diagram.png) 143 | 144 | ## References 145 | 146 | * [The pyang GitHub repository](https://github.com/mbj4668/pyang) 147 | 148 | * [A pyang tutorial](https://www.ietf.org/slides/slides-edu-pyang-tutorial-01.pdf) 149 | 150 | * [The PlantUML home page](https://plantuml.com/) 151 | 152 | -------------------------------------------------------------------------------- /docs/references.md: -------------------------------------------------------------------------------- 1 | # References 2 | 3 | ## Standards 4 | 5 | ### YANG 6 | 7 | The most important standards that define the YANG data modeling language are: 8 | 9 | * [RFC 6020: YANG - A Data Modeling Language for the Network Configuration Protocol (NETCONF)](https://datatracker.ietf.org/doc/html/rfc6020) 10 | * [RFC 6244: An Architecture for Network Management Using NETCONF and YANG](https://datatracker.ietf.org/doc/html/rfc6244) 11 | * [RFC 7950: The YANG 1.1 Data Modeling Language](https://datatracker.ietf.org/doc/html/rfc7950) 12 | * [RFC 8407: Guidelines for Authors and Reviewers of Documents Containing YANG Data Models](https://datatracker.ietf.org/doc/html/rfc8407) 13 | 14 | For a complete list of YANG related standards see [IETF NETMOD standards](https://datatracker.ietf.org/wg/netmod/documents/) 15 | 16 | ### NETMOD 17 | 18 | * [The IETF NETMOD working group](https://datatracker.ietf.org/wg/netmod/about/) 19 | * [IETF NETMOD standards](https://datatracker.ietf.org/wg/netmod/documents/) 20 | 21 | ### NETCONF 22 | 23 | * [The IETF NETCONF working group](https://datatracker.ietf.org/wg/netconf/about/) 24 | * [IETF NETCONF standards](https://datatracker.ietf.org/wg/netconf/documents/) 25 | 26 | ### RESTCONF 27 | 28 | TODO 29 | 30 | ### gNMI 31 | 32 | TODO 33 | 34 | ## Tutorials 35 | 36 | * [Learn YANG - Full Tutorial for Beginners (Ultra Config)](https://ultraconfig.com.au/blog/learn-yang-full-tutorial-for-beginners/) 37 | -------------------------------------------------------------------------------- /docs/tail-f-confd.md: -------------------------------------------------------------------------------- 1 | # Tail-f ConfD 2 | 3 | ## Introduction 4 | 5 | [Tail-f](https://www.tail-f.com/) is a company that specializes in network programmability and 6 | data model driven device management. 7 | Tail-f was acquired by [Cisco](https://www.cisco.com/) in 2014. 8 | 9 | One of their products is ConfD: an on-device network management agent that uses YANG data modeling, 10 | that provides NETCONF and RESTCONF management protocols as well as a command line interface (CLI), 11 | and that provides a centralized transactional configuration database. 12 | 13 | Tail-f ConfD comes in two versions: 14 | [ConfD premium](https://www.tail-f.com/management-agent/) which is a paid version, 15 | and [ConfD basic](https://www.tail-f.com/confd-basic/) which is a free version with a subset 16 | of the features. 17 | 18 | In this tutorial we use the ConfD basic running on Ubuntu. 19 | 20 | TODO: I cannot download ConfD basic. The Tail-f website reports 21 | "ConfD Basic Downloads are temporarily disabled. Please contact confdbasicinfo@cisco.com with any 22 | questions you may have.” 23 | 24 | ## References 25 | 26 | * [The tail-f company homepage (a Cisco company)](https://www.tail-f.com/) 27 | 28 | * [The CONFD basic product homepage](https://www.tail-f.com/confd-basic/) 29 | 30 | * [The CONFD premium product homepage](https://www.tail-f.com/management-agent/) 31 | -------------------------------------------------------------------------------- /docs/tutorial-install.md: -------------------------------------------------------------------------------- 1 | # Setting up the environment for this tutorial 2 | 3 | ## Cloning and setting up this repository 4 | 5 | Clone this repository: 6 | 7 |
 8 | $ git clone https://github.com/brunorijsman/yang-tutorial.git
 9 | Cloning into 'yang-tutorial'...
10 | remote: Enumerating objects: 32, done.
11 | remote: Counting objects: 100% (32/32), done.
12 | remote: Compressing objects: 100% (21/21), done.
13 | remote: Total 32 (delta 8), reused 29 (delta 5), pack-reused 0
14 | Unpacking objects: 100% (32/32), 848.05 KiB | 1.58 MiB/s, done.
15 | 
16 | 17 | In the remainder of this tutorial I will assume that you cloned the repository into your home 18 | directory. If not, replace `~` with whatever directory you cloned the repository into. 19 | 20 | ## Setting up a python virtual environment 21 | 22 | Make sure that we have version 3.8 or higher of Python installed: 23 | 24 |
25 | $ python3 --version
26 | Python 3.8.10
27 | 
28 | 29 | Create a Python virtual environment: 30 | 31 |
32 | $ cd yang-tutorial
33 | $ python3 -m venv venv
34 | 
35 | 36 | Activate the Python virtual environment: 37 | 38 |
39 | $ source venv/bin/activate
40 | (venv) $
41 | 
42 | 43 | Install the Python dependencies: 44 | 45 |
46 | $ pip install -r requirements.txt
47 | Collecting lxml==4.8.0
48 |   Using cached lxml-4.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl (6.9 MB)
49 | Collecting pyang==2.5.2
50 |   Using cached pyang-2.5.2-py2.py3-none-any.whl (595 kB)
51 | Installing collected packages: lxml, pyang
52 | Successfully installed lxml-4.8.0 pyang-2.5.2
53 | 
54 | -------------------------------------------------------------------------------- /docs/yang-validator.md: -------------------------------------------------------------------------------- 1 | # YANG validator 2 | 3 | ## Introduction 4 | 5 | [YANG validator](https://yangcatalog.org/yangvalidator) is a web-based YANG data model validator. 6 | It is part of the [YANG catalog](https://yangcatalog.org/home.html) website. 7 | 8 | The home page of the YANG validator looks like this: 9 | 10 | ![YANG validator - home page](figures/yang-validator-home.png) 11 | 12 | ## Validate a correct YANG data model 13 | 14 | To validate the `interfaces.yang` data model, click the 15 | 16 | button in the 17 | "I have one or multiple YANG files and I want to validate them" 18 | section, select file `interfaces.yang` and then click the 19 | 20 | button. 21 | 22 | The validation results page reports the following results: 23 | 24 | * Extraction results from [XYM](https://github.com/xym-tool/xym) which is a tool to extract YANG data models 25 | from a file (e.g. an IETF ID or RFC). 26 | 27 | * Validation results from the pyang YANG validator. 28 | See the [pyang page in this tutorial](tutorial/payng.md) for more details on pyang. 29 | 30 | * Validation results from the Cisco Tail-f ConfD YANG compiler. 31 | See the [CONFD page in this tutorial](tutorial/confd.md) (TODO) for more details on ConfD. 32 | 33 | * Validation results from the yanglint YANG validator. 34 | See the [yanglint page in this tutorial](tutorial/yanglint.md) for more details on yanglint. 35 | 36 | * Validation results from the YumaWorks yangdump-pro YANG validator. 37 | See the [yangdump-pro page in this tutorial](tutorial/yangdump-pro.md) (TODO) for more details on yangdump-pro. 38 | 39 | ![YANG validator - good validation results ](figures/yang-validator-validation-good.png) 40 | 41 | ## Validate an incorrect YANG data model 42 | 43 | The following screenshot shows an example of validating an incorrect YANG data model, 44 | namely `bad-interfaces.yang`. 45 | 46 | ![YANG validator - bad validation results ](figures/yang-validator-validation-bad.png) 47 | 48 | ## Validate an IETF internet draft (ID) or request for comment (RFC) 49 | 50 | YANG validator can also validate an IETF internet draft (ID) or request for comment (RFC) 51 | that contains YANG data models (as described in section 3.2 of 52 | [RFC 8407](https://datatracker.ietf.org/doc/rfc8407/)). 53 | 54 | For example, enter [8348](https://datatracker.ietf.org/doc/rfc8348/) 55 | in the field in the 56 | "I know the number of IETF RFC and I want to validate it" 57 | section, then click the 58 | 59 | button, and accept the default values in the "Additional Information Required" window 60 | 61 | ## References 62 | 63 | * [YANG Validator home page](https://yangcatalog.org/yangvalidator) 64 | 65 | * [XYM YANG data model extraction tool](https://github.com/xym-tool/xym) 66 | -------------------------------------------------------------------------------- /docs/yanglint.md: -------------------------------------------------------------------------------- 1 | # Yanglint 2 | 3 | ## Introduction 4 | 5 | [Yanglint](https://www.mankier.com/1/yanglint) 6 | is command-line tool for validating and converting YANG schemas and YANG modeled data. 7 | It is part of the [libyang](https://github.com/CESNET/libyang) open source project and 8 | implemented in C. 9 | 10 | ## Install Yanglint 11 | 12 | Install `yang-tools` (which includes `yanglint`). On Ubuntu this can be done as follows: 13 | 14 |
 15 | $ sudo apt install -y yang-tools
 16 | 
17 | 18 | Verify that `yanglint` is properly installed: 19 | 20 |
 21 | $ yanglint --version
 22 | yanglint 0.16.105
 23 | 
24 | 25 | ## Validate a YANG data model 26 | 27 | The simplest way of using `yanglint` is to validate the correctness of a YANG data model: 28 | 29 |
 30 | $ yanglint interfaces.yang
 31 | 
32 | 33 | The fact that we get no output means that the YANG file was correct. In addition, the program 34 | returns status code zero, so you can do something like this: 35 | 36 |
 37 | $ if yanglint interfaces.yang; then echo "All good"; else "There are errors"; fi
 38 | All good
 39 | 
40 | 41 | Validate YANG data model `bad-interfaces.yang` to see an example of the error messages produced 42 | by `yanglint` (note hat unlike `pyang`, `yanglint` stops after the first error). 43 | 44 |
 45 | $ yanglint bad-interfaces.yang
 46 | err : Invalid keyword "organisation".
 47 | err : Module "bad-interfaces" parsing failed.
 48 | 
49 | 50 | 51 | ## Convert a YANG data model 52 | 53 | YANG data models tend to be very long and verbose. Yanglint can produce a summary of the YANG data 54 | model in a tree format: 55 | 56 |
 57 | $ yanglint -f tree interfaces.yang
 58 | module: interfaces
 59 |   +--rw interfaces
 60 |      +--rw interface* [name]
 61 |         +--rw name                string
 62 |         +--rw ipv4-address?       string
 63 |         +--ro sent-packets?       uint64
 64 |         +--ro received-packets?   uint64
 65 | 
66 | 67 | The command `yanglint --tree-help` displays an explanation of the symbols in the tree diagram. 68 | 69 | In addition to producing a tree summary, Yanglint can also convert the YANG data model to 70 | several other formats: 71 | 72 |
 73 | $ yanglint --help
 74 | Usage:
 75 |     yanglint [options] [-f { yang | yin | tree | tree-rfc | jsons}] <file>...
 76 |         Validates the YANG module in <file>, and all its dependencies.
 77 | 
 78 |     yanglint [options] [-f { xml | json }] <schema>... <file>...
 79 |         Validates the YANG modeled data in <file> according to the <schema>.
 80 | 
 81 |     yanglint
 82 |         Starts interactive mode with more features.
 83 | 
 84 | Options:
 85 |   -h, --help            Show this help message and exit.
 86 | 
 87 | [...]
 88 | 
 89 |   -f FORMAT, --format=FORMAT
 90 |                         Convert to FORMAT. Supported formats: 
 91 |                         yang, yin, tree and jsons (JSON) for schemas,
 92 |                         xml, json for data.
 93 | 
 94 | [...]
 95 | 
96 | 97 | 98 | As an example, the following example converts the YANG data model to JSON: 99 | 100 |
101 | $ yanglint -f jsons interfaces.yang
102 | {"interfaces":{"namespace":"http://remoteautonomy.com/yang-schemas/interfaces","prefix":"intf","description":{"text":"A simplistic tutorial data model for interfaces on a device."},"organization":{"text":"Remote Autonomy"},"contact":{"text":"Bruno Rijsman\u000Abrunorijsman@remoteautonomy.com"},"yang-version":{"value":"1.0"},"revision":{"2022-03-12":{"description":{"text":"Initial revision."}}},"data":{"interfaces":{"nodetype":"container"}}}}
103 | 
104 | 105 | The JSON output is more readable if you pretty print it using [jq](https://manpages.ubuntu.com/manpages/bionic/man1/jq.1.html): 106 | 107 |
108 | $ yanglint -f jsons interfaces.yang | jq
109 | {
110 |   "interfaces": {
111 |     "namespace": "http://remoteautonomy.com/yang-schemas/interfaces",
112 |     "prefix": "intf",
113 |     "description": {
114 |       "text": "A simplistic tutorial data model for interfaces on a device."
115 |     },
116 |     "organization": {
117 |       "text": "Remote Autonomy"
118 |     },
119 |     "contact": {
120 |       "text": "Bruno Rijsman\nbrunorijsman@remoteautonomy.com"
121 |     },
122 |     "yang-version": {
123 |       "value": "1.0"
124 |     },
125 |     "revision": {
126 |       "2022-03-12": {
127 |         "description": {
128 |           "text": "Initial revision."
129 |         }
130 |       }
131 |     },
132 |     "data": {
133 |       "interfaces": {
134 |         "nodetype": "container"
135 |       }
136 |     }
137 |   }
138 | }
139 | 
140 | 141 | ## Interactive mode 142 | 143 | It is also possible to run `yanglint` in interactive mode: 144 | 145 |
146 | $ yanglint
147 | > load interfaces
148 | > print interfaces
149 | module: interfaces
150 |   +--rw interfaces
151 |      +--rw interface* [name]
152 |         +--rw name                string
153 |         +--rw ipv4-address?       string
154 |         +--ro sent-packets?       uint64
155 |         +--ro received-packets?   uint64
156 | > print interfaces -f jsons
157 | {"interfaces":{"namespace":"http://remoteautonomy.com/yang-schemas/interfaces","prefix":"intf","description":{"text":"A simplistic tutorial data model for interfaces on a device."},"organization":{"text":"Remote Autonomy"},"contact":{"text":"Bruno Rijsman\u000Abrunorijsman@remoteautonomy.com"},"yang-version":{"value":"1.0"},"revision":{"2022-03-12":{"description":{"text":"Initial revision."}}},"data":{"interfaces":{"nodetype":"container"}}}}
158 | > quit
159 | 
160 | 161 | ## Validate and convert instance data 162 | 163 | In addition to validating and converting data models, `yanglint` can also validate that instance 164 | data confirms to a given data model and convert instance data. 165 | 166 | Consider the following instance data in XML format (these are the contents of file 167 | [`yanglint/data.xml`](https://github.com/brunorijsman/yang-tutorial/blob/main/yanglint/data.xml) 168 | in the YANG tutorial repo): 169 | 170 | ```xml 171 | 172 | 173 | eth1 174 | 1.1.1.1 175 | 176 | 177 | eth2 178 | 2.2.2.2 179 | 180 | 181 | ``` 182 | 183 | The following sequence of commends in `yanglint` interactive mode validates that the above 184 | instance data confirms to the `interfaces.yang` data model and converts the instance data from 185 | XML to JSON: 186 | 187 |
188 | $ yanglint
189 | > load interfaces
190 | > data -s -t config yanglint/data.xml -f json
191 | {
192 |   "interfaces:interfaces": {
193 |     "interface": [
194 |       {
195 |         "name": "eth1",
196 |         "ipv4-address": "1.1.1.1"
197 |       },
198 |       {
199 |         "name": "eth2",
200 |         "ipv4-address": "2.2.2.2"
201 |       }
202 |     ]
203 |   }
204 | }
205 | 
206 | 207 | Here the `-s` option enables strict validation, the `-t config` option indicates that we are 208 | validating configuration data, and the `-f json` option indicates that the instance data must 209 | be converted to JSON. 210 | 211 | We can also perform the instance data validation and conversion from the command-line: 212 | 213 |
214 | $ yanglint -s -t config yanglint/data.xml -f json interfaces.yang
215 | {
216 |   "interfaces:interfaces": {
217 |     "interface": [
218 |       {
219 |         "name": "eth1",
220 |         "ipv4-address": "1.1.1.1"
221 |       },
222 |       {
223 |         "name": "eth2",
224 |         "ipv4-address": "2.2.2.2"
225 |       }
226 |     ]
227 |   }
228 | }
229 | 
230 | 231 | Now, to demonstration a validation failure, 232 | consider the following instance data in XML format (these are the contents of file 233 | [`yanglint/bad-data.xml`](https://github.com/brunorijsman/yang-tutorial/blob/main/yanglint/bad-data.xml) 234 | in the YANG tutorial repo). 235 | Note that the IPv4 address is invalid (the first byte 300 is not in the range 0-255). 236 | 237 | ```xml 238 | 239 | 240 | eth 241 | 300.1.1.1 242 | 243 | 244 | ``` 245 | 246 | Validating this instance data produces the following error message: 247 | 248 |
249 | $ yanglint -s -t config yanglint/bad-data.xml -f json interfaces.yang
250 | err : Value "300.1.1.1" does not satisfy the constraint "(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])" (range, length, or pattern). (/interfaces:interfaces/interface[name='eth']/ipv4-address)
251 | 
252 | 253 | ## References 254 | 255 | * [The yanglint manual page](https://www.mankier.com/1/yanglint) 256 | 257 | * [The libyang GitHub repository](https://github.com/CESNET/libyang) 258 | 259 | -------------------------------------------------------------------------------- /docs/yuma-pro-client.md: -------------------------------------------------------------------------------- 1 | # YumaPro yangdump-pro from YumaWorks 2 | 3 | ## Introduction 4 | 5 | [YumaWorks](https://www.yumaworks.com/) is a company that offers a suite of network management 6 | and control plane automation tools, with a focus on YANG, NETCONF, and RESTCONF. 7 | 8 | Their product [YumaPro Client](https://www.yumaworks.com/download/yumapro-client-21-10-5-zip/) 9 | consists of three tools: 10 | 11 | 1. yangdump-pro: [TODO] Summary 12 | 13 | 2. yangdiff-pro: [TODO] Summary 14 | 15 | 3. yangcli-pro: [TODO] Summary 16 | 17 | 18 | YumaPro Client also includes an installer for YumaBench, but we discuss YumaBench separately 19 | [here](yumabench.md). 20 | 21 | The YumaPro Client software is free. 22 | The license allows you to use it 23 | "for internal use only, for the sole purpose of defining and managing networking devices 24 | on its own internal (enterprise) network." 25 | Note: I am not affiliated with YumaWorks in any way and I don't get any commission. 26 | 27 | ## Download and install 28 | 29 | 30 | You can download the YumaPro Client software from the 31 | [download page](https://www.yumaworks.com/support/download-yumapro-client/) 32 | It is available for macOS and for several Linux distributions. 33 | I evaluated version 21.10-5 for macOS. 34 | 35 | The installation procedure downloads a zip file with the following contents: 36 | 37 | ``` 38 | . 39 | ├── etc 40 | │   └── yumapro 41 | │   ├── yangcli-pro-sample.conf 42 | │   ├── yangdiff-pro-sample.conf 43 | │   └── yangdump-pro-sample.conf 44 | └── usr 45 | └── local 46 | ├── bin 47 | │   ├── yangcli-pro 48 | │   ├── yangdiff-pro 49 | │   ├── yangdump-pro 50 | │   └── yumabench-mac-os-installer 51 | ├── lib 52 | │   ├── libyumapro_mgr.dylib 53 | │   ├── libyumapro_ncx.dylib 54 | │   └── libyumapro_ycli.dylib 55 | └── share 56 | ├── doc 57 | │   └── yumapro 58 | │   ├── AUTHORS 59 | │   ├── README.yumapro-client 60 | │   ├── yumapro-client-user-license.pdf 61 | │   └── yumapro-legal-notices.pdf 62 | ├── man 63 | │   └── man1 64 | │   ├── yangcli-pro.1.gz 65 | │   ├── yangdiff-pro.1.gz 66 | │   ├── yangdump-pro.1.gz 67 | │   └── yumabench-mac-os-installer.1.gz 68 | └── yumapro 69 | └── modules 70 | ├── ietf 71 | │   └── RFC 72 | │   ├── iana-crypt-hash.yang 73 | │   ├── iana-hardware.yang 74 | ... ... 75 | │   └── notifications.yang 76 | ├── mib 77 | │   ├── IANAifType-MIB.yang 78 | │   ├── IF-MIB.yang 79 | ... ... 80 | │   └── yang-smi.yang 81 | ├── netconfcentral 82 | │   ├── toaster.yang 83 | │   ├── yuma-app-common.yang 84 | ... ... 85 | │   └── yuma-xsd.yang 86 | └── yumaworks 87 | ├── example-fan.yang 88 | ├── netconfd-pro.yang 89 | ... ... 90 | └── yumaworks-yp-ha.yang 91 | ``` 92 | 93 | ## Getting the executables to run 94 | 95 | The directory `usr/local/bin` in the downloaded zip file contains the executables 96 | `yangcli-pro`, `yangdiff-pro`, and `yangdump-pro`. 97 | When you try to run any of these executables for the first time, you get an error 98 | similar to the following: 99 | 100 | ![YumaPro Client Execute Error 1](figures/yuma-pro-client-execute-error-1.png) 101 | 102 | When that happens, click on cancel. 103 | Then open the System Preferences app, 104 | go into the Security & Privacy tab, and click the Allow Anyway button next to the warning 105 | "yangdump-pro" was blocked from use because it is not from an identified developer. 106 | When you run the executable again, click op Open when you get the following warning: 107 | 108 | ![YumaPro Client Execute Error 2](figures/yuma-pro-client-execute-error-2.png) 109 | 110 | When you click on Open, you get an error similar to the following: 111 | 112 |
113 | $ ./yangdump-pro
114 | dyld: Library not loaded: libyumapro_ncx.dylib
115 |   Referenced from: /Users/brunorijsman/Downloads/yumapro-client-21.10-5/usr/local/bin/./yangdump-pro
116 |   Reason: image not found
117 | [1]    31095 abort      ./yangdump-pro
118 | 
119 | 120 | The next attempt to run the tool complains that the shared library cannot be verified: 121 | 122 | ![YumaPro Client Execute Error 3](figures/yuma-pro-client-execute-error-3.png) 123 | 124 | As before, go into System Preferences at click Allow Anyway. 125 | 126 | The next attempt to run the tool complains that it developer of the shared library cannot be 127 | verified: 128 | 129 | ![YumaPro Client Execute Error 4](figures/yuma-pro-client-execute-error-4.png) 130 | 131 | Once again, click Open. 132 | 133 | Now you get the following error message: 134 | 135 |
136 |  $ ./yangdump-pro
137 | 
138 | Load module 'yuma-ncx' failed (module not found)
139 | yangdump-sdk: Error exit (module not found)
140 | 
141 | 142 | To work around this error, 143 | (1) add `usr/local/bin` to the PATH, 144 | (2) run the tool from the `usr/local/share/yumapro/modules` directory, 145 | (3) use the `--modpath=.` command line option: 146 | 147 |
148 | $ export PATH=${PATH}:~/Downloads/yumapro-client-21.10-5/usr/local/bin
149 | $ cd ~/Downloads/yumapro-client-21.10-5/usr/local/share/yumapro/modules
150 | $ yangdump-pro --modpath= --version
151 | 
152 | yangdump-sdk 21.10-5
153 | 
154 | 155 | ## Validate a YANG file 156 | 157 | The tool `yangdump-pro` can be used to validate a YANG file: 158 | 159 |
160 | $ yangdump-pro --modpath=. ~/yang-tutorial/interfaces.yang
161 | 
162 | *** /Users/brunorijsman/yang-tutorial/interfaces.yang
163 | *** 0 Errors, 0 Warnings
164 | 
165 | 166 | Here is an example output for a YANG file that contains errors: 167 | 168 |
169 | $ yangdump-pro --modpath=. ~/yang-tutorial/bad-interfaces.yang
170 | 
171 | Error:  Got 'organisation', Expected: module header statement
172 | bad-interfaces.yang:6.5: error(246): wrong token value
173 | 
174 | Error: type 'uint46' not found
175 | bad-interfaces.yang:47.17: error(299): unknown data type
176 | 
177 | *** /Users/brunorijsman/yang-tutorial/bad-interfaces.yang
178 | *** 2 Errors, 0 Warnings
179 | 
180 | 181 | ## Convert a YANG file 182 | 183 | The tool `yangdump-pro` can be used to convert a YANG file to a different format. 184 | 185 | The following command converts a YANG file to HTML: 186 | 187 |
188 | $ yangdump-pro --modpath=. --format=html ~/git-personal/yang-tutorial/interfaces.yang --output=.
189 | 
190 | 191 | This produces file `./interfaces@2022-03-12.html` which can be viewed in a browser: 192 | 193 |
194 | $ open interfaces@2022-03-12.html
195 | 
196 | 197 | ![YumaPro Client YangDump HTML file](figures/yuma-pro-html-file.png) 198 | 199 | Yangdump-pro can also convert a YANG file to a YIN file: 200 | 201 | ``` 202 | $ yangdump-pro --modpath=. --format=yin ~/git-personal/yang-tutorial/interfaces.yang 203 | 204 | *** /Users/brunorijsman/git-personal/yang-tutorial/interfaces.yang 205 | *** 0 Errors, 0 Warnings 206 | 207 | 211 | [...] 212 | 213 | 214 | 215 | 216 | The number of IPv4 packets received over this interface 217 | 218 | 219 | 220 | 221 | 222 | ``` 223 | 224 | Yangdump-pro can also generate C code (`--format=c`) and generate a schema for an SQL database 225 | (`--format=sqldb`). 226 | 227 | ## References 228 | 229 | * [The YumaWorks company homepage](https://www.yumaworks.com/) 230 | 231 | * [The YumaPro Client product page](https://www.yumaworks.com/download/yumapro-client-21-10-5-zip/) 232 | 233 | * [YumaPro yangdump-pro and yangdump-sdk manual](https://www.yumaworks.com/pub/docs/latest/html/yangdump/yumapro-yangdump-manual.xhtml) 234 | -------------------------------------------------------------------------------- /docs/yuma-pro-sdk.md: -------------------------------------------------------------------------------- 1 | # YumaPro SDK from YumaWorks 2 | 3 | ## Introduction 4 | 5 | [YumaWorks](https://www.yumaworks.com/) is a company that offers a suite of network management 6 | and control plane automation tools, with a focus on YANG, NETCONF, and RESTCONF. 7 | 8 | Their product [YumaPro SDK](https://www.yumaworks.com/tools/multi-protocol-server/) 9 | (Software Development Kit), also referred to as the 10 | multi-protocol network management server toolkit or simply the multi-protocol server, 11 | is a network automation management platform that provides developers a framework for developing 12 | device management interfaces. 13 | 14 | YumaPro SDK consists of the following components: 15 | 16 | ![YumaPro SDK Components](figures/yuma-pro-sdk-components.png) 17 | 18 | YumaPro SDK is available in binary and in source code. 19 | 20 | YumaPro SDK Basic offers a subset of the 21 | YumaPro SDK features and can be used for free for internal use subject to restrictions 22 | (see the 23 | [license document](https://www.yumaworks.com/download/yumapro-sdk-basic-license/) 24 | for details): 25 | 26 | ![YumaPro SDK Basic Components](figures/yuma-pro-sdk-basic-components.png) 27 | 28 | ![YumaPro SDK Feature Comparison](figures/yuma-pro-sdk-feature-comparison.png) 29 | 30 | In this tutorial we will be using the basic version. 31 | 32 | ## Documentation 33 | 34 | The YumaPro SDK documentation is [online here](https://docs.yumaworks.com/en/latest/). 35 | 36 | ## Installation 37 | 38 | The installation steps described below are based on the YumaWorks 39 | [installation guide](https://www.yumaworks.com/pub/latest/install/yumapro-installation-guide.html) 40 | but deviate in some small details. 41 | 42 | ### Install the dependencies 43 | 44 | Install the dependencies: 45 | 46 |
 47 | sudo apt-get update
 48 | sudo apt-get install -y libxml2-dev
 49 | sudo apt-get install -y openssh-server
 50 | sudo apt-get install -y openssl
 51 | sudo apt-get install -y libssl-dev
 52 | sudo apt-get install -y libcurl4-gnutls-dev
 53 | sudo apt-get install -y libfcgi-dev
 54 | sudo apt-get install -y libssh2-1-dev
 55 | sudo apt-get install -y libncurses5-dev
 56 | sudo apt-get install -y zlib1g-dev
 57 | 
58 | 59 | ### Download YumaPro SDK 60 | 61 | Download the YumaPro SDK Basic software and documentation from the 62 | [download page](https://www.yumaworks.com/support/download-yumapro-sdk-basic/) 63 | It is available for several Linux distributions; we use Ubuntu 22.04 LTS. 64 | 65 | As of 28 June 2023, this downloads file `yumapro-sdk-basic-21.10-12.u2204.amd64.deb`. 66 | 67 | ### Install YumaPro SDK 68 | 69 | Install the YumaPro SDK Basic software package: 70 | 71 |
 72 | sudo dpkg -i yumapro-sdk-basic-21.10-12.u2204.amd64.deb
 73 | 
74 | 75 | Verify that YumaPro SDK has been installed: 76 | 77 |
 78 | $ /usr/sbin/netconfd-pro --version
 79 | 
 80 | Starting netconfd-pro...
 81 | Copyright (c) 2008-2012, Andy Bierman, All Rights Reserved.
 82 | Copyright (c) 2012-2022, YumaWorks, Inc., All Rights Reserved.
 83 | 
 84 | netconfd-pro version 21.10-12-1fcb
 85 | 
86 | 87 | ### Configure SSH 88 | 89 | Edit sshd_config, for example using `vi`: 90 | 91 |
 92 | sudo vi /etc/ssh/sshd_config
 93 | 
94 | 95 | The installation guide instructs you to add the following lines: 96 | 97 |
 98 | Port 22
 99 | Port 830
100 | Subsystem netconf /usr/sbin/netconf-subsystem-pro
101 | 
102 | 103 | Using the following `Subsystem` configuration instead will allow you to view the XML messages that 104 | are exchanged over the SSH system (this cannot easily be done with normal packet capture tools such 105 | as Wireshark because they cannot easily decode the encrypted SSH session): 106 | 107 |
108 | Subsystem netconf "/bin/sh -c 'tee /tmp/netconf-rx.txt | /usr/sbin/netconf-subsystem-pro | tee /tmp/netconf-tx.txt'"
109 | 
110 | 111 | The NETCONF server will write all received XML messages to file `/tmp/netconf-rx.txt` and all 112 | sent XML messages to file `/tmp/netconf-tx.txt`. 113 | 114 | The `multitail` program is handy to monitor both files at the same time. 115 | 116 | Install `multitail`: 117 | 118 |
119 | sudo apt-get install -y multitail
120 | 
121 | 122 | Monitor both files at the same time using different colors: 123 | 124 |
125 | multitail -ci magenta /tmp/netconf-rx.txt -ci green /tmp/netconf-tx.txt
126 | 
127 | 128 | Press `F1` to get help on the interactive keys that multitail supports. Some handy keys are `B` to 129 | scroll back and `N` to clear the window. 130 | 131 | ### Configure SSH 132 | 133 | TODO: Are we actually using a key? It seems that we are using username/password below. 134 | 135 | Use `ssh-keygen` to generate a public-private key pair (accept defaults for all prompts): 136 | 137 |
138 | $ ssh-keygen -t ed25519
139 | Generating public/private ed25519 key pair.
140 | Enter file in which to save the key (/home/ubuntu/.ssh/id_ed25519):
141 | Enter passphrase (empty for no passphrase):
142 | Enter same passphrase again:
143 | Your identification has been saved in /home/ubuntu/.ssh/id_ed25519
144 | Your public key has been saved in /home/ubuntu/.ssh/id_ed25519.pub
145 | The key fingerprint is:
146 | SHA256:e59bSBR6oP/pO+NjJwauL9S1cXQ+8pLa6vPLvLGsoD8 ubuntu@ip-172-31-28-171
147 | The key's randomart image is:
148 | +--[ED25519 256]--+
149 | |          . .    |
150 | |         . o .. .|
151 | |        . . o. o |
152 | |         . oo....|
153 | |        S....++ .|
154 | |        ..oo.= . |
155 | |       ..o..*.o  |
156 | |        oEo=@++  |
157 | |       .o=+B%^o  |
158 | +----[SHA256]-----+
159 | 
160 | 161 | Restart SSH to make the keys take effect: 162 | 163 |
164 | sudo service ssh restart
165 | 
166 | 167 | ## Set a password 168 | 169 | For this demo, we will be using username and password authentication. 170 | 171 | If you are using an AWS Ubuntu instance, user `ubuntu` does not have a password by default. 172 | Set a password as follows: 173 | 174 |
175 | $ sudo su -
176 | $ passwd ubuntu
177 | New password: topsecret
178 | Retype new password: topsecret
179 | passwd: password updated successfully
180 | 
181 | 182 | ## Start the NETCONF server 183 | 184 | Start the `netconfd-pro` server (with maximum debug logging; use `debug` instead of `debug4` to 185 | reduce the verbosity): 186 | 187 |
188 | $ netconfd-pro --log-level=debug4 --access-control=off
189 | 
190 | Starting netconfd-pro...
191 | Copyright (c) 2008-2012, Andy Bierman, All Rights Reserved.
192 | Copyright (c) 2012-2022, YumaWorks, Inc., All Rights Reserved.
193 | 
194 | ...lots of output...
195 | 
196 | netconfd-pro init OK, ready for sessions
197 | 
198 | Running netconfd-pro server (21.10-12-1fcb)
199 | 
200 | Binding to AF_LOCAL socket /tmp/ncxserver.sock
201 | 
202 | agt_ncxserver: listen ncxsock fd: 3
203 | 
204 | 205 | ## Start the command line interface (CLI) client 206 | 207 | In a separate Terminal window, start the `yangcli-pro` client: 208 | 209 |
210 | $ yangcli-pro
211 | 
212 |   yangcli-pro version 21.10-12
213 |   libssh2 version 1.8.0
214 | 
215 |   Copyright (c) 2008-2012, Andy Bierman, All Rights Reserved.
216 |   Copyright (c) 2012-2022, YumaWorks, Inc., All Rights Reserved.
217 | 
218 | ...more output...
219 | 
220 | parallels@localhost>
221 | 
222 | 223 | ## Connect the CLI client to the NETCONF server 224 | 225 | Enter the following command in the CLI to connect to the server 226 | (use your Linux username and password, and put the password in quotes if it contains a question mark): 227 | 228 |
229 | parallels@localhost> connect server=localhost user=<username> password=<password>
230 | 
231 | NETCONF 1.1 session established for parallels on localhost
232 | 
233 | Client Session Id: 1
234 | Server Session Id: 4
235 | 
236 | ...more output...
237 | 
238 | Protocol version set to: RFC 6241 (base:1.1)
239 | Default target set to: 
240 | Save operation mapped to: commit
241 | Default with-defaults behavior: explicit
242 | Additional with-defaults behavior: trim,report-all,report-all-tagged
243 | YANG library set to: 1.0 (RFC 7895)
244 | module-set-id: 4269
245 | 
246 | 247 | ## View the NETCONF messages 248 | 249 | In the `multitail` window that we had started in an earlier step, we can see the NETCONF messages 250 | that are being exchanged between the NETCONF client and server. 251 | 252 | The client sends a `hello`: 253 | 254 | ```xml 255 | 256 | 257 | urn:ietf:params:netconf:base:1.0 258 | urn:ietf:params:netconf:base:1.1 259 | 260 | 261 | ``` 262 | 263 | Note: throughout these examples, we have used the `xmllint` program to pretty-print the XML in 264 | the NETCONF messages. One side-effect of this is that the XML elements and attributes may appear 265 | in a different order. 266 | 267 | The server responds with a `hello`: 268 | 269 | ```xml 270 | 271 | 272 | urn:ietf:params:netconf:base:1.0 273 | urn:ietf:params:netconf:base:1.1 274 | urn:ietf:params:netconf:capability:candidate:1.0 275 | urn:ietf:params:netconf:capability:confirmed-commit:1.0 276 | urn:ietf:params:netconf:capability:confirmed-commit:1.1 277 | urn:ietf:params:netconf:capability:rollback-on-error:1.0 278 | urn:ietf:params:netconf:capability:validate:1.0 279 | urn:ietf:params:netconf:capability:validate:1.1 280 | urn:ietf:params:netconf:capability:url:1.0?scheme=file 281 | urn:ietf:params:netconf:capability:xpath:1.0 282 | urn:ietf:params:netconf:capability:notification:1.0 283 | urn:ietf:params:netconf:capability:interleave:1.0 284 | urn:ietf:params:netconf:capability:partial-lock:1.0 285 | urn:ietf:params:netconf:capability:with-defaults:1.0?basic-mode=explicit&also-supported=trim,report-all,report-all-tagged 286 | urn:yumaworks:params:xml:ns:netconf:config-id?id=13 287 | urn:ietf:params:xml:ns:netconf:base:1.0?module=ietf-netconf&revision=2011-06-01&features=candidate,confirmed-commit,rollback-on-error,validate,url,xpath 288 | urn:ietf:params:xml:ns:yang:iana-crypt-hash?module=iana-crypt-hash&revision=2014-08-06&features=crypt-hash-md5,crypt-hash-sha-256,crypt-hash-sha-512 289 | urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&revision=2013-07-15 290 | urn:ietf:params:xml:ns:yang:ietf-netconf-acm?module=ietf-netconf-acm&revision=2018-02-14 291 | ... 292 | http://yumaworks.com/ns/yumaworks-types?module=yumaworks-types&revision=2021-05-15 293 | urn:ietf:params:netconf:capability:yang-library:1.0?revision=2016-06-21&module-set-id=4269 294 | 295 | 5 296 | 297 | ``` 298 | 299 | The client issues a `get` filtering on subtree `ietf-yang-library` 300 | to retrieve the details of the modules that the server supports 301 | (see [RFC8525](https://datatracker.ietf.org/doc/rfc8525/) for details) 302 | (output truncated): 303 | 304 | ```xml 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | ``` 313 | 314 | The server responds with the requested information (output truncated): 315 | 316 | ```xml 317 | 318 | 319 | 320 | 4269 321 | 322 | ietf-netconf 323 | 2011-06-01 324 | urn:ietf:params:xml:ns:netconf:base:1.0 325 | candidate 326 | confirmed-commit 327 | rollback-on-error 328 | validate 329 | url 330 | xpath 331 | implement 332 | 333 | 334 | iana-crypt-hash 335 | 2014-08-06 336 | http://localhost/restconf/yang/iana-crypt-hash/2014-08-06 337 | urn:ietf:params:xml:ns:yang:iana-crypt-hash 338 | crypt-hash-md5 339 | crypt-hash-sha-256 340 | crypt-hash-sha-512 341 | implement 342 | 343 | 344 | ietf-inet-types 345 | 2013-07-15 346 | http://localhost/restconf/yang/ietf-inet-types/2013-07-15 347 | urn:ietf:params:xml:ns:yang:ietf-inet-types 348 | import 349 | 350 | 351 | ietf-netconf-acm 352 | 2018-02-14 353 | http://localhost/restconf/yang/ietf-netconf-acm/2018-02-14 354 | urn:ietf:params:xml:ns:yang:ietf-netconf-acm 355 | implement 356 | 357 | ... 358 | 359 | yumaworks-types 360 | 2021-05-15 361 | http://localhost/restconf/yang/yumaworks-types/2021-05-15 362 | http://yumaworks.com/ns/yumaworks-types 363 | import 364 | 365 | 366 | 367 | 368 | ``` 369 | 370 | ## Issue a command in the CLI client 371 | 372 | In the CLI client, the `show modules` command can be used to view the YANG modules that the 373 | server reports: 374 | 375 |
376 | parallels@localhost> show modules
377 | 
378 |   ianach:iana-crypt-hash@2014-08-06
379 |   inet:ietf-inet-types@2013-07-15
380 |   nacm:ietf-netconf-acm@2018-02-14
381 |   ncm:ietf-netconf-monitoring@2010-10-04
382 |   ncn:ietf-netconf-notifications@2012-02-06
383 |   pl:ietf-netconf-partial-lock@2009-10-19
384 |   ncwd:ietf-netconf-with-defaults@2011-06-01
385 |   rc:ietf-restconf@2017-01-26
386 |   rcmon:ietf-restconf-monitoring@2017-01-26
387 |   yanglib:ietf-yang-library@2016-06-21
388 |   ypatch:ietf-yang-patch@2017-02-22
389 |   sx:ietf-yang-structure-ext@2020-06-17
390 |   yang:ietf-yang-types@2013-07-15
391 |   manageEvent:nc-notifications@2008-07-14
392 |   ncEvent:notifications@2013-03-15
393 |   yd:yang-data-ext@2017-07-03
394 |   appcmn:yuma-app-common@2017-07-25
395 |   ncx:yuma-ncx@2015-10-16
396 |   nc:yuma-netconf@2015-04-30
397 |   timefilter:yuma-time-filter@2012-11-15
398 |   yt:yuma-types@2019-11-29
399 |   ywapp:yumaworks-app-common@2021-08-24
400 |   ef:yumaworks-event-filter@2014-02-09
401 |   ywes:yumaworks-event-stream@2021-05-15
402 |   ywx:yumaworks-extensions@2021-12-14
403 |   ybulk:yumaworks-getbulk@2021-08-07
404 |   yid:yumaworks-ids@2014-07-12
405 |   yrc:yumaworks-restconf@2017-07-03
406 |   yss:yumaworks-support-save@2017-07-27
407 |   ysys:yumaworks-system@2022-03-08
408 |   ytemp:yumaworks-templates@2017-02-20
409 |   ytm:yumaworks-term-msg@2019-05-05
410 |   ywt:yumaworks-types@2021-05-15
411 | 
412 | 413 | ## Retrieve the (empty) configuration 414 | 415 | In the CLI client, issue a `get-config` command to retrieve the running configuration: 416 | 417 |
418 | parallels@localhost> get-config source=running
419 | 
420 | RPC Data Reply 10 for session 4 [default]:
421 | 
422 | rpc-reply {
423 |   data {
424 |   }
425 | }
426 | 
427 | 428 | In this example, there is no configuration yet (we will add some configuration below). 429 | 430 | The client sends a `get-config`: 431 | 432 | ```xml 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | ``` 441 | 442 | The server responds with the requested configuration: 443 | 444 | ```xml 445 | 446 | 447 | 448 | ``` 449 | 450 | ## Retrieve a subtree of the operational state 451 | 452 | In the CLI client, issue an `sget` command to retrieve operational state for the 453 | `/netconf-state/sessions` subtree of the operational state tree (use `/` if you want to see the 454 | whole tree): 455 | 456 |
457 | parallels@localhost> sget /netconf-state/sessions
458 | 
459 | Filling container /netconf-state/sessions:
460 | RPC Data Reply 2 for session 4 [default]:
461 | 
462 | rpc-reply {
463 |   data {
464 |     netconf-state {
465 |       sessions {
466 |         session  4 {
467 |           session-id 4
468 |           transport ncm:netconf-ssh
469 |           username parallels
470 |           source-host 127.0.0.1
471 |           login-time 2022-09-08T14:09:15Z
472 |           in-rpcs 1
473 |           in-bad-rpcs 0
474 |           out-rpc-errors 0
475 |           out-notifications 0
476 |         }
477 |       }
478 |     }
479 |   }
480 | }
481 | 
482 | 483 | The client sends a `get` with the filter for the subtree: 484 | 485 | ```xml 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | ``` 496 | 497 | The server responds with the requested operational state: 498 | 499 | ```xml 500 | 501 | 502 | 503 | 504 | 505 | 5 506 | ncm:netconf-ssh 507 | parallels 508 | 127.0.0.1 509 | 2022-09-09T15:07:13Z 510 | 2 511 | 0 512 | 0 513 | 0 514 | 515 | 516 | 517 | 518 | 519 | ``` 520 | 521 | ## Retrieve the YANG schema for a module 522 | 523 | In the CLI client, issue the `get-schema` command to retrieve the YANG schema for a specific 524 | module from the server: 525 | 526 |
527 | parallels@localhost> get-schema identifier=ietf-netconf-notifications
528 | 
529 | RPC Data Reply 10 for session 5 [default]:
530 | 
531 | rpc-reply {
532 |   data '
533 | module ietf-netconf-notifications {
534 | 
535 |    namespace
536 |      "urn:ietf:params:xml:ns:yang:ietf-netconf-notifications";
537 | 
538 |    prefix ncn;
539 | 
540 |    import ietf-inet-types { prefix inet; }
541 |    import ietf-netconf { prefix nc; }
542 | 
543 |    organization
544 |      "IETF NETCONF (Network Configuration Protocol) Working Group";
545 | 
546 |    contact
547 |      "WG Web:   <http://tools.ietf.org/wg/netconf/>
548 |       WG List:  <mailto:netconf@ietf.org>
549 | 
550 |       WG Chair: Bert Wijnen
551 |                 <mailto:bertietf@bwijnen.net>
552 | 
553 |       WG Chair: Mehmet Ersue
554 |                 <mailto:mehmet.ersue@nsn.com>
555 | 
556 |       Editor:   Andy Bierman
557 |                 <mailto:andy@netconfcentral.org>";
558 | 
559 |    description
560 |      "This module defines a YANG data model for use with the
561 |       NETCONF protocol that allows the NETCONF client to
562 |       receive common NETCONF base event notifications.
563 | 
564 |       Copyright (c) 2012 IETF Trust and the persons identified as
565 |       the document authors.  All rights reserved.
566 | 
567 |       Redistribution and use in source and binary forms, with or
568 |       without modification, is permitted pursuant to, and subject
569 |       to the license terms contained in, the Simplified BSD License
570 |       set forth in Section 4.c of the IETF Trust's Legal Provisions
571 |       Relating to IETF Documents
572 |       (http://trustee.ietf.org/license-info).
573 | 
574 |       This version of this YANG module is part of RFC 6470; see
575 |       the RFC itself for full legal notices.";
576 | 
577 |    revision "2012-02-06" {
578 |      description
579 |        "Initial version. Errata 3957 added.";
580 |      reference
581 |        "RFC 6470: NETCONF Base Notifications";
582 |    }
583 | 
584 |   grouping common-session-parms {
585 |     description
586 |       "Common session parameters to identify a
587 |        management session.";
588 | 
589 |     leaf username {
590 |       type string;
591 |       mandatory true;
592 |       description
593 |         "Name of the user for the session.";
594 |     }
595 | 
596 |     leaf session-id {
597 |       type nc:session-id-or-zero-type;
598 |       mandatory true;
599 |       description
600 |         "Identifier of the session.
601 |          A NETCONF session MUST be identified by a non-zero value.
602 |          A non-NETCONF session MAY be identified by the value zero.";
603 |     }
604 | 
605 |     ...
606 | 
607 |     leaf timeout {
608 |       when
609 |         "../confirm-event = 'start' or ../confirm-event = 'extend'";
610 |       type uint32;
611 |       units "seconds";
612 |       description
613 |         "The configured timeout value if the event type
614 |          is 'start' or 'extend'.  This value represents
615 |          the approximate number of seconds from the event
616 |          time when the 'timeout' event might occur.";
617 |     }
618 |   } // notification netconf-confirmed-commit
619 | 
620 | }
621 | '
622 | }
623 | 
624 | 625 | The client sends a `get-schema` for the module: 626 | 627 | ```xml 628 | 629 | 630 | ietf-netconf-notifications 631 | 632 | 633 | ``` 634 | 635 | The server responds with the requested schema: 636 | 637 | ```xml 638 | 639 | 640 | module ietf-netconf-notifications { 641 | 642 | namespace 643 | "urn:ietf:params:xml:ns:yang:ietf-netconf-notifications"; 644 | 645 | prefix ncn; 646 | 647 | import ietf-inet-types { prefix inet; } 648 | import ietf-netconf { prefix nc; } 649 | 650 | organization 651 | "IETF NETCONF (Network Configuration Protocol) Working Group"; 652 | 653 | contact 654 | "WG Web: <http://tools.ietf.org/wg/netconf/> 655 | WG List: <mailto:netconf@ietf.org> 656 | 657 | WG Chair: Bert Wijnen 658 | <mailto:bertietf@bwijnen.net> 659 | 660 | WG Chair: Mehmet Ersue 661 | <mailto:mehmet.ersue@nsn.com> 662 | 663 | Editor: Andy Bierman 664 | <mailto:andy@netconfcentral.org>"; 665 | 666 | description 667 | "This module defines a YANG data model for use with the 668 | NETCONF protocol that allows the NETCONF client to 669 | receive common NETCONF base event notifications. 670 | 671 | Copyright (c) 2012 IETF Trust and the persons identified as 672 | the document authors. All rights reserved. 673 | 674 | Redistribution and use in source and binary forms, with or 675 | without modification, is permitted pursuant to, and subject 676 | to the license terms contained in, the Simplified BSD License 677 | set forth in Section 4.c of the IETF Trust's Legal Provisions 678 | Relating to IETF Documents 679 | (http://trustee.ietf.org/license-info). 680 | 681 | This version of this YANG module is part of RFC 6470; see 682 | the RFC itself for full legal notices."; 683 | 684 | revision "2012-02-06" { 685 | description 686 | "Initial version. Errata 3957 added."; 687 | reference 688 | "RFC 6470: NETCONF Base Notifications"; 689 | } 690 | 691 | grouping common-session-parms { 692 | description 693 | "Common session parameters to identify a 694 | management session."; 695 | 696 | leaf username { 697 | type string; 698 | mandatory true; 699 | 700 | description 701 | "Name of the user for the session."; 702 | } 703 | 704 | leaf session-id { 705 | type nc:session-id-or-zero-type; 706 | mandatory true; 707 | description 708 | "Identifier of the session. 709 | A NETCONF session MUST be identified by a non-zero value. 710 | A non-NETCONF session MAY be identified by the value zero."; 711 | } 712 | 713 | ... 714 | 715 | leaf timeout { 716 | when 717 | "../confirm-event = 'start' or ../confirm-event = 'extend'"; 718 | type uint32; 719 | units "seconds"; 720 | description 721 | "The configured timeout value if the event type 722 | is 'start' or 'extend'. This value represents 723 | the approximate number of seconds from the event 724 | time when the 'timeout' event might occur."; 725 | } 726 | } // notification netconf-confirmed-commit 727 | 728 | } 729 | 730 | 731 | ``` 732 | 733 | ## Exit from the CLI client 734 | 735 | Exit from the CLI client: 736 | 737 |
738 | parallels@localhost> quit
739 | 
740 | 741 | ## Adding a plugin for your own data model 742 | 743 | We will now add a plugin for our example YANG data model: [interfaces.yang](../interfaces.yang), 744 | following the instructions in the 745 | [YumaPro Developer Manual](https://www.yumaworks.com/pub/latest/dev/yumapro-dev-manual.html) 746 | . 747 | 748 | If you haven't already done so, clone the `yang-tutorial` repo: 749 | 750 |
751 | $ cd ~
752 | $ git clone https://github.com/brunorijsman/yang-tutorial.git
753 | 
754 | 755 | By default YumaPro SDK expects the YANG data models to be installed in `~/modules`. 756 | Copy the example YANG data model [interfaces.yang](../interfaces.yang) into `~/modules`: 757 | 758 |
759 | $ mkdir ~/modules
760 | $ cd ~/modules
761 | $ cp ~/yang-tutorial/interfaces.yang .
762 | 
763 | 764 | YumaPro SDK support a few different flavors of plugins. 765 | We will use the SIL flavor, which is dynamically linked into the NETCONF server and which uses 766 | synchronous callbacks. 767 | 768 | We will put our plugin code in the `~/plugins` directory: 769 | 770 |
771 | $ mkdir ~/plugins
772 | $ cd ~/plugins
773 | 
774 | 775 | Run the YumaWorks `make_sil_dir_pro` script to generate the C stub code from the YANG data model: 776 | 777 |
778 | $ make_sil_dir_pro interfaces --sil-get2 --sil-edit2
779 | 
780 | 781 | If all goes well, this generates the following directories and files: 782 | 783 |
784 | $ tree interfaces
785 | interfaces/
786 | ├── bin
787 | ├── lib
788 | ├── Makefile
789 | └── src
790 |     ├── Makefile
791 |     ├── u_interfaces.c
792 |     ├── u_interfaces.h
793 |     ├── y_interfaces.c
794 |     └── y_interfaces.h
795 | 
796 | 797 | The files starting with `u_` (for user) can be edited to customize the behavior of the plugin. 798 | We will edit the stub C code that YumaPro SDK generated to provide values for the operational 799 | state attributes. 800 | There are many other callbacks that can be edited in the stub code, for example to do something 801 | when an interface is added or removed, when an IPv4 address is set, changed, or removed, etc. 802 | For a complete list of all the callbacks that can be customized see the 803 | [YumaPro Developers Manual](https://www.yumaworks.com/pub/latest/dev/yumapro-dev-manual.html#) 804 | . 805 | For now, we will keep it as simple as possible and only implement the callback for providing packet 806 | counter values. 807 | 808 | Edit the generated stub file `u_interfaces.c`: 809 | 810 |
811 | $ vi ~/plugins/interfaces/src/u_interfaces.c
812 | 
813 | 814 | Edit function `u_intf_sent_packets_get`: 815 | 816 | ```c 817 | status_t u_intf_sent_packets_get ( 818 | getcb_get2_t *get2cb, 819 | const xmlChar *k_intf_name) 820 | { 821 | ... 822 | } 823 | ``` 824 | 825 | Change the following lines: 826 | 827 | ```c 828 | /* check if the requested node exists; determined by the 829 | * SIL or SIL-SA callback based on instances in the system 830 | * CHANGE node_exists TO TRUE WHEN VALUE CODE FILLED IN */ 831 | boolean node_exists = FALSE; 832 | 833 | if (!node_exists) { 834 | return ERR_NCX_NO_INSTANCE; 835 | } 836 | 837 | obj_template_t *obj = GETCB_GET2_OBJ(get2cb); 838 | status_t res = NO_ERR; 839 | 840 | /* get the real value from the system somehow */ 841 | uint64 v_sent_packets = 0; 842 | ``` 843 | 844 | Into the following lines (to keep things as simple as possible, we return a random value for the 845 | number of sent packets counter): 846 | 847 | ```c 848 | /* check if the requested node exists; determined by the 849 | * SIL or SIL-SA callback based on instances in the system 850 | * CHANGE node_exists TO TRUE WHEN VALUE CODE FILLED IN */ 851 | boolean node_exists = TRUE; // <<< Changed this line 852 | 853 | if (!node_exists) { 854 | return ERR_NCX_NO_INSTANCE; 855 | } 856 | 857 | obj_template_t *obj = GETCB_GET2_OBJ(get2cb); 858 | status_t res = NO_ERR; 859 | 860 | /* get the real value from the system somehow */ 861 | uint64 v_sent_packets = rand() % 1000; // <<< Changed this line 862 | ``` 863 | 864 | Make a similar change in the function `u_intf_received_packets_get`: 865 | 866 | ```c 867 | /* check if the requested node exists; determined by the 868 | * SIL or SIL-SA callback based on instances in the system 869 | * CHANGE node_exists TO TRUE WHEN VALUE CODE FILLED IN */ 870 | boolean node_exists = TRUE; 871 | 872 | if (!node_exists) { 873 | return ERR_NCX_NO_INSTANCE; 874 | } 875 | 876 | obj_template_t *obj = GETCB_GET2_OBJ(get2cb); 877 | status_t res = NO_ERR; 878 | 879 | /* get the real value from the system somehow */ 880 | uint64 v_received_packets = rand() % 1000; 881 | ``` 882 | 883 | Save the changes. 884 | 885 | Build and install the plugin (the `make` step generates some warnings about unused parameters 886 | which you can ignore for now): 887 | 888 |
889 | $ cd interfaces
890 | $ make
891 | $ sudo make install
892 | 
893 | 894 | Go back to the CLI client which we started earlier in this tutorial and issue the following 895 | command to instruct the NETCONF server to load the new YANG module: 896 | 897 |
898 | parallels@localhost> load interfaces
899 | 
900 | RPC Data Reply 5 for session 4 [default]:
901 | 
902 | rpc-reply {
903 |   mod-revision 2022-03-12
904 | }
905 | 
906 | 907 | We separate need to load the YANG module into the CLI client: 908 | 909 |
910 | parallels@localhost> mgrload interfaces
911 | 
912 | Load module 'interfaces' OK
913 | 
914 | 915 | Note: instead of issuing CLI commands to load the YANG module into the server and the client, we 916 | can also start the server with a `--module` command line option: 917 | 918 |
919 | $ netconfd-pro --log-level=debug4 --access-control=off --module=interfaces
920 | 
921 | 922 | Still in the CLI client, configure a couple of interfaces: 923 | 924 |
925 | parallels@localhost> config term
926 | parallels@localhost# interfaces
927 | parallels@localhost(interfaces)# interface eth0
928 | parallels@localhost(interface)# ipv4-address 1.1.1.1
929 | parallels@localhost(interface)# exit
930 | parallels@localhost(interfaces)# interface eth1
931 | parallels@localhost(interface)# ipv4-address 2.2.2.2
932 | parallels@localhost(interface)# exit
933 | parallels@localhost(interfaces)# exit
934 | parallels@localhost# exit
935 | parallels@localhost> commit
936 | RPC OK Reply 7 for session 4 [default]:
937 | 
938 | 939 | Get the configuration to double check: 940 | 941 |
942 | parallels@localhost> sget-config source=running /interfaces
943 | 
944 | Filling container /interfaces:
945 | RPC Data Reply 3 for session 5 [default]:
946 | 
947 | rpc-reply {
948 |   data {
949 |     interfaces {
950 |       interface  eth0 {
951 |         name eth0
952 |         ipv4-address 1.1.1.1
953 |       }
954 |       interface  eth1 {
955 |         name eth1
956 |         ipv4-address 2.2.2.2
957 |       }
958 |     }
959 |   }
960 | }
961 | 
962 | 963 | Get the operational state for the interfaces; we get random values for the packet counters: 964 | 965 |
966 | parallels@localhost> sget /interfaces
967 | 
968 | Filling container /interfaces:
969 | RPC Data Reply 29 for session 3 [default]:
970 | 
971 | rpc-reply {
972 |   data {
973 |     interfaces {
974 |       interface  eth0 {
975 |         name eth0
976 |         ipv4-address 1.1.1.1
977 |         sent-packets 383
978 |         received-packets 886
979 |       }
980 |       interface  eth1 {
981 |         name eth1
982 |         ipv4-address 2.2.2.2
983 |         sent-packets 777
984 |         received-packets 915
985 |       }
986 |     }
987 |   }
988 | }
989 | 
990 | 991 | -------------------------------------------------------------------------------- /docs/yumabench.md: -------------------------------------------------------------------------------- 1 | # YumaWorks YumaBench 2 | 3 | ## Introduction 4 | 5 | [YumaWorks](https://www.yumaworks.com/) is a company that specializes in YANG management tools. 6 | 7 | One of their products, 8 | [YumaBench](https://www.yumaworks.com/tools/yumabench/) 9 | is a 10 | NETCONF client that can connect to a NETCONF server and that offers a graphical user interface 11 | for exploring and editing the data store in the NETCONF server. 12 | 13 | ## Download and install YumaBench 14 | 15 | The 16 | [YumaBench page](https://www.yumaworks.com/tools/yumabench/) 17 | contains links to download the software and installation instructions. 18 | Additional instructions are in the 19 | [user manual](https://www.yumaworks.com/pub/docs/yumabench/yumabench-user-manual.pdf) 20 | . 21 | Downloads are available for Ubuntu/Debian, RedHat/CentOS/Fedora, and macOS. 22 | We used the Ubuntu version. 23 | 24 | ## Start a NETCONF server 25 | 26 | This YumaBench tutorial assumes that there is a NETCONF server running that YumaBench can 27 | connect to. 28 | See the 29 | [YumaPro SDK](yuma-pro-sdk.md) 30 | tutorial for instructions on how to start the YumaWorks NETCONF server and how to load 31 | our simple `interfaces.yang` example YANG module into that server. 32 | 33 | ## Start YumaBench 34 | 35 | To start YumaBench, type the command `yuma-bench` in a terminal window. 36 | 37 | The YumaBench initial startup screen looks as follows: 38 | 39 | ![YumaBench startup screen](figures/yumabench-startup.png) 40 | 41 | ## Initial setup of YumaBench 42 | 43 | We need to configure YumaBench with the device to manage (in this case the NETCONF server running 44 | locally), user credentials (a user name and password in this example, but other authentication 45 | mechanisms are supported as well), and a NETCONF session. 46 | 47 | Add a device by selecting _Devices_ from the dropdown menu and clicking on the +Add button: 48 | 49 | ![YumaBench startup screen](figures/yumabench-select-devices.png) 50 | 51 | Enter the device details as follows and click the Apply button: 52 | 53 | ![YumaBench add device](figures/yumabench-add-device.png) 54 | 55 | Add a user by selecting _Users_ from the dropdown menu and clicking on the +Add button. 56 | Enter the user details and click the Apply button: 57 | 58 | ![YumaBench add user](figures/yumabench-add-user.png) 59 | 60 | Add a session by selecting _Sessions_ from the dropdown menu and clicking on the +Add button. 61 | Enter the session details and click the Apply button: 62 | 63 | ![YumaBench add session](figures/yumabench-add-session.png) 64 | 65 | ## Start the NETCONF session 66 | 67 | On the same screen where the session was just added, click on the Start "Start session" button. 68 | This brings up the session window: 69 | 70 | ![YumaBench session window](figures/yumabench-session-window.png) 71 | 72 | We start in the configuration tab, and we see that we can configure event-filters, event-streams, 73 | interfaces (which is the example YANG data model used in this tutorial), nacm, and templates. 74 | 75 | Note that we did not have to configure or import any YANG modules in the YumaBench browser; 76 | instead the browser uses the NETCONF protocol to automatically discover which YANG modules 77 | the device supports and to download the corresponding YANG data models from the device. 78 | This is only possible if the device supports 79 | [RFC 7895 (YANG Library)](https://datatracker.ietf.org/doc/rfc8525/) 80 | (which the YumaPro SDK NETCONF server used 81 | in this example does). 82 | 83 | ## Add some interfaces 84 | 85 | We will now add an interface to our example interfaces YANG module. 86 | 87 | First click on interfaces in the tree to expand it. 88 | A new entry interface appears in the tree; click on this to expand it as well. 89 | The name and ipv4-address fields appear in the tree. 90 | Fill them as follows and click on the Apply button: 91 | 92 | ![YumaBench add interface](figures/yumabench-add-interface.png) 93 | 94 | Note that the interface labels change from orange to black after applying the changes to 95 | indicate that the changes have been committed. 96 | 97 | Add another interface, by selecting interface and clicking the Add button. 98 | Fill in the details of the new interface and click Apply. 99 | 100 | ![YumaBench add 2nd interface](figures/yumabench-add-2nd-interface.png) 101 | 102 | ## Change an interface 103 | 104 | To change one or more interface attributes, click on the attribute, and change the value. 105 | You can remove optional attributes by clicking on the attribute an then the remove button. 106 | To remove an entire interface, click on the interface tree node and then on the Remove button. 107 | Click on the Apply button to commit the changes. 108 | If you click on Cancel before committing the change, all edits are undone. 109 | 110 | ## View operational state 111 | 112 | Click on the Monitoring tab to view the operational state. 113 | Click on Refresh to retrieve the most recent operational state. 114 | Expand nodes in the tree to view the operational attributes that you are interested in, in this 115 | case the interfaces: 116 | 117 | ![YumaBench operational state](figures/yumabench-operational-state.png) 118 | 119 | ## Notifications 120 | 121 | Click on the Notifications tab to see NETCONF notifications. 122 | In this example, we can see all the configuration changes that we made: 123 | 124 | ![YumaBench notifications](figures/yumabench-notifications.png) 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /interfaces.yang: -------------------------------------------------------------------------------- 1 | module interfaces { 2 | 3 | namespace "http://remoteautonomy.com/yang-schemas/interfaces"; 4 | prefix intf; 5 | 6 | organization 7 | "Remote Autonomy"; 8 | 9 | contact 10 | "Bruno Rijsman 11 | brunorijsman@remoteautonomy.com"; 12 | 13 | description 14 | "A simplistic tutorial data model for interfaces on a device."; 15 | 16 | revision 2022-03-12 { 17 | description 18 | "Initial revision."; 19 | } 20 | 21 | container interfaces { 22 | description 23 | "Interface parameters."; 24 | 25 | list interface { 26 | key "name"; 27 | description 28 | "The list of interfaces on the device."; 29 | 30 | leaf name { 31 | type string; 32 | description 33 | "The name of the interface."; 34 | } 35 | 36 | leaf ipv4-address { 37 | type string { 38 | pattern 39 | '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' 40 | + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; 41 | } 42 | description 43 | "The IPv4 address of the interface."; 44 | } 45 | 46 | leaf sent-packets { 47 | type uint64; 48 | config false; 49 | description 50 | "The number of IPv4 packets sent out over this interface"; 51 | } 52 | 53 | leaf received-packets { 54 | type uint64; 55 | config false; 56 | description 57 | "The number of IPv4 packets received over this interface"; 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /ncclient/__pycache__/netconf_server_info.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brunorijsman/yang-tutorial/4d3b53bb5309f056f8070f7956e02e035a9551fe/ncclient/__pycache__/netconf_server_info.cpython-39.pyc -------------------------------------------------------------------------------- /ncclient/demo_client.py: -------------------------------------------------------------------------------- 1 | from ncclient import manager 2 | 3 | with manager.connect(host="127.0.0.1", 4 | port=830, 5 | username="parallels", 6 | password="Virtu33l?", 7 | hostkey_verify=False) as m: 8 | c = m.get_config(source='running').data_xml 9 | with open("out.xml", 'w') as f: 10 | f.write(c) 11 | -------------------------------------------------------------------------------- /ncclient/edit_config.py: -------------------------------------------------------------------------------- 1 | from ncclient import manager 2 | import netconf_server_info 3 | 4 | 5 | with manager.connect(host=netconf_server_info.address(), 6 | port=830, 7 | username=netconf_server_info.username(), 8 | password=netconf_server_info.password(), 9 | hostkey_verify=False) as mgr: 10 | 11 | cfg_interface = """ 12 | 13 | 14 | 15 | eth1 16 | 2.2.2.2 17 | 18 | 19 | 20 | """ 21 | reply = mgr.edit_config(config=cfg_interface) 22 | assert reply.xpath("/rpc-reply/ok") != [] 23 | reply = mgr.commit() 24 | assert reply.xpath("/rpc-reply/ok") != [] 25 | -------------------------------------------------------------------------------- /ncclient/netconf_server_info.py: -------------------------------------------------------------------------------- 1 | import psutil 2 | import os 3 | 4 | 5 | def address(): 6 | address = os.getenv('NETCONF_SERVER_ADDRESS') 7 | if address is None: 8 | return '127.0.0.1' 9 | return address 10 | 11 | 12 | def username(): 13 | username = os.getenv('NETCONF_SERVER_USERNAME') 14 | if username is None: 15 | return psutil.Process().username() 16 | return username 17 | 18 | 19 | def password(): 20 | return os.getenv('NETCONF_SERVER_PASSWORD') 21 | -------------------------------------------------------------------------------- /ncclient/show_capabilities.py: -------------------------------------------------------------------------------- 1 | from ncclient import manager 2 | from bs4 import BeautifulSoup 3 | import netconf_server_info 4 | 5 | 6 | with manager.connect(host=netconf_server_info.address(), 7 | port=830, 8 | username=netconf_server_info.username(), 9 | password=netconf_server_info.password(), 10 | hostkey_verify=False) as mgr: 11 | print("Client capabilities:") 12 | for capability in mgr.client_capabilities: 13 | print(f" {capability}") 14 | print("Server capabilities:") 15 | for capability in mgr.server_capabilities: 16 | print(f" {capability}") 17 | -------------------------------------------------------------------------------- /ncclient/show_config.py: -------------------------------------------------------------------------------- 1 | from ncclient import manager 2 | from bs4 import BeautifulSoup 3 | import netconf_server_info 4 | 5 | 6 | with manager.connect(host=netconf_server_info.address(), 7 | port=830, 8 | username=netconf_server_info.username(), 9 | password=netconf_server_info.password(), 10 | hostkey_verify=False) as mgr: 11 | config_xml = mgr.get_config(source='running').data_xml 12 | print(BeautifulSoup(config_xml, 'xml').prettify()) 13 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | appdirs==1.4.4 2 | bcrypt==3.2.0 3 | beautifulsoup4==4.10.0 4 | bs4==0.0.1 5 | certifi==2021.10.8 6 | cffi==1.15.0 7 | charset-normalizer==2.0.12 8 | confusable-homoglyphs==3.2.0 9 | cryptography==36.0.1 10 | decorator==5.1.1 11 | Deprecated==1.2.13 12 | Django==2.2.28 13 | django-registration==3.1.2 14 | docutils==0.16 15 | gitdb==4.0.9 16 | GitPython==3.1.27 17 | idna==3.3 18 | Jinja2==2.11.3 19 | lxml==4.8.0 20 | MarkupSafe==2.0.1 21 | ncclient==0.6.12 22 | netmiko==2.3.3 23 | networkx==1.11 24 | packaging==19.0 25 | paramiko==2.10.1 26 | pexpect==4.8.0 27 | psutil==5.9.0 28 | ptyprocess==0.7.0 29 | pyang==2.5.2 30 | pycparser==2.21 31 | PyGithub==1.55 32 | PyJWT==2.3.0 33 | PyNaCl==1.5.0 34 | pyparsing==3.0.7 35 | pyserial==3.5 36 | python-json-logger==0.1.10 37 | python-slugify==4.0.1 38 | pytz==2021.3 39 | PyYAML==6.0 40 | requests==2.27.1 41 | scp==0.14.4 42 | six==1.16.0 43 | smmap==5.0.0 44 | soupsieve==2.3.1 45 | text-unidecode==1.3 46 | textfsm==0.4.1 47 | urllib3==1.26.8 48 | whitenoise==4.1.4 49 | wrapt==1.14.0 50 | xeger==0.3.4 51 | yangsuite==2.8.7 52 | yangsuite-devices==2.9.2 53 | yangsuite-filemanager==1.8.1 54 | yangsuite-netconf==1.15.3 55 | yangsuite-yangtree==1.19.1 56 | -------------------------------------------------------------------------------- /yanglint/bad-data.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | eth 4 | 300.1.1.1 5 | 6 | 7 | -------------------------------------------------------------------------------- /yanglint/data.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | eth1 4 | 1.1.1.1 5 | 6 | 7 | eth2 8 | 2.2.2.2 9 | 10 | 11 | --------------------------------------------------------------------------------