- About
- NSO 5.7 Getting Started Guide
- NSO 5.7 User Guide
- NSO Installation Guide
- NSO 5.7 Administration Guide
- NSO 5.7 Northbound APIs
- NSO 5.7 Development Guide
- Preface
- The Configuration Database and YANG
- Basic Automation with Python
- Creating a Service
- Applications in NSO
- The NSO Java VM
- The NSO Python VM
- Embedded Erlang applications
- The YANG Data Modeling Language
- Using CDB
- Java API Overview
- Python API Overview
- NSO Packages
- Package Development
- Developing NSO Services
- Templates
- NED Upgrades and Migration
- Developing Alarm Applications
- SNMP Notification Receiver
- The web server
- Kicker
- Scheduler
- Progress Trace
- Nano Services for Staged Provisioning
- Encryption Keys
- External Logging
- NSO 5.7 Web UI
- NSO CDM Migration Guide
- NSO Layered Service Architecture
- NSO 5.7 NED Development
- NSO 5.7 Manual Pages
- SDK API Reference
- NSO on DevNet
- Get Support
Kickers constitutes a declarative notification mechanism for triggering actions on certain stimuli like a database change or a received notification. These different stimuli and their kickers are defined separately as data-kicker and notification-kicker respectively.
Common to all types of kickers is that they are declarative. Kickers are modeled in YANG and Kicker instances stored as configuration data in CDB.
Immediately after a transaction which defines a new kicker is committed the kicker will be active. The same holds for removal. This also implies that the amount of programming for a kicker is a matter of implementing the action to be invoked.
The data-kicker replicates much of the functionality otherwise attained by a CDB subscriber. Without the extra coding in registration and runtime daemon that comes with a CDB subscriber. The data-kicker works for all data providers.
The notification-kicker reacts on
notifications received by NSO using a defined notification
subscription under
/ncs:devices/device/notifications/subscription
.
This simplifies handling of southbound emitted
notifications. Traditionally these where choosen to be stored in CDB as
operational data and a separate CDB subscriber was used to act
on the received notifications. With the use of
notification-kicker the CDB subscriber can
be removed and there is no longer any need to store the received
notification in CDB.
An action as defined by YANG contains an input parameter definition and an output parameter definition. However a kicker that invokes an action treats the input parameters in a specific way.
The kicker mechanism first checks if the input parameters
matches those in the kicker:action-input-params
YANG grouping defined in the tailf-kicker.yang
file.
If so the action will be invoked with the input parameters:
id
-
The id (name) of the invoking kicker.
monitor
-
The path of the current monitor triggering the kicker
tid
-
The transaction id to a synthetic transaction containing the changes that lead to the triggering of the kicker.
The "synthetic" transaction implies that this is a copy of the original transaction that lead to the kicker triggering. It only contains the data tree under the monitor. The original transaction is already committed and this data might no longer reflect the "running" datastore. Its useful in that the action implementation can attach and diff-iterate over this transaction and retrieve the certain changes that lead to the kicker invocation.
If the kicker mechanism finds an action that do not match the
above input parameters it will invoke the action with an empty
parameter list. This implies that an kicker action must either
match the above kicker:action-input-params
grouping
precisely or accept an empty incoming parameter list.
Otherwise the action invocation will fail.
For a Data Kicker the following principles hold:
-
Kicker are triggered by changes in the sub-tree indicated by the
monitor
. potentially triggers a Kicker. -
Actions are invoked during the commit phase. Hence an aborted transaction never trigger kickers.
-
No distinction is made between configuration and operational data.
-
No distinction is made between CRUD types, i.e. create, delete, update. All changes potentially trigger kickers.
-
Kickers may have constraints that suppress invocations. Changes in the sub-tree indicated by
monitor
is a necessary but perhaps not a sufficient condition for the action to be invoked.
For a Data Kicker it is the monitor
that specifies
which subtree under which a change should invoke the kicker.
The monitor
leaf is of type
node-instance-identifier
which means that
predicates for keys are optional, i.e. keys may be omitted and
then represent all instances for that key.
The resulting evaluation of the monitor defines a node-set. Each node in this node-set will be root context for any further xpath evaluations necessary before invoking the kicker action.
The following example shows the strengths of using xpath to define the kickers. Say that we have a situation described by the following YANG model snippet:
module example { namespace "http://tail-f.com/ns/test/example"; prefix example; ... container sys { list ifc { key name; max-elements 64; leaf name { type interfaceName; } leaf description { type string; } leaf enabled { type boolean; default true; } container hw { leaf speed { type interfaceSpeed; } leaf duplex { type interfaceDuplex; } leaf mtu { type mtuSize; } leaf mac { type string; } } list ip { key address; max-elements 1024; leaf address { type inet:ipv4-address; } leaf prefix-length { type prefixLengthIPv4; mandatory true; } leaf broadcast { type inet:ipv4-address; } } tailf:action local_me { tailf:actionpoint kick-me-point; input { } output { } } } tailf:action kick_me { tailf:actionpoint kick-me-point; input { } output { } } tailf:action iter_me { tailf:actionpoint kick-me-point; input { uses kicker:action-input-params; } output { } } } }
Then we can define a kicker for monitoring a specific element in the list and calling the correlated local_me action:
admin@ncs(config)#kickers data-kicker e1 \ > monitor /sys/ifc[name='port-0'] \ >kick-node /sys/ifc[name='port-0']\ > action-name local_me
admin(config-data-kicker-e1)#commit
Commit complete admin(config-data-kicker-e1)#top
admin@ncs(config)#show full-configuration kickers
kickers data-kicker e1 monitor /sys/ifc[name='port-0'] kick-node /sys/ifc[name='port-0'] action-name local_me !
On the other hand we can define a kicker for monitoring all elements of the list and and call the correlated local_me action for each element:
admin@ncs(config)#kickers data-kicker e2 \ > monitor /sys/ifc \ >kick-node . \ > action-name local_me
admin(config-data-kicker-e2)#commit
Commit complete admin(config-data-kicker-e2)#top
admin@ncs(config)#show full-configuration kickers
kickers data-kicker e2 monitor /sys/ifc kick-node . action-name local_me !
Here the "." in the kick-node
refer to the
current node in the node-set defined by the monitor
.
A Data Kicker may be constrained by adding conditions that suppress
invocations. The leaf trigger-expression
contains
a boolean XPath expression that is evaluated twice, before and after
the change-set of the commit has been applied to the
database(s).
The Xpath expression has to evaluated twice in order to detect the change caused by the transaction.
The two boolean results together with the leaf
trigger-type
controls if the Kicker should be
triggered or not:
enter-and-leave
-
false -> true (i.e. positive flank) or true -> false (negative flank)
enter
-
false -> true
admin(config)#kickers data-kicker k1 monitor /sys/ifc \ > trigger-expr "hw/mtu > 800" \ > trigger-type enter \ > kick-node /sys \ > action-name kick_me
admin(config-data-kicker-k1)#commit
Commit complete admin(config-data-kicker-k1)#top
admin@ncs% admin@ncs%show kickers
kickers data-kicker k1 monitor /sys/ifc trigger-expr "hw/mtu > 800" trigger-type enter kick-node /sys action-name kick_me !
Start by changing the MTU to 800:
admin(config)#sys ifc port-0 hw mtu 800
admin(config-ifc-port-0)#commit | debug kicker
2017-02-15T16:35:36.039 kicker: k1 at /kicker_example:sys/kicker_example:ifc[kicker_example:name='port-0'] changed; not invoking 'kick_me' trigger-expr false -> false Commit complete.
Since the trigger-expression
evaluates to false,
the kicker is not triggered. Let's try again:
admin(config)#sys ifc port-0 hw mtu 801
admin(config-ifc-port-0)#commit | debug kicker
2017-02-15T16:35:36.039 kicker: k1 at /kicker_example:sys/kicker_example:ifc[kicker_example:name='port-0'] changed; invoking 'kick-me' trigger-expr false -> true Commit complete.
A Data Kicker may be provided with a list of variables (named
values). Each variable binding consists of a name and a XPath
expression. The Xpath expressions are evaluated on-demand,
i.e. when used in either of monitor
or
trigger-expression
nodes.
admin@ncs(config)# set kickers data-kicker k3 monitor $PATH/c
kick-node /x/y[id='n1']
action-name kick-me
variable PATH value "/a/b[k1=3][k2='3']"
admin@ncs(config)#
In the example above PATH
is defined and refered
to by the monitor
expression by using the
expression $PATH
.
Note
A monitor expression is not evaluated by the XPath engine. Hence no trace of the evaluation can be found in the the Xpath log.
Monitor expressions are expanded and installed in an internal data-structure at kicker creation/compile time. XPath may be used while defining kickers by referring to a named XPath expression.
This example is part of the
examples.ncs/web-server-farm/web-site-service
example. It consists of an action and a
README_KICKER
file.
For all kickers defined in this example the same action is
used. This action is defined in the
website-service package. The following is the yang snippet for
the action definition from the website.yang
file:
module web-site { namespace "http://examples.com/web-site"; prefix wse; ... augment /ncs:services { ... container actions { tailf:action diffcheck { tailf:actionpoint diffcheck; input { uses kicker:action-input-params; } output { } } } } }
The implementation of the action can be found in the
WebSiteServiceRFS.java
class file.
Since it takes the kicker:action-input-params as input, the "Tid"
for the synthetic transaction is available.
This transaction is attached and diff-iterated.
The result of the diff-iteration is printed in the ncs-java-vm.log:
class WebSiteServiceRFS { .... @ActionCallback(callPoint="diffcheck", callType=ActionCBType.ACTION) public ConfXMLParam[] diffcheck(DpActionTrans trans, ConfTag name, ConfObject[] kp, ConfXMLParam[] params) throws DpCallbackException { try { System.out.println("-------------------"); System.out.println(params[0]); System.out.println(params[1]); System.out.println(params[2]); ConfUInt32 val = (ConfUInt32) params[2].getValue(); int tid = (int)val.longValue(); Socket s3 = new Socket("127.0.0.1", Conf.NCS_PORT); Maapi maapi3 = new Maapi(s3); maapi3.attach(tid, -1); maapi3.diffIterate(tid, new MaapiDiffIterate() { // Override the Default iterate function in the TestCase class public DiffIterateResultFlag iterate(ConfObject[] kp, DiffIterateOperFlag op, ConfObject oldValue, ConfObject newValue, Object initstate) { System.out.println("path = " + new ConfPath(kp)); System.out.println("op = " + op); System.out.println("newValue = " + newValue); return DiffIterateResultFlag.ITER_RECURSE; } }); maapi3.detach(tid); s3.close(); return new ConfXMLParam[]{}; } catch (Exception e) { throw new DpCallbackException("diffcheck failed", e); } } }
We are now ready to start the website-service example and define our data-kicker. Do the following:
$make all
$ncs-netsim start
$ncs
$ncs_cli -C -u admin
admin@ncs#devices sync-from
sync-result { device lb0 result true } sync-result { device www0 result true } sync-result { device www1 result true } sync-result { device www2 result true }
The kickers are defined under the hide-group "debug". To be able to show and declare kickers we need first to unhide this hide-group:
admin@ncs#config
admin@ncs(config)#unhide debug
We now define a data-kicker for the "profile" list under the by the service augmented container "/services/properties/wsp:web-site":
admin@ncs(config)#kickers data-kicker a1 \ > monitor /services/properties/wsp:web-site/profile \ > kick-node /services/wse:actions action-name diffcheck
admin@ncs(config-data-kicker-a1)#commit
admin@ncs(config-data-kicker-a1)#top
admin@ncs(config)#show full-configuration kickers data-kicker a1
kickers data-kicker a1 monitor /services/properties/wsp:web-site/profile kick-node /services/wse:actions action-name diffcheck !
We now commit a change in the profile list and we use the "debug kicker" pipe option to be able to follow the kicker invokation:
admin@ncs(config)#services properties web-site profile lean lb lb0
admin@ncs(config-profile-lean)#commit | debug kicker
2017-02-15T16:35:36.039 kicker: a1 at /ncs:services/ncs:properties/wsp:web-site/wsp:profile[wsp:name='lean'] changed; invoking diffcheck Commit complete. admin@ncs(config-profile-lean)#top
admin@ncs(config)#exit
We can also check the result of the action by looking into the ncs-java-vm.log:
admin@ncs# file show logs/ncs-java-vm.log
In the end we will find the following printout from the diffcheck action:
------------------- {[669406386|id], a1} {[669406386|monitor], /ncs:services/properties/web-site/profile{lean}} {[669406386|tid], 168} path = /ncs:services/properties/wsp:web-site/profile{lean} op = MOP_CREATED newValue = null path = /ncs:services/properties/wsp:web-site/profile{lean}/name op = MOP_VALUE_SET newValue = lean path = /ncs:services/properties/wsp:web-site/profile{lean}/lb op = MOP_VALUE_SET newValue = lb0 [ok][2017-02-15 17:11:59]
For a Notification Kicker the following principles hold:
-
Notification Kickers are triggered by the arrival of notifications from any device subscription. These subscriptions are defined under the
/devices/device/notification/subscription
path. -
Storing the received notifications in CDB is optional and not part of the notification kicker functionality.
-
The kicker invocations are serialized under a certain subscription i.e. kickers are invoked in the same sequence as notifications are received for the same subscription. This means that invocations are queued up and executed as quickly as the action permits.
The notification kicker is defined using a mandatory "selector-expr"
which is an XPATH 1.0 expression.
When the notification is received a synthetic transaction is
started and the notification is written as if it would be
stored under the path
/devices/device/notification/received-notifications/data
.
Actually storing the notification in CDB is optional. The
selector-expr
is evaluated with the notification node
as the current context and '/' as the root context. For example, if
the device model defines a notification like this:
module device { ... notification mynotif { leaf message { type string; } } ... }
the notification node 'mynotif' will be the current context for the
selector-expr
There are four predefined variable bindings used when
evaluating this expression:
DEVICE
-
The name of the device emitting the current notification.
SUBSCRIPTION_NAME
-
The name of the current subscription from which the notification was received. the kicker
NOTIFICATION_NAME
-
The name of the current notification.
NOTIFICATION_NS
-
The namespace of the current notification.
The selector-expr
technique for defining the
notification kickers is very flexible.
For instance a kicker can be defined:
-
To receive all notifications for a device.
-
To receive all notifications of a certain type for any device.
-
To receive a subset of notifications of a subset of devices by the use of specific subscriptions with the same name in several devices.
In addition to this usage of the predefined variable bindings it is possible to further drill down into the specific notification to trigger on certain leafs in the notification.
In addition to the four variable bindings mentioned above, a Notification Kicker may also be provided with a list of variables (named values). Each variable binding consists of a name and a XPath expression. The Xpath expression is evaluated when the selector-expr is run.
admin@ncs(config)# set kickers notification-kicker k4
selector-expr "$NOTIFICATION_NAME=linkUp and address[ip=$IP]"
kick-node /x/y[id='n1']
action-name kick-me
variable IP value '192.168.128.55'
admin@ncs(config)#
In the example above PATH
is defined and refered
to by the monitor
expression by using the
expression $PATH
.
Note
A monitor expression is not evaluated by the XPath engine. Hence no trace of the evaluation can be found in the the Xpath log.
Monitor expressions are expanded and installed in an internal data-structure at kicker creation/compile time. XPath may be used while defining kickers by referring to a named XPath expression.
In this example we use the same action and setup as in the Data kicker example above. The procedure for starting is also the same.
The website-service example has devices that has notifications generated on the stream "interface". We start with defining the notification kicker for a certain SUBSCRIPTION_NAME = "mysub". This subscription does not exist for the moment and the kicker will therefore not be triggered:
admin@ncs#config
admin@ncs(config)#kickers notification-kicker n1 \ > selector-expr "$SUBSCRIPTION_NAME = 'mysub'" \ > kick-node /services/wse:actions \ > action-name diffcheck
admin@ncs(config-notification-kicker-n1)#commit
admin@ncs(config-notification-kicker-n1)#top
admin@ncs(config)#show full-configuration kickers notification-kicker n1 kickers notification-kicker n1
selector-expr "$SUBSCRIPTION_NAME = 'mysub'" kick-node /services/wse:actions action-name diffcheck !
Now we define the "mysub" subscription on a device "www0" and refer to the notification stream "interface". As soon as this definition is committed the kicker will start triggering:
admin@ncs(config)#devices device www0 notifications subscription mysub \ > local-user admin stream interface
admin@ncs(config-subscription-mysub)#commit
admin@ncs(config-profile-lean)#top
admin@ncs(config)#exit
If we now inspect the ncs-java-vm.log we will see a number of notifications that are received. We also see that the transaction that is diff-iterated contains the notification as data under the path /devices/device/notifications/received-notifications/notification/data. This is a operational data list. However this transaction is synthetic and will not be committed. If the notification will be stored CDB is optional and not depending on the notification kicker functionality:
admin@ncs# file show logs/ncs-java-vm.log
-------------------
{[669406386|id], n1}
{[669406386|monitor], /ncs:devices/device{www0}/notifications.../data/linkUp}
{[669406386|tid], 758}
path = /ncs:devices/device{www0}
op = MOP_MODIFIED
newValue = null
path = /ncs:devices/device{www0}/notifications...
op = MOP_CREATED
newValue = null
path = /ncs:devices/device{www0}/notifications.../event-time
op = MOP_VALUE_SET
newValue = 2017-02-15T16:35:36.039204+00:00
path = /ncs:devices/device{www0}/notifications.../sequence-no
op = MOP_VALUE_SET
newValue = 0
path = /ncs:devices/device{www0}/notifications.../data/notif:linkUp
op = MOP_CREATED
newValue = null
path = /ncs:devices/device{www0}/notifications.../data/notif:linkUp/address{192.168.128.55}
op = MOP_CREATED
newValue = null
path = /ncs:devices/device{www0}/notifications.../data/notif:linkUp/address{192.168.128.55}/ip
op = MOP_VALUE_SET
newValue = 192.168.128.55
path = /ncs:devices/device{www0}/notifications.../data/notif:linkUp/address{192.168.128.55}/mask
op = MOP_VALUE_SET
newValue = 255.255.255.0
path = /ncs:devices/device{www0}/notifications.../data/notif:linkUp/ifName
op = MOP_VALUE_SET
newValue = eth2
path = /ncs:devices/device{www0}/notifications.../data/notif:linkUp/linkProperty{0}
op = MOP_CREATED
newValue = null
path = /ncs:devices/device{www0}/notifications.../data/notif:linkUp/linkProperty{0}/extensions{0}
op = MOP_CREATED
newValue = 4668
path = /ncs:devices/device{www0}/notifications.../data/notif:linkUp/linkProperty{0}/extensions{1}/name
op = MOP_VALUE_SET
newValue = 2
path = /ncs:devices/device{www0}/notifications.../data/notif:linkUp/linkProperty{0}/flags
op = MOP_VALUE_SET
newValue = 42
path = /ncs:devices/device{www0}/notifications.../data/notif:linkUp/linkProperty{0}/newlyAdded
op = MOP_CREATED
newValue = null
We end by removing the kicker and the subscription:
admin@ncs# config admin@ncs(config)#no kickers notification-kicker
admin@ncs(config)#no devices device www0 notifications subscription
admin@ncs(config)#commit
This example illustrates how to write a reactive FastMap application using the Kicker. The idea is to let the service code create a kicker which redeploys a service when something happens.
Kickers are very often used as an implementation technique for Reactive FastMap services. Assume an NFV/ESC based application which:
-
Asks ESC to start a VM
-
Once the VM is ready, wants to configure the VM
Such an application would create a kicker with a monitor for
/devices/device[name=<vmname>]/ready
Once the VM is 'ready', the service would be redeployed and it can
continue its Reactive FastMap execution further and provision config
to the newly started VM.
Prior to the kickers, it was common with CDB subscriber code that
-
Subscribed to some change
-
Read that change, and then redeployed some service which the CDB subscriber code knew was waiting for that change
Now, with kickers we can simply such code by having a CDB subscriber that simply
-
Subscribes to some change (for example a device notification listener)
-
Writes some operational data field somewhere
The RFM service code is then responsible for setting up a kicker with the monitor pointing to that field written by the CDB subscriber. Thus effectively decoupling the CDB subscriber code from the RFM service code making them independent of each other. Another advantage is that the error handling code when the redeploy fails is unified inside the NSO kicker implementation.
The example can be
found in
examples.ncs/getting-started/developing-with-ncs/21-kicker
and uses two NSO packages. The router package introduced
in ../0-router-network
and a package called 'ppp-accounting' which
is described in this section.
The example is a bit contrived, but since want to exemplify the usage of kickers, it's simplified and artificial.
$ ls ./packages
router ppp-accounting
To build the three packages, do
$ make all
To start the ncs-netsim network, follow the instructions in
../0-router-network
, it's the same network here.
$ ncs-netsim start
DEVICE ex0 OK STARTED
DEVICE ex1 OK STARTED
DEVICE ex2 OK STARTED
All the code for this example resides in ./packages/ppp-accounting
To run the example we do:
$ ncs
This will start NSO, and NSO will load the two packages, load the data models defined by the two packages and start the Java code defined by the packages.
The service data model we have here looks like:
list ppp-accounting { uses ncs:service-data; ncs:servicepoint kickerspnt; key "interface"; leaf interface { type string; } } list ppp-accounting-data { description "This is helper data, created by the service code for /ppp-accounting"; key "interface"; leaf interface { type string; } leaf accounting { description "populated externally"; type string; } }
The purpose of the service /ppp-accounting
is to set the accounting
field in the provided ppp interface on all routers in our
example network.
The catch here is that the name of the 'accounting' field is not provided
as in input parameter to the service, instead it is populated externally
and read and used by the service code.
The FastMap code tries to read the field
/ppp-accounting-data[interface=<if>]/accounting
and if it doesn't exist, the code creates a kicker on that
field and returns.
If the 'accounting' field exists, it used and data is written into the
/devices tree for our routers.
To run this we do:
$make all
$ncs-netsim start
$ncs
$ncs_cli -u admin
admin connected from 127.0.0.1 using console on mac admin@ncs>request devices sync-from
sync-result { device ex0 result true } sync-result { device ex1 result true } sync-result { device ex2 result true } [ok][2016-12-13 16:18:45] admin@ncs>configure
Entering configuration mode private [ok][2016-12-13 16:19:06] [edit] admin@ncs%set ppp-accounting ppp0
[ok][2016-12-13 16:20:01] [edit] admin@ncs%commit
Commit complete. [ok][2016-12-13 16:20:04] [edit] admin@ncs%request ppp-accounting ppp0 get-modifications
cli { local-node { data } }
We created the service, and verified that it didn't do anything.
Looking at the code in
packages/ppp-accounting/src/java/src/com/example/kicker/KickerServiceRFS.java
we can see though that the code created a kicker.
Let's take a look at that:
admin@ncs% show kickers
---------------------------------^
syntax error: element does not exist
[error][2016-12-13 16:22:53]
The kicker data is hidden, and we cannot directly view it in the CLI.
The src/ncs/yang/tailf-kicker.yang
file says:
container kickers { tailf:info "Kicker specific configuration"; tailf:hidden debug; list data-kicker { key id; ......
To view the kickers data we must do two things:
-
Provide an entry in the ncs.conf file
-
Unhide in the CLI
See the section called “Unhide Kickers” for details.
And now the kicker container is visible:
admin@ncs%$ show kickers
data-kicker ncs-internal-side-effects {
monitor /ncs:side-effect-queue;
kick-node /ncs:side-effect-queue;
action-name invoke;
}
data-kicker ppp-accounting-ppp0 {
monitor /ppp-accounting-data[interface='ppp0']/accounting;
kick-node /ppp-accounting[interface='ppp0'];
action-name reactive-re-deploy;
}
There we can see our newly created kicker.
To trigger this kicker, which will then execute the redeploy
on the /ppp-accounting[interface='ppp0']
service, all we need to do
is to assign some data to the field that is monitored by the kicker.
admin@ncs%$set ppp-accounting-data ppp0 accounting radius
[ok][2016-12-13 16:26:43] [edit] admin@ncs%$commit
Commit complete. [ok][2016-12-13 16:26:46] [edit] admin@ncs%$request ppp-accounting ppp0 get-modifications
cli { local-node { data devices { device ex0 { config { r:sys { interfaces { serial ppp0 { ppp { - accounting acme; + accounting radius; } } } } } } device ex1 { config { r:sys { interfaces { serial ppp0 { ppp { - accounting acme; + accounting radius; ..........
Note
Looking at the RFM java code we see that the /ppp-accounting-data
help
entry is created by a so called PRE_MODIFICATION
hook.
This is a common trick in RFM applications. We don't want that data to
be part of the FastMap diffset. Usually the help entry is also used to
contain various 'config false' fields pertaining to the service instance.
If that data was part of FastMap diffset, the data would disappear with
every redeploy turn, thus we use the PRE_MODIFICATION
trick.
In order to find out why a Kicker kicked when it shouldn't or more commonly and annoying, why it didn't kick when it should, use the CLI pipe debug kicker.
Evaluation of potential Kicker invocations are reported in the CLI together with XPath evaluation results:
admin@ncs(config)#set sys ifc port-0 hw mtu 8000
admin@ncs(config)#commit | debug kicker
2017-02-15T16:35:36.039 kicker: k1 at /kicker_example:sys/kicker_example:ifc[kicker_example:name='port-0'] changed; not invoking 'kick-me' trigger-expr false -> false Commit complete. admin@ncs(config)#
The top level container kickers
is by default
invisible due to a hidden attribute. In order to make kickers
visible in the CLI, two steps are required. First
the following XML snippet must be added to ncs.conf
:
Now the unhide command may be used in the CLI session:
Detailed information from the XPath evaluator can be enabled
and made available in the xpath log. Add the following snippet to
ncs.conf
.
Error information is written to the development log.
The development log is meant to be
used as support while developing the application. It is enabled
in ncs.conf
:
<developer-log> <enabled>true</enabled> <file> <name>./logs/devel.log</name> <enabled>true</enabled> </file> </developer-log> <developer-log-level>trace</developer-log-level>