A YANG action is like an RPC operation in many ways except it is associated with the data node where the action is defined. The SIL code for an action callback is a combination of the RPC callbacks and the EDIT callbacks.  The call flow is the same as for RPC operations. The parameters are similar as well, except the ancestor keys for the instance are provided, so the SIL callback knows which instance to apply the action.

All YANG actions are data-driven within the server, using the YANG action statement for the operation and SIL callback functions.

Any new data-specific actions can be added by defining a new YANG action statement within a container or list, and providing the proper SIL code.

When using the make_sil_dir_pro script for YANG actions, the --split parameter should always be used. This allows the keys to be easily processed. The examples shown below are done using the following command:


Example YANG Action Module


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";
        }
      }
    }
  }
}


Example YANG Action Request


 <?xml version="1.0" encoding="UTF-8"?>
 <rpc message-id="1"
  xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <action xmlns="urn:ietf:params:xml:ns:yang:1">
    <server xmlns="http://netconfcentral.org/ns/ex-action">
      <name>test1</name>
      <reset>
        <reset-msg>diagnostic mode 1</reset-msg>
      </reset>
    </server>
  </action>
 </rpc>



Example YANG Action Response


<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply message-id="1"
 xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
 <reset-finished-at xmlns="http://netconfcentral.org/ns/ex-action">2020-03-08T19:01:22Z</reset-finished-at>
</rpc-reply>


YANG Action Callback Template


 
/* Template for Action server callbacks
 * The same template is used for all Action callback phases
 * The callback is expected to validate if needed and then
 * invoke if needed.
 *
 * The entire input hierarchy for an action is contained in
 * the msg->rpc_input node.  The 'actionval' node passed
 * to the callback points at the action node nested in the
 * input (like <ping> in the example below)

 * INPUTS:
 *   scb == session invoking the RPC
 *   msg == message in progress for this <rpc> request
 *   methnode == XML node for the operation, which can be used
 *               in error reporting (or ignored
 *   actionval == the nested 'action-method-name' node that was
 *             parsed within the topval subtree, in the
 *             RPC <action> request; this is used to help derive
 *             the list keys
 * RETURNS:
 *   status == return status for the phase; an error in validate phase
 *             will cancel invoke phase; an rpc-error will be added
 *             if an error is returned and the msg error Q is empty
 */
typedef status_t
    (*agt_action_cb_t) (ses_cb_t *scb,
                        rpc_msg_t *msg,
                        xml_node_t *methnode,
                        val_value_t *actionval);


Example YANG Action Invoke Callback


/********************************************************************
* FUNCTION u_ex_action_server_reset_action_inv
*
* YANG 1.1 action invoke callback
* Path: /server/reset
*
* INPUTS:
*     see agt/agt_action.h for details
*     k_ parameters are ancestor list key values.
*
* RETURNS:
*     error status
********************************************************************/
status_t u_ex_action_server_reset_action_inv (
    ses_cb_t *scb,
    rpc_msg_t *msg,
    xml_node_t *methnode,
    val_value_t *actionval,
    const xmlChar *k_server_name)
{
    status_t res = NO_ERR;

    if (LOGDEBUG) {
        log_debug("\nEnter u_ex_action_server_reset_action_inv for action <reset>");
    }

    val_value_t *v_reset_msg_val = NULL;
    const xmlChar *v_reset_msg = NULL;

    if (actionval) {
        v_reset_msg_val = val_find_child(
            actionval,
            y_ex_action_M_ex_action,
            y_ex_action_N_reset_msg);
        if (v_reset_msg_val) {
            v_reset_msg = VAL_STRING(v_reset_msg_val);
        }
    }

    /* display the reset logging message */
    log_info("\nex-action: Resetting server %s\n", k_server_name);
    if (v_reset_msg) {
        log_info_append("%s\n", v_reset_msg);
    }

    /* the invoke function would schedule or execute the server reset here */

    /* remove the next line if scb is used */
    (void)scb;

    /* remove the next line if methnode is used */
    (void)methnode;

    /* invoke your device instrumentation code here */

    /* Following output nodes expected:
     * leaf reset-finished-at
     */
    if (actionval == NULL) {
        return ERR_NCX_OPERATION_FAILED;  // should not happen
    }

    obj_template_t *obj =
        obj_find_child(VAL_OBJ(actionval),
                       NULL,
                       NCX_EL_OUTPUT);
    if (obj == NULL) {
        return ERR_NCX_DEF_NOT_FOUND;  // should not happen
    }

    /* return the current time */
    xmlChar buff[TSTAMP_MIN_SIZE+1];
    tstamp_datetime(buff);

    val_value_t *val =
        agt_make_leaf(obj,
                      y_ex_action_N_reset_finished_at,
                      buff,
                      &res);
    if (val) {
        agt_rpc_add_return_val(val, msg);
    } // else res set to error

    return res;

} /* u_ex_action_server_reset_action_inv */


Action Data Output Handling


YANG actions can return data to the client if the operation succeeds. The YANG “output” statement defines the return data for each YANG action.  Constructing YANG data is covered in detail elsewhere. This section shows a simple example SIL action invoke function that returns data.



The output data is usually constructed with APIs like agt_make_leaf from agt_util.h.

To use these APIs, the output object is needed.

The following code can be used to get this object:


    if (actionval == NULL) {
        return ERR_NCX_OPERATION_FAILED;  // should not happen
    }

    obj_template_t *obj =
        obj_find_child(VAL_OBJ(actionval),
                       NULL,
                       NCX_EL_OUTPUT);
    if (obj == NULL) {
        return ERR_NCX_DEF_NOT_FOUND;  // should not happen
    }


Refer to section 6.5 in the YumaPro Developer Manual for more details on YANG actions.