12  DB-API Subsystem

The DB-API subsystem provides a special datastore editing interface for subsystems to access the YANG-based data controlled by the main server.  It can be used by network management components within the device that operate in addition to the netconfd-pro server..

The DB-API service provides the ability for a subsystem to send a configuration edit to the main server.  The YControl protocol is used to manage the connection and communication with the main server.

The db-api-app program “main.c” function shows an example of how the DB-API interface can be used to send an edit request to the server. It also shows how db-lock feature can be utilized.

 Example DB-API Application

 

/********************************************************************

* FUNCTION check_db_lock_test

*

* Check elapsed time to simulate local-lock and local-unlock

* operations to cause the server to get db-lock failures

*

*********************************************************************/

static void

    check_db_lock_test (uint32 st_time, uint32 change_time, boolean *done)

{

    static int32 lock_count = 0; // restrict infinite loop

    time_t timenow;

    (void)time(&timenow);

 

    //uint32 start_wait = 30;   // wait this long before anything

    //uint32 change_wait = 7;   // wait to change lock state

 

    double timediff = difftime(timenow, start_time);

 

    if ( lock_count > 50) {

        *done = TRUE ;

        log_info("\nTest Completed!\n");

        return;

    }

 

    if (timediff < (double)st_time) {

        return;

    }

 

    status_t res = NO_ERR;

    if (last_time == 0) {

        /* request first local lock */

        res = db_api_request_local_db_lock();

        if (res == NO_ERR) {

            log_info("\ndb-lock-test: Got local db-lock");

            locked = TRUE;

            (void)time(&last_time);

        } else {

            log_info("\ndb-lock-test: First local-lock failed (%s)",

                     get_error_string(res));

        }

        lock_count++;

    } else {

        timediff = difftime(timenow, last_time);

        if (timediff < (double)change_time) {

            return;

        }

 

        if (locked) {

            res = db_api_release_local_db_lock();

            if (res == NO_ERR) {

                log_info("\ndb-lock-test: Released local db-lock");

                locked = FALSE;

                last_time = timenow;   // reset timer

            } else {

                log_info("\ndb-lock-test: Release local-lock failed (%s)",

                         get_error_string(res));

            }

        } else {

            res = db_api_request_local_db_lock();

            if (res == NO_ERR) {

                log_info("\ndb-lock-test: Request local db-lock");

                locked = TRUE;

                last_time = timenow;

            } else {

                log_info("\ndb-lock-test: Request local-lock failed (%s)",

                         get_error_string(res));

            }

        }

        lock_count++ ;

    }

 

}  /* check_db_lock_test */

/********************************************************************

* FUNCTION send_test_edit

*

* This is an example send edit function.

*

*********************************************************************/

static void

    send_test_edit (void)

{

    /* simple leaf test from test.yang */

    const xmlChar *path_str = (const xmlChar *)"/int8.1";

    const xmlChar *operation_str = (const xmlChar *)"merge";

    const xmlChar *value_str = (const xmlChar *)"<int8.1>42</int8.1>";

 

    status_t res = db_api_send_edit(path_str, operation_str, value_str);

    if (res != NO_ERR) {

        log_error("\nSend test edit failed %s %s = %s (%s)\n",

                  operation_str, path_str, value_str,

                  get_error_string(res));

    } else if (LOGDEBUG) {

        log_debug("\nSend test edit OK  %s %s = %s\n",

                  operation_str, path_str, value_str);

    }

 

}  /* send_test_edit */

 

 

/********************************************************************

* FUNCTION send_complex_test_edit

*

* This is an example send edit function.

* It uses multiple APIs to build a patch with 3 edits

* The module test.yang needs to be loaded for this to work

*********************************************************************/

static void

    send_complex_test_edit (void)

