---
title: "Building a Kea testbed with NETCONF"
slug: "building-a-kea-testbed-with-netconf"
description: "Instructions on installing Kea, Sysrepo, NETCONF, and Netopeer2 for testing on nearly all Linux distributions."
tags: ["kea dhcp"]
updated: 2024-08-08T10:20:22Z
published: 2024-08-08T10:20:22Z
canonical: "kb.isc.org/building-a-kea-testbed-with-netconf"
---

> ## Documentation Index
> Fetch the complete documentation index at: https://kb.isc.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Building a Kea testbed with NETCONF

NETCONF is a protocol defined by the IETF to “install, manipulate, and delete the configuration of network devices.” That sounds quite reasonable, but the installation is a bit more complex than it appears at first.

This article provides detailed instructions allowing a system administrator to install [Kea](https://www.isc.org/kea/), [Sysrepo](https://www.sysrepo.org), and [Netopeer2](https://github.com/CESNET/Netopeer2), for testing and proof-of-concept.

The base operating system is [Ubuntu 24.04](http://releases.ubuntu.com/24.04/), but the same procedure should work with only minor changes on nearly all Linux distributions.

Please note that in the following examples, a "Demo User" with the username `demouser` is used. The userid is not a de-mouser for getting rid of rodents.

Most of the text in grey boxes:

```
shell commands here
```

can be selected and pasted into the Linux shell. Beware that there are some locations that use the `~demouser` shell expansion; if you do not use the same username, the results will not be as expected.

If the text in the grey box is preceded by a dollar sign ($), the command is shown, followed by the output. For example:

```
$ ls
libnetconf2   libssh-0.8.6.tar.gz  Netopeer2-0.7-r1  v0.16-r3.tar.gz  v0.7-r1.tar.gz    v0.7-r1.tar.gz.2  zlib-1.2.11.tar.xz
libssh-0.8.6  libyang-0.16-r3      sysrepo-0.7.7     v0.7.8.tar.gz    v0.7-r1.tar.gz.1  zlib-1.2.11
```

This shows that the `ls` command was executed, and the following two lines were sample output.

## Getting started

It is recommended that you do this work in a new, pristine working directory.

```
mkdir ~demouser/KeaNetconf
cd ~demouser/KeaNetconf
```

## Installation

 The software installs following this message are all done by building from source code.  To ensure easy removal and reinstallation, especially in the event that Kea moves to other dependency versions, they are installed in custom directories.

                         

### Dependencies

The first thing to do is confirm that dependencies are met. Installing these from maintained repositories means that they can be upgraded automatically:

```
sudo apt-get install \
  autoconf automake bison cmake flex gcc g++ git gnupg \
  libboost-system-dev libpcap-dev libtool libssl-dev \
  liblog4cplus-dev make
```

Sysrepo and Netopeer are fast evolving projects that often break compatibility, with no stable releases. Kea pins its NETCONF dependencies to ensure reliable behavior. As of Kea 2.4.0, the versions for these dependencies are pinned as follows:

- libyang v2.1.4
- sysrepo v2.2.12
- libyang-cpp v1.1.0 (git commit ae7d649ea75da081725c119dd553b2ef3121a6f8)
- sysrepo-cpp v1.1.0 (git commit 02634174ffc60568301c3d9b9b7cf710cff6a586)
- netopeer2 v2.2.28

#### libyang

`libyang` is a YANG (data modeling language for the definition of data sent over the NETCONF network configuration protocol) parser and toolkit written (and providing API) in C. `libyang` is required by `netopeer2` and `sysrepo`.

```
git clone https://github.com/CESNET/libyang.git
pushd libyang
git checkout v2.1.4
mkdir -p ./build
pushd ./build
cmake ..                                                \
  -DCMAKE_C_FLAGS='-Wno-incompatible-pointer-types'     \
  -DCMAKE_INSTALL_PREFIX='/opt/libyang'
make
sudo make install
popd
```

```
git clone https://github.com/CESNET/libyang-cpp.git
pushd libyang-cpp
git checkout ae7d649ea75da081725c119dd553b2ef3121a6f8
git apply <<EOF
diff --git a/src/Context.cpp b/src/Context.cpp
index b2fe887..add11cc 100644
--- a/src/Context.cpp
+++ b/src/Context.cpp
@@ -13,2 +13,3 @@
 #include <libyang/libyang.h>
+#include <algorithm>
 #include <span>
EOF
mkdir -p ./build
pushd ./build
export CMAKE_PREFIX_PATH='/opt/libyang'
cmake ..                                                \
  -DBUILD_TESTING=OFF                                   \
  -DCMAKE_INSTALL_PREFIX='/opt/libyang-cpp'
make
sudo make install
popd
```

#### sysrepo

`sysrepo` is a YANG-based configuration and operational state data store for Unix/Linux applications. As of the publication of this article, the newest version of `sysrepo` is 0.7.7.

```
git clone https://github.com/sysrepo/sysrepo.git
pushd sysrepo
git checkout v2.2.12
mkdir -p ./build
pushd ./build
export CMAKE_PREFIX_PATH='/opt/libyang'
cmake ..                                                \
  -DREPO_PATH='/etc/sysrepo'                            \
  -DCMAKE_INSTALL_PREFIX='/opt/sysrepo'
make
sudo make install
popd
```

```
git clone https://github.com/sysrepo/sysrepo-cpp.git
pushd sysrepo-cpp
git checkout 02634174ffc60568301c3d9b9b7cf710cff6a586
mkdir -p ./build
pushd ./build
export CMAKE_PREFIX_PATH='/opt/libyang:/opt/libyang-cpp:/opt/sysrepo'
cmake ..                                                \
  -DBUILD_TESTING=OFF                                   \
  -DCMAKE_INSTALL_PREFIX='/opt/sysrepo-cpp'
make
sudo make install
popd
```

#### zlib

The compression library `zlib` is required by netopeer2. Note that this could probably be installed via `apt-get`, but following these instructions makes sure that you get the 1.2.11 version:

```
wget http://www.zlib.net/zlib-1.2.11.tar.xz && \
  tar -xf zlib-1.2.11.tar.xz && \
  rm zlib-1.2.11.tar.xz && \
  pushd zlib-1.2.11 && mkdir build && cd build && \
  cmake .. && \
  make && \
  sudo make install && \
  popd
```

#### libssh

You will need to install a recent version of `libssh`. Unfortunately, many repositories run significantly behind, so this installs the latest (as of the publication of this KB article):

```
wget https://git.libssh.org/projects/libssh.git/snapshot/libssh-0.8.6.tar.gz && \
  tar -xf libssh-0.8.6.tar.gz && \
  rm libssh-0.8.6.tar.gz && \
 pushd libssh-0.8.6 && mkdir build && cd build && \
  cmake .. && \
  make && \
  sudo make install && \
  popd
```

#### libnetconf2

`libnetconf2` is a NETCONF library in C intended for building NETCONF clients and servers. The following instructions install `libnetconf2` from GitHub. Unfortunately, we need a specific commit at this time:

```
git clone https://github.com/CESNET/libnetconf2.git && \
  pushd libnetconf2 && \
  git checkout 526f9f8d09b415a7df1cba4b5dcfc4705ad6f29b && \
  mkdir build && cd build && \
  cmake .. && \
  make && \
  sudo make install && \
  popd
```

#### netopeer2

`netopeer2` is a second-generation set of tools which implement network configuration tools based on the NETCONF protocol.

The `netopeer` daemon will be started during installation, so `ldconfig` must be run to ensure that the previously installed libraries are available.

```
ldconfig
wget https://github.com/CESNET/Netopeer2/archive/v0.7-r1.tar.gz && \
  tar -xf v0.7-r1.tar.gz && \
  rm v0.7-r1.tar.gz && \
  pushd Netopeer2-0.7-r1 && \
  cd keystored && mkdir build && cd build && \
  cmake .. && \
  make && \
  sudo make install && \
  cd ../../server && mkdir build && cd build && \
  cmake .. && \
  make && \
  sudo make install && \
  cd ../../cli/ && mkdir build && cd build && \
  cmake .. && \
  make && \
  sudo make install && \
  popd
```

---

## CONFIGURATION

To ensure that all libraries that have been installed are now available, execute:

```
sudo ldconfig
```

### Testing

The simplest check to see if `netopeer2-server` is installed correctly is to run it with the `-h` (help) option:

```
$ netopeer2-server -h
Usage: netopeer2-server [-dhV] [-v level] [-c category]
 -d                  debug mode (do not daemonize and print
                     verbose messages to stderr instead of syslog)
 -h                  display help
 -V                  show program version
 -v level            verbose output level:
                         0 - errors
                         1 - errors and warnings
                         2 - errors, warnings and verbose messages
 -c category[,category]*  verbose debug level, print only these debug message categories
 categories: DICT, YANG, YIN, XPATH, DIFF, MSG, EDIT_CONFIG, SSH, SYSREPO
```

Similarly, confirm that `netopeer2-cli` is installed and functional:

```
$ netopeer2-cli
get_netconf_dir: Configuration directory "/home/demouser/.netopeer2-cli" did not exist, created.
load_config: No saved history.
load_config: No saved configuration.
> ^D
```

You should confirm that `sysrepo` is installed and runnable:

```
$ sysrepoctl -l
Sysrepo schema directory: /etc/sysrepo/yang/
Sysrepo data directory:   /etc/sysrepo/data/
(Do not alter the contents of these directories manually)

Module Name                | Revision   | Conformance | Data Owner          | Permissions | Submodules                    | Enabled Features
-----------------------------------------------------------------------------------------------------------------------------------------------
ietf-netconf-notifications | 2012-02-06 | Installed   | root:root           | 666         |                               |
ietf-netconf               | 2011-06-01 | Installed   | root:root           | 666         |                               | writable-running candidate rollback-on-error validate startup xpath
ietf-netconf-acm           | 2018-02-14 | Imported    |                     |             |                               |
nc-notifications           | 2008-07-14 | Installed   | root:root           | 666         |                               |
[...]
```

### Configuring Netopeer2

To authenticate to the `netopeer2` daemon, you will need a set of SSH credentials (public/private keypair). It is highly recommended that you create a separate set of credentials from those that you use elsewhere:

```
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/demouser/.ssh/id_rsa): /home/demouser/.ssh/demouser_net
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/demouser/.ssh/demouser_net.
Your public key has been saved in /home/demouser/.ssh/demouser_net.pub.
The key fingerprint is:
SHA256:g2bNYVLYKRE7[...]NUP8hEbot0 demouser@ubuntu
The key's randomart image is:
+---[RSA 2048]----+
|     .+=..       |
|   .o=Eoo        |
|  o.=+B.o        |
| . + E.B .       |
|  . o.B.S        |
|o.o o+o. .       |
|** + o           |
|BoB   .          |
|o*.o..           |
+----[SHA256]-----+
$ cat ~demouser/.ssh/demouser_net.pub
ssh-rsa AAAAB3NzaC1yc2EAAA[...]IU5VpoyTkx/lPZ63YZQIYs91YzoN/FtHQ7oZsXrnv3WToO2V demouser@ubuntu
```

### Update `load_auth_pubkey.xml`

The file as, found in the source tarball, should look exactly like this:

```
$ cat Netopeer2-0.7-r1/server/configuration/load_auth_pubkey.xml
<system xmlns="urn:ietf:params:xml:ns:yang:ietf-system">
  <authentication>
    <user>
      <name>[system-username]</name>
      <authorized-key>
        <name>[arbitrary-key-name]</name>
        <algorithm>[key-algorithm]</algorithm>
        <key-data>[key-data]</key-data>
      </authorized-key>
    </user>
  </authentication>
</system>
```

It has to be updated to match the previously generated key:

```
cp Netopeer2-0.7-r1/server/configuration/load_auth_pubkey.xml .
```

Then edit it to include the `ssh` key as created above (replace the `AAA ... O2V` in the following text with the public portion of the `ssh` key that was created above. Note that you will be changing:

1. user name
2. authorized-key name
3. authorized-key algorithm
4. authorized-key key-data

```
<system xmlns="urn:ietf:params:xml:ns:yang:ietf-system">
  <authentication>
    <user>
      <name>demouser</name>
      <authorized-key>
        <name>demouser_net</name>
        <algorithm>ssh-rsa</algorithm>
        <key-data>AAAAB3NzaC1yc2EAAAADAQABA[...]Ys91YzoN/FtHQ7oZsXrnv3WToO2V</key-data>
      </authorized-key>
    </user>
  </authentication>
</system>
```

The edited `load_auth_pubkey.xml` must now be uploaded into the `sysrepo` datastore:

```
sudo sysrepocfg --import=load_auth_pubkey.xml ietf-system --datastore=startup
```

### Configure `netopeer2-cli`

At this point there should not be any keys imported:

```
$ netopeer2-cli
> auth keys
The keys used for SSH authentication:
(none)
>
```

To import generated keys, execute the following:

```
> auth keys add /home/demouser/.ssh/demouser_net.pub /home/demouser/.ssh/demouser_net
> auth keys
The keys used for SSH authentication:
#0: /home/demouser/.ssh/demouser_rsa.pub (private /home/demouser/.ssh/demouser_rsa)
>
```

To check the preferences of authentication:

```
> auth pref
The SSH authentication method preferences:
	'publickey':   1
	'password':    2
	'interactive': 3
>
```

It is possible to change these using `auth pref interactive N` where N is a priority number (a lower number has higher precedence).

### Start `netopeer` processes:

```
$ sudo netopeer2-server
```

You may want to start `netopeer2-server` in debug mode:

```
$ sudo netopeer2-server -d -v3
```

At this point, you should be able to connect to the `netopeer2-server`:

```
$ netopeer2-cli
> connect
Interactive SSH Authentication
Type your password:
Password:
>
```

and also check the running configuration:

```
> get-config --source running
DATA
<netconf-server xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-server">
  <listen>
    <endpoint>
      <name>all-interfaces</name>
      <ssh>
        <address>0.0.0.0</address>
        <port>830</port>
        <host-keys>
          <host-key>
            <name>imported SSH key</name>
            <public-key>ssh_host_rsa_key</public-key>
          </host-key>
        </host-keys>
      </ssh>
    </endpoint>
  </listen>
</netconf-server>
<system xmlns="urn:ietf:params:xml:ns:yang:ietf-system">
  <authentication>
    <user>
      <name>demouser</name>
      <authorized-key>
        <name>demouser_net</name>
        <algorithm>ssh-rsa</algorithm>
        <key-data>AAAAB3NzaC1yc2EAAAADAQABA[...]Ys91YzoN/FtHQ7oZsXrnv3WToO2V</key-data>
      </authorized-key>
    </user>
  </authentication>
</system>
```

## KEA INSTALLATION and CONFIGURATION

### Download and install Kea 2.6.1

Note that this installs Kea into the directory `kea-bin` in the demouser's home directory. It does not install software into system paths:

```
wget https://ftp.isc.org/isc/kea/2.6.1/kea-2.6.1.tar.gz && \
  tar -xf kea-2.6.1.tar.gz && \
  rm kea-2.6.1.tar.gz && \
  pushd kea-2.6.1 && \
  autoreconf -if && \
  ./configure --prefix=/home/demouser/kea-bin \
    --with-libyang=/opt/libyang --with-libyang-cpp=/opt/libyang-cpp \
    --with-sysrepo=/opt/sysrepo --with-sysrepo-cpp=/opt/sysrepo-cpp
  make && \
  sudo make install && \
  popd
```

Confirm that the file `kea-2.6.1/config.report` contains:

```
NETCONF:
  yes

  libyang:
    LIBYANG_CPPFLAGS:
    LIBYANG_INCLUDEDIR:    -I/opt/libyang/include
    LIBYANG_LIBS:          -L/opt/libyang/lib -lyang -Wl,-R/opt/libyang/lib -lyang
    LIBYANG_PREFIX:        /opt/libyang
    LIBYANG_VERSION:       2.1.4

  libyang-cpp:
    LIBYANGCPP_CPPFLAGS:
    LIBYANGCPP_INCLUDEDIR: -I/opt/libyang-cpp/include -I/opt/libyang/include
    LIBYANGCPP_LIBS:       -L/opt/libyang-cpp/lib -lyang-cpp -Wl,-R/opt/libyang-cpp/lib -lyang-cpp
    LIBYANGCPP_PREFIX:     /opt/libyang-cpp
    LIBYANGCPP_VERSION:    1.1.0

  sysrepo:
    SYSREPO_CPPFLAGS:
    SYSREPO_INCLUDEDIR:    -I/opt/sysrepo/include -I/opt/libyang/include
    SYSREPO_LIBS:          -L/opt/sysrepo/lib -lsysrepo -Wl,-R/opt/sysrepo/lib -lsysrepo
    SYSREPO_PREFIX:        /opt/sysrepo
    SYSREPO_VERSION:       2.2.12

    SR_REPO_PATH:          /etc/sysrepo
    SR_PLUGINS_PATH:       /opt/sysrepo/lib/sysrepo/plugins
    SRPD_PLUGINS_PATH:     /opt/sysrepo/lib/sysrepo-plugind/plugins

  sysrepo-cpp:
    SYSREPOCPP_CPPFLAGS:
    SYSREPOCPP_INCLUDEDIR: -I/opt/sysrepo-cpp/include -I/opt/sysrepo/include -I/opt/libyang-cpp/include -I/opt/libyang/include
    SYSREPOCPP_LIBS:       -L/opt/sysrepo-cpp/lib -lsysrepo-cpp -Wl,-R/opt/sysrepo-cpp/lib -lsysrepo-cpp
    SYSREPOCPP_PREFIX :    /opt/sysrepo-cpp
    SYSREPOCPP_VERSION:    1.1.0
```

Now you need to install all the Kea YANG modules:

```
/home/demouser/kea-bin/share/kea/yang/modules/utils/reinstall.sh
```

That should work, but if problems are encountered, the modules can also be installed manually:

```
pushd /home/demouser/kea-bin/share/kea/yang/modules/
for i in \
  keatest-module \
  ietf-interfaces \
  ietf-dhcpv6-common \
  ietf-dhcpv6-client \
  ietf-dhcpv6-relay \
  ietf-dhcpv6-server \
  ietf-yang-types \
  ietf-dhcpv6-options \
  ietf-dhcpv6-types \
  ietf-inet-types \
  kea-types \
  kea-dhcp-types \
  kea-dhcp-ddns \
  kea-ctrl-agent \
  kea-dhcp4-server \
  kea-dhcp6-server \
; do
  sudo /opt/sysrepoctl -i "${i}"
done
popd
```

At this point, you will need to prepare three config files:

1. `kea-startup.xml` for Kea, which will be uploaded to `sysrepo`:

```
$ cat kea-startup.xml
<config xmlns="urn:ietf:params:xml:ns:yang:kea-dhcp6-server">
  <control-socket>
    <socket-name>/home/demouser/.control_socket</socket-name>
    <socket-type>unix</socket-type>
  </control-socket>
</config>
```

Upload it to the `sysrepo` startup datastore using the command:

```
sudo sysrepocfg --datastore=startup --import=kea-startup.xml
```

1. `kea.conf` file for `kea-dhcp6`.  The most important configuration options at this point are `logging` and `socket`.

```
$ cat kea.conf
{
  "Dhcp6": {
    "interfaces-config": {
      "interfaces": [
        "enp0s8"
      ]
    },
    "subnet6": [],
    "lease-database": {
      "type": "memfile",
      "lfc-interval": 0
    },
    "control-socket": {
      "socket-type": "unix",
      "socket-name": "/home/demouser/.control_socket"
    }
  },
  "Logging": {
    "loggers": [
      {
        "name": "kea-dhcp6",
        "output-options": [
          {
            "output": "stdout"
          }
        ],
        "debuglevel": 99,
        "severity": "DEBUG"
      }
    ]
  }
}
```

and 3) `keanetconf.conf` for the Kea netconf module (be sure to use the same socket as above):

```
$ cat keanetconf.conf
{
  "Netconf": {
    "managed-servers": {
      "dhcp6": {
        "model": "kea-dhcp6-server",
        "comment": "DHCP6 server",
        "boot-update": true,
        "subscribe-changes": true,
        "validate-changes": true,
        "control-socket": {
          "socket-name": "/home/demouser/.control_socket",
          "socket-type": "unix"
        }
      }
    }
  },
  "Logging": {
    "loggers": [
      {
        "name": "kea-netconf",
        "output-options": [
          {
            "output": "stdout"
          }
        ],
        "severity": "DEBUG",
        "debuglevel": 99
      }
    ]
  }
}
```

## Testing:

### Start `kea-dhcp6`:

```
$ sudo ~demouser/kea-bin/sbin/kea-dhcp6 -c ~demouser/KeaNetconf/kea.conf
```

### Start `kea-netconf`:

```
$ sudo ~demouser/kea-bin/sbin/kea-netconf -c ~demouser/KeaNetconf/keanetconf.conf
```

At this point kea should be automatically reconfigured with configuration stored in `kea-startup.xml` which was uploaded to the startup datastore.

You must now create a config that you want to upload. Remember to use the same socket location or you will lose the connection with Kea.

 You will need to change the interface from `enp0s8` to match your system

                         

```
$ cat kea.xml
<config xmlns="urn:ietf:params:xml:ns:yang:kea-dhcp6-server">
  <subnet6>
    <id>1</id>
    <pool>
      <start-address>2001:db8::1:0</start-address>
      <end-address>2001:db8::1:1</end-address>
    </pool>
    <subnet>2001:db8::/64</subnet>
  </subnet6>
  <interfaces-config>
    <interfaces>enp0s8</interfaces>
  </interfaces-config>
  <control-socket>
    <socket-name>/home/demouser/.control_socket</socket-name>
    <socket-type>unix</socket-type>
  </control-socket>
</config>
```

Connect to netopeer2-server:

```
$ netopeer2-cli
> connect
Interactive SSH Authentication
Type your password:
Password:
>
```

Send pre-prepared config to running datastore:

```
> edit-config --target running --config=kea.xml
```

If you see:

```
> edit-config --target running --config=kea.xml
OK
```

`kea-netconf` should detect the change and only verify the config:

```
019-01-17 15:47:09.918 INFO  [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGE_EVENT Received YANG configuration change VERIFY event
2019-01-17 15:47:09.918 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/subnet6[id='1'] (list instance)
2019-01-17 15:47:09.918 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/subnet6[id='1']/id = 1
2019-01-17 15:47:09.918 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/subnet6[id='1']/pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:1'] (list instance)
2019-01-17 15:47:09.918 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/subnet6[id='1']/pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:1']/start-address = 2001:db8::1:0
2019-01-17 15:47:09.918 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/subnet6[id='1']/pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:1']/end-address = 2001:db8::1:1
2019-01-17 15:47:09.918 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/subnet6[id='1']/subnet = 2001:db8::/64
2019-01-17 15:47:09.918 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: moved: /kea-dhcp6-server:config/subnet6[id='1'] first
2019-01-17 15:47:09.918 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/interfaces-config (container)
2019-01-17 15:47:09.918 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/interfaces-config/interfaces = enp0s8
2019-01-17 15:47:09.919 INFO  [kea-netconf.netconf/6911] NETCONF_VALIDATE_CONFIG_STARTED started validating configuration for dhcp6 server
2019-01-17 15:47:09.929 DEBUG [kea-netconf.netconf/6911] NETCONF_VALIDATE_CONFIG validating configuration with dhcp6 server: {
  "Dhcp6": {
    "control-socket": {
      "socket-name": "/home/demouser/.control_socket",
      "socket-type": "unix"
    },
    "interfaces-config": {
      "interfaces": [ "enp0s8" ]
    },
    "subnet6": [
      {
        "id": 1,
        "pools": [
          {
            "pool": "2001:db8::1:0 - 2001:db8::1:1"
          }
        ],
        "subnet": "2001:db8::/64"
      }
    ]
  }
}
2019-01-17 15:47:09.930 INFO  [kea-netconf.netconf/6911] NETCONF_VALIDATE_CONFIG_COMPLETED completed validating configuration for dhcp6 server
```

When you are ready to apply changes, use:

```
> edit-config --target running --defop=replace --config=kea.xml
OK
> commit
OK
```

At this point, `kea-netconf` should have logged:

```
2019-01-17 15:47:09.939 INFO  [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGE_EVENT Received YANG configuration change APPLY event
2019-01-17 15:47:09.940 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/subnet6[id='1'] (list instance)
2019-01-17 15:47:09.940 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/subnet6[id='1']/id = 1
2019-01-17 15:47:09.940 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/subnet6[id='1']/pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:1'] (list instance)
2019-01-17 15:47:09.940 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/subnet6[id='1']/pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:1']/start-address = 2001:db8::1:0
2019-01-17 15:47:09.940 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/subnet6[id='1']/pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:1']/end-address = 2001:db8::1:1
2019-01-17 15:47:09.941 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/subnet6[id='1']/subnet = 2001:db8::/64
2019-01-17 15:47:09.941 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: moved: /kea-dhcp6-server:config/subnet6[id='1'] first
2019-01-17 15:47:09.941 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/interfaces-config (container)
2019-01-17 15:47:09.941 DEBUG [kea-netconf.netconf/6911] NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: /kea-dhcp6-server:config/interfaces-config/interfaces = enp0s8
2019-01-17 15:47:09.944 INFO  [kea-netconf.netconf/6911] NETCONF_UPDATE_CONFIG_STARTED started updating configuration for dhcp6 server
2019-01-17 15:47:09.956 DEBUG [kea-netconf.netconf/6911] NETCONF_UPDATE_CONFIG updating configuration with dhcp6 server: {
  "Dhcp6": {
    "control-socket": {
      "socket-name": "/home/demouser/.control_socket",
      "socket-type": "unix"
    },
    "interfaces-config": {
      "interfaces": [ "enp0s8" ]
    },
    "subnet6": [
      {
        "id": 1,
        "pools": [
          {
            "pool": "2001:db8::1:0 - 2001:db8::1:1"
          }
        ],
        "subnet": "2001:db8::/64"
      }
    ]
  }
}
2019-01-17 15:47:09.958 INFO  [kea-netconf.netconf/6911] NETCONF_UPDATE_CONFIG_COMPLETED completed updating configuration for dhcp6 server
```

`kea-dhcp6` will log:

```
2019-01-17 15:47:09.956 INFO  [kea-dhcp6.commands/6909] COMMAND_RECEIVED Received command 'config-set'
2019-01-17 15:47:09.956 INFO  [kea-dhcp6.hosts/6909] HOSTS_BACKENDS_REGISTERED the following host backend types are available:
2019-01-17 15:47:09.956 INFO  [kea-dhcp6.dhcpsrv/6909] DHCPSRV_CFGMGR_ADD_IFACE listening on interface enp0s8
2019-01-17 15:47:09.956 INFO  [kea-dhcp6.dhcpsrv/6909] DHCPSRV_CFGMGR_NEW_SUBNET6 a new subnet has been added to configuration: 2001:db8::/64 with params t1=900, t2=1800, preferred-lifetime=3600, valid-lifetime=7200, rapid-commit is disabled
2019-01-17 15:47:09.956 INFO  [kea-dhcp6.dhcp6/6909] DHCP6_CONFIG_COMPLETE DHCPv6 server has completed configuration: added IPv6 subnets: 1; DDNS: disabled
2019-01-17 15:47:09.956 INFO  [kea-dhcp6.dhcpsrv/6909] DHCPSRV_MEMFILE_DB opening memory file lease database: type=memfile universe=6
```

At this point, you can claim success! Everything is working as it should!

## Errors:

If you see messages like:

```
> edit-config --target running --config=kea.xml
ERROR
	type:     application
	tag:      operation-failed
	severity: error
	message:  Validation of the changes failed
```

that means that `kea.xml` is invalid.

If you see:

```
> edit-config --target running --config=kea.xml
ERROR
	type:     application
	tag:      operation-failed
	severity: error
	path:     /kea-dhcp6-server:config/subnet6[id='1']
	message:  The node is not enabled in the running datastore
```

That means that kea-netconf is not running!

### Additional sample commands:

Get current model of kea-dhcp6-server (that includes revision date):

```
get-schema --model kea-dhcp6-server
```

Replace the current running datastore:

```
edit-config --target running --defop=replace --config=kea.xml
```

Merge the current running datastore with kea.xml (can produce conflicts, this is default action):

```
edit-config --target running --defop=replace --config=kea.xml
```
