Option to receive only leaf nodes in websocket notifs 73/52173/8
authorJosh <jhershbe@redhat.com>
Wed, 22 Feb 2017 13:06:36 +0000 (15:06 +0200)
committerJosh <jhershbe@redhat.com>
Sun, 19 Mar 2017 11:28:01 +0000 (13:28 +0200)
commit222b2357ecf95f109673e052600600f6ade9986f
treec52f711fc974fddb9f1c041e8e285e614a697e2c
parentd91dcb79ffb2447d0013cab742a882400b43189e
Option to receive only leaf nodes in websocket notifs

Change for Bug-7718 in the netvirt project.

The notifications sent over websockets contain the
entire subtree, even if just one node changed. This is
very inefficient for monitoring subtrees that may have
large numbers of nodes. Point in case, we need to monitor
changes to the port statuses under /neutron/ports/ but we
do not want to have to IO and parse the entire list of
ports for each change. This change proposes a new query
parameter to the "data-change-event-subscription" REST call
that specifies that the subscriber is only interested in
receiving the leaf nodes that have changed. Each leaf node
is (already) accompanied by its path.

Here are examples of the notifications sent with the query
param and without. The notification is generated by one of
two port's status transitioning from DOWN to ACTIVE.

Here it is without the query param. Note how all existing
ports are sent. Note how the status is sent three times
and the port twice (the notification send each level of the
tree in it's entirety):
{
    "notification": {
        "data-changed-notification": {
            "data-change-event": [
                {
                    "data": {
                        "status": {
                            "content": "ACTIVE",
                            "xmlns": "urn:opendaylight:neutron"
                        }
                    },
                    "operation": "updated",
                    "path": "/neutron:neutron/neutron:ports/neutron:port[neutron:uuid='97a251dc-3bbe-49b1-a08f-b164922bb0c3']/neutron:status"
                },
                {
                    "data": {
                        "port": {
                            "status": "ACTIVE",
                            "uuid": "97a251dc-3bbe-49b1-a08f-b164922bb0c3",
                            "xmlns": "urn:opendaylight:neutron"
                        }
                    },
                    "operation": "updated",
                    "path": "/neutron:neutron/neutron:ports/neutron:port[neutron:uuid='97a251dc-3bbe-49b1-a08f-b164922bb0c3']"
                },
                {
                    "data": {
                        "ports": {
                            "port": [
                                {
                                    "status": "ACTIVE",
                                    "uuid": "97a251dc-3bbe-49b1-a08f-b164922bb0c3"
                                },
                                {
                                    "status": "ACTIVE",
                                    "uuid": "2278122f-1e21-4557-8631-c9cef5299ba4"
                                }
                            ],
                            "xmlns": "urn:opendaylight:neutron"
                        }
                    },
                    "operation": "updated",
                    "path": "/neutron:neutron/neutron:ports"
                }
            ],
            "xmlns": "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote"
        },
        "eventTime": "2017-02-22T02:42:08+02:00",
        "xmlns": "urn:ietf:params:xml:ns:netconf:notification:1.0"
    }
}

Here is the same exact notification but generated with a registration
using the new query param:
{
    "notification": {
        "data-changed-notification": {
            "data-change-event": {
                "data": {
                    "status": {
                        "content": "ACTIVE",
                        "xmlns": "urn:opendaylight:neutron"
                    }
                },
                "operation": "updated",
                "path": "/neutron:neutron/neutron:ports/neutron:port[neutron:uuid='d6e6335d-9568-4949-aef1-4107e34c5f28']/neutron:status"
            },
            "xmlns": "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote"
        },
        "eventTime": "2017-02-22T02:27:32+02:00",
        "xmlns": "urn:ietf:params:xml:ns:netconf:notification:1.0"
    }
}

Here is an example of the REST call with the new query param:
curl -u admin:admin http://10.9.8.1:8181/restconf/streams/stream/data-change-event-subscription/neutron:neutron/neutron:ports/datastore=OPERATIONAL/scope=SUBTREE?odlLeafNodesOnly=true

Also fixed the existing unit test and added one. However,
there are some issues with jersey where sporadically the
InputStream it passes in to read the post data is EoF.

Change-Id: Ic383a28396f32132da73d4d92fc020c93278eb00
Signed-off-by: Josh <jhershbe@redhat.com>
restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/streams/listeners/AbstractQueryParams.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/streams/listeners/ListenerAdapter.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/SubscribeToStreamUtil.java
restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ExpressionParserTest.java
restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/websockets/test/RestStreamTest.java [moved from restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/websockets/test/RestStream.java with 74% similarity]