{

    const xmlChar *patch_id_str = (const xmlChar *)"complex-P2";

    boolean system_edit = TRUE;

    yang_patch_cb_t *pcb = NULL;

 

    /* Step 1: create a patch control block */

    status_t res =

        db_api_start_patch(patch_id_str,

                           system_edit,

                           &pcb);

 

    if (pcb == NULL) {

        log_error("\nCreate patch failed (%s)\n", get_error_string(res));

        return;

    }

 

    const xmlChar *edit_id_str = (const xmlChar *)"edit1";

    const xmlChar *edit_target_str = (const xmlChar *)"/int8.1";

    const xmlChar *edit_operation_str = (const xmlChar *)"replace";

    const xmlChar *edit_xml_value = (const xmlChar *)

        "<int8.1 xmlns='http://netconfcentral.org/ns/test'>44</int8.1>";

    const xmlChar *insert_point = NULL;

    const xmlChar *insert_where = NULL;

 

    /* Step 2: add edit1 */

    res = db_api_add_edit(pcb,

                          edit_id_str,

                          edit_target_str,

                          edit_operation_str,

                          edit_xml_value,

                          insert_point,

                          insert_where);

    if (res != NO_ERR) {

        log_error("\nAdd edit1 failed for complex test edit (%s)\n",

                  get_error_string(res));

        db_api_free_patch(pcb);

        return;

    }

 

    /* Step 3: add edit2 */

    edit_id_str = (const xmlChar *)"edit2";

    edit_target_str = (const xmlChar *)"/int16.1";

    edit_operation_str = (const xmlChar *)"remove";

    edit_xml_value = NULL;

 

    res = db_api_add_edit(pcb,

                          edit_id_str,

                          edit_target_str,

                          edit_operation_str,

                          edit_xml_value,

                          insert_point,

                          insert_where);

    if (res != NO_ERR) {

        log_error("\nAdd edit2 failed for complex test edit (%s)\n",

                  get_error_string(res));

        db_api_free_patch(pcb);

        return;

    }

 

    /* Step 4: add edit3 */

    edit_id_str = (const xmlChar *)"edit3";

    edit_target_str = (const xmlChar *)"/uint32.1";

    edit_operation_str = (const xmlChar *)"create";

    edit_xml_value = (const xmlChar *)

        "<uint32.1 xmlns='http://netconfcentral.org/ns/test'>400</uint32.1>";

 

    res = db_api_add_edit(pcb,

                          edit_id_str,

                          edit_target_str,

                          edit_operation_str,

                          edit_xml_value,

                          insert_point,

                          insert_where);

    if (res != NO_ERR) {

        log_error("\nAdd edit3 failed for complex test edit (%s)\n",

                  get_error_string(res));

        db_api_free_patch(pcb);

        return;

    }

 

    /* Step 4: send patch request */

    res = db_api_send_patch(pcb);

    if (res != NO_ERR) {

        log_error("\nSend complex test edit failed (%s)\n",

                  get_error_string(res));

    } else if (LOGDEBUG) {

        log_debug("\nSend complex test edit OK\n");

    }

 

    /* step 5: free the patch control block */

    db_api_free_patch(pcb);

 

}  /* send_complex_test_edit */

 

 

/********************************************************************

* FUNCTION main

*

* This is an example main function.

*

* RETURNS:

*   0 if NO_ERR

*   status code if error connecting or logging into ncxserver

*********************************************************************/

int main (int argc, char **argv)

{

#ifdef MEMORY_DEBUG

    mtrace();

#endif

 

    /* in case db-lock-test is used */

    (void)time(&start_time);

    last_time = 0;

    locked = FALSE;

 

    /* 1) setup yumapro messaging service profile */

    status_t res = ycontrol_init(argc, argv,

                                 (const xmlChar *)"subsys1");

 

    boolean getconfig = false;

    boolean withdef = false;

    boolean with_state = false;

    const char *filespec = NULL;

    const char *xpath_filter = NULL;

    uint32 cnt = 0;

    uint32 max_count = 0;

    uint32 change_time = 7;

    uint32 st_time = 30;

    boolean entermaint = false;

    boolean exitmaint = false;

    const char *dlevel = NULL;

    uint32 maintbits = 0;

    boolean db_lock_test = FALSE;

 

    boolean edit_full2 = false;

 

    if (res == NO_ERR) {

        res = check_cli_parms(argv,

                              &getconfig,

                              &withdef,

                              &with_state,

                              &filespec,

                              &xpath_filter,

                              &max_count,

                              &change_time,

                              &st_time,

                              &entermaint,

                              &exitmaint,

                              &dlevel,

                              &maintbits,

                              &db_lock_test);

        if (res != NO_ERR) {

            print_usage();

        }

    }

 

    if (getconfig && (filespec==NULL)) {

        res = ERR_NCX_MISSING_PARM;

        print_usage();

    }

 

    if ((res == NO_ERR) && entermaint && exitmaint) {

        res = ERR_NCX_EXTRA_PARM;

        print_usage();

    }

 

    /* 2) register services with the control layer */

    if (res == NO_ERR) {

        res = db_api_register_service_ex(db_lock_test);

    }

 

    /* 3) do 2nd stage init of the control manager (connect to server) */

    if (res == NO_ERR) {

        res = ycontrol_init2();

    }

 

    boolean done = FALSE;

 

    /* pick whether the simple edit or the complex edit is sent */

    boolean complex_edit = FALSE;

 

    /* 4) call ycontrol_check_io periodically from the main program

     * control loop

     */

#ifdef DB_API_APP_DEBUG

    int id = 0;

#endif  // DB_API_APP_DEBUG

 

    boolean test_done = FALSE;

    const xmlChar *error_msg = NULL;

 

    while (!done && res == NO_ERR) {

#ifdef DB_API_APP_DEBUG

        if (LOGDEBUG3) {

            log_debug3("\ndb-api-app: checking ycontrol IO %d", id++);

        }

#endif  // DB_API_APP_DEBUG

 

        res = ycontrol_check_io();

        if (res != NO_ERR) {

            continue;

        }

 

        if (ycontrol_shutdown_now()) {

            // YControl has received a <shutdown-event>

            // from the server subsystem is no longer active

            // could ignore or shut down YControl IO loop

            done = TRUE;

        }

 

        // Using sleep to represent other program work; remove for real

#ifdef DO_SLEEP

        if (!done && (res == NO_ERR)) {

            useconds_t usleep_val = 100000;  // 100K micro-sec == 1/10 sec

            (void)usleep(usleep_val);

        }

#endif  // DO_SLEEP

 

        if (db_api_service_ready() && !test_done) {

            if (db_lock_test) {

                check_db_lock_test(st_time, change_time, &done);

                continue;

            } else if (getconfig) {

                send_test_getconfig(filespec,

                                    withdef,

                                    with_state,

                                    xpath_filter);

            } else if (complex_edit) {

                /* send the complex test edit */

                send_complex_test_edit();

            } else if (entermaint) {

                send_test_enter_maintmode(maintbits);

            } else if (exitmaint) {

                send_test_exit_maintmode();

            } else if (dlevel) {

                send_test_set_loglevel(dlevel);

            } else if (edit_full2) {

                /*send the test for edit with skip_sil*/

                send_test_edit_full2();

            } else {

                /* send the simple test edit */

                send_test_edit();

            }

 

            test_done = TRUE;

        } else if (db_api_service_ready() && test_done) {

            /* check the test edit */

            res = db_api_check_edit_ex(&error_msg);

            if (res == NO_ERR) {

                log_info("\nTest %u succeeded\n", cnt+1);

 

                if (cnt < max_count) {

                    cnt++;

                    log_debug("\nStart send edit %u", cnt);

                    send_test_edit();

                } else {

                    done = TRUE;

                }

            } else {

                if (res == ERR_NCX_SKIPPED) {

                    res = ERR_NCX_OPERATION_FAILED;

                }

 

                log_info("\nTest failed with error: %d '%s'\n\n",

                         res, error_msg ? error_msg :

                         (const xmlChar *)get_error_string(res));

 

                done = TRUE;

            }

        }

    }

 

    /* 5) cleanup the control layer before exit */

    ycontrol_cleanup();

 

#ifdef MEMORY_DEBUG

    muntrace();

#endif

 

    return (int)res;

 

}  /* main */

