Can I read and manage CDB outside of ConfD?

The way applications interact with CDB is by using the Libraries that ConfD provides.
The MOAPI (Managed Object API) is the API intended for applications to read and write to CDB.

CDB is an integrated database and is only managed through ConfD (initialization, upgrade, etc…).

An external program can still interact directly with CDB through the cdb_* interface by linking with the libconfd library.

Any program linked with libconfd can interact with ConfD either locally or remotely; The case of blades in a chassis system running applications, interested in configuration stored in CDB, is a valid case. Some remote systems might be running under a different environment (Processor, OS, etc…), confdLib can be rebuilt for these targets as the source code and build instructions are available to developers.

Details about this can be found in: confd-basic-.libconfd.tar.gz

For matters related to CDB backup and restore, ConfD provides commands that allow users to safely backup CDB when ConfD is running:

man confd ...

   --loadxmlfiles File ...
       Load configuration in XML format from Files. The configuration is completely
       replaced by the contents in Files.

   --mergexmlfiles File ...
       Load configuration in XML format from Files. The configuration is merged with the
       contents in Files. The XML may use the 'operation' attribute, in the same way as it
       is used in a NETCONF <edit-config> operation.

   --cdb-backup File
       Save a snapshot of the CDB database into a GZipp:ed tar archive file (given by the
       File argument). If the File argument is a relative path, the file will be saved
       relative the ConfD daemon's current working directory. Only configuration data
       stored in CDB is saved (persistent CDB operational data is not). Note: if the
       database is locked for writing, the command will fail.`

If ConfD is not running, CDB files can be copied and saved for a future restore operation.

Nabil,

From the above, I understand that it is possible to save a configuration using “confd_load”, and to restore the configuration using “confd --loadxmlfiles”.

These mechanisms presume access to the shell. Is there a way to retrieve a complete configuration backup in XML format, and to load such a backup, using the REST API?

I understand that individual nodes can be accessed via the REST API by using GET, POST, PATCH, and so forth, to specific URLs underneath /api/config. However, if I try to retrieve the entire configuration by doing a GET to /api/config or /api/running, nothing is returned.

Similarly, I would like to upload a configuration via REST and have it overwrite the currently running configuration, similar to the way “confd --loadxmlfiles” does in the shell.

Thank you,
Jude

$ pwd
/Users/tailf/confd-6.2/examples.confd/rest/router
$ make clean all start
...

The current config in CDB:

$ curl -u admin:admin -X GET "http://localhost:8008/api/running/sys?deep"

<sys xmlns="http://example.com/router" xmlns:y="http://tail-f.com/ns/rest"  xmlns:r="http://example.com/router">
  <interfaces>
    <interface>
      <name>eth0</name>
      <description>test</description>
      <unit>
        <name>0</name>
        <enabled>true</enabled>
        <status>
        </status>
        <family>
          <inet>
            <address>
              <name>192.168.1.2</name>
              <prefix-length>16</prefix-length>
            </address>
          </inet>
        </family>
      </unit>
      <unit>
        <name>1</name>
        <enabled>true</enabled>
        <status>
        </status>
        <family>
          <inet>
            <address>
              <name>192.168.1.3</name>
              <prefix-length>16</prefix-length>
            </address>
          </inet>
        </family>
      </unit>
      <unit>
        <name>2</name>
        <enabled>true</enabled>
        <description>My Vlan</description>
        <vlan-id>18</vlan-id>
        <status>
        </status>
      </unit>
    </interface>
    <serial xmlns="http://example.com/example-serial">
      <name>ppp0</name>
      <ppp>
        <accounting>acme</accounting>
      </ppp>
      <authentication>
        <method>pap</method>
      </authentication>
      <authorization>admin</authorization>
      <ipcp>
      </ipcp>
    </serial>
  </interfaces>
  <routes>
    <inet>
      <route>
        <name>10.10.0.0</name>
        <prefix-length>16</prefix-length>
        <description>Route 1</description>
        <enabled>true</enabled>
        <type>next-hop</type>
        <next-hop>
          <name>192.168.10.1</name>
          <metric>100</metric>
        </next-hop>
      </route>
      <route>
        <name>10.20.0.0</name>
        <prefix-length>16</prefix-length>
        <description>Route 2</description>
        <enabled>true</enabled>
        <type>next-hop</type>
        <next-hop>
          <name>192.168.10.2</name>
          <metric>100</metric>
        </next-hop>
      </route>
      <route>
        <name>10.30.0.0</name>
        <prefix-length>16</prefix-length>
        <description>Route 3</description>
        <enabled>true</enabled>
        <type>next-hop</type>
        <next-hop>
          <name>192.168.10.3</name>
          <metric>100</metric>
        </next-hop>
      </route>
      <route>
        <name>10.40.0.0</name>
        <prefix-length>16</prefix-length>
        <description>Route 4</description>
        <enabled>true</enabled>
        <type>next-hop</type>
        <next-hop>
          <name>192.168.10.4</name>
          <metric>100</metric>
        </next-hop>
      </route>
      <route>
        <name>10.50.0.0</name>
        <prefix-length>16</prefix-length>
        <description>Route 5</description>
        <enabled>true</enabled>
        <type>next-hop</type>
        <next-hop>
          <name>192.168.10.5</name>
          <metric>100</metric>
        </next-hop>
      </route>
      <route>
        <name>10.60.0.0</name>
        <prefix-length>16</prefix-length>
        <description>Route 6</description>
        <enabled>true</enabled>
        <type>next-hop</type>
        <next-hop>
          <name>192.168.10.6</name>
          <metric>100</metric>
        </next-hop>
      </route>
      <route>
        <name>10.70.0.0</name>
        <prefix-length>16</prefix-length>
        <description>Route 7</description>
        <enabled>true</enabled>
        <type>next-hop</type>
        <next-hop>
          <name>192.168.10.7</name>
          <metric>100</metric>
        </next-hop>
      </route>
    </inet>
  </routes>
  <syslog>
    <server>
      <name>10.3.4.5</name>
      <enabled>true</enabled>
      <selector>
        <name>8</name>
        <facility>auth</facility>
        <facility>authpriv</facility>
        <facility>local0</facility>
      </selector>
      <y:operations>
        <archive-log>/api/running/sys/syslog/server/10.3.4.5/_operations/archive-log</archive-log>
      </y:operations>
    </server>
  </syslog>
  <ntp>
    <server>
      <name>10.2.3.4</name>
      <enabled>true</enabled>
      <peer>false</peer>
      <version>4</version>
      <key>2</key>
    </server>
    <local-clock>
      <enabled>true</enabled>
      <stratum>10</stratum>
    </local-clock>
    <key>
      <name>2</name>
      <trusted>true</trusted>
    </key>
    <controlkey>2</controlkey>
  </ntp>
  <dns>
    <server>
      <address>10.2.3.4</address>
    </server>
  </dns>
</sys>

We save the current config to a “backup.xml” file:

$ curl -u admin:admin -X GET "http://localhost:8008/api/running/sys?deep" > backup.xml

Delete the current config:

$ curl -u admin:admin -X DELETE http://127.0.0.1:8008/api/running/sys -H "Content-Type: application/vnd.yang.data+xml"

Only some default values remain:

$ curl -u admin:admin -X GET "http://localhost:8008/api/running/sys?deep"

<sys xmlns="http://example.com/router" xmlns:y="http://tail-f.com/ns/rest"  xmlns:r="http://example.com/router">
  <routes>
  </routes>
  <ntp>
    <local-clock>
      <enabled>true</enabled>
      <stratum>10</stratum>
    </local-clock>
  </ntp>
  <dns>
  </dns>
</sys>

Now we write the backup config from the backup.xml file:

$ curl -w "HTTP/1.1 %{http_code}\n" -u admin:admin -T ./backup.xml -X PUT http://127.0.0.1:8008/api/running/sys -H "Content-Type: application/vnd.yang.data+xml"
HTTP/1.1 204

…and the config is back:

$ curl -u admin:admin -X GET "http://localhost:8008/api/running/sys?deep"

<sys xmlns="http://example.com/router" xmlns:y="http://tail-f.com/ns/rest"  xmlns:r="http://example.com/router">
  <interfaces>
    <interface>
      <name>eth0</name>
      <description>test</description>
      <unit>
        <name>0</name>
        <enabled>true</enabled>
        <status>
        </status>
        <family>
          <inet>
            <address>
              <name>192.168.1.2</name>
              <prefix-length>16</prefix-length>
            </address>
          </inet>
        </family>
      </unit>
      <unit>
        <name>1</name>
        <enabled>true</enabled>
        <status>
        </status>
        <family>
          <inet>
            <address>
              <name>192.168.1.3</name>
              <prefix-length>16</prefix-length>
            </address>
          </inet>
        </family>
      </unit>
      <unit>
        <name>2</name>
        <enabled>true</enabled>
        <description>My Vlan</description>
        <vlan-id>18</vlan-id>
        <status>
        </status>
      </unit>
    </interface>
    <serial xmlns="http://example.com/example-serial">
      <name>ppp0</name>
      <ppp>
        <accounting>acme</accounting>
      </ppp>
      <authentication>
        <method>pap</method>
      </authentication>
      <authorization>admin</authorization>
      <ipcp>
      </ipcp>
    </serial>
  </interfaces>
  <routes>
    <inet>
      <route>
        <name>10.10.0.0</name>
        <prefix-length>16</prefix-length>
        <description>Route 1</description>
        <enabled>true</enabled>
        <type>next-hop</type>
        <next-hop>
          <name>192.168.10.1</name>
          <metric>100</metric>
        </next-hop>
      </route>
      <route>
        <name>10.20.0.0</name>
        <prefix-length>16</prefix-length>
        <description>Route 2</description>
        <enabled>true</enabled>
        <type>next-hop</type>
        <next-hop>
          <name>192.168.10.2</name>
          <metric>100</metric>
        </next-hop>
      </route>
      <route>
        <name>10.30.0.0</name>
        <prefix-length>16</prefix-length>
        <description>Route 3</description>
        <enabled>true</enabled>
        <type>next-hop</type>
        <next-hop>
          <name>192.168.10.3</name>
          <metric>100</metric>
        </next-hop>
      </route>
      <route>
        <name>10.40.0.0</name>
        <prefix-length>16</prefix-length>
        <description>Route 4</description>
        <enabled>true</enabled>
        <type>next-hop</type>
        <next-hop>
          <name>192.168.10.4</name>
          <metric>100</metric>
        </next-hop>
      </route>
      <route>
        <name>10.50.0.0</name>
        <prefix-length>16</prefix-length>
        <description>Route 5</description>
        <enabled>true</enabled>
        <type>next-hop</type>
        <next-hop>
          <name>192.168.10.5</name>
          <metric>100</metric>
        </next-hop>
      </route>
      <route>
        <name>10.60.0.0</name>
        <prefix-length>16</prefix-length>
        <description>Route 6</description>
        <enabled>true</enabled>
        <type>next-hop</type>
        <next-hop>
          <name>192.168.10.6</name>
          <metric>100</metric>
        </next-hop>
      </route>
      <route>
        <name>10.70.0.0</name>
        <prefix-length>16</prefix-length>
        <description>Route 7</description>
        <enabled>true</enabled>
        <type>next-hop</type>
        <next-hop>
          <name>192.168.10.7</name>
          <metric>100</metric>
        </next-hop>
      </route>
    </inet>
  </routes>
  <syslog>
    <server>
      <name>10.3.4.5</name>
      <enabled>true</enabled>
      <selector>
        <name>8</name>
        <facility>auth</facility>
        <facility>authpriv</facility>
        <facility>local0</facility>
      </selector>
      <y:operations>
        <archive-log>/api/running/sys/syslog/server/10.3.4.5/_operations/archive-log</archive-log>
      </y:operations>
    </server>
  </syslog>
  <ntp>
    <server>
      <name>10.2.3.4</name>
      <enabled>true</enabled>
      <peer>false</peer>
      <version>4</version>
      <key>2</key>
    </server>
    <local-clock>
      <enabled>true</enabled>
      <stratum>10</stratum>
    </local-clock>
    <key>
      <name>2</name>
      <trusted>true</trusted>
    </key>
    <controlkey>2</controlkey>
  </ntp>
  <dns>
    <server>
      <address>10.2.3.4</address>
    </server>
  </dns>
</sys>

Thank you. The DELETE operation, as you have described in the example with “DELETE http://127.0.0.1:8008/api/running/sys” appears to work for a subtree “sys” in the configuration.
However, I would like to clear the entire configuration and then restore it. When I try the DELETE operation on the entire configuration with “DELETE http://127.0.0.1:8008/api/running”, it does not work. Is this not supported, or is there a different way to accomplish this via REST?