Jump to: navigation, search

OpenDaylight Controller:MD-SAL:Restconf:Change event notification subscription

Change-event notification subscribtion makes it possible to obtain notifications about data manipulation (inserting, changing, deleting) which are done on any specified part of any specified datastore with specific scope.

To subscribe to event change notifications receiving the following steps are necessary :

  1. Invoke rpc create-data-change-event-subscription
    Specify HTTP request as follows:
    • URI: http://<host>:<port>/restconf/operations/sal-remote:create-data-change-event-subscription
    • HEADER: Content-Type=application/xml, Accept=application/xml
    • OPERATION: POST
    • DATA:
      <input xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote">
        <path xmlns:a="urn:opendaylight:inventory">/a:nodes</path>
        <datastore xmlns="urn:sal:restconf:event:subscription">CONFIGURATION</datastore>
        <scope xmlns="urn:sal:restconf:event:subscription">BASE</scope>  
      </input>
      

      Remark: For more information about rpc's input see section below

    After sending this request following payload in response should be received:

    <output xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote">
      <stream-name>data-change-event-subscription/opendaylight-inventory:nodes/datastore=CONFIGURATION/scope=BASE</stream-name>
    </output>
    

    Remark: The new listener (if didn't exist) for stream-name is created.

    Remark: Stream name contains information about subscription type, datastore and scope.
  2. Subscribing to stream
    • URI: http://<host>:<port>/restconf/streams/stream/data-change-event-subscription/opendaylight-inventory:nodes/datastore=CONFIGURATION/scope=BASE
    • HEADER: Content-Type=application/xml
    • OPERATION: GET


    After sending this request status code 200 OK should be received and in HTTP response header in location attribute should be URI e. g.

    ws://<host>:<port>/data-change-event-subscription/opendaylight-inventory:nodes/datastore=CONFIGURATION/scope=BASE

    This URI represents address on which notification can be received.

    Remark: During this phase it is checked whether listener for steam-name from URI exists. For concrete datastore, scope and path (information are get from URI) is listener registered in DOM data broker.

  3. Client for notification receiving
    To be able to receive notification (demonstration purpose) on URI the simple application WebSocketClient was created. The application is placed in \opendaylight\md-sal\sal-rest-connector\target\test-classes\org\opendaylight\controller\sal\restconf\impl\websockets\client\WebSocketClient.class project and accepts as input parameter URI on which will listen for notifications. After starting (in my case dirrectly in Eclipse) the output similar to following should display at console
    WebSocket Client connecting
    09:49:05.000 [main] DEBUG i.n.util.internal.ThreadLocalRandom - -Dio.netty.initialSeedUniquifier: 0x80ce8f641c63fccc (took 7 ms)
    09:49:05.024 [main] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.allocator.type: unpooled
    09:49:05.024 [main] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.threadLocalDirectBufferSize: 65536
    09:49:05.065 [nioEventLoopGroup-2-1] DEBUG io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetectionLevel: simple
    09:49:05.077 [nioEventLoopGroup-2-1] DEBUG i.n.u.i.JavassistTypeParameterMatcherGenerator - Generated: io.netty.util.internal.__matchers__.io.netty.handler.codec.http.HttpObjectMatcher
    09:49:05.085 [nioEventLoopGroup-2-1] DEBUG i.n.h.c.h.w.WebSocketClientHandshaker13 - WebSocket version 13 client handshake key: zgELhwqOOTvpVQSu/iBjOw==, expected response: boGRHnxqN1Inx4rbbJyCHpFwSbQ=
    09:49:05.090 [nioEventLoopGroup-2-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxCapacity.default: 262144
    09:49:05.094 [nioEventLoopGroup-2-1] DEBUG io.netty.util.internal.Cleaner0 - java.nio.ByteBuffer.cleaner(): available
    09:49:05.100 [nioEventLoopGroup-2-1] DEBUG i.n.u.i.JavassistTypeParameterMatcherGenerator - Generated: io.netty.util.internal.__matchers__.io.netty.handler.codec.http.websocketx.WebSocketFrameMatcher
    09:49:05.106 [nioEventLoopGroup-2-1] INFO  c.o.c.s.r.i.w.c.WebSocketClientHandler - WebSocket Client connected!
    

  4. Receiving notification
    To receive notification it is necessary to do some activity in CONFIGURATION datastore at path opendaylight-inventory:nodes. As example some data can be inserted to nodes:
    • URI: http://<host>:<port>/restconf/config
    • HEADER: Content-Type=application/xml, Accept=application/xml
    • OPERATION: POST
    • DATA:
      <nodes xmlns="urn:opendaylight:inventory">
        <node>
          <id>56</id>
        </node>
      </nodes>
      

    Response status code should be 204 No Content and in console there should appear notification message similar to following:

    <notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
        <eventTime>2016-08-02T01:07:31+02:00</eventTime>
        <data-changed-notification xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote">
            <data-change-event>
                <path xmlns:uwlv="urn:opendaylight:inventory">/uwlv:nodes</path>
                <operation>created</operation>
                <data>
                    <nodes xmlns="urn:opendaylight:inventory">
                        <node>
                            <id>56</id>
                        </node>
                    </nodes>
                </data>
            </data-change-event>
        </data-changed-notification>
    </notification>
    

Rpc create-data-change-event-subscription defined in yang file /opendaylight/md-sal/sal-remote/src/main/yangopendaylight-md-sal-remote.yang (module sal-remote) was augmented via /opendaylight/md-sal/sal-rest-connector/src/main/yang/sal-remote-augment.yang. Leaf for holding information about datastore and scope were added. Currently rpc looks as follows

rpc create-data-change-event-subscription {
    input {
        leaf path {
            type instance-identifier;
            description "Subtree path. ";
        }
        leaf datastore {
            type enumeration {
                enum OPERATIONAL;
                enum CONFIGURATION;
            }
        }
        leaf scope {
            type enumeration {
                enum BASE;
                enum ONE;
                enum SUBTREE;
            }
        }  
     }
     output {
        leaf stream-name {
            type string;
            description "Notification stream name.";
        }
     }
}

For more information about scope meaning see javadoc for class opendaylight/md-sal/sal-common-api/AsyncDataBroker$DataChangeScope in controller repository.