12.1  DB-API Interface Functions

The DB-API service uses the YControl subsystem similar to the SIL-SA service. The same YControl callback interface is used for handling database access messages.

Refer to db-api/db_api.h for details.

 

Setup

Single Edit Patch

 

Multi-Edit Patch

 

Get Configuration Data

 

Get Filtered Configuration or Operational Data

Check Status

 

Maintenance Mode

DB-LOCK-TEST mode

Set Log Level

 

SubRPC

 

 

 

/********************************************************************

* FUNCTION db_api_register_service

*

*  Register the DB-API service with the YControl layer

*

* RETURNS:

*   status

*********************************************************************/

extern status_t

    db_api_register_service (void);

 

 

/********************************************************************

* FUNCTION db_api_service_ready

*

* RETURNS:

*   TRUE if ready state; FALSE otherwise

*********************************************************************/

extern boolean

    db_api_service_ready (void);

 

 

/********************************************************************

* FUNCTION db_api_send_edit

*

* Create a YANG Patch edit request and send it to the DB-API service

* on the main server.

*

* The content should represent the intended target resource

* as specified in YANG-API (NOT RESTCONF)

* Only the data resource identifier is provided, not the

* API wrapper identifiers (so this can change when RESTCONF is supported)

* Example leaf:

*

*   edit_target == /interfaces/interface/eth0/mtu

*   edit_value == "<mtu>9000</mtu>

*   edit_operation == "merge"

*

* Example list:

*

*   edit_operation == "create"

*   edit_target == /interfaces/interface/eth0/ipv4

*   edit_value == "<ipv4>

*                    <enabled>true</enabled><

*                    <forwarding>true</forwarding>

*                    <address>204.102.10.4</address>

*                    <prefix-length>24</prefix-length>

*                  </ipv4>"

*

* INPUTS:

*   edit_target == target resource (YANG-API path expression)

*   edit_operation == edit operation (create merge replace delete remove)

*   edit_xml_value == XML payload in string form, whitespace allowed

*                     MAY BE NULL if no value required (delete remove))

* RETURNS:

*   status

*********************************************************************/

extern status_t

    db_api_send_edit (const xmlChar *edit_target,

                      const xmlChar *edit_operation,

                      const xmlChar *edit_xml_value);

 

 

12.1.1  Filtered Retrieval Example

The db_api_send_getfilter function is similar to db_api_send_getconfig, but with extended parameters.

 

 

/********************************************************************

* FUNCTION db_api_send_getfilter

*

* Create a <getconfig> request and send it to the main server.

* An XPath filter can be sent as a parameter

* INPUTS:

*   filespec == file specification to contain the XML instance

*               document retrieved from the server

*   withdef == TRUE to get with defaults; FALSE to leave out defaults

*   get_config == TRUE for config only; FALSE for get (config + state)

*   xpath_filter == XPath expression (may be nULL)

* RETURNS:

*   status

*********************************************************************/

extern status_t

    db_api_send_getfilter (const xmlChar *filespec,

                           boolean withdef,

                           boolean get_config,

                           const xmlChar *xpath_filter);

 

 

The db-api-app can be used to send a filtered retrieval request.

This example retrieves the RESTCONF monitoring state information:

 

 

 > db-api-app --getconfig --withdef --with-state \
    --xpath-filter=/restconf-state --filespec=test.xml

 

 

 

test.xml:

 

 

