Remove JournalWriter.getLastEntry()
[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:`MD-SAL <mdsal_dev_guide>` - messaging and data storage
32    functionality for data, notifications and RPCs modeled by application
33    developers. MD-SAL uses YANG as the modeling for both interface and
34    data definitions, and provides a messaging and data-centric runtime
35    for such services based on YANG modeling.
36
37 -  **MD-SAL Clustering** - enables cluster support for core MD-SAL
38    functionality and provides location-transparent accesss to
39    YANG-modeled data.
40
41 The OpenDaylight Controller supports external access to applications and
42 data using following model-driven protocols:
43
44 -  **NETCONF** - XML-based RPC protocol, which provides abilities for
45    client to invoke YANG-modeled RPCs, receive notifications and to
46    read, modify and manipulate YANG modeled data.
47
48 -  **RESTCONF** - HTTP-based protocol, which provides REST-like APIs to
49    manipulate YANG modeled data and invoke YANG modeled RPCs, using XML
50    or JSON as payload format.
51
52 .. _mdsal_dev_guide:
53
54 MD-SAL Overview
55 ---------------
56
57 The Model-Driven Service Adaptation Layer (MD-SAL) is message-bus
58 inspired extensible middleware component that provides messaging and
59 data storage functionality based on data and interface models defined by
60 application developers (i.e. user-defined models).
61
62 The MD-SAL:
63
64 -  Defines a **common-layer, concepts, data model building blocks and
65    messaging patterns** and provides infrastructure / framework for
66    applications and inter-application communication.
67
68 -  Provide common support for user-defined transport and payload
69    formats, including payload serialization and adaptation (e.g. binary,
70    XML or JSON).
71
72 The MD-SAL uses **YANG** as the modeling language for both interface and
73 data definitions, and provides a messaging and data-centric runtime for
74 such services based on YANG modeling.
75
76 | The MD-SAL provides two different API types (flavours):
77
78 -  **MD-SAL Binding:** MD-SAL APIs which extensively uses APIs and
79    classes generated from YANG models, which provides compile-time
80    safety.
81
82 -  **MD-SAL DOM:** (Document Object Model) APIs which uses DOM-like
83    representation of data, which makes them more powerful, but provides
84    less compile-time safety.
85
86 .. note::
87
88     Model-driven nature of the MD-SAL and **DOM**-based APIs allows for
89     behind-the-scene API and payload type mediation and transformation
90     to facilitate seamless communication between applications - this
91     enables for other components and applications to provide connectors
92     / expose different set of APIs and derive most of its functionality
93     purely from models, which all existing code can benefit from without
94     modification. For example **RESTCONF Connector** is an application
95     built on top of MD-SAL and exposes YANG-modeled application APIs
96     transparently via HTTP and adds support for XML and JSON payload
97     type.
98
99 Basic concepts
100 ~~~~~~~~~~~~~~
101
102 Basic concepts are building blocks which are used by applications, and
103 from which MD-SAL uses to define messaging patterns and to provide
104 services and behavior based on developer-supplied YANG models.
105
106 Data Tree
107     All state-related data are modeled and represented as data tree,
108     with possibility to address any element / subtree
109
110     -  **Operational Data Tree** - Reported state of the system,
111        published by the providers using MD-SAL. Represents a feedback
112        loop for applications to observe state of the network / system.
113
114     -  **Configuration Data Tree** - Intended state of the system or
115        network, populated by consumers, which expresses their intention.
116
117 Instance Identifier
118     Unique identifier of node / subtree in data tree, which provides
119     unambiguous information, how to reference and retrieve node /
120     subtree from conceptual data trees.
121
122 Notification
123     Asynchronous transient event which may be consumed by subscribers
124     and they may act upon it
125
126 RPC
127     asynchronous request-reply message pair, when request is triggered
128     by consumer, send to the provider, which in future replies with
129     reply message.
130
131     .. note::
132
133         In MD-SAL terminology, the term *RPC* is used to define the
134         input and output for a procedure (function) that is to be
135         provided by a provider, and mediated by the MD-SAL, that means
136         it may not result in remote call.
137
138 Messaging Patterns
139 ~~~~~~~~~~~~~~~~~~
140
141 MD-SAL provides several messaging patterns using broker derived from
142 basic concepts, which are intended to transfer YANG modeled data between
143 applications to provide data-centric integration between applications
144 instead of API-centric integration.
145
146 -  **Unicast communication**
147
148    -  **Remote Procedure Calls** - unicast between consumer and
149       provider, where consumer sends **request** message to provider,
150       which asynchronously responds with **reply** message
151
152 -  **Publish / Subscribe**
153
154    -  **Notifications** - multicast transient message which is published
155       by provider and is delivered to subscribers
156
157    -  **Data Change Events** - multicast asynchronous event, which is
158       sent by data broker if there is change in conceptual data tree,
159       and is delivered to subscribers
160
161 -  **Transactional access to Data Tree**
162
163    -  Transactional **reads** from conceptual **data tree** - read-only
164       transactions with isolation from other running transactions.
165
166    -  Transactional **modification** to conceptual **data tree** - write
167       transactions with isolation from other running transactions.
168
169    -  **Transaction chaining**
170
171 MD-SAL Data Transactions
172 ------------------------
173
174 MD-SAL **Data Broker** provides transactional access to conceptual
175 **data trees** representing configuration and operational state.
176
177 .. note::
178
179     **Data tree** usually represents state of the modeled data, usually
180     this is state of controller, applications and also external systems
181     (network devices).
182
183 **Transactions** provide :ref:`stable and isolated
184 view <transaction_isolation>` from other currently running
185 transactions. The state of running transaction and underlying data tree
186 is not affected by other concurrently running transactions.
187
188 Write-Only
189     Transaction provides only modification capabilities, but does not
190     provide read capabilities. Write-only transaction is allocated using
191     ``newWriteOnlyTransaction()``.
192
193     .. note::
194
195         This allows less state tracking for write-only transactions and
196         allows MD-SAL Clustering to optimize internal representation of
197         transaction in cluster.
198
199 Read-Write
200     Transaction provides both read and write capabilities. It is
201     allocated using ``newReadWriteTransaction()``.
202
203 Read-Only
204     Transaction provides stable read-only view based on current data
205     tree. Read-only view is not affected by any subsequent write
206     transactions. Read-only transaction is allocated using
207     ``newReadOnlyTransaction()``.
208
209     .. note::
210
211         If an application needs to observe changes itself in data tree,
212         it should use **data tree listeners** instead of read-only
213         transactions and polling data tree.
214
215 Transactions may be allocated using the **data broker** itself or using
216 **transaction chain**. In the case of **transaction chain**, the new
217 allocated transaction is not based on current state of data tree, but
218 rather on state introduced by previous transaction from the same chain,
219 even if the commit for previous transaction has not yet occurred (but
220 transaction was submitted).
221
222 Write-Only & Read-Write Transaction
223 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
224
225 Write-Only and Read-Write transactions provide modification capabilities
226 for the conceptual data trees.
227
228 1. application allocates new transactions using
229    ``newWriteOnlyTransaction()`` or ``newReadWriteTransaction()``.
230
231 2. application `modifies data tree <#_modification_of_data_tree>`__
232    using ``put``, ``merge`` and/or ``delete``.
233
234 3. application finishes transaction using
235    ``submit()``, which :ref:`seals transaction
236    and submits <submitting_transaction>` it to be processed.
237
238 4. application observes the result of the transaction commit using
239    either blocking or asynchronous calls.
240
241 The **initial state** of the write transaction is a **stable snapshot**
242 of the current data tree state captured when transaction was created and
243 it’s state and underlying data tree are not affected by other
244 concurrently running transactions.
245
246 Write transactions are **isolated** from other concurrent write
247 transactions. All :ref:`writes are local <transaction_local_state>`
248 to the transaction and represents only a **proposal of state change**
249 for data tree and **are not visible** to any other concurrently running
250 transactions (including read-only transactions).
251
252 The transaction :ref:`commit may fail <commit_failure_scenarios>` due
253 to failing verification of data or concurrent transaction modifying and
254 affected data in an incompatible way.
255
256 Modification of Data Tree
257 ^^^^^^^^^^^^^^^^^^^^^^^^^
258
259 Write-only and read-write transaction provides following methods to
260 modify data tree:
261
262 put
263     .. code:: java
264
265         <T> void put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data);
266
267     Stores a piece of data at a specified path. This acts as an **add /
268     replace** operation, which is to say that whole subtree will be
269     replaced by the specified data.
270
271 merge
272     .. code:: java
273
274         <T> void merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data);
275
276     Merges a piece of data with the existing data at a specified path.
277     Any **pre-existing data** which are not explicitly overwritten
278     **will be preserved**. This means that if you store a container, its
279     child subtrees will be merged.
280
281 delete
282     .. code:: java
283
284         void delete(LogicalDatastoreType store, InstanceIdentifier<?> path);
285
286     Removes a whole subtree from a specified path.
287
288 .. _submitting_transaction:
289
290 Submitting transaction
291 ^^^^^^^^^^^^^^^^^^^^^^
292
293 Transaction is submitted to be processed and committed using following
294 method:
295
296 .. code:: java
297
298     CheckedFuture<Void,TransactionCommitFailedException> submit();
299
300 Applications publish the changes proposed in the transaction by calling
301 ``submit()`` on the transaction. This **seals the transaction**
302 (preventing any further writes using this transaction) and submits it to
303 be processed and applied to global conceptual data tree. The
304 ``submit()`` method does not block, but rather returns
305 ``ListenableFuture``, which will complete successfully once processing
306 of transaction is finished and changes are applied to data tree. If
307 **commit** of data failed, the future will fail with
308 ``TransactionFailedException``.
309
310 Application may listen on commit state asynchronously using
311 ``ListenableFuture``.
312
313 .. code:: java
314
315     Futures.addCallback( writeTx.submit(), new FutureCallback<Void>() {
316             public void onSuccess( Void result ) {
317                 LOG.debug("Transaction committed successfully.");
318             }
319
320             public void onFailure( Throwable t ) {
321                 LOG.error("Commit failed.",e);
322             }
323         });
324
325 -  Submits ``writeTx`` and registers application provided
326    ``FutureCallback`` on returned future.
327
328 -  Invoked when future completed successfully - transaction ``writeTx``
329    was successfully committed to data tree.
330
331 -  Invoked when future failed - commit of transaction ``writeTx``
332    failed. Supplied exception provides additional details and cause of
333    failure.
334
335 If application need to block till commit is finished it may use
336 ``checkedGet()`` to wait till commit is finished.
337
338 .. code:: java
339
340     try {
341         writeTx.submit().checkedGet();
342     } catch (TransactionCommitFailedException e) {
343         LOG.error("Commit failed.",e);
344     }
345
346 -  Submits ``writeTx`` and blocks till commit of ``writeTx`` is
347    finished. If commit fails ``TransactionCommitFailedException`` will
348    be thrown.
349
350 -  Catches ``TransactionCommitFailedException`` and logs it.
351
352 .. _transaction_local_state:
353
354 Transaction local state
355 ^^^^^^^^^^^^^^^^^^^^^^^
356
357 Read-Write transactions maintain transaction-local state, which renders
358 all modifications as if they happened, but this is only local to
359 transaction.
360
361 Reads from the transaction returns data as if the previous modifications
362 in transaction already happened.
363
364 Let assume initial state of data tree for ``PATH`` is ``A``.
365
366 .. code:: java
367
368     ReadWriteTransaction rwTx = broker.newReadWriteTransaction();
369
370     rwRx.read(OPERATIONAL,PATH).get();
371     rwRx.put(OPERATIONAL,PATH,B);
372     rwRx.read(OPERATIONAL,PATH).get();
373     rwRx.put(OPERATIONAL,PATH,C);
374     rwRx.read(OPERATIONAL,PATH).get();
375
376 -  Allocates new ``ReadWriteTransaction``.
377
378 -  Read from ``rwTx`` will return value ``A`` for ``PATH``.
379
380 -  Writes value ``B`` to ``PATH`` using ``rwTx``.
381
382 -  Read will return value ``B`` for ``PATH``, since previous write
383    occurred in same transaction.
384
385 -  Writes value ``C`` to ``PATH`` using ``rwTx``.
386
387 -  Read will return value ``C`` for ``PATH``, since previous write
388    occurred in same transaction.
389
390 .. _transaction_isolation:
391
392 Transaction isolation
393 ~~~~~~~~~~~~~~~~~~~~~
394
395 Running (not submitted) transactions are isolated from each other and
396 changes done in one transaction are not observable in other currently
397 running transaction.
398
399 Lets assume initial state of data tree for ``PATH`` is ``A``.
400
401 .. code:: java
402
403     ReadOnlyTransaction txRead = broker.newReadOnlyTransaction();
404     ReadWriteTransaction txWrite = broker.newReadWriteTransaction();
405
406     txRead.read(OPERATIONAL,PATH).get();
407     txWrite.put(OPERATIONAL,PATH,B);
408     txWrite.read(OPERATIONAL,PATH).get();
409     txWrite.submit().get();
410     txRead.read(OPERATIONAL,PATH).get();
411     txAfterCommit = broker.newReadOnlyTransaction();
412     txAfterCommit.read(OPERATIONAL,PATH).get();
413
414 -  Allocates read only transaction, which is based on data tree which
415    contains value ``A`` for ``PATH``.
416
417 -  Allocates read write transaction, which is based on data tree which
418    contains value ``A`` for ``PATH``.
419
420 -  Read from read-only transaction returns value ``A`` for ``PATH``.
421
422 -  Data tree is updated using read-write transaction, ``PATH`` contains
423    ``B``. Change is not public and only local to transaction.
424
425 -  Read from read-write transaction returns value ``B`` for ``PATH``.
426
427 -  Submits changes in read-write transaction to be committed to data
428    tree. Once commit will finish, changes will be published and ``PATH``
429    will be updated for value ``B``. Previously allocated transactions
430    are not affected by this change.
431
432 -  Read from previously allocated read-only transaction still returns
433    value ``A`` for ``PATH``, since it provides stable and isolated view.
434
435 -  Allocates new read-only transaction, which is based on data tree,
436    which contains value ``B`` for ``PATH``.
437
438 -  Read from new read-only transaction return value ``B`` for ``PATH``
439    since read-write transaction was committed.
440
441 .. note::
442
443     Examples contain blocking calls on future only to illustrate that
444     action happened after other asynchronous action. The use of the
445     blocking call ``ListenableFuture#get()`` is discouraged for most
446     use-cases and you should use
447     ``Futures#addCallback(ListenableFuture, FutureCallback)`` to listen
448     asynchronously for result.
449
450 .. _commit_failure_scenarios:
451
452 Commit failure scenarios
453 ~~~~~~~~~~~~~~~~~~~~~~~~
454
455 A transaction commit may fail because of following reasons:
456
457 Optimistic Lock Failure
458     Another transaction finished earlier and **modified the same node in
459     a non-compatible way**. The commit (and the returned future) will
460     fail with an ``OptimisticLockFailedException``.
461
462     It is the responsibility of the caller to create a new transaction
463     and submit the same modification again in order to update data tree.
464
465     .. warning::
466
467         ``OptimisticLockFailedException`` usually exposes **multiple
468         writers** to the same data subtree, which may conflict on same
469         resources.
470
471         In most cases, retrying may result in a probability of success.
472
473         There are scenarios, albeit unusual, where any number of retries
474         will not succeed. Therefore it is strongly recommended to limit
475         the number of retries (2 or 3) to avoid an endless loop.
476
477 Data Validation
478     The data change introduced by this transaction **did not pass
479     validation** by commit handlers or data was incorrectly structured.
480     The returned future will fail with a
481     ``DataValidationFailedException``. User **should not retry** to
482     create new transaction with same data, since it probably will fail
483     again.
484
485 Example conflict of two transactions
486 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
487
488 This example illustrates two concurrent transactions, which derived from
489 same initial state of data tree and proposes conflicting modifications.
490
491 .. code:: java
492
493     WriteTransaction txA = broker.newWriteTransaction();
494     WriteTransaction txB = broker.newWriteTransaction();
495
496     txA.put(CONFIGURATION, PATH, A);
497     txB.put(CONFIGURATION, PATH, B);
498
499     CheckedFuture<?,?> futureA = txA.submit();
500     CheckedFuture<?,?> futureB = txB.submit();
501
502 -  Updates ``PATH`` to value ``A`` using ``txA``
503
504 -  Updates ``PATH`` to value ``B`` using ``txB``
505
506 -  Seals & submits ``txA``. The commit will be processed asynchronously
507    and data tree will be updated to contain value ``A`` for ``PATH``.
508    The returned ‘ListenableFuture’ will complete successfully once state
509    is applied to data tree.
510
511 -  Seals & submits ``txB``. Commit of ``txB`` will fail, because
512    previous transaction also modified path in a concurrent way. The
513    state introduced by ``txB`` will not be applied. The returned
514    ``ListenableFuture`` will fail with ``OptimisticLockFailedException``
515    exception, which indicates that concurrent transaction prevented the
516    submitted transaction from being applied.
517
518 Example asynchronous retry-loop
519 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
520
521 .. code:: java
522
523     private void doWrite( final int tries ) {
524         WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
525
526         MyDataObject data = ...;
527         InstanceIdentifier<MyDataObject> path = ...;
528         writeTx.put( LogicalDatastoreType.OPERATIONAL, path, data );
529
530         Futures.addCallback( writeTx.submit(), new FutureCallback<Void>() {
531             public void onSuccess( Void result ) {
532                 // succeeded
533             }
534
535             public void onFailure( Throwable t ) {
536                 if( t instanceof OptimisticLockFailedException && (( tries - 1 ) > 0)) {
537                     doWrite( tries - 1 );
538                 }
539             }
540           });
541     }
542     ...
543     doWrite( 2 );
544
545 Concurrent change compatibility
546 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
547
548 There are several sets of changes which could be considered incompatible
549 between two transactions which are derived from same initial state.
550 Rules for conflict detection applies recursively for each subtree level.
551
552 Following table shows state changes and failures between two concurrent
553 transactions, which are based on same initial state, ``tx1`` is
554 submitted before ``tx2``.
555
556 INFO: Following tables stores numeric values and shows data using
557 ``toString()`` to simplify examples.
558
559 +--------------------+--------------------+--------------------+--------------------+
560 | Initial state      | tx1                | tx2                | Observable Result  |
561 +====================+====================+====================+====================+
562 | Empty              | ``put(A,1)``       | ``put(A,2)``       | ``tx2`` will fail, |
563 |                    |                    |                    | value of ``A`` is  |
564 |                    |                    |                    | ``1``              |
565 +--------------------+--------------------+--------------------+--------------------+
566 | Empty              | ``put(A,1)``       | ``merge(A,2)``     | value of ``A`` is  |
567 |                    |                    |                    | ``2``              |
568 +--------------------+--------------------+--------------------+--------------------+
569 | Empty              | ``merge(A,1)``     | ``put(A,2)``       | ``tx2`` will fail, |
570 |                    |                    |                    | value of ``A`` is  |
571 |                    |                    |                    | ``1``              |
572 +--------------------+--------------------+--------------------+--------------------+
573 | Empty              | ``merge(A,1)``     | ``merge(A,2)``     | ``A`` is ``2``     |
574 +--------------------+--------------------+--------------------+--------------------+
575 | A=0                | ``put(A,1)``       | ``put(A,2)``       | ``tx2`` will fail, |
576 |                    |                    |                    | ``A`` is ``1``     |
577 +--------------------+--------------------+--------------------+--------------------+
578 | A=0                | ``put(A,1)``       | ``merge(A,2)``     | ``A`` is ``2``     |
579 +--------------------+--------------------+--------------------+--------------------+
580 | A=0                | ``merge(A,1)``     | ``put(A,2)``       | ``tx2`` will fail, |
581 |                    |                    |                    | value of ``A`` is  |
582 |                    |                    |                    | ``1``              |
583 +--------------------+--------------------+--------------------+--------------------+
584 | A=0                | ``merge(A,1)``     | ``merge(A,2)``     | ``A`` is ``2``     |
585 +--------------------+--------------------+--------------------+--------------------+
586 | A=0                | ``delete(A)``      | ``put(A,2)``       | ``tx2`` will fail, |
587 |                    |                    |                    | ``A`` does not     |
588 |                    |                    |                    | exists             |
589 +--------------------+--------------------+--------------------+--------------------+
590 | A=0                | ``delete(A)``      | ``merge(A,2)``     | ``A`` is ``2``     |
591 +--------------------+--------------------+--------------------+--------------------+
592
593 Table: Concurrent change resolution for leaves and leaf-list items
594
595 +--------------------+--------------------+--------------------+--------------------+
596 | Initial state      | ``tx1``            | ``tx2``            | Result             |
597 +====================+====================+====================+====================+
598 | Empty              | put(TOP,[])        | put(TOP,[])        | ``tx2`` will fail, |
599 |                    |                    |                    | state is TOP=[]    |
600 +--------------------+--------------------+--------------------+--------------------+
601 | Empty              | put(TOP,[])        | merge(TOP,[])      | TOP=[]             |
602 +--------------------+--------------------+--------------------+--------------------+
603 | Empty              | put(TOP,[FOO=1])   | put(TOP,[BAR=1])   | ``tx2`` will fail, |
604 |                    |                    |                    | state is           |
605 |                    |                    |                    | TOP=[FOO=1]        |
606 +--------------------+--------------------+--------------------+--------------------+
607 | Empty              | put(TOP,[FOO=1])   | merge(TOP,[BAR=1]) | TOP=[FOO=1,BAR=1]  |
608 +--------------------+--------------------+--------------------+--------------------+
609 | Empty              | merge(TOP,[FOO=1]) | put(TOP,[BAR=1])   | ``tx2`` will fail, |
610 |                    |                    |                    | state is           |
611 |                    |                    |                    | TOP=[FOO=1]        |
612 +--------------------+--------------------+--------------------+--------------------+
613 | Empty              | merge(TOP,[FOO=1]) | merge(TOP,[BAR=1]) | TOP=[FOO=1,BAR=1]  |
614 +--------------------+--------------------+--------------------+--------------------+
615 | TOP=[]             | put(TOP,[FOO=1])   | put(TOP,[BAR=1])   | ``tx2`` will fail, |
616 |                    |                    |                    | state is           |
617 |                    |                    |                    | TOP=[FOO=1]        |
618 +--------------------+--------------------+--------------------+--------------------+
619 | TOP=[]             | put(TOP,[FOO=1])   | merge(TOP,[BAR=1]) | state is           |
620 |                    |                    |                    | TOP=[FOO=1,BAR=1]  |
621 +--------------------+--------------------+--------------------+--------------------+
622 | TOP=[]             | merge(TOP,[FOO=1]) | put(TOP,[BAR=1])   | ``tx2`` will fail, |
623 |                    |                    |                    | state is           |
624 |                    |                    |                    | TOP=[FOO=1]        |
625 +--------------------+--------------------+--------------------+--------------------+
626 | TOP=[]             | merge(TOP,[FOO=1]) | merge(TOP,[BAR=1]) | state is           |
627 |                    |                    |                    | TOP=[FOO=1,BAR=1]  |
628 +--------------------+--------------------+--------------------+--------------------+
629 | TOP=[]             | delete(TOP)        | put(TOP,[BAR=1])   | ``tx2`` will fail, |
630 |                    |                    |                    | state is empty     |
631 |                    |                    |                    | store              |
632 +--------------------+--------------------+--------------------+--------------------+
633 | TOP=[]             | delete(TOP)        | merge(TOP,[BAR=1]) | state is           |
634 |                    |                    |                    | TOP=[BAR=1]        |
635 +--------------------+--------------------+--------------------+--------------------+
636 | TOP=[]             | put(TOP/FOO,1)     | put(TOP/BAR,1])    | state is           |
637 |                    |                    |                    | TOP=[FOO=1,BAR=1]  |
638 +--------------------+--------------------+--------------------+--------------------+
639 | TOP=[]             | put(TOP/FOO,1)     | merge(TOP/BAR,1)   | state is           |
640 |                    |                    |                    | TOP=[FOO=1,BAR=1]  |
641 +--------------------+--------------------+--------------------+--------------------+
642 | TOP=[]             | merge(TOP/FOO,1)   | put(TOP/BAR,1)     | state is           |
643 |                    |                    |                    | TOP=[FOO=1,BAR=1]  |
644 +--------------------+--------------------+--------------------+--------------------+
645 | TOP=[]             | merge(TOP/FOO,1)   | merge(TOP/BAR,1)   | state is           |
646 |                    |                    |                    | TOP=[FOO=1,BAR=1]  |
647 +--------------------+--------------------+--------------------+--------------------+
648 | TOP=[]             | delete(TOP)        | put(TOP/BAR,1)     | ``tx2`` will fail, |
649 |                    |                    |                    | state is empty     |
650 |                    |                    |                    | store              |
651 +--------------------+--------------------+--------------------+--------------------+
652 | TOP=[]             | delete(TOP)        | merge(TOP/BAR,1]   | ``tx2`` will fail, |
653 |                    |                    |                    | state is empty     |
654 |                    |                    |                    | store              |
655 +--------------------+--------------------+--------------------+--------------------+
656 | TOP=[FOO=1]        | put(TOP/FOO,2)     | put(TOP/BAR,1)     | state is           |
657 |                    |                    |                    | TOP=[FOO=2,BAR=1]  |
658 +--------------------+--------------------+--------------------+--------------------+
659 | TOP=[FOO=1]        | put(TOP/FOO,2)     | merge(TOP/BAR,1)   | state is           |
660 |                    |                    |                    | TOP=[FOO=2,BAR=1]  |
661 +--------------------+--------------------+--------------------+--------------------+
662 | TOP=[FOO=1]        | merge(TOP/FOO,2)   | put(TOP/BAR,1)     | state is           |
663 |                    |                    |                    | TOP=[FOO=2,BAR=1]  |
664 +--------------------+--------------------+--------------------+--------------------+
665 | TOP=[FOO=1]        | merge(TOP/FOO,2)   | merge(TOP/BAR,1)   | state is           |
666 |                    |                    |                    | TOP=[FOO=2,BAR=1]  |
667 +--------------------+--------------------+--------------------+--------------------+
668 | TOP=[FOO=1]        | delete(TOP/FOO)    | put(TOP/BAR,1)     | state is           |
669 |                    |                    |                    | TOP=[BAR=1]        |
670 +--------------------+--------------------+--------------------+--------------------+
671 | TOP=[FOO=1]        | delete(TOP/FOO)    | merge(TOP/BAR,1]   | state is           |
672 |                    |                    |                    | TOP=[BAR=1]        |
673 +--------------------+--------------------+--------------------+--------------------+
674
675 Table: Concurrent change resolution for containers, lists, list items
676
677 MD-SAL RPC routing
678 ------------------
679
680 The MD-SAL provides a way to deliver Remote Procedure Calls (RPCs) to a
681 particular implementation based on content in the input as it is modeled
682 in YANG. This part of the RPC input is referred to as a **context
683 reference**.
684
685 The MD-SAL does not dictate the name of the leaf which is used for this
686 RPC routing, but provides necessary functionality for YANG model author
687 to define their **context reference** in their model of RPCs.
688
689 MD-SAL routing behavior is modeled using following terminology and its
690 application to YANG models:
691
692 Context Type
693     Logical type of RPC routing. Context type is modeled as YANG
694     ``identity`` and is referenced in model to provide scoping
695     information.
696
697 Context Instance
698     Conceptual location in data tree, which represents context in which
699     RPC could be executed. Context instance usually represent logical
700     point to which RPC execution is attached.
701
702 Context Reference
703     Field of RPC input payload which contains Instance Identifier
704     referencing **context instance** in which the RPC should be
705     executed.
706
707 Modeling a routed RPC
708 ~~~~~~~~~~~~~~~~~~~~~
709
710 In order to define routed RPCs, the YANG model author needs to declare
711 (or reuse) a **context type**, set of possible **context instances** and
712 finally RPCs which will contain **context reference** on which they will
713 be routed.
714
715 Declaring a routing context type
716 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
717
718 .. code::
719
720     identity node-context {
721         description "Identity used to mark node context";
722     }
723
724 This declares an identity named ``node-context``, which is used as
725 marker for node-based routing and is used in other places to reference
726 that routing type.
727
728 Declaring possible context instances
729 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
730
731 In order to define possible values of **context instances** for routed
732 RPCs, we need to model that set accordingly using ``context-instance``
733 extension from the ``yang-ext`` model.
734
735 .. code::
736
737     import yang-ext { prefix ext; }
738
739     /** Base structure **/
740     container nodes {
741         list node {
742             key "id";
743             ext:context-instance "node-context";
744             // other node-related fields would go here
745         }
746     }
747
748 The statement ``ext:context-instance "node-context";`` marks any element
749 of the ``list node`` as a possible valid **context instance** in
750 ``node-context`` based routing.
751
752 .. note::
753
754     The existence of a **context instance** node in operational or
755     config data tree is not strongly tied to existence of RPC
756     implementation.
757
758     For most routed RPC models, there is relationship between the data
759     present in operational data tree and RPC implementation
760     availability, but this is not enforced by MD-SAL. This provides some
761     flexibility for YANG model writers to better specify their routing
762     model and requirements for implementations. Details when RPC
763     implementations are available should be documented in YANG model.
764
765     If user invokes RPC with a **context instance** that has no
766     registered implementation, the RPC invocation will fail with the
767     exception ``DOMRpcImplementationNotAvailableException``.
768
769 Declaring a routed RPC
770 ^^^^^^^^^^^^^^^^^^^^^^
771
772 To declare RPC to be routed based on ``node-context`` we need to add
773 leaf of ``instance-identifier`` type (or type derived from
774 ``instance-identifier``) to the RPC and mark it as **context
775 reference**.
776
777 This is achieved using YANG extension ``context-reference`` from
778 ``yang-ext`` model on leaf, which will be used for RPC routing.
779
780 .. code::
781
782     rpc example-routed-rpc  {
783         input {
784             leaf node {
785                 ext:context-reference "node-context";
786                 type "instance-identifier";
787             }
788             // other input to the RPC would go here
789         }
790     }
791
792 The statement ``ext:context-reference "node-context"`` marks
793 ``leaf node`` as **context reference** of type ``node-context``. The
794 value of this leaf, will be used by the MD-SAL to select the particular
795 RPC implementation that registered itself as the implementation of the
796 RPC for particular **context instance**.
797
798 Using routed RPCs
799 ~~~~~~~~~~~~~~~~~
800
801 From a user perspective (e.g. invoking RPCs) there is no difference
802 between routed and non-routed RPCs. Routing information is just an
803 additional leaf in RPC which must be populated.
804
805 Implementing a routed RPC
806 ~~~~~~~~~~~~~~~~~~~~~~~~~
807
808 Implementation
809
810 Registering implementations
811 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
812
813 Implementations of a routed RPC (e.g., southbound plugins) will specify
814 an instance-identifier for the **context reference** (in this case a
815 node) for which they want to provide an implementation during
816 registration. Consumers, e.g., those calling the RPC are required to
817 specify that instance-identifier (in this case the identifier of a node)
818 when invoking RPC.
819
820 Simple code which showcases that for add-flow via Binding-Aware APIs
821 (`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>`__
822 ):
823
824 .. code:: java
825
826      61  @Override
827      62  public void onSessionInitiated(ProviderContext session) {
828      63      assertNotNull(session);
829      64      firstReg = session.addRoutedRpcImplementation(SalFlowService.class, salFlowService1);
830      65  }
831
832 Line 64: We are registering salFlowService1 as implementation of
833 SalFlowService RPC
834
835 .. code:: java
836
837     107  NodeRef nodeOne = createNodeRef("foo:node:1");
838     109  /**
839     110   * Provider 1 registers path of node 1
840     111   */
841     112  firstReg.registerPath(NodeContext.class, nodeOne);
842
843 Line 107: We are creating NodeRef (encapsulation of InstanceIdentifier)
844 for "foo:node:1".
845
846 Line 112: We register salFlowService1 as implementation for nodeOne.
847
848 The salFlowService1 will be executed only for RPCs which contains
849 Instance Identifier for foo:node:1.
850
851 RPCs and cluster
852 ^^^^^^^^^^^^^^^^
853
854 In case there is is only a single provider of an RPC in the cluster
855 the RPC registration is propagated to other nodes via Gossip protocol
856 and the RPC calls from other nodes are correctly routed to the
857 provider. Since the registrations are not expected to change rapidly
858 there is a latency of about 1 second until the registration is reflected
859 on the remote nodes.
860
861
862 OpenDaylight Controller MD-SAL: RESTCONF
863 ----------------------------------------
864
865 RESTCONF operations overview
866 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
867
868 | RESTCONF allows access to datastores in the controller.
869 | There are two datastores:
870
871 -  Config: Contains data inserted via controller
872
873 -  Operational: Contains other data
874
875 .. note::
876
877     | Each request must start with the URI /rests.
878     | RESTCONF listens on port 8080 for HTTP requests.
879
880 RESTCONF supports **OPTIONS**, **GET**, **PUT**, **POST**, and
881 **DELETE** operations. Request and response data can either be in the
882 XML or JSON format. XML structures according to yang are defined at:
883 `XML-YANG <https://www.rfc-editor.org/rfc/rfc6020>`__. JSON structures are
884 defined at:
885 `JSON-YANG <https://datatracker.ietf.org/doc/html/draft-lhotka-netmod-yang-json-02>`__.
886 Data in the request must have a correctly set **Content-Type** field in
887 the http header with the allowed value of the media type. The media type
888 of the requested data has to be set in the **Accept** field. Get the
889 media types for each resource by calling the OPTIONS operation. Most of
890 the paths of the pathsRestconf endpoints use `Instance
891 Identifier <https://wiki-archive.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Concepts#Instance_Identifier>`__.
892 ``<identifier>`` is used in the explanation of the operations.
893
894 | **<identifier>**
895
896 -  It must start with <moduleName>:<nodeName> where <moduleName> is a
897    name of the module and <nodeName> is the name of a node in the
898    module. It is sufficient to just use <nodeName> after
899    <moduleName>:<nodeName>. Each <nodeName> has to be separated by /.
900
901 -  <nodeName> can represent a data node which is a list or container
902    yang built-in type. If the data node is a list, there must be defined
903    keys of the list behind the data node name for example,
904    <nodeName>=<valueOfKey1>,<valueOfKey2>.
905
906 -  | The format <moduleName>:<nodeName> has to be used in this case as
907      well:
908    | Module A has node A1. Module B augments node A1 by adding node X.
909      Module C augments node A1 by adding node X. For clarity, it has to
910      be known which node is X (for example: C:X). For more details about
911      encoding, see: `RESTCONF RFC 8040 - Encoding YANG Instance Identifiers in
912      the Request
913      URI. <https://datatracker.ietf.org/doc/html/rfc8040#section-3.5.3>`__
914
915 Mount point
916 ~~~~~~~~~~~
917
918 | A Node can be behind a mount point. In this case, the URI has to be in
919   format <identifier>/**yang-ext:mount**/<identifier>. The first
920   <identifier> is the path to a mount point and the second <identifier>
921   is the path to a node behind the mount point. A URI can end in a mount
922   point itself by using <identifier>/**yang-ext:mount**.
923 | More information on how to actually use mountpoints is available at:
924   `OpenDaylight
925   Controller:Config:Examples:Netconf <https://wiki-archive.opendaylight.org/view/OpenDaylight_Controller:Config:Examples:Netconf>`__.
926
927 HTTP methods
928 ~~~~~~~~~~~~
929
930 OPTIONS /rests
931 ^^^^^^^^^^^^^^
932
933 -  Returns the XML description of the resources with the required
934    request and response media types in Web Application Description
935    Language (WADL)
936
937 GET /rests/data/<identifier>?content=config
938 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
939
940 -  Returns a data node from the Config datastore.
941
942 -  <identifier> points to a data node which must be retrieved.
943
944 GET /rests/data/<identifier>?content=nonconfig
945 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
946
947 -  Returns the value of the data node from the non-configuration datastore.
948
949 -  <identifier> points to a data node which must be retrieved.
950
951 PUT /rests/data/<identifier>
952 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
953
954 -  Updates or creates data in the Config datastore and returns the state
955    about success.
956
957 -  <identifier> points to a data node which must be stored.
958
959 | **Example:**
960
961 ::
962
963     PUT http://<controllerIP>:8080/rests/data/module1:foo/bar
964     Content-Type: applicaton/xml
965     <bar>
966       …
967     </bar>
968
969 | **Example with mount point:**
970
971 ::
972
973     PUT http://<controllerIP>:8080/rests/data/module1:foo1/foo2/yang-ext:mount/module2:foo/bar
974     Content-Type: applicaton/xml
975     <bar>
976       …
977     </bar>
978
979 POST /rests/data
980 ^^^^^^^^^^^^^^^^
981
982 -  Creates the data if it does not exist
983
984 | For example:
985
986 ::
987
988     POST URL: http://localhost:8080/rests/data/
989     content-type: application/yang.data+json
990     JSON payload:
991
992        {
993          "toaster:toaster" :
994          {
995            "toaster:toasterManufacturer" : "General Electric",
996            "toaster:toasterModelNumber" : "123",
997            "toaster:toasterStatus" : "up"
998          }
999       }
1000
1001 POST /rests/data/<identifier>
1002 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1003
1004 -  Creates the data if it does not exist in the Config datastore, and
1005    returns the state about success.
1006
1007 -  <identifier> points to a data node where data must be stored.
1008
1009 -  The root element of data must have the namespace (data are in XML) or
1010    module name (data are in JSON.)
1011
1012 | **Example:**
1013
1014 ::
1015
1016     POST http://<controllerIP>:8080/rests/data/module1:foo
1017     Content-Type: applicaton/xml/
1018     <bar xmlns=“module1namespace”>
1019       …
1020     </bar>
1021
1022 **Example with mount point:**
1023
1024 ::
1025
1026     http://<controllerIP>:8080/rests/data/module1:foo1/foo2/yang-ext:mount/module2:foo
1027     Content-Type: applicaton/xml
1028     <bar xmlns=“module2namespace”>
1029       …
1030     </bar>
1031
1032 POST /rests/operations/<moduleName>:<rpcName>
1033 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1034
1035 -  Invokes RPC.
1036
1037 -  <moduleName>:<rpcName> - <moduleName> is the name of the module and
1038    <rpcName> is the name of the RPC in this module.
1039
1040 -  The Root element of the data sent to RPC must have the name “input”.
1041
1042 -  The result can be the status code or the retrieved data having the
1043    root element “output”.
1044
1045 | **Example:**
1046
1047 ::
1048
1049     POST http://<controllerIP>:8080/rests/operations/module1:fooRpc
1050     Content-Type: applicaton/xml
1051     Accept: applicaton/xml
1052     <input>
1053       …
1054     </input>
1055
1056     The answer from the server could be:
1057     <output>
1058       …
1059     </output>
1060
1061 | **An example using a JSON payload:**
1062
1063 ::
1064
1065     POST http://localhost:8080/rests/operations/toaster:make-toast
1066     Content-Type: application/yang.data+json
1067     {
1068       "input" :
1069       {
1070          "toaster:toasterDoneness" : "10",
1071          "toaster:toasterToastType":"wheat-bread"
1072       }
1073     }
1074
1075 .. note::
1076
1077     Even though this is a default for the toasterToastType value in the
1078     yang, you still need to define it.
1079
1080 DELETE /rests/data/<identifier>
1081 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1082
1083 -  Removes the data node in the Config datastore and returns the state
1084    about success.
1085
1086 -  <identifier> points to a data node which must be removed.
1087
1088 More information is available in the `RESTCONF
1089 RFC <https://datatracker.ietf.org/doc/html/rfc8040>`__.
1090
1091 How RESTCONF works
1092 ~~~~~~~~~~~~~~~~~~
1093
1094 | RESTCONF uses these base classes:
1095
1096 InstanceIdentifier
1097     Represents the path in the data tree
1098
1099 ConsumerSession
1100     Used for invoking RPCs
1101
1102 DataBrokerService
1103     Offers manipulation with transactions and reading data from the
1104     datastores
1105
1106 SchemaContext
1107     Holds information about yang modules
1108
1109 MountService
1110     Returns MountInstance based on the InstanceIdentifier pointing to a
1111     mount point
1112
1113 MountInstace
1114     Contains the SchemaContext behind the mount point
1115
1116 DataSchemaNode
1117     Provides information about the schema node
1118
1119 SimpleNode
1120     Possesses the same name as the schema node, and contains the value
1121     representing the data node value
1122
1123 CompositeNode
1124     Can contain CompositeNode-s and SimpleNode-s
1125
1126 GET in action
1127 ~~~~~~~~~~~~~
1128
1129 Figure 1 shows the GET operation with URI rests/data/M:N?content=config
1130 where M is the module name, and N is the node name.
1131
1132 .. figure:: ./images/Get.png
1133    :alt: Get
1134
1135    Get
1136
1137 1. The requested URI is translated into the InstanceIdentifier which
1138    points to the data node. During this translation, the DataSchemaNode
1139    that conforms to the data node is obtained. If the data node is
1140    behind the mount point, the MountInstance is obtained as well.
1141
1142 2. RESTCONF asks for the value of the data node from DataBrokerService
1143    based on InstanceIdentifier.
1144
1145 3. DataBrokerService returns CompositeNode as data.
1146
1147 4. StructuredDataToXmlProvider or StructuredDataToJsonProvider is called
1148    based on the **Accept** field from the http request. These two
1149    providers can transform CompositeNode regarding DataSchemaNode to an
1150    XML or JSON document.
1151
1152 5. XML or JSON is returned as the answer on the request from the client.
1153
1154 PUT in action
1155 ~~~~~~~~~~~~~
1156
1157 Figure 2 shows the PUT operation with the URI rests/data/M:N where
1158 M is the module name, and N is the node name. Data is sent in the
1159 request either in the XML or JSON format.
1160
1161 .. figure:: ./images/Put.png
1162    :alt: Put
1163
1164    Put
1165
1166 1. Input data is sent to JsonToCompositeNodeProvider or
1167    XmlToCompositeNodeProvider. The correct provider is selected based on
1168    the Content-Type field from the http request. These two providers can
1169    transform input data to CompositeNode. However, this CompositeNode
1170    does not contain enough information for transactions.
1171
1172 2. The requested URI is translated into InstanceIdentifier which points
1173    to the data node. DataSchemaNode conforming to the data node is
1174    obtained during this translation. If the data node is behind the
1175    mount point, the MountInstance is obtained as well.
1176
1177 3. CompositeNode can be normalized by adding additional information from
1178    DataSchemaNode.
1179
1180 4. RESTCONF begins the transaction, and puts CompositeNode with
1181    InstanceIdentifier into it. The response on the request from the
1182    client is the status code which depends on the result from the
1183    transaction.
1184
1185 Something practical
1186 ~~~~~~~~~~~~~~~~~~~
1187
1188 1. Create a new flow on the switch openflow:1 in table 2.
1189
1190 | **HTTP request**
1191
1192 ::
1193
1194     Operation: POST
1195     URI: http://192.168.11.1:8080/rests/data/opendaylight-inventory:nodes/node=openflow:1/table=2
1196     Content-Type: application/xml
1197
1198 ::
1199
1200     <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1201     <flow
1202         xmlns="urn:opendaylight:flow:inventory">
1203         <strict>false</strict>
1204         <instructions>
1205             <instruction>
1206                 <order>1</order>
1207                 <apply-actions>
1208                     <action>
1209                       <order>1</order>
1210                         <flood-all-action/>
1211                     </action>
1212                 </apply-actions>
1213             </instruction>
1214         </instructions>
1215         <table_id>2</table_id>
1216         <id>111</id>
1217         <cookie_mask>10</cookie_mask>
1218         <out_port>10</out_port>
1219         <installHw>false</installHw>
1220         <out_group>2</out_group>
1221         <match>
1222             <ethernet-match>
1223                 <ethernet-type>
1224                     <type>2048</type>
1225                 </ethernet-type>
1226             </ethernet-match>
1227             <ipv4-destination>10.0.0.1/24</ipv4-destination>
1228         </match>
1229         <hard-timeout>0</hard-timeout>
1230         <cookie>10</cookie>
1231         <idle-timeout>0</idle-timeout>
1232         <flow-name>FooXf22</flow-name>
1233         <priority>2</priority>
1234         <barrier>false</barrier>
1235     </flow>
1236
1237 | **HTTP response**
1238
1239 ::
1240
1241     Status: 204 No Content
1242
1243 1. Change *strict* to *true* in the previous flow.
1244
1245 | **HTTP request**
1246
1247 ::
1248
1249     Operation: PUT
1250     URI: http://192.168.11.1:8080/rests/data/opendaylight-inventory:nodes/node=openflow:1/table=2/flow=111
1251     Content-Type: application/xml
1252
1253 ::
1254
1255     <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1256     <flow
1257         xmlns="urn:opendaylight:flow:inventory">
1258         <strict>true</strict>
1259         <instructions>
1260             <instruction>
1261                 <order>1</order>
1262                 <apply-actions>
1263                     <action>
1264                       <order>1</order>
1265                         <flood-all-action/>
1266                     </action>
1267                 </apply-actions>
1268             </instruction>
1269         </instructions>
1270         <table_id>2</table_id>
1271         <id>111</id>
1272         <cookie_mask>10</cookie_mask>
1273         <out_port>10</out_port>
1274         <installHw>false</installHw>
1275         <out_group>2</out_group>
1276         <match>
1277             <ethernet-match>
1278                 <ethernet-type>
1279                     <type>2048</type>
1280                 </ethernet-type>
1281             </ethernet-match>
1282             <ipv4-destination>10.0.0.1/24</ipv4-destination>
1283         </match>
1284         <hard-timeout>0</hard-timeout>
1285         <cookie>10</cookie>
1286         <idle-timeout>0</idle-timeout>
1287         <flow-name>FooXf22</flow-name>
1288         <priority>2</priority>
1289         <barrier>false</barrier>
1290     </flow>
1291
1292 | **HTTP response**
1293
1294 ::
1295
1296     Status: 200 OK
1297
1298 1. Show flow: check that *strict* is *true*.
1299
1300 | **HTTP request**
1301
1302 ::
1303
1304     Operation: GET
1305     URI: http://192.168.11.1:8080/rests/data/opendaylight-inventory:nodes/node=openflow:1/table=2/flow=111?content=config
1306     Accept: application/xml
1307
1308 | **HTTP response**
1309
1310 ::
1311
1312     Status: 200 OK
1313
1314 ::
1315
1316     <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1317     <flow
1318         xmlns="urn:opendaylight:flow:inventory">
1319         <strict>true</strict>
1320         <instructions>
1321             <instruction>
1322                 <order>1</order>
1323                 <apply-actions>
1324                     <action>
1325                       <order>1</order>
1326                         <flood-all-action/>
1327                     </action>
1328                 </apply-actions>
1329             </instruction>
1330         </instructions>
1331         <table_id>2</table_id>
1332         <id>111</id>
1333         <cookie_mask>10</cookie_mask>
1334         <out_port>10</out_port>
1335         <installHw>false</installHw>
1336         <out_group>2</out_group>
1337         <match>
1338             <ethernet-match>
1339                 <ethernet-type>
1340                     <type>2048</type>
1341                 </ethernet-type>
1342             </ethernet-match>
1343             <ipv4-destination>10.0.0.1/24</ipv4-destination>
1344         </match>
1345         <hard-timeout>0</hard-timeout>
1346         <cookie>10</cookie>
1347         <idle-timeout>0</idle-timeout>
1348         <flow-name>FooXf22</flow-name>
1349         <priority>2</priority>
1350         <barrier>false</barrier>
1351     </flow>
1352
1353 1. Delete the flow created.
1354
1355 | **HTTP request**
1356
1357 ::
1358
1359     Operation: DELETE
1360     URI: http://192.168.11.1:8080/rests/data/opendaylight-inventory:nodes/node=openflow:1/table=2/flow=111
1361
1362 | **HTTP response**
1363
1364 ::
1365
1366     Status: 200 OK
1367