Split out odl-controller-dom-api
[controller.git] / docs / dev-guide.rst
1 .. _controller-dev-guide:
2
3 Controller
4 ==========
5
6 Overview
7 --------
8
9 OpenDaylight Controller is Java-based, model-driven controller using
10 YANG as its modeling language for various aspects of the system and
11 applications and with its components serves as a base platform for other
12 OpenDaylight applications.
13
14 The OpenDaylight Controller relies on the following technologies:
15
16 -  **OSGI** - This framework is the back-end of OpenDaylight as it
17    allows dynamically loading of bundles and packages JAR files, and
18    binding bundles together for exchanging information.
19
20 -  **Karaf** - Application container built on top of OSGI, which
21    simplifies operational aspects of packaging and installing
22    applications.
23
24 -  **YANG** - a data modeling language used to model configuration and
25    state data manipulated by the applications, remote procedure calls,
26    and notifications.
27
28 The OpenDaylight Controller provides following model-driven subsystems
29 as a foundation for Java applications:
30
31 -  :ref:`config_subsystem` - an activation,
32    dependency-injection and configuration framework, which allows
33    two-phase commits of configuration and dependency-injection, and
34    allows for run-time rewiring.
35
36 -  :ref:`MD-SAL <mdsal_dev_guide>` - messaging and data storage
37    functionality for data, notifications and RPCs modeled by application
38    developers. MD-SAL uses YANG as the modeling for both interface and
39    data definitions, and provides a messaging and data-centric runtime
40    for such services based on YANG modeling.
41
42 -  **MD-SAL Clustering** - enables cluster support for core MD-SAL
43    functionality and provides location-transparent accesss to
44    YANG-modeled data.
45
46 The OpenDaylight Controller supports external access to applications and
47 data using following model-driven protocols:
48
49 -  **NETCONF** - XML-based RPC protocol, which provides abilities for
50    client to invoke YANG-modeled RPCs, receive notifications and to
51    read, modify and manipulate YANG modeled data.
52
53 -  **RESTCONF** - HTTP-based protocol, which provides REST-like APIs to
54    manipulate YANG modeled data and invoke YANG modeled RPCs, using XML
55    or JSON as payload format.
56
57 .. _mdsal_dev_guide:
58
59 MD-SAL Overview
60 ---------------
61
62 The Model-Driven Service Adaptation Layer (MD-SAL) is message-bus
63 inspired extensible middleware component that provides messaging and
64 data storage functionality based on data and interface models defined by
65 application developers (i.e. user-defined models).
66
67 The MD-SAL:
68
69 -  Defines a **common-layer, concepts, data model building blocks and
70    messaging patterns** and provides infrastructure / framework for
71    applications and inter-application communication.
72
73 -  Provide common support for user-defined transport and payload
74    formats, including payload serialization and adaptation (e.g. binary,
75    XML or JSON).
76
77 The MD-SAL uses **YANG** as the modeling language for both interface and
78 data definitions, and provides a messaging and data-centric runtime for
79 such services based on YANG modeling.
80
81 | The MD-SAL provides two different API types (flavours):
82
83 -  **MD-SAL Binding:** MD-SAL APIs which extensively uses APIs and
84    classes generated from YANG models, which provides compile-time
85    safety.
86
87 -  **MD-SAL DOM:** (Document Object Model) APIs which uses DOM-like
88    representation of data, which makes them more powerful, but provides
89    less compile-time safety.
90
91 .. note::
92
93     Model-driven nature of the MD-SAL and **DOM**-based APIs allows for
94     behind-the-scene API and payload type mediation and transformation
95     to facilitate seamless communication between applications - this
96     enables for other components and applications to provide connectors
97     / expose different set of APIs and derive most of its functionality
98     purely from models, which all existing code can benefit from without
99     modification. For example **RESTCONF Connector** is an application
100     built on top of MD-SAL and exposes YANG-modeled application APIs
101     transparently via HTTP and adds support for XML and JSON payload
102     type.
103
104 Basic concepts
105 ~~~~~~~~~~~~~~
106
107 Basic concepts are building blocks which are used by applications, and
108 from which MD-SAL uses to define messaging patterns and to provide
109 services and behavior based on developer-supplied YANG models.
110
111 Data Tree
112     All state-related data are modeled and represented as data tree,
113     with possibility to address any element / subtree
114
115     -  **Operational Data Tree** - Reported state of the system,
116        published by the providers using MD-SAL. Represents a feedback
117        loop for applications to observe state of the network / system.
118
119     -  **Configuration Data Tree** - Intended state of the system or
120        network, populated by consumers, which expresses their intention.
121
122 Instance Identifier
123     Unique identifier of node / subtree in data tree, which provides
124     unambiguous information, how to reference and retrieve node /
125     subtree from conceptual data trees.
126
127 Notification
128     Asynchronous transient event which may be consumed by subscribers
129     and they may act upon it
130
131 RPC
132     asynchronous request-reply message pair, when request is triggered
133     by consumer, send to the provider, which in future replies with
134     reply message.
135
136     .. note::
137
138         In MD-SAL terminology, the term *RPC* is used to define the
139         input and output for a procedure (function) that is to be
140         provided by a provider, and mediated by the MD-SAL, that means
141         it may not result in remote call.
142
143 Messaging Patterns
144 ~~~~~~~~~~~~~~~~~~
145
146 MD-SAL provides several messaging patterns using broker derived from
147 basic concepts, which are intended to transfer YANG modeled data between
148 applications to provide data-centric integration between applications
149 instead of API-centric integration.
150
151 -  **Unicast communication**
152
153    -  **Remote Procedure Calls** - unicast between consumer and
154       provider, where consumer sends **request** message to provider,
155       which asynchronously responds with **reply** message
156
157 -  **Publish / Subscribe**
158
159    -  **Notifications** - multicast transient message which is published
160       by provider and is delivered to subscribers
161
162    -  **Data Change Events** - multicast asynchronous event, which is
163       sent by data broker if there is change in conceptual data tree,
164       and is delivered to subscribers
165
166 -  **Transactional access to Data Tree**
167
168    -  Transactional **reads** from conceptual **data tree** - read-only
169       transactions with isolation from other running transactions.
170
171    -  Transactional **modification** to conceptual **data tree** - write
172       transactions with isolation from other running transactions.
173
174    -  **Transaction chaining**
175
176 MD-SAL Data Transactions
177 ------------------------
178
179 MD-SAL **Data Broker** provides transactional access to conceptual
180 **data trees** representing configuration and operational state.
181
182 .. note::
183
184     **Data tree** usually represents state of the modeled data, usually
185     this is state of controller, applications and also external systems
186     (network devices).
187
188 **Transactions** provide :ref:`stable and isolated
189 view <transaction_isolation>` from other currently running
190 transactions. The state of running transaction and underlying data tree
191 is not affected by other concurrently running transactions.
192
193 Write-Only
194     Transaction provides only modification capabilities, but does not
195     provide read capabilities. Write-only transaction is allocated using
196     ``newWriteOnlyTransaction()``.
197
198     .. note::
199
200         This allows less state tracking for write-only transactions and
201         allows MD-SAL Clustering to optimize internal representation of
202         transaction in cluster.
203
204 Read-Write
205     Transaction provides both read and write capabilities. It is
206     allocated using ``newReadWriteTransaction()``.
207
208 Read-Only
209     Transaction provides stable read-only view based on current data
210     tree. Read-only view is not affected by any subsequent write
211     transactions. Read-only transaction is allocated using
212     ``newReadOnlyTransaction()``.
213
214     .. note::
215
216         If an application needs to observe changes itself in data tree,
217         it should use **data tree listeners** instead of read-only
218         transactions and polling data tree.
219
220 Transactions may be allocated using the **data broker** itself or using
221 **transaction chain**. In the case of **transaction chain**, the new
222 allocated transaction is not based on current state of data tree, but
223 rather on state introduced by previous transaction from the same chain,
224 even if the commit for previous transaction has not yet occurred (but
225 transaction was submitted).
226
227 Write-Only & Read-Write Transaction
228 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
229
230 Write-Only and Read-Write transactions provide modification capabilities
231 for the conceptual data trees.
232
233 1. application allocates new transactions using
234    ``newWriteOnlyTransaction()`` or ``newReadWriteTransaction()``.
235
236 2. application `modifies data tree <#_modification_of_data_tree>`__
237    using ``put``, ``merge`` and/or ``delete``.
238
239 3. application finishes transaction using
240    ``submit()``, which :ref:`seals transaction
241    and submits <submitting_transaction>` it to be processed.
242
243 4. application observes the result of the transaction commit using
244    either blocking or asynchronous calls.
245
246 The **initial state** of the write transaction is a **stable snapshot**
247 of the current data tree state captured when transaction was created and
248 it’s state and underlying data tree are not affected by other
249 concurrently running transactions.
250
251 Write transactions are **isolated** from other concurrent write
252 transactions. All :ref:`writes are local <transaction_local_state>`
253 to the transaction and represents only a **proposal of state change**
254 for data tree and **are not visible** to any other concurrently running
255 transactions (including read-only transactions).
256
257 The transaction :ref:`commit may fail <commit_failure_scenarios>` due
258 to failing verification of data or concurrent transaction modifying and
259 affected data in an incompatible way.
260
261 Modification of Data Tree
262 ^^^^^^^^^^^^^^^^^^^^^^^^^
263
264 Write-only and read-write transaction provides following methods to
265 modify data tree:
266
267 put
268     .. code:: java
269
270         <T> void put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data);
271
272     Stores a piece of data at a specified path. This acts as an **add /
273     replace** operation, which is to say that whole subtree will be
274     replaced by the specified data.
275
276 merge
277     .. code:: java
278
279         <T> void merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data);
280
281     Merges a piece of data with the existing data at a specified path.
282     Any **pre-existing data** which are not explicitly overwritten
283     **will be preserved**. This means that if you store a container, its
284     child subtrees will be merged.
285
286 delete
287     .. code:: java
288
289         void delete(LogicalDatastoreType store, InstanceIdentifier<?> path);
290
291     Removes a whole subtree from a specified path.
292
293 .. _submitting_transaction:
294
295 Submitting transaction
296 ^^^^^^^^^^^^^^^^^^^^^^
297
298 Transaction is submitted to be processed and committed using following
299 method:
300
301 .. code:: java
302
303     CheckedFuture<Void,TransactionCommitFailedException> submit();
304
305 Applications publish the changes proposed in the transaction by calling
306 ``submit()`` on the transaction. This **seals the transaction**
307 (preventing any further writes using this transaction) and submits it to
308 be processed and applied to global conceptual data tree. The
309 ``submit()`` method does not block, but rather returns
310 ``ListenableFuture``, which will complete successfully once processing
311 of transaction is finished and changes are applied to data tree. If
312 **commit** of data failed, the future will fail with
313 ``TransactionFailedException``.
314
315 Application may listen on commit state asynchronously using
316 ``ListenableFuture``.
317
318 .. code:: java
319
320     Futures.addCallback( writeTx.submit(), new FutureCallback<Void>() {
321             public void onSuccess( Void result ) {
322                 LOG.debug("Transaction committed successfully.");
323             }
324
325             public void onFailure( Throwable t ) {
326                 LOG.error("Commit failed.",e);
327             }
328         });
329
330 -  Submits ``writeTx`` and registers application provided
331    ``FutureCallback`` on returned future.
332
333 -  Invoked when future completed successfully - transaction ``writeTx``
334    was successfully committed to data tree.
335
336 -  Invoked when future failed - commit of transaction ``writeTx``
337    failed. Supplied exception provides additional details and cause of
338    failure.
339
340 If application need to block till commit is finished it may use
341 ``checkedGet()`` to wait till commit is finished.
342
343 .. code:: java
344
345     try {
346         writeTx.submit().checkedGet();
347     } catch (TransactionCommitFailedException e) {
348         LOG.error("Commit failed.",e);
349     }
350
351 -  Submits ``writeTx`` and blocks till commit of ``writeTx`` is
352    finished. If commit fails ``TransactionCommitFailedException`` will
353    be thrown.
354
355 -  Catches ``TransactionCommitFailedException`` and logs it.
356
357 .. _transaction_local_state:
358
359 Transaction local state
360 ^^^^^^^^^^^^^^^^^^^^^^^
361
362 Read-Write transactions maintain transaction-local state, which renders
363 all modifications as if they happened, but this is only local to
364 transaction.
365
366 Reads from the transaction returns data as if the previous modifications
367 in transaction already happened.
368
369 Let assume initial state of data tree for ``PATH`` is ``A``.
370
371 .. code:: java
372
373     ReadWriteTransaction rwTx = broker.newReadWriteTransaction();
374
375     rwRx.read(OPERATIONAL,PATH).get();
376     rwRx.put(OPERATIONAL,PATH,B);
377     rwRx.read(OPERATIONAL,PATH).get();
378     rwRx.put(OPERATIONAL,PATH,C);
379     rwRx.read(OPERATIONAL,PATH).get();
380
381 -  Allocates new ``ReadWriteTransaction``.
382
383 -  Read from ``rwTx`` will return value ``A`` for ``PATH``.
384
385 -  Writes value ``B`` to ``PATH`` using ``rwTx``.
386
387 -  Read will return value ``B`` for ``PATH``, since previous write
388    occurred in same transaction.
389
390 -  Writes value ``C`` to ``PATH`` using ``rwTx``.
391
392 -  Read will return value ``C`` for ``PATH``, since previous write
393    occurred in same transaction.
394
395 .. _transaction_isolation:
396
397 Transaction isolation
398 ~~~~~~~~~~~~~~~~~~~~~
399
400 Running (not submitted) transactions are isolated from each other and
401 changes done in one transaction are not observable in other currently
402 running transaction.
403
404 Lets assume initial state of data tree for ``PATH`` is ``A``.
405
406 .. code:: java
407
408     ReadOnlyTransaction txRead = broker.newReadOnlyTransaction();
409     ReadWriteTransaction txWrite = broker.newReadWriteTransaction();
410
411     txRead.read(OPERATIONAL,PATH).get();
412     txWrite.put(OPERATIONAL,PATH,B);
413     txWrite.read(OPERATIONAL,PATH).get();
414     txWrite.submit().get();
415     txRead.read(OPERATIONAL,PATH).get();
416     txAfterCommit = broker.newReadOnlyTransaction();
417     txAfterCommit.read(OPERATIONAL,PATH).get();
418
419 -  Allocates read only transaction, which is based on data tree which
420    contains value ``A`` for ``PATH``.
421
422 -  Allocates read write transaction, which is based on data tree which
423    contains value ``A`` for ``PATH``.
424
425 -  Read from read-only transaction returns value ``A`` for ``PATH``.
426
427 -  Data tree is updated using read-write transaction, ``PATH`` contains
428    ``B``. Change is not public and only local to transaction.
429
430 -  Read from read-write transaction returns value ``B`` for ``PATH``.
431
432 -  Submits changes in read-write transaction to be committed to data
433    tree. Once commit will finish, changes will be published and ``PATH``
434    will be updated for value ``B``. Previously allocated transactions
435    are not affected by this change.
436
437 -  Read from previously allocated read-only transaction still returns
438    value ``A`` for ``PATH``, since it provides stable and isolated view.
439
440 -  Allocates new read-only transaction, which is based on data tree,
441    which contains value ``B`` for ``PATH``.
442
443 -  Read from new read-only transaction return value ``B`` for ``PATH``
444    since read-write transaction was committed.
445
446 .. note::
447
448     Examples contain blocking calls on future only to illustrate that
449     action happened after other asynchronous action. The use of the
450     blocking call ``ListenableFuture#get()`` is discouraged for most
451     use-cases and you should use
452     ``Futures#addCallback(ListenableFuture, FutureCallback)`` to listen
453     asynchronously for result.
454
455 .. _commit_failure_scenarios:
456
457 Commit failure scenarios
458 ~~~~~~~~~~~~~~~~~~~~~~~~
459
460 A transaction commit may fail because of following reasons:
461
462 Optimistic Lock Failure
463     Another transaction finished earlier and **modified the same node in
464     a non-compatible way**. The commit (and the returned future) will
465     fail with an ``OptimisticLockFailedException``.
466
467     It is the responsibility of the caller to create a new transaction
468     and submit the same modification again in order to update data tree.
469
470     .. warning::
471
472         ``OptimisticLockFailedException`` usually exposes **multiple
473         writers** to the same data subtree, which may conflict on same
474         resources.
475
476         In most cases, retrying may result in a probability of success.
477
478         There are scenarios, albeit unusual, where any number of retries
479         will not succeed. Therefore it is strongly recommended to limit
480         the number of retries (2 or 3) to avoid an endless loop.
481
482 Data Validation
483     The data change introduced by this transaction **did not pass
484     validation** by commit handlers or data was incorrectly structured.
485     The returned future will fail with a
486     ``DataValidationFailedException``. User **should not retry** to
487     create new transaction with same data, since it probably will fail
488     again.
489
490 Example conflict of two transactions
491 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
492
493 This example illustrates two concurrent transactions, which derived from
494 same initial state of data tree and proposes conflicting modifications.
495
496 .. code:: java
497
498     WriteTransaction txA = broker.newWriteTransaction();
499     WriteTransaction txB = broker.newWriteTransaction();
500
501     txA.put(CONFIGURATION, PATH, A);
502     txB.put(CONFIGURATION, PATH, B);
503
504     CheckedFuture<?,?> futureA = txA.submit();
505     CheckedFuture<?,?> futureB = txB.submit();
506
507 -  Updates ``PATH`` to value ``A`` using ``txA``
508
509 -  Updates ``PATH`` to value ``B`` using ``txB``
510
511 -  Seals & submits ``txA``. The commit will be processed asynchronously
512    and data tree will be updated to contain value ``A`` for ``PATH``.
513    The returned ‘ListenableFuture’ will complete successfully once state
514    is applied to data tree.
515
516 -  Seals & submits ``txB``. Commit of ``txB`` will fail, because
517    previous transaction also modified path in a concurrent way. The
518    state introduced by ``txB`` will not be applied. The returned
519    ``ListenableFuture`` will fail with ``OptimisticLockFailedException``
520    exception, which indicates that concurrent transaction prevented the
521    submitted transaction from being applied.
522
523 Example asynchronous retry-loop
524 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
525
526 .. code:: java
527
528     private void doWrite( final int tries ) {
529         WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
530
531         MyDataObject data = ...;
532         InstanceIdentifier<MyDataObject> path = ...;
533         writeTx.put( LogicalDatastoreType.OPERATIONAL, path, data );
534
535         Futures.addCallback( writeTx.submit(), new FutureCallback<Void>() {
536             public void onSuccess( Void result ) {
537                 // succeeded
538             }
539
540             public void onFailure( Throwable t ) {
541                 if( t instanceof OptimisticLockFailedException && (( tries - 1 ) > 0)) {
542                     doWrite( tries - 1 );
543                 }
544             }
545           });
546     }
547     ...
548     doWrite( 2 );
549
550 Concurrent change compatibility
551 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
552
553 There are several sets of changes which could be considered incompatible
554 between two transactions which are derived from same initial state.
555 Rules for conflict detection applies recursively for each subtree level.
556
557 Following table shows state changes and failures between two concurrent
558 transactions, which are based on same initial state, ``tx1`` is
559 submitted before ``tx2``.
560
561 INFO: Following tables stores numeric values and shows data using
562 ``toString()`` to simplify examples.
563
564 +--------------------+--------------------+--------------------+--------------------+
565 | Initial state      | tx1                | tx2                | Observable Result  |
566 +====================+====================+====================+====================+
567 | Empty              | ``put(A,1)``       | ``put(A,2)``       | ``tx2`` will fail, |
568 |                    |                    |                    | value of ``A`` is  |
569 |                    |                    |                    | ``1``              |
570 +--------------------+--------------------+--------------------+--------------------+
571 | Empty              | ``put(A,1)``       | ``merge(A,2)``     | value of ``A`` is  |
572 |                    |                    |                    | ``2``              |
573 +--------------------+--------------------+--------------------+--------------------+
574 | Empty              | ``merge(A,1)``     | ``put(A,2)``       | ``tx2`` will fail, |
575 |                    |                    |                    | value of ``A`` is  |
576 |                    |                    |                    | ``1``              |
577 +--------------------+--------------------+--------------------+--------------------+
578 | Empty              | ``merge(A,1)``     | ``merge(A,2)``     | ``A`` is ``2``     |
579 +--------------------+--------------------+--------------------+--------------------+
580 | A=0                | ``put(A,1)``       | ``put(A,2)``       | ``tx2`` will fail, |
581 |                    |                    |                    | ``A`` is ``1``     |
582 +--------------------+--------------------+--------------------+--------------------+
583 | A=0                | ``put(A,1)``       | ``merge(A,2)``     | ``A`` is ``2``     |
584 +--------------------+--------------------+--------------------+--------------------+
585 | A=0                | ``merge(A,1)``     | ``put(A,2)``       | ``tx2`` will fail, |
586 |                    |                    |                    | value of ``A`` is  |
587 |                    |                    |                    | ``1``              |
588 +--------------------+--------------------+--------------------+--------------------+
589 | A=0                | ``merge(A,1)``     | ``merge(A,2)``     | ``A`` is ``2``     |
590 +--------------------+--------------------+--------------------+--------------------+
591 | A=0                | ``delete(A)``      | ``put(A,2)``       | ``tx2`` will fail, |
592 |                    |                    |                    | ``A`` does not     |
593 |                    |                    |                    | exists             |
594 +--------------------+--------------------+--------------------+--------------------+
595 | A=0                | ``delete(A)``      | ``merge(A,2)``     | ``A`` is ``2``     |
596 +--------------------+--------------------+--------------------+--------------------+
597
598 Table: Concurrent change resolution for leaves and leaf-list items
599
600 +--------------------+--------------------+--------------------+--------------------+
601 | Initial state      | ``tx1``            | ``tx2``            | Result             |
602 +====================+====================+====================+====================+
603 | Empty              | put(TOP,[])        | put(TOP,[])        | ``tx2`` will fail, |
604 |                    |                    |                    | state is TOP=[]    |
605 +--------------------+--------------------+--------------------+--------------------+
606 | Empty              | put(TOP,[])        | merge(TOP,[])      | TOP=[]             |
607 +--------------------+--------------------+--------------------+--------------------+
608 | Empty              | put(TOP,[FOO=1])   | put(TOP,[BAR=1])   | ``tx2`` will fail, |
609 |                    |                    |                    | state is           |
610 |                    |                    |                    | TOP=[FOO=1]        |
611 +--------------------+--------------------+--------------------+--------------------+
612 | Empty              | put(TOP,[FOO=1])   | merge(TOP,[BAR=1]) | TOP=[FOO=1,BAR=1]  |
613 +--------------------+--------------------+--------------------+--------------------+
614 | Empty              | merge(TOP,[FOO=1]) | put(TOP,[BAR=1])   | ``tx2`` will fail, |
615 |                    |                    |                    | state is           |
616 |                    |                    |                    | TOP=[FOO=1]        |
617 +--------------------+--------------------+--------------------+--------------------+
618 | Empty              | merge(TOP,[FOO=1]) | merge(TOP,[BAR=1]) | TOP=[FOO=1,BAR=1]  |
619 +--------------------+--------------------+--------------------+--------------------+
620 | TOP=[]             | put(TOP,[FOO=1])   | put(TOP,[BAR=1])   | ``tx2`` will fail, |
621 |                    |                    |                    | state is           |
622 |                    |                    |                    | TOP=[FOO=1]        |
623 +--------------------+--------------------+--------------------+--------------------+
624 | TOP=[]             | put(TOP,[FOO=1])   | merge(TOP,[BAR=1]) | state is           |
625 |                    |                    |                    | TOP=[FOO=1,BAR=1]  |
626 +--------------------+--------------------+--------------------+--------------------+
627 | TOP=[]             | merge(TOP,[FOO=1]) | put(TOP,[BAR=1])   | ``tx2`` will fail, |
628 |                    |                    |                    | state is           |
629 |                    |                    |                    | TOP=[FOO=1]        |
630 +--------------------+--------------------+--------------------+--------------------+
631 | TOP=[]             | merge(TOP,[FOO=1]) | merge(TOP,[BAR=1]) | state is           |
632 |                    |                    |                    | TOP=[FOO=1,BAR=1]  |
633 +--------------------+--------------------+--------------------+--------------------+
634 | TOP=[]             | delete(TOP)        | put(TOP,[BAR=1])   | ``tx2`` will fail, |
635 |                    |                    |                    | state is empty     |
636 |                    |                    |                    | store              |
637 +--------------------+--------------------+--------------------+--------------------+
638 | TOP=[]             | delete(TOP)        | merge(TOP,[BAR=1]) | state is           |
639 |                    |                    |                    | TOP=[BAR=1]        |
640 +--------------------+--------------------+--------------------+--------------------+
641 | TOP=[]             | put(TOP/FOO,1)     | put(TOP/BAR,1])    | state is           |
642 |                    |                    |                    | TOP=[FOO=1,BAR=1]  |
643 +--------------------+--------------------+--------------------+--------------------+
644 | TOP=[]             | put(TOP/FOO,1)     | merge(TOP/BAR,1)   | state is           |
645 |                    |                    |                    | TOP=[FOO=1,BAR=1]  |
646 +--------------------+--------------------+--------------------+--------------------+
647 | TOP=[]             | merge(TOP/FOO,1)   | put(TOP/BAR,1)     | state is           |
648 |                    |                    |                    | TOP=[FOO=1,BAR=1]  |
649 +--------------------+--------------------+--------------------+--------------------+
650 | TOP=[]             | merge(TOP/FOO,1)   | merge(TOP/BAR,1)   | state is           |
651 |                    |                    |                    | TOP=[FOO=1,BAR=1]  |
652 +--------------------+--------------------+--------------------+--------------------+
653 | TOP=[]             | delete(TOP)        | put(TOP/BAR,1)     | ``tx2`` will fail, |
654 |                    |                    |                    | state is empty     |
655 |                    |                    |                    | store              |
656 +--------------------+--------------------+--------------------+--------------------+
657 | TOP=[]             | delete(TOP)        | merge(TOP/BAR,1]   | ``tx2`` will fail, |
658 |                    |                    |                    | state is empty     |
659 |                    |                    |                    | store              |
660 +--------------------+--------------------+--------------------+--------------------+
661 | TOP=[FOO=1]        | put(TOP/FOO,2)     | put(TOP/BAR,1)     | state is           |
662 |                    |                    |                    | TOP=[FOO=2,BAR=1]  |
663 +--------------------+--------------------+--------------------+--------------------+
664 | TOP=[FOO=1]        | put(TOP/FOO,2)     | merge(TOP/BAR,1)   | state is           |
665 |                    |                    |                    | TOP=[FOO=2,BAR=1]  |
666 +--------------------+--------------------+--------------------+--------------------+
667 | TOP=[FOO=1]        | merge(TOP/FOO,2)   | put(TOP/BAR,1)     | state is           |
668 |                    |                    |                    | TOP=[FOO=2,BAR=1]  |
669 +--------------------+--------------------+--------------------+--------------------+
670 | TOP=[FOO=1]        | merge(TOP/FOO,2)   | merge(TOP/BAR,1)   | state is           |
671 |                    |                    |                    | TOP=[FOO=2,BAR=1]  |
672 +--------------------+--------------------+--------------------+--------------------+
673 | TOP=[FOO=1]        | delete(TOP/FOO)    | put(TOP/BAR,1)     | state is           |
674 |                    |                    |                    | TOP=[BAR=1]        |
675 +--------------------+--------------------+--------------------+--------------------+
676 | TOP=[FOO=1]        | delete(TOP/FOO)    | merge(TOP/BAR,1]   | state is           |
677 |                    |                    |                    | TOP=[BAR=1]        |
678 +--------------------+--------------------+--------------------+--------------------+
679
680 Table: Concurrent change resolution for containers, lists, list items
681
682 MD-SAL RPC routing
683 ------------------
684
685 The MD-SAL provides a way to deliver Remote Procedure Calls (RPCs) to a
686 particular implementation based on content in the input as it is modeled
687 in YANG. This part of the RPC input is referred to as a **context
688 reference**.
689
690 The MD-SAL does not dictate the name of the leaf which is used for this
691 RPC routing, but provides necessary functionality for YANG model author
692 to define their **context reference** in their model of RPCs.
693
694 MD-SAL routing behavior is modeled using following terminology and its
695 application to YANG models:
696
697 Context Type
698     Logical type of RPC routing. Context type is modeled as YANG
699     ``identity`` and is referenced in model to provide scoping
700     information.
701
702 Context Instance
703     Conceptual location in data tree, which represents context in which
704     RPC could be executed. Context instance usually represent logical
705     point to which RPC execution is attached.
706
707 Context Reference
708     Field of RPC input payload which contains Instance Identifier
709     referencing **context instance** in which the RPC should be
710     executed.
711
712 Modeling a routed RPC
713 ~~~~~~~~~~~~~~~~~~~~~
714
715 In order to define routed RPCs, the YANG model author needs to declare
716 (or reuse) a **context type**, set of possible **context instances** and
717 finally RPCs which will contain **context reference** on which they will
718 be routed.
719
720 Declaring a routing context type
721 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
722
723 .. code::
724
725     identity node-context {
726         description "Identity used to mark node context";
727     }
728
729 This declares an identity named ``node-context``, which is used as
730 marker for node-based routing and is used in other places to reference
731 that routing type.
732
733 Declaring possible context instances
734 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
735
736 In order to define possible values of **context instances** for routed
737 RPCs, we need to model that set accordingly using ``context-instance``
738 extension from the ``yang-ext`` model.
739
740 .. code::
741
742     import yang-ext { prefix ext; }
743
744     /** Base structure **/
745     container nodes {
746         list node {
747             key "id";
748             ext:context-instance "node-context";
749             // other node-related fields would go here
750         }
751     }
752
753 The statement ``ext:context-instance "node-context";`` marks any element
754 of the ``list node`` as a possible valid **context instance** in
755 ``node-context`` based routing.
756
757 .. note::
758
759     The existence of a **context instance** node in operational or
760     config data tree is not strongly tied to existence of RPC
761     implementation.
762
763     For most routed RPC models, there is relationship between the data
764     present in operational data tree and RPC implementation
765     availability, but this is not enforced by MD-SAL. This provides some
766     flexibility for YANG model writers to better specify their routing
767     model and requirements for implementations. Details when RPC
768     implementations are available should be documented in YANG model.
769
770     If user invokes RPC with a **context instance** that has no
771     registered implementation, the RPC invocation will fail with the
772     exception ``DOMRpcImplementationNotAvailableException``.
773
774 Declaring a routed RPC
775 ^^^^^^^^^^^^^^^^^^^^^^
776
777 To declare RPC to be routed based on ``node-context`` we need to add
778 leaf of ``instance-identifier`` type (or type derived from
779 ``instance-identifier``) to the RPC and mark it as **context
780 reference**.
781
782 This is achieved using YANG extension ``context-reference`` from
783 ``yang-ext`` model on leaf, which will be used for RPC routing.
784
785 .. code::
786
787     rpc example-routed-rpc  {
788         input {
789             leaf node {
790                 ext:context-reference "node-context";
791                 type "instance-identifier";
792             }
793             // other input to the RPC would go here
794         }
795     }
796
797 The statement ``ext:context-reference "node-context"`` marks
798 ``leaf node`` as **context reference** of type ``node-context``. The
799 value of this leaf, will be used by the MD-SAL to select the particular
800 RPC implementation that registered itself as the implementation of the
801 RPC for particular **context instance**.
802
803 Using routed RPCs
804 ~~~~~~~~~~~~~~~~~
805
806 From a user perspective (e.g. invoking RPCs) there is no difference
807 between routed and non-routed RPCs. Routing information is just an
808 additional leaf in RPC which must be populated.
809
810 Implementing a routed RPC
811 ~~~~~~~~~~~~~~~~~~~~~~~~~
812
813 Implementation
814
815 Registering implementations
816 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
817
818 Implementations of a routed RPC (e.g., southbound plugins) will specify
819 an instance-identifier for the **context reference** (in this case a
820 node) for which they want to provide an implementation during
821 registration. Consumers, e.g., those calling the RPC are required to
822 specify that instance-identifier (in this case the identifier of a node)
823 when invoking RPC.
824
825 Simple code which showcases that for add-flow via Binding-Aware APIs
826 (`RoutedServiceTest.java <https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blob;f=opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/RoutedServiceTest.java;h=d49d6f0e25e271e43c8550feb5eef63d96301184;hb=HEAD>`__
827 ):
828
829 .. code:: java
830
831      61  @Override
832      62  public void onSessionInitiated(ProviderContext session) {
833      63      assertNotNull(session);
834      64      firstReg = session.addRoutedRpcImplementation(SalFlowService.class, salFlowService1);
835      65  }
836
837 Line 64: We are registering salFlowService1 as implementation of
838 SalFlowService RPC
839
840 .. code:: java
841
842     107  NodeRef nodeOne = createNodeRef("foo:node:1");
843     109  /**
844     110   * Provider 1 registers path of node 1
845     111   */
846     112  firstReg.registerPath(NodeContext.class, nodeOne);
847
848 Line 107: We are creating NodeRef (encapsulation of InstanceIdentifier)
849 for "foo:node:1".
850
851 Line 112: We register salFlowService1 as implementation for nodeOne.
852
853 The salFlowService1 will be executed only for RPCs which contains
854 Instance Identifier for foo:node:1.
855
856 RPCs and cluster
857 ^^^^^^^^^^^^^^^^
858
859 In case there is is only a single provider of an RPC in the cluster
860 the RPC registration is propagated to other nodes via Gossip protocol
861 and the RPC calls from other nodes are correctly routed to the
862 provider. Since the registrations are not expected to change rapidly
863 there is a latency of about 1 second until the registration is reflected
864 on the remote nodes.
865
866
867 OpenDaylight Controller MD-SAL: RESTCONF
868 ----------------------------------------
869
870 RESTCONF operations overview
871 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
872
873 | RESTCONF allows access to datastores in the controller.
874 | There are two datastores:
875
876 -  Config: Contains data inserted via controller
877
878 -  Operational: Contains other data
879
880 .. note::
881
882     | Each request must start with the URI /restconf.
883     | RESTCONF listens on port 8080 for HTTP requests.
884
885 RESTCONF supports **OPTIONS**, **GET**, **PUT**, **POST**, and
886 **DELETE** operations. Request and response data can either be in the
887 XML or JSON format. XML structures according to yang are defined at:
888 `XML-YANG <http://tools.ietf.org/html/rfc6020>`__. JSON structures are
889 defined at:
890 `JSON-YANG <http://tools.ietf.org/html/draft-lhotka-netmod-yang-json-02>`__.
891 Data in the request must have a correctly set **Content-Type** field in
892 the http header with the allowed value of the media type. The media type
893 of the requested data has to be set in the **Accept** field. Get the
894 media types for each resource by calling the OPTIONS operation. Most of
895 the paths of the pathsRestconf endpoints use `Instance
896 Identifier <https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Concepts#Instance_Identifier>`__.
897 ``<identifier>`` is used in the explanation of the operations.
898
899 | **<identifier>**
900
901 -  It must start with <moduleName>:<nodeName> where <moduleName> is a
902    name of the module and <nodeName> is the name of a node in the
903    module. It is sufficient to just use <nodeName> after
904    <moduleName>:<nodeName>. Each <nodeName> has to be separated by /.
905
906 -  <nodeName> can represent a data node which is a list or container
907    yang built-in type. If the data node is a list, there must be defined
908    keys of the list behind the data node name for example,
909    <nodeName>/<valueOfKey1>/<valueOfKey2>.
910
911 -  | The format <moduleName>:<nodeName> has to be used in this case as
912      well:
913    | Module A has node A1. Module B augments node A1 by adding node X.
914      Module C augments node A1 by adding node X. For clarity, it has to
915      be known which node is X (for example: C:X). For more details about
916      encoding, see: `RESTCONF 02 - Encoding YANG Instance Identifiers in
917      the Request
918      URI. <http://tools.ietf.org/html/draft-bierman-netconf-restconf-02#section-5.3.1>`__
919
920 Mount point
921 ~~~~~~~~~~~
922
923 | A Node can be behind a mount point. In this case, the URI has to be in
924   format <identifier>/**yang-ext:mount**/<identifier>. The first
925   <identifier> is the path to a mount point and the second <identifier>
926   is the path to a node behind the mount point. A URI can end in a mount
927   point itself by using <identifier>/**yang-ext:mount**.
928 | More information on how to actually use mountpoints is available at:
929   `OpenDaylight
930   Controller:Config:Examples:Netconf <https://wiki.opendaylight.org/view/OpenDaylight_Controller:Config:Examples:Netconf>`__.
931
932 HTTP methods
933 ~~~~~~~~~~~~
934
935 OPTIONS /restconf
936 ^^^^^^^^^^^^^^^^^
937
938 -  Returns the XML description of the resources with the required
939    request and response media types in Web Application Description
940    Language (WADL)
941
942 GET /restconf/config/<identifier>
943 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
944
945 -  Returns a data node from the Config datastore.
946
947 -  <identifier> points to a data node which must be retrieved.
948
949 GET /restconf/operational/<identifier>
950 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
951
952 -  Returns the value of the data node from the Operational datastore.
953
954 -  <identifier> points to a data node which must be retrieved.
955
956 PUT /restconf/config/<identifier>
957 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
958
959 -  Updates or creates data in the Config datastore and returns the state
960    about success.
961
962 -  <identifier> points to a data node which must be stored.
963
964 | **Example:**
965
966 ::
967
968     PUT http://<controllerIP>:8080/restconf/config/module1:foo/bar
969     Content-Type: applicaton/xml
970     <bar>
971       …
972     </bar>
973
974 | **Example with mount point:**
975
976 ::
977
978     PUT http://<controllerIP>:8080/restconf/config/module1:foo1/foo2/yang-ext:mount/module2:foo/bar
979     Content-Type: applicaton/xml
980     <bar>
981       …
982     </bar>
983
984 POST /restconf/config
985 ^^^^^^^^^^^^^^^^^^^^^
986
987 -  Creates the data if it does not exist
988
989 | For example:
990
991 ::
992
993     POST URL: http://localhost:8080/restconf/config/
994     content-type: application/yang.data+json
995     JSON payload:
996
997        {
998          "toaster:toaster" :
999          {
1000            "toaster:toasterManufacturer" : "General Electric",
1001            "toaster:toasterModelNumber" : "123",
1002            "toaster:toasterStatus" : "up"
1003          }
1004       }
1005
1006 POST /restconf/config/<identifier>
1007 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1008
1009 -  Creates the data if it does not exist in the Config datastore, and
1010    returns the state about success.
1011
1012 -  <identifier> points to a data node where data must be stored.
1013
1014 -  The root element of data must have the namespace (data are in XML) or
1015    module name (data are in JSON.)
1016
1017 | **Example:**
1018
1019 ::
1020
1021     POST http://<controllerIP>:8080/restconf/config/module1:foo
1022     Content-Type: applicaton/xml/
1023     <bar xmlns=“module1namespace”>
1024       …
1025     </bar>
1026
1027 **Example with mount point:**
1028
1029 ::
1030
1031     http://<controllerIP>:8080/restconf/config/module1:foo1/foo2/yang-ext:mount/module2:foo
1032     Content-Type: applicaton/xml
1033     <bar xmlns=“module2namespace”>
1034       …
1035     </bar>
1036
1037 POST /restconf/operations/<moduleName>:<rpcName>
1038 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1039
1040 -  Invokes RPC.
1041
1042 -  <moduleName>:<rpcName> - <moduleName> is the name of the module and
1043    <rpcName> is the name of the RPC in this module.
1044
1045 -  The Root element of the data sent to RPC must have the name “input”.
1046
1047 -  The result can be the status code or the retrieved data having the
1048    root element “output”.
1049
1050 | **Example:**
1051
1052 ::
1053
1054     POST http://<controllerIP>:8080/restconf/operations/module1:fooRpc
1055     Content-Type: applicaton/xml
1056     Accept: applicaton/xml
1057     <input>
1058       …
1059     </input>
1060
1061     The answer from the server could be:
1062     <output>
1063       …
1064     </output>
1065
1066 | **An example using a JSON payload:**
1067
1068 ::
1069
1070     POST http://localhost:8080/restconf/operations/toaster:make-toast
1071     Content-Type: application/yang.data+json
1072     {
1073       "input" :
1074       {
1075          "toaster:toasterDoneness" : "10",
1076          "toaster:toasterToastType":"wheat-bread"
1077       }
1078     }
1079
1080 .. note::
1081
1082     Even though this is a default for the toasterToastType value in the
1083     yang, you still need to define it.
1084
1085 DELETE /restconf/config/<identifier>
1086 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1087
1088 -  Removes the data node in the Config datastore and returns the state
1089    about success.
1090
1091 -  <identifier> points to a data node which must be removed.
1092
1093 More information is available in the `RESTCONF
1094 RFC <http://tools.ietf.org/html/draft-bierman-netconf-restconf-02>`__.
1095
1096 How RESTCONF works
1097 ~~~~~~~~~~~~~~~~~~
1098
1099 | RESTCONF uses these base classes:
1100
1101 InstanceIdentifier
1102     Represents the path in the data tree
1103
1104 ConsumerSession
1105     Used for invoking RPCs
1106
1107 DataBrokerService
1108     Offers manipulation with transactions and reading data from the
1109     datastores
1110
1111 SchemaContext
1112     Holds information about yang modules
1113
1114 MountService
1115     Returns MountInstance based on the InstanceIdentifier pointing to a
1116     mount point
1117
1118 MountInstace
1119     Contains the SchemaContext behind the mount point
1120
1121 DataSchemaNode
1122     Provides information about the schema node
1123
1124 SimpleNode
1125     Possesses the same name as the schema node, and contains the value
1126     representing the data node value
1127
1128 CompositeNode
1129     Can contain CompositeNode-s and SimpleNode-s
1130
1131 GET in action
1132 ~~~~~~~~~~~~~
1133
1134 Figure 1 shows the GET operation with URI restconf/config/M:N where M is
1135 the module name, and N is the node name.
1136
1137 .. figure:: ./images/Get.png
1138    :alt: Get
1139
1140    Get
1141
1142 1. The requested URI is translated into the InstanceIdentifier which
1143    points to the data node. During this translation, the DataSchemaNode
1144    that conforms to the data node is obtained. If the data node is
1145    behind the mount point, the MountInstance is obtained as well.
1146
1147 2. RESTCONF asks for the value of the data node from DataBrokerService
1148    based on InstanceIdentifier.
1149
1150 3. DataBrokerService returns CompositeNode as data.
1151
1152 4. StructuredDataToXmlProvider or StructuredDataToJsonProvider is called
1153    based on the **Accept** field from the http request. These two
1154    providers can transform CompositeNode regarding DataSchemaNode to an
1155    XML or JSON document.
1156
1157 5. XML or JSON is returned as the answer on the request from the client.
1158
1159 PUT in action
1160 ~~~~~~~~~~~~~
1161
1162 Figure 2 shows the PUT operation with the URI restconf/config/M:N where
1163 M is the module name, and N is the node name. Data is sent in the
1164 request either in the XML or JSON format.
1165
1166 .. figure:: ./images/Put.png
1167    :alt: Put
1168
1169    Put
1170
1171 1. Input data is sent to JsonToCompositeNodeProvider or
1172    XmlToCompositeNodeProvider. The correct provider is selected based on
1173    the Content-Type field from the http request. These two providers can
1174    transform input data to CompositeNode. However, this CompositeNode
1175    does not contain enough information for transactions.
1176
1177 2. The requested URI is translated into InstanceIdentifier which points
1178    to the data node. DataSchemaNode conforming to the data node is
1179    obtained during this translation. If the data node is behind the
1180    mount point, the MountInstance is obtained as well.
1181
1182 3. CompositeNode can be normalized by adding additional information from
1183    DataSchemaNode.
1184
1185 4. RESTCONF begins the transaction, and puts CompositeNode with
1186    InstanceIdentifier into it. The response on the request from the
1187    client is the status code which depends on the result from the
1188    transaction.
1189
1190 Something practical
1191 ~~~~~~~~~~~~~~~~~~~
1192
1193 1. Create a new flow on the switch openflow:1 in table 2.
1194
1195 | **HTTP request**
1196
1197 ::
1198
1199     Operation: POST
1200     URI: http://192.168.11.1:8080/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/2
1201     Content-Type: application/xml
1202
1203 ::
1204
1205     <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1206     <flow
1207         xmlns="urn:opendaylight:flow:inventory">
1208         <strict>false</strict>
1209         <instructions>
1210             <instruction>
1211                 <order>1</order>
1212                 <apply-actions>
1213                     <action>
1214                       <order>1</order>
1215                         <flood-all-action/>
1216                     </action>
1217                 </apply-actions>
1218             </instruction>
1219         </instructions>
1220         <table_id>2</table_id>
1221         <id>111</id>
1222         <cookie_mask>10</cookie_mask>
1223         <out_port>10</out_port>
1224         <installHw>false</installHw>
1225         <out_group>2</out_group>
1226         <match>
1227             <ethernet-match>
1228                 <ethernet-type>
1229                     <type>2048</type>
1230                 </ethernet-type>
1231             </ethernet-match>
1232             <ipv4-destination>10.0.0.1/24</ipv4-destination>
1233         </match>
1234         <hard-timeout>0</hard-timeout>
1235         <cookie>10</cookie>
1236         <idle-timeout>0</idle-timeout>
1237         <flow-name>FooXf22</flow-name>
1238         <priority>2</priority>
1239         <barrier>false</barrier>
1240     </flow>
1241
1242 | **HTTP response**
1243
1244 ::
1245
1246     Status: 204 No Content
1247
1248 1. Change *strict* to *true* in the previous flow.
1249
1250 | **HTTP request**
1251
1252 ::
1253
1254     Operation: PUT
1255     URI: http://192.168.11.1:8080/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/2/flow/111
1256     Content-Type: application/xml
1257
1258 ::
1259
1260     <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1261     <flow
1262         xmlns="urn:opendaylight:flow:inventory">
1263         <strict>true</strict>
1264         <instructions>
1265             <instruction>
1266                 <order>1</order>
1267                 <apply-actions>
1268                     <action>
1269                       <order>1</order>
1270                         <flood-all-action/>
1271                     </action>
1272                 </apply-actions>
1273             </instruction>
1274         </instructions>
1275         <table_id>2</table_id>
1276         <id>111</id>
1277         <cookie_mask>10</cookie_mask>
1278         <out_port>10</out_port>
1279         <installHw>false</installHw>
1280         <out_group>2</out_group>
1281         <match>
1282             <ethernet-match>
1283                 <ethernet-type>
1284                     <type>2048</type>
1285                 </ethernet-type>
1286             </ethernet-match>
1287             <ipv4-destination>10.0.0.1/24</ipv4-destination>
1288         </match>
1289         <hard-timeout>0</hard-timeout>
1290         <cookie>10</cookie>
1291         <idle-timeout>0</idle-timeout>
1292         <flow-name>FooXf22</flow-name>
1293         <priority>2</priority>
1294         <barrier>false</barrier>
1295     </flow>
1296
1297 | **HTTP response**
1298
1299 ::
1300
1301     Status: 200 OK
1302
1303 1. Show flow: check that *strict* is *true*.
1304
1305 | **HTTP request**
1306
1307 ::
1308
1309     Operation: GET
1310     URI: http://192.168.11.1:8080/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/2/flow/111
1311     Accept: application/xml
1312
1313 | **HTTP response**
1314
1315 ::
1316
1317     Status: 200 OK
1318
1319 ::
1320
1321     <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1322     <flow
1323         xmlns="urn:opendaylight:flow:inventory">
1324         <strict>true</strict>
1325         <instructions>
1326             <instruction>
1327                 <order>1</order>
1328                 <apply-actions>
1329                     <action>
1330                       <order>1</order>
1331                         <flood-all-action/>
1332                     </action>
1333                 </apply-actions>
1334             </instruction>
1335         </instructions>
1336         <table_id>2</table_id>
1337         <id>111</id>
1338         <cookie_mask>10</cookie_mask>
1339         <out_port>10</out_port>
1340         <installHw>false</installHw>
1341         <out_group>2</out_group>
1342         <match>
1343             <ethernet-match>
1344                 <ethernet-type>
1345                     <type>2048</type>
1346                 </ethernet-type>
1347             </ethernet-match>
1348             <ipv4-destination>10.0.0.1/24</ipv4-destination>
1349         </match>
1350         <hard-timeout>0</hard-timeout>
1351         <cookie>10</cookie>
1352         <idle-timeout>0</idle-timeout>
1353         <flow-name>FooXf22</flow-name>
1354         <priority>2</priority>
1355         <barrier>false</barrier>
1356     </flow>
1357
1358 1. Delete the flow created.
1359
1360 | **HTTP request**
1361
1362 ::
1363
1364     Operation: DELETE
1365     URI: http://192.168.11.1:8080/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/2/flow/111
1366
1367 | **HTTP response**
1368
1369 ::
1370
1371     Status: 200 OK
1372
1373 Websocket change event notification subscription tutorial
1374 ---------------------------------------------------------
1375
1376 Subscribing to data change notifications makes it possible to obtain
1377 notifications about data manipulation (insert, change, delete) which are
1378 done on any specified **path** of any specified **datastore** with
1379 specific **scope**. In following examples *{odlAddress}* is address of
1380 server where ODL is running and *{odlPort}* is port on which
1381 OpenDaylight is running.
1382
1383 Websocket notifications subscription process
1384 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1385
1386 In this section we will learn what steps need to be taken in order to
1387 successfully subscribe to data change event notifications.
1388
1389 Create stream
1390 ^^^^^^^^^^^^^
1391
1392 In order to use event notifications you first need to call RPC that
1393 creates notification stream that you can later listen to. You need to
1394 provide three parameters to this RPC:
1395
1396 -  **path**: data store path that you plan to listen to. You can
1397    register listener on containers, lists and leaves.
1398
1399 -  **datastore**: data store type. *OPERATIONAL* or *CONFIGURATION*.
1400
1401 -  **scope**: Represents scope of data change. Possible options are:
1402
1403    -  BASE: only changes directly to the data tree node specified in the
1404       path will be reported
1405
1406    -  ONE: changes to the node and to direct child nodes will be
1407       reported
1408
1409    -  SUBTREE: changes anywhere in the subtree starting at the node will
1410       be reported
1411
1412 The RPC to create the stream can be invoked via RESTCONF like this:
1413
1414 -  URI:
1415    http://{odlAddress}:{odlPort}/restconf/operations/sal-remote:create-data-change-event-subscription
1416
1417 -  HEADER: Content-Type=application/json
1418
1419 -  OPERATION: POST
1420
1421 -  DATA:
1422
1423    .. code:: json
1424
1425        {
1426            "input": {
1427                "path": "/toaster:toaster/toaster:toasterStatus",
1428                "sal-remote-augment:datastore": "OPERATIONAL",
1429                "sal-remote-augment:scope": "ONE"
1430            }
1431        }
1432
1433 The response should look something like this:
1434
1435 .. code:: json
1436
1437     {
1438         "output": {
1439             "stream-name": "data-change-event-subscription/toaster:toaster/toaster:toasterStatus/datastore=CONFIGURATION/scope=SUBTREE"
1440         }
1441     }
1442
1443 **stream-name** is important because you will need to use it when you
1444 subscribe to the stream in the next step.
1445
1446 .. note::
1447
1448     Internally, this will create a new listener for *stream-name* if it
1449     did not already exist.
1450
1451 Subscribe to stream
1452 ^^^^^^^^^^^^^^^^^^^
1453
1454 In order to subscribe to stream and obtain WebSocket location you need
1455 to call *GET* on your stream path. The URI should generally be
1456 http://{odlAddress}:{odlPort}/restconf/streams/stream/{streamName},
1457 where *{streamName}* is the *stream-name* parameter contained in
1458 response from *create-data-change-event-subscription* RPC from the
1459 previous step.
1460
1461 -  URI:
1462    http://{odlAddress}:{odlPort}/restconf/streams/stream/data-change-event-subscription/toaster:toaster/datastore=CONFIGURATION/scope=SUBTREE
1463
1464 -  OPERATION: GET
1465
1466 The subscription call may be modified with the following query parameters defined in the RESTCONF RFC:
1467
1468 -  `filter <https://tools.ietf.org/html/draft-ietf-netconf-restconf-05#section-4.8.6>`__
1469
1470 -  `start-time <https://tools.ietf.org/html/draft-ietf-netconf-restconf-05#section-4.8.7>`__
1471
1472 -  `end-time <https://tools.ietf.org/html/draft-ietf-netconf-restconf-05#section-4.8.8>`__
1473
1474 In addition, the following ODL extension query parameter is supported:
1475
1476 :odl-leaf-nodes-only:
1477   If this parameter is set to "true", create and update notifications will only
1478   contain the leaf nodes modified instead of the entire subscription subtree.
1479   This can help in reducing the size of the notifications.
1480
1481 The expected response status is 200 OK and response body should be
1482 empty. You will get your WebSocket location from **Location** header of
1483 response. For example in our particular toaster example location header
1484 would have this value:
1485 *ws://{odlAddress}:8185/toaster:toaster/datastore=CONFIGURATION/scope=SUBTREE*
1486
1487 .. note::
1488
1489     During this phase there is an internal check for to see if a
1490     listener for the *stream-name* from the URI exists. If not, new a
1491     new listener is registered with the DOM data broker.
1492
1493 Receive notifications
1494 ^^^^^^^^^^^^^^^^^^^^^
1495
1496 You should now have a data change notification stream created and have
1497 location of a WebSocket. You can use this WebSocket to listen to data
1498 change notifications. To listen to notifications you can use a
1499 JavaScript client or if you are using chrome browser you can use the
1500 `Simple WebSocket
1501 Client <https://chrome.google.com/webstore/detail/simple-websocket-client/pfdhoblngboilpfeibdedpjgfnlcodoo>`__.
1502
1503 Also, for testing purposes, there is simple Java application named
1504 WebSocketClient. The application is placed in the
1505 *-sal-rest-connector-classes.class* project. It accepts a WebSocket URI
1506 as and input parameter. After starting the utility (WebSocketClient
1507 class directly in Eclipse/InteliJ Idea) received notifications should be
1508 displayed in console.
1509
1510 Notifications are always in XML format and look like this:
1511
1512 .. code:: xml
1513
1514     <notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
1515         <eventTime>2014-09-11T09:58:23+02:00</eventTime>
1516         <data-changed-notification xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote">
1517             <data-change-event>
1518                 <path xmlns:meae="http://netconfcentral.org/ns/toaster">/meae:toaster</path>
1519                 <operation>updated</operation>
1520                 <data>
1521                    <!-- updated data -->
1522                 </data>
1523             </data-change-event>
1524         </data-changed-notification>
1525     </notification>
1526
1527 Example use case
1528 ~~~~~~~~~~~~~~~~
1529
1530 The typical use case is listening to data change events to update web
1531 page data in real-time. In this tutorial we will be using toaster as the
1532 base.
1533
1534 When you call *make-toast* RPC, it sets *toasterStatus* to "down" to
1535 reflect that the toaster is busy making toast. When it finishes,
1536 *toasterStatus* is set to "up" again. We will listen to this toaster
1537 status changes in data store and will reflect it on our web page in
1538 real-time thanks to WebSocket data change notification.
1539
1540 Simple javascript client implementation
1541 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1542
1543 We will create simple JavaScript web application that will listen
1544 updates on *toasterStatus* leaf and update some element of our web page
1545 according to new toaster status state.
1546
1547 Create stream
1548 ^^^^^^^^^^^^^
1549
1550 First you need to create stream that you are planing to subscribe to.
1551 This can be achieved by invoking "create-data-change-event-subscription"
1552 RPC on RESTCONF via AJAX request. You need to provide data store
1553 **path** that you plan to listen on, **data store type** and **scope**.
1554 If the request is successful you can extract the **stream-name** from
1555 the response and use that to subscribe to the newly created stream. The
1556 *{username}* and *{password}* fields represent your credentials that you
1557 use to connect to OpenDaylight via RESTCONF:
1558
1559 .. note::
1560
1561     The default user name and password are "admin".
1562
1563 .. code:: javascript
1564
1565     function createStream() {
1566         $.ajax(
1567             {
1568                 url: 'http://{odlAddress}:{odlPort}/restconf/operations/sal-remote:create-data-change-event-subscription',
1569                 type: 'POST',
1570                 headers: {
1571                   'Authorization': 'Basic ' + btoa('{username}:{password}'),
1572                   'Content-Type': 'application/json'
1573                 },
1574                 data: JSON.stringify(
1575                     {
1576                         'input': {
1577                             'path': '/toaster:toaster/toaster:toasterStatus',
1578                             'sal-remote-augment:datastore': 'OPERATIONAL',
1579                             'sal-remote-augment:scope': 'ONE'
1580                         }
1581                     }
1582                 )
1583             }).done(function (data) {
1584                 // this function will be called when ajax call is executed successfully
1585                 subscribeToStream(data.output['stream-name']);
1586             }).fail(function (data) {
1587                 // this function will be called when ajax call fails
1588                 console.log("Create stream call unsuccessful");
1589             })
1590     }
1591
1592 Subscribe to stream
1593 ^^^^^^^^^^^^^^^^^^^
1594
1595 The Next step is to subscribe to the stream. To subscribe to the stream
1596 you need to call *GET* on
1597 *http://{odlAddress}:{odlPort}/restconf/streams/stream/{stream-name}*.
1598 If the call is successful, you get WebSocket address for this stream in
1599 **Location** parameter inside response header. You can get response
1600 header by calling *getResponseHeader(\ *Location*)* on HttpRequest
1601 object inside *done()* function call:
1602
1603 .. code:: javascript
1604
1605     function subscribeToStream(streamName) {
1606         $.ajax(
1607             {
1608                 url: 'http://{odlAddress}:{odlPort}/restconf/streams/stream/' + streamName;
1609                 type: 'GET',
1610                 headers: {
1611                   'Authorization': 'Basic ' + btoa('{username}:{password}'),
1612                 }
1613             }
1614         ).done(function (data, textStatus, httpReq) {
1615             // we need function that has http request object parameter in order to access response headers.
1616             listenToNotifications(httpReq.getResponseHeader('Location'));
1617         }).fail(function (data) {
1618             console.log("Subscribe to stream call unsuccessful");
1619         });
1620     }
1621
1622 Receive notifications
1623 ^^^^^^^^^^^^^^^^^^^^^
1624
1625 Once you got WebSocket server location you can now connect to it and
1626 start receiving data change events. You need to define functions that
1627 will handle events on WebSocket. In order to process incoming events
1628 from OpenDaylight you need to provide a function that will handle
1629 *onmessage* events. The function must have one parameter that represents
1630 the received event object. The event data will be stored in
1631 *event.data*. The data will be in an XML format that you can then easily
1632 parse using jQuery.
1633
1634 .. code:: javascript
1635
1636     function listenToNotifications(socketLocation) {
1637         try {
1638             var notificatinSocket = new WebSocket(socketLocation);
1639
1640             notificatinSocket.onmessage = function (event) {
1641                 // we process our received event here
1642                 console.log('Received toaster data change event.');
1643                 $($.parseXML(event.data)).find('data-change-event').each(
1644                     function (index) {
1645                         var operation = $(this).find('operation').text();
1646                         if (operation == 'updated') {
1647                             // toaster status was updated so we call function that gets the value of toasterStatus leaf
1648                             updateToasterStatus();
1649                             return false;
1650                         }
1651                     }
1652                 );
1653             }
1654             notificatinSocket.onerror = function (error) {
1655                 console.log("Socket error: " + error);
1656             }
1657             notificatinSocket.onopen = function (event) {
1658                 console.log("Socket connection opened.");
1659             }
1660             notificatinSocket.onclose = function (event) {
1661                 console.log("Socket connection closed.");
1662             }
1663             // if there is a problem on socket creation we get exception (i.e. when socket address is incorrect)
1664         } catch(e) {
1665             alert("Error when creating WebSocket" + e );
1666         }
1667     }
1668
1669 The *updateToasterStatus()* function represents function that calls
1670 *GET* on the path that was modified and sets toaster status in some web
1671 page element according to received data. After the WebSocket connection
1672 has been established you can test events by calling make-toast RPC via
1673 RESTCONF.
1674
1675 .. note::
1676
1677     for more information about WebSockets in JavaScript visit `Writing
1678     WebSocket client
1679     applications <https://developer.mozilla.org/en-US/docs/WebSockets/Writing_WebSocket_client_applications>`__
1680
1681 .. _config_subsystem:
1682
1683 Config Subsystem
1684 ----------------
1685
1686 Overview
1687 ~~~~~~~~
1688
1689 The Controller configuration operation has three stages:
1690
1691 -  First, a Proposed configuration is created. Its target is to replace
1692    the old configuration.
1693
1694 -  Second, the Proposed configuration is validated, and then committed.
1695    If it passes validation successfully, the Proposed configuration
1696    state will be changed to Validated.
1697
1698 -  Finally, a Validated configuration can be Committed, and the affected
1699    modules can be reconfigured.
1700
1701 In fact, each configuration operation is wrapped in a transaction. Once
1702 a transaction is created, it can be configured, that is to say, a user
1703 can abort the transaction during this stage. After the transaction
1704 configuration is done, it is committed to the validation stage. In this
1705 stage, the validation procedures are invoked. If one or more validations
1706 fail, the transaction can be reconfigured. Upon success, the second
1707 phase commit is invoked. If this commit is successful, the transaction
1708 enters the last stage, committed. After that, the desired modules are
1709 reconfigured. If the second phase commit fails, it means that the
1710 transaction is unhealthy - basically, a new configuration instance
1711 creation failed, and the application can be in an inconsistent state.
1712
1713 .. figure:: ./images/configuration.jpg
1714    :alt: Configuration states
1715
1716    Configuration states
1717
1718 .. figure:: ./images/Transaction.jpg
1719    :alt: Transaction states
1720
1721    Transaction states
1722
1723 Validation
1724 ~~~~~~~~~~
1725
1726 To secure the consistency and safety of the new configuration and to
1727 avoid conflicts, the configuration validation process is necessary.
1728 Usually, validation checks the input parameters of a new configuration,
1729 and mostly verifies module-specific relationships. The validation
1730 procedure results in a decision on whether the proposed configuration is
1731 healthy.
1732
1733 Dependency resolver
1734 ~~~~~~~~~~~~~~~~~~~
1735
1736 Since there can be dependencies between modules, a change in a module
1737 configuration can affect the state of other modules. Therefore, we need
1738 to verify whether dependencies on other modules can be resolved. The
1739 Dependency Resolver acts in a manner similar to dependency injectors.
1740 Basically, a dependency tree is built.
1741
1742 APIs and SPIs
1743 ~~~~~~~~~~~~~
1744
1745 This section describes configuration system APIs and SPIs.
1746
1747 SPIs
1748 ^^^^
1749
1750 **Module** org.opendaylight.controller.config.spi. Module is the common
1751 interface for all modules: every module must implement it. The module is
1752 designated to hold configuration attributes, validate them, and create
1753 instances of service based on the attributes. This instance must
1754 implement the AutoCloseable interface, owing to resources clean up. If
1755 the module was created from an already running instance, it contains an
1756 old instance of the module. A module can implement multiple services. If
1757 the module depends on other modules, setters need to be annotated with
1758 @RequireInterface.
1759
1760 **Module creation**
1761
1762 1. The module needs to be configured, set with all required attributes.
1763
1764 2. The module is then moved to the commit stage for validation. If the
1765    validation fails, the module attributes can be reconfigured.
1766    Otherwise, a new instance is either created, or an old instance is
1767    reconfigured. A module instance is identified by ModuleIdentifier,
1768    consisting of the factory name and instance name.
1769
1770 | **ModuleFactory** org.opendaylight.controller.config.spi. The
1771   ModuleFactory interface must be implemented by each module factory.
1772 | A module factory can create a new module instance in two ways:
1773
1774 -  From an existing module instance
1775
1776 -  | An entirely new instance
1777    | ModuleFactory can also return default modules, useful for
1778      populating registry with already existing configurations. A module
1779      factory implementation must have a globally unique name.
1780
1781 APIs
1782 ^^^^
1783
1784 +--------------------------------------+--------------------------------------+
1785 | ConfigRegistry                       | Represents functionality provided by |
1786 |                                      | a configuration transaction (create, |
1787 |                                      | destroy module, validate, or abort   |
1788 |                                      | transaction).                        |
1789 +--------------------------------------+--------------------------------------+
1790 | ConfigTransactionController          | Represents functionality for         |
1791 |                                      | manipulating with configuration      |
1792 |                                      | transactions (begin, commit config). |
1793 +--------------------------------------+--------------------------------------+
1794 | RuntimeBeanRegistratorAwareConfiBean | The module implementing this         |
1795 |                                      | interface will receive               |
1796 |                                      | RuntimeBeanRegistrator before        |
1797 |                                      | getInstance is invoked.              |
1798 +--------------------------------------+--------------------------------------+
1799
1800 Runtime APIs
1801 ^^^^^^^^^^^^
1802
1803 +--------------------------------------+--------------------------------------+
1804 | RuntimeBean                          | Common interface for all runtime     |
1805 |                                      | beans                                |
1806 +--------------------------------------+--------------------------------------+
1807 | RootRuntimeBeanRegistrator           | Represents functionality for root    |
1808 |                                      | runtime bean registration, which     |
1809 |                                      | subsequently allows hierarchical     |
1810 |                                      | registrations                        |
1811 +--------------------------------------+--------------------------------------+
1812 | HierarchicalRuntimeBeanRegistration  | Represents functionality for runtime |
1813 |                                      | bean registration and                |
1814 |                                      | unreregistration from hierarchy      |
1815 +--------------------------------------+--------------------------------------+
1816
1817 JMX APIs
1818 ^^^^^^^^
1819
1820 | JMX API is purposed as a transition between the Client API and the JMX
1821   platform.
1822
1823 +--------------------------------------+--------------------------------------+
1824 | ConfigTransactionControllerMXBean    | Extends ConfigTransactionController, |
1825 |                                      | executed by Jolokia clients on       |
1826 |                                      | configuration transaction.           |
1827 +--------------------------------------+--------------------------------------+
1828 | ConfigRegistryMXBean                 | Represents entry point of            |
1829 |                                      | configuration management for         |
1830 |                                      | MXBeans.                             |
1831 +--------------------------------------+--------------------------------------+
1832 | Object names                         | Object Name is the pattern used in   |
1833 |                                      | JMX to locate JMX beans. It consists |
1834 |                                      | of domain and key properties (at     |
1835 |                                      | least one key-value pair). Domain is |
1836 |                                      | defined as                           |
1837 |                                      | "org.opendaylight.controller". The   |
1838 |                                      | only mandatory property is "type".   |
1839 +--------------------------------------+--------------------------------------+
1840
1841 Use case scenarios
1842 ^^^^^^^^^^^^^^^^^^
1843
1844 | A few samples of successful and unsuccessful transaction scenarios
1845   follow:
1846
1847 **Successful commit scenario**
1848
1849 1.  The user creates a transaction calling creteTransaction() method on
1850     ConfigRegistry.
1851
1852 2.  ConfigRegisty creates a transaction controller, and registers the
1853     transaction as a new bean.
1854
1855 3.  Runtime configurations are copied to the transaction. The user can
1856     create modules and set their attributes.
1857
1858 4.  The configuration transaction is to be committed.
1859
1860 5.  The validation process is performed.
1861
1862 6.  After successful validation, the second phase commit begins.
1863
1864 7.  Modules proposed to be destroyed are destroyed, and their service
1865     instances are closed.
1866
1867 8.  Runtime beans are set to registrator.
1868
1869 9.  The transaction controller invokes the method getInstance on each
1870     module.
1871
1872 10. The transaction is committed, and resources are either closed or
1873     released.
1874
1875 | **Validation failure scenario**
1876 | The transaction is the same as the previous case until the validation
1877   process.
1878
1879 1. If validation fails, (that is to day, illegal input attributes values
1880    or dependency resolver failure), the validationException is thrown
1881    and exposed to the user.
1882
1883 2. The user can decide to reconfigure the transaction and commit again,
1884    or abort the current transaction.
1885
1886 3. On aborted transactions, TransactionController and JMXRegistrator are
1887    properly closed.
1888
1889 4. Unregistration event is sent to ConfigRegistry.
1890
1891 Default module instances
1892 ^^^^^^^^^^^^^^^^^^^^^^^^
1893
1894 The configuration subsystem provides a way for modules to create default
1895 instances. A default instance is an instance of a module, that is
1896 created at the module bundle start-up (module becomes visible for
1897 configuration subsystem, for example, its bundle is activated in the
1898 OSGi environment). By default, no default instances are produced.
1899
1900 The default instance does not differ from instances created later in the
1901 module life-cycle. The only difference is that the configuration for the
1902 default instance cannot be provided by the configuration subsystem. The
1903 module has to acquire the configuration for these instances on its own.
1904 It can be acquired from, for example, environment variables. After the
1905 creation of a default instance, it acts as a regular instance and fully
1906 participates in the configuration subsystem (It can be reconfigured or
1907 deleted in following transactions.).

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.