<?xml version="1.0" encoding="UTF-8"?>

<config xmlns="http://yumaworks.com/ns/yumaworks-db-api">

  <restconf-state xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf-monitoring">

    <capabilities>

      <capability>urn:ietf:params:restconf:capability:depth:1.0</capability>

      <capability>urn:ietf:params:restconf:capability:with-defaults:1.0</capability>

      <capability>urn:ietf:params:restconf:capability:defaults:1.0?basic-mode=explicit</capability>

      <capability>urn:ietf:params:restconf:capability:fields:1.0</capability>

      <capability>urn:ietf:params:restconf:capability:replay:1.0</capability>

      <capability>urn:ietf:params:restconf:capability:filter:1.0</capability>

      <capability>urn:ietf:params:restconf:capability:yang-patch:1.0</capability>

    </capabilities>

    <streams>

      <stream>

        <access>

          <encoding>xml</encoding>

          <location>http://localhost/restconf/stream</location>

        </access>

        <description>default RESTCONF event stream</description>

        <name>RESTCONF</name>

        <replay-log-creation-time>2018-06-05T16:17:40Z</replay-log-creation-time>

        <replay-support>true</replay-support>

      </stream>

    </streams>

  </restconf-state>

</config>

 

 

12.1.2  Subsystem RPC Request Example

The <subrpc-request> message is used by a subsystem to send an RPC Operation Request to the server.

The <subrpc-response> message is used by the server to send an RPC reply message to the subsystem that sent the subrpc-request message.

The db_api_send_subrpc_request function is used for this operation:

 

/********************************************************************

* FUNCTION db_api_send_subrpc_request

*

* Create a <subrpc-request> request and send it to the main server.

* INPUTS:

*   user_id == user name to run RPC on server; NULL == system user

*   rpc_modname == module name containing the RPC or NULL to scan

*                  all modules for the first match of rpc_name

*   rpc_name == name of the RPC (must be present)

*   in_filespec == file specification to contain the XML instance

*               document for the rpc-method element (if needed)

*   out_filespec == file specification to contain the XML instance

*               document retrieved from the server (must be present)

* OUTPUTS:

*   file named by out_filespec created if operation succeeded.

* RETURNS:

*   status

*********************************************************************/

extern status_t

    db_api_send_subrpc_request (const xmlChar *user_id,

                                const xmlChar *rpc_modname,

                                const xmlChar *rpc_name,

                                const xmlChar *in_filespec,

                                const xmlChar *out_filespec);

 

 

The rpc1.yang module is used for this example:

 

module rpc1 {

  namespace "http://www.yumaworks.com/ns/rpc1";

  prefix r1;

  revision "2020-02-25";

 

  rpc rpc1 {

    input {

      leaf A {

        type string;

      }

      leaf B {

        type int32;

      }

    }

    output {

      leaf C {

        type string;

      }

      leaf D {

        type int32;

      }

    }

   }

 

} // module rpc1

 

The input file rpc1.xml:

 

<rpc1 xmlns="http://www.yumaworks.com/ns/rpc1">

  <A>test</A>

  <B>11</B>

 </rpc1>

 

The code to send the RPC request to the server:

 

 

#include “dp_api.h”

 

….

 

const xmlChar *user_id = (const xmlChar *)”admin1”;

const xmlChar *rpc_modname = (const xmlChar *)”rpc1”;

const xmlChar *rpc_name = (const xmlChar *)”rpc1”;

const xmlChar *in_filename = (const xmlChar *)”rpc1.xml”;

const xmlChar *out_filename = (const xmlChar *)”rpc1-out.xml”;

 

status_t res =

    db_api_send_subrpc_request(user_id,

                               rpc_modname,

                               rpc_name,

                               in_filename,

                               out_filename);

 

The output file rpc1-out.xml:

 

<?xml version="1.0" encoding="UTF-8"?>

