In this chapter we reintroduce the links.yang
model from the Yang chapter and see how we can use that
model to render all northbound interfaces.
This chapter is an overview, and all concepts touched upon in this chapter are thoroughly described in later chapters.
The links.yang
data model introduced in the "Yang"
chapter defines a set of interfaces. Compiling
the links.yang
file into an .fxs file is the
first required step.
module links { namespace "http://example.com/ns/link"; prefix link; import ietf-yang-types { prefix yang; } grouping LinkFlagsType { leaf UP { type empty; } leaf NOARP { type empty; } leaf BROADCAST { type empty; } leaf MULTICAST { type empty; } leaf LOOPBACK { type empty; } leaf NOTRAILERS { type empty; } } typedef QueueDisciplineType { type enumeration { enum pfifo_fast; enum noqueue; enum noop; enum htb; } } container config { container links { list link { key name; unique addr; max-elements 1024; leaf name { type string; } container flags { uses LinkFlagsType; } leaf addr { type yang:mac-address; mandatory true; } leaf brd { type yang:mac-address; mandatory true; } leaf mtu { type uint32; default 1500; } } } container queueDisciplines { list queueDiscipline { key linkName; max-elements 1024; leaf linkName { type leafref { path "/config/links/link/name"; } } leaf type { type QueueDisciplineType; mandatory true; } leaf length { type uint32; } } } container linkLimitations { list linkLimitation { key linkName; leaf linkName { type leafref { path "/config/links/link/name"; } } container limitations { leaf only10Mbps { type boolean; default false; } leaf onlyHalfDuplex { type boolean; default false; } } } } container defaultLink { leaf linkName { type leafref { path "/config/links/link/name"; } } } } }
The command to compile the YANG file is confdc -c links.yang Thus in our Makefile we have:
all: links.fxs %.fxs: %.yang $(CONFD_DIR)/bin/confdc -c $*.yang
The Makefile requires the UNIX environment variable
CONFD_DIR
to be set to the directory where
ConfD is installed.
Once we have the .fxs file, it's time to start ConfD. To do that we have some initial steps that must be taken care of first.
We must have a configuration file for ConfD it self.
This file is usually referred to as confd.conf
.
There is a multitude of things we can configure in
confd.conf(5)
but for this initial example we'll just focus on the
things we need to get the links.yang
example to
work. We can copy the confd.conf
file from
etc/confd/confd.conf
relative to the installation
directory of ConfD and add "." to the loadPath
Now with our newly compiled links.yang
file
we can start ConfD as:
# source /path/to/installed_confd/confdrc # confd --foreground --verbose -c ./confd.conf
This starts ConfD in the foreground with all log messages displayed on stdout. This is a convenient way of running ConfD during development.
The first thing we can try out is how a Juniper style CLI looks and feels on our data model. The ConfD CLI(s) are entirely rendered from the data model. It's possible to extend and tweak the looks of the CLI in several ways, but for now, we try just what we get from the plain data model. The ConfD CLI is run through a small C program called confd_cli which is typically used as a login shell on the target host. During development, it's usually more convenient to just invoke that program directly from the UNIX prompt. The confd_cli program communicates with the ConfD daemon over the loopback socket.
Here is an actual session:
# confd_cli Welcome to the ConfD CLI admin connected from 127.0.0.1 using console on buzz admin@buzz 17:37:17> configure Entering configuration mode private [ok][2009-03-17 17:37:26] [edit] admin@buzz 17:37:26% set config links link eth0 addr 00:12:3f:7d:b0:32 brd 00:1 2:3f:7d:b0:32 [ok][2009-03-17 17:37:48] [edit] admin@buzz 17:37:48% set config links link eth0 flags BROADCAST [ok][2009-03-17 17:38:05] [edit] admin@buzz 17:38:05% set config links link eth0 flags Possible completions: BROADCAST LOOPBACK MULTICAST NOARP NOTRAILERS UP admin@buzz 17:38:05% set config links link eth0 flags LOOPBACK [ok][2009-03-17 17:38:25] [edit] admin@buzz 17:38:25% commit Commit complete. [ok][2009-03-17 17:38:31] [edit] admin@buzz 17:38:31% exit [ok][2009-03-17 17:38:34] admin@buzz 17:38:34> show configuration config links { link eth0 { flags { UP; BROADCAST; LOOPBACK; } addr 00:12:3f:7d:b0:32; brd 00:12:3f:7d:b0:32; } } [ok][2009-03-17 17:38:44] admin@buzz 17:38:44> exit #
Thus from the data model we got a fully functional Juniper like CLI.
We can also get a Cisco like CLI towards the same data model:
# confd_cli -C Welcome to the ConfD CLI admin connected from 127.0.0.1 using console on buzz buzz# show running-config config config links link eth0 flags UP flags BROADCAST flags LOOPBACK addr 00:12:3f:7d:b0:32 brd 00:12:3f:7d:b0:32 ! buzz# config Entering configuration mode terminal buzz(config)# config links link <TAB> Possible completions: <name:string> eth0 buzz(config)# config links link eth0 <TAB> Possible completions: addr brd flags mtu <cr> buzz(config)# config links link eth0 mtu 1200 buzz(config-link-eth0)# commit Commit complete. buzz(config-link-eth0)# buzz(config)# config <TAB> Possible completions: defaultLink linkLimitations links queueDisciplines buzz(config)# config defaultLink linkName eth0 buzz(config)# commit Commit complete.
The rendered CLIs are highly capable containing all features expected by a modern CLI.
The data model contains a top level config
container.
This makes sense from a data modeling perspective since it
wraps all configuration items inside a container. However,
we may wish to do away with the container in the CLI. We want to
issue the command defaultLink linkName eth0
as
opposed to the command config defaultLink linkName eth0
.
The ConfD CLI can be tweaked in a myriad different ways. The typical development cycle is to define the data model to be as succinct and understandable as possible. This makes life easier for the application programmers who write C/C++ code that access the data model. Once the YANG model is good, we tweak the CLI to become what we want.
In this tiny example we write a really small CLI modification file:
<clispec xmlns="http://tail-f.com/ns/clispec/1.0" style="c"> <operationalMode> </operationalMode> <configureMode> <modifications> <dropElem src="config"/> </modifications> </configureMode> </clispec>
Save that file as mods.cli
and compile that
file as:
# confdc -c mods.cli
This results in a file called mods.ccl
that
needs to be put in the load path of ConfD. We then re-launch the
Cisco CLI:
# confd_cli -C Welcome to the ConfD CLI admin connected from 127.0.0.1 using console on buzz buzz# config Entering configuration mode terminal buzz(config)# links link eth0 <TAB> Possible completions: addr brd flags mtu <cr> buzz(config)# links link eth0 mtu ? Possible completions: <unsignedInt>[1200] buzz(config)# links link eth0 mtu 1400 buzz(config-link-eth0)# commit Commit complete. buzz(config-link-eth0)#
NETCONF is a powerful protocol that can be used
to programmatically reconfigure a device. We're still
running ConfD with the links.yang
data model.
The easiest way to interact with the NETCONF agent in ConfD is to use a small python based program called netconf-console that ships with ConfD. Let's just run it from the UNIX prompt and see what we get:
# netconf-console --user=admin --password=admin --get-config -x '/config' <?xml version="1.0" encoding="UTF-8"?> <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1"> <data> <config xmlns="http://example.com/ns/link"> <links> <link> <name>eth0</name> <flags> <UP/> <BROADCAST/> <LOOPBACK/> </flags> <addr>00:12:3f:7d:b0:32</addr> <brd>00:12:3f:7d:b0:32</brd> <mtu>1400</mtu> </link> </links> <queueDisciplines/> <linkLimitations> <linkLimitation> <linkName>eth0</linkName> <limitations> <only10Mbps>true</only10Mbps> </limitations> </linkLimitation> </linkLimitations> <defaultLink> <linkName>eth0</linkName> </defaultLink> </config> </data> </rpc-reply>
The above command uses the python paramiko ssh client to
establish an SSH session to ConfD. It then issues a
NETCONF get-config RPC to retrieve all configuration
data found below the XPath /config
, i.e. this is
precisely the data we have just entered in the CLI. The command
netconf-console --get-config is a great way
to extract a backup of the entire configuration of the device.
If we want to manipulate the configuration with the netconf-consoleprogram , we must prepare some XML data that can be sent as an edit-config and feed it to netconf-console.
Here is an example, save the following to a file,
set-mtu.xml
.
<edit-config> <target> <running/> </target> <config xmlns="http://example.com/ns/link"> <config> <links> <link> <name>eth0</name> <mtu>1100</mtu> </link> </links> </config> </config> </edit-config>
Then run this with:
# netconf-console --user=admin --password=admin --rpc set-mtu.xml <?xml version="1.0" encoding="UTF-8"?> <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1"> <ok/> </rpc-reply>
It's also fairly instructive to directly connect to the agent using OpenSSH as in:
# ssh -s -p 2022 admin@localhost netconf admin@localhost's password: <?xml version="1.0" encoding="UTF-8"?> <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <capabilities> <capability>urn:ietf:params:netconf:base:1.0</capability> <capability>urn:ietf:params:netconf:capability:writable-running:1.0</capability> <capability>urn:ietf:params:netconf:capability:candidate:1.0</capability> <capability>urn:ietf:params:netconf:capability:confirmed-commit:1.0</capability> <capability>urn:ietf:params:netconf:capability:xpath:1.0</capability> <capability>urn:ietf:params:netconf:capability:url:1.0?scheme=ftp,file</capability> <capability>urn:ietf:params:netconf:capability:validate:1.0</capability> <capability>urn:ietf:params:netconf:capability:rollback-on-error:1.0</capability> <capability>http://example.com/ns/link</capability> <capability>http://tail-f.com/ns/aaa/1.1</capability> </capabilities> <session-id>14</session-id></hello>
The agent replies with the capabilities it supports.
It is of course entirely possible to use the
netconf-console
program to XML script towards a NETCONF agent. An alternative is
to use a Java library such as JNC to interact with the NETCONF
agent. JNC is in the Open SOurce and can by found on github at
https://github.com/tail-f-systems/JNC/
.