<rpc-reply xmlns="http://www.yumaworks.com/ns/rpc1">

  <C>test1</C>

  <D>14</D>

</rpc-reply>

 

12.1.3  Subsystem Action Request Example

A YANG Action Request is just a special form of the RPC operation. The same format is used here as in the NETCONF protocol for the YANG action RPC.

 

The ex-action.yang module is used for the example:

 

module ex-action {

  yang-version 1.1;

  namespace "http://netconfcentral.org/ns/ex-action";

  prefix exa;

  import ietf-yang-types { prefix yang; }

  revision 2020-03-06;

 

  list server {

    key name;

    leaf name {

      type string;

      description "Server name";

    }

    action reset {

      input {

        leaf reset-msg {

          type string;

          description "Log message to print before server reset";

        }

      }

      output {

        leaf reset-finished-at {

          type yang:date-and-time;

          description "Time the reset was done on the server";

        }

      }

    }

  }

}

 

The act1.xml input file:

 

 <action xmlns="urn:ietf:params:xml:ns:yang:1">

  <server xmlns="http://netconfcentral.org/ns/ex-action">

   <name>test1</name>

   <reset>

    <reset-msg>this is a reset message</reset-msg>

   </reset>

  </server>

 </action>

 

The code to send the action request to the server:

 

 

#include “dp_api.h”

 

….

 

const xmlChar *user_id = (const xmlChar *)”admin1”;

const xmlChar *rpc_modname = (const xmlChar *)”ex-action”;

const xmlChar *rpc_name = (const xmlChar *)”reset”;

const xmlChar *in_filename = (const xmlChar *)”act1.xml”;

const xmlChar *out_filename = (const xmlChar *)”act1-out.xml”;

 

status_t res =

    db_api_send_subrpc_request(user_id,

                               rpc_modname,

                               rpc_name,

                               in_filename,

                               out_filename);

 

The output file act1-out.xml:

 

<?xml version="1.0" encoding="UTF-8"?>

<rpc-reply xmlns="http://netconfcentral.org/ns/ex-action">

  <reset-finished-at>2020-03-11T19:50:30Z</reset-finished-at>

</rpc-reply>

 

 

 

 

12.2  DB-API Messages

The DB-API messages are defined in the yumaworks-db-api.yang module.

The only message defined at this time is “edit-request”. This is sent as a “subsys-request” by the subsystem to the main server. The server will send an “ok” or “error” reply as a ”server-response” message.

 

 

module yumaworks-db-api {

 

    namespace "http://yumaworks.com/ns/yumaworks-db-api";

 

    prefix "ydb";

 

    import ietf-yang-types { prefix yang; }

    import ietf-yang-patch { prefix yp; }

    import yumaworks-ycontrol { prefix yctl; }

    import yuma-ncx { prefix ncx; }

    import yuma-types { prefix yt; }

 

    organization "YumaWorks, Inc.";

 

    contact

        "Support <support at yumaworks.com>";

 

    description

       "YumaPro Database API Sub-Agent message definitions.

 

     Copyright (c) 2014 - 2020, YumaWorks, Inc. All rights reserved.

 

     Redistribution and use in source and binary forms, with or

     without modification, is permitted pursuant to, and subject

     to the license terms contained in, the BSD 3-Clause License

     http://opensource.org/licenses/BSD-3-Clause";

 

    revision 2020-02-19 {

        description

          "Add subrpc-request and subrpc-response messages.";

    }

 

    revision 2019-01-27 {

        description

          "Add allowed parameter to maintenance mode.

           Add db-lock messages";

    }

 

    revision 2018-11-13 {

        description

          "Add maintenance mode and set-loglevel support";

    }

 

    revision 2018-06-13 {

        description

          "Add skip-sil parameter to edit-request message";

    }

 

    revision 2018-05-31 {

        description

          "Add parameters to getconfig message";

    }

 

    revision 2017-10-30 {

        description

          "Add getconfig message";

    }

 

    revision 2017-09-19 {

        description

          "Fix broken augment statement for payload";

    }

 

    revision 2016-08-29 {

        description

          "Update yp-ha-mode event";

    }

 

    revision 2016-07-31 {

        description

          "Add new events to support YP-HA mode changes.";

    }

 

    revision 2015-03-29 {

        description

          "Add edit-type parameter to edit-request.";

    }

 

    revision 2014-11-18 {

        description

          "Initial version for datastore access.";

    }

 

    grouping lock-id {

      leaf lock-id {

        type string {

          length "1 .. 64";

        }

        mandatory true;

        description

          "The lock identifier sent by the server in the

           db-lock request. Used to prevent late replies

           from being interpreted as a reply to a new request.";

      }

    }

 

    augment "/yctl:ycontrol/yctl:message-payload/yctl:payload/yctl:payload" {

      container db-api {

 

        choice message-type {

          mandatory true;

 

          leaf register-request {

            type empty;

            description

             "Message type: subsys-request;

              Purpose: register the DB-API subsystem

              Expected Response Message: ok or error";

          }

 

          container edit-request {

            description

             "Message type: subsys-request;

              Purpose: Ask the main server to accept an edit request

              to be added to the running configuration, and saved to

              NV-storage unless the :startup capability is supported.

 

              Expected Response Message: ok or error";

 

            leaf target {

              type string;  // target-path-string

              mandatory true;

              description

               "Identifies the target resource for the edit

                operation.";

            }

 

            leaf edit-type {

              type enumeration {

                enum user {

                  description "A user edit with access control";

                }

                enum system {

                  description "A system edit without access control";

                }

              }

              default user;

              description

               "Indicates whether this is a user edit or system edit.

                System edits will bypass all access control enforcement,

                including the ncx:user-write extension.";

            }

 

            leaf skip-sil {

              type boolean;

              default true;

              description

               "Skip the SIL and SIL-SA callbacks for this transaction.

                This is the normal mode since the DB-API edit is

                generated by the system, so the edits do not need

                to be applied again by the server.";

            }

 

            uses yp:yang-patch;

 

          }  // container edit-request

 

          container yp-ha-mode {

            description

             "Message type: subsys-event;

              Purpose: send mode change event to the server

              Expected Response Message: none";

 

            choice action {

              mandatory true;

              leaf go-active {

                type empty;

                description

                  "Become the YP-HA active server.

                   All normal management operations are supported

                   in this mode.";

              }

              container go-standby {

                description

                  "Become a YP-HA standby server, and try to connect

                   to the active server 'new-active'. Only the superuser

                   can use management sessions in this mode.";

 

                leaf new-active {

                  type string;

                  mandatory true;

                  description

                    "Server name of the active server to use";

                }

              }

              leaf go-none {

                type empty;

                description

                  "Leave current YP-HA role and wait new role.

                   Only the superuser can use management sessions

                   in this mode.";

              }

 

            }

          }  // container yp-ha-mode

 

          container getconfig {

            description

             "Message type: subsys-request;

              Purpose: Ask the main server to send the running

              configuration contents

 

              Expected Response Message: config";

 

              leaf withdef {

                type boolean;

                default false;

                description

                  "Include defaults (according to the server

                   --default-style CLI parameter) if 'true'.

                   Do not include defaults if 'false'.";

              }

 

              leaf with-state {

                type boolean;

                default false;

                description

                  "Include operational data (like <get> operation)";

              }

 

              leaf xpath-filter {

                type yang:xpath1.0;

                description

                  "XPath filter to use for this retrieval operation";

              }

 

          }  // container getconfig

 

          container config {

            ncx:root;

            description

             "Message type: server-response;

              Purpose: Provide the contents of the running

              configuration contents

 

              Expected Response Message: none";

 

          }  // container config

 

 

          container enter-maintmode {

            description

             "Message type: subsys-request.

              Purpose: Enter maintenance mode.

              Expected Response Message: server-response

              The server will send ok or error.";

 

            leaf allowed {

              type bits {

                bit read {

                  position 0;

                  description

                    "Allow client sessions for operations that

                     read datastores or operational data.";

                }

                bit operation {

                  position 1;

                  description

                    "Allow client sessions for general operations

                     that do not access any datastores.";

                }

              }

              default "";

              description

                "The client activity that is allowed during

                 maintenance mode. By default client sessions

                 are disabled during maintenance mode, and any

                 existing sessions will get 'access-denied' errors

                 for all operations started after maintenance mode

                 is started.";

            }

          }  // container enter-maintmode

 

          container exit-maintmode {

            description

             "Message type: subsys-request.

              Purpose: Exit maintenance mode.

              Expected Response Message: server-response

              The server will send ok or error.";

 

          }  // container exit-maintmode

 

          container set-log-level {

            description

             "Message type: subsys-request.

              Purpose: Set the log-level parameter.

              Expected Response Message: server-response

              The server will send ok or error.";

 

            leaf log-level {

              type yt:NcDebugType;

              mandatory true;

              description "The new log level to set";

            }

 

          }  // container set-log-level

 

          container db-lock-init {

            description

             "Message type: subsys-request.

              Purpose: Establish the subsystem as the DB-Edit-Lock

              controller. This is done once after the db-api service

              is registered.

              Expected Response Message: server-response

              The server will send ok or error.";

          }

 

          container db-lock {

            description

             "Message type: server-request.

              Purpose: Request the system config write lock.

              Expected Response Message: subsys-response

              The subsystem will send db-lock-response or error.";

            uses lock-id;

          }

 

          container db-lock-response {

            description

             "Message type: subsys-response.

              Purpose: Response for the system config write lock.

              Expected Response Message: none";

            uses lock-id;

          }

 

          container db-unlock {

            description

             "Message type: server-event.

              Purpose: Release the system config write lock.

              Expected Response Message: none";

            uses lock-id;

          }

 

          container subrpc-request {

            description

             "Message type: subsys-request;

              Purpose: Start an RPC transaction to the main server.

 

              This message requests that a new remote procedure

              call be validated and invoked on the server and

              possibly one or more SIL-SA subsystems.

 

              If not valid or if the operation cannot be performed,

              the server must return an error.

 

              Expected Response Message: subrpc-response";

 

            leaf user-id {

              type string;

              description

                "Identifies the user that should be used for

                 access control and logging purposes.

                 If not present then the system user will be used

                 and all access control will be skipped.";

            }

 

            leaf rpc-module {

              type yt:NcxName;

              description

                "Identifies the module name of the RPC definition.

                 If not present then the server will use the first

                 RPC method with the same name as 'rpc-name'.";

            }

 

            leaf rpc-name {

              type yt:NcxName;

              mandatory true;

              description

                "Identifies the name of the RPC definition.";

            }

 

            anyxml rpc-method {

              description

                "Contains the RPC method element and all child nodes

                 representing the input parameters. This is structured

                 exactly the same as the contents of an <rpc> element

                 from RFC 6241. If not present then an empty method

                 element will be constructed using 'rpc-module' and

                 'rpc-name' values.";

            }

          }

 

          container subrpc-response {

            description

             "Message type: server-response

              Purpose: Return <rpc-reply> message

              Expected Response Message: none";

 

            leaf rpc-module {

              type yt:NcxName;

              mandatory true;

              description

                "Identifies the module name of the RPC definition.";

            }

 

            leaf rpc-name {

              type yt:NcxName;

              mandatory true;

              description

                "Identifies the name of the RPC definition.";

            }

 

            anyxml reply {

               mandatory true;

               description

                 "Contains the RPC reply message for the subrpc-request.";

            }

          }

 

        } // choice message-type

      } // container db-api

    } // augment

}