X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=docs%2Fdeveloper-guide%2Fcontroller.rst;h=fd3d02900d1b3770a6ce0b6f22755b6afc63a235;hb=975a06fde6546a1680b19d72d3005ac5811c95f2;hp=6d656aac3a698309078bc5a057ac46d3f865ff11;hpb=7263d800d129ea81a1a4fdccdfe40c7b6a4b3fbf;p=docs.git diff --git a/docs/developer-guide/controller.rst b/docs/developer-guide/controller.rst index 6d656aac3..fd3d02900 100644 --- a/docs/developer-guide/controller.rst +++ b/docs/developer-guide/controller.rst @@ -1,3 +1,5 @@ +.. _controller-dev-guide: + Controller ========== @@ -26,12 +28,12 @@ The OpenDaylight Controller relies on the following technologies: The OpenDaylight Controller provides following model-driven subsystems as a foundation for Java applications: -- **`Config Subsystem <#_config_subsystem>`__** - an activation, +- :ref:`config_subsystem` - an activation, dependency-injection and configuration framework, which allows two-phase commits of configuration and dependency-injection, and allows for run-time rewiring. -- **`MD-SAL <#_md_sal_overview>`__** - messaging and data storage +- :ref:`MD-SAL ` - messaging and data storage functionality for data, notifications and RPCs modeled by application developers. MD-SAL uses YANG as the modeling for both interface and data definitions, and provides a messaging and data-centric runtime @@ -52,6 +54,8 @@ data using following model-driven protocols: manipulate YANG modeled data and invoke YANG modeled RPCs, using XML or JSON as payload format. +.. _mdsal_dev_guide: + MD-SAL Overview --------------- @@ -181,8 +185,8 @@ MD-SAL **Data Broker** provides transactional access to conceptual this is state of controller, applications and also external systems (network devices). -**Transactions** provide **`stable and isolated -view <#_transaction_isolation>`__** from other currently running +**Transactions** provide :ref:`stable and isolated +view ` from other currently running transactions. The state of running transaction and underlying data tree is not affected by other concurrently running transactions. @@ -233,8 +237,8 @@ for the conceptual data trees. using ``put``, ``merge`` and/or ``delete``. 3. application finishes transaction using - ```submit()`` <#_submitting_transaction>`__, which seals transaction - and submits it to be processed. + ``submit()``, which :ref:`seals transaction + and submits ` it to be processed. 4. application observes the result of the transaction commit using either blocking or asynchronous calls. @@ -245,12 +249,12 @@ it’s state and underlying data tree are not affected by other concurrently running transactions. Write transactions are **isolated** from other concurrent write -transactions. All **`writes are local <#_transaction_local_state>`__** +transactions. All :ref:`writes are local ` to the transaction and represents only a **proposal of state change** for data tree and **are not visible** to any other concurrently running transactions (including read-only transactions). -The transaction **`commit may fail <#_commit_failure_scenarios>`__** due +The transaction :ref:`commit may fail ` due to failing verification of data or concurrent transaction modifying and affected data in an incompatible way. @@ -286,6 +290,8 @@ delete Removes a whole subtree from a specified path. +.. _submitting_transaction: + Submitting transaction ^^^^^^^^^^^^^^^^^^^^^^ @@ -311,12 +317,12 @@ Application may listen on commit state asynchronously using .. code:: java - Futures.addCallback( writeTx.submit(), new FutureCallback() { - public void onSuccess( Void result ) { + Futures.addCallback( writeTx.submit(), new FutureCallback() { + public void onSuccess( Void result ) { LOG.debug("Transaction committed successfully."); } - public void onFailure( Throwable t ) { + public void onFailure( Throwable t ) { LOG.error("Commit failed.",e); } }); @@ -337,8 +343,8 @@ If application need to block till commit is finished it may use .. code:: java try { - writeTx.submit().checkedGet(); - } catch (TransactionCommitFailedException e) { + writeTx.submit().checkedGet(); + } catch (TransactionCommitFailedException e) { LOG.error("Commit failed.",e); } @@ -348,6 +354,8 @@ If application need to block till commit is finished it may use - Catches ``TransactionCommitFailedException`` and logs it. +.. _transaction_local_state: + Transaction local state ^^^^^^^^^^^^^^^^^^^^^^^ @@ -362,13 +370,13 @@ Let assume initial state of data tree for ``PATH`` is ``A``. .. code:: java - ReadWriteTransaction rwTx = broker.newReadWriteTransaction(); + ReadWriteTransaction rwTx = broker.newReadWriteTransaction(); - rwRx.read(OPERATIONAL,PATH).get(); - rwRx.put(OPERATIONAL,PATH,B); - rwRx.read(OPERATIONAL,PATH).get(); - rwRx.put(OPERATIONAL,PATH,C); - rwRx.read(OPERATIONAL,PATH).get(); + rwRx.read(OPERATIONAL,PATH).get(); + rwRx.put(OPERATIONAL,PATH,B); + rwRx.read(OPERATIONAL,PATH).get(); + rwRx.put(OPERATIONAL,PATH,C); + rwRx.read(OPERATIONAL,PATH).get(); - Allocates new ``ReadWriteTransaction``. @@ -384,6 +392,8 @@ Let assume initial state of data tree for ``PATH`` is ``A``. - Read will return value ``C`` for ``PATH``, since previous write occurred in same transaction. +.. _transaction_isolation: + Transaction isolation ~~~~~~~~~~~~~~~~~~~~~ @@ -395,16 +405,16 @@ Lets assume initial state of data tree for ``PATH`` is ``A``. .. code:: java - ReadOnlyTransaction txRead = broker.newReadOnlyTransaction(); - ReadWriteTransaction txWrite = broker.newReadWriteTransaction(); + ReadOnlyTransaction txRead = broker.newReadOnlyTransaction(); + ReadWriteTransaction txWrite = broker.newReadWriteTransaction(); - txRead.read(OPERATIONAL,PATH).get(); - txWrite.put(OPERATIONAL,PATH,B); - txWrite.read(OPERATIONAL,PATH).get(); - txWrite.submit().get(); - txRead.read(OPERATIONAL,PATH).get(); - txAfterCommit = broker.newReadOnlyTransaction(); - txAfterCommit.read(OPERATIONAL,PATH).get(); + txRead.read(OPERATIONAL,PATH).get(); + txWrite.put(OPERATIONAL,PATH,B); + txWrite.read(OPERATIONAL,PATH).get(); + txWrite.submit().get(); + txRead.read(OPERATIONAL,PATH).get(); + txAfterCommit = broker.newReadOnlyTransaction(); + txAfterCommit.read(OPERATIONAL,PATH).get(); - Allocates read only transaction, which is based on data tree which contains value ``A`` for ``PATH``. @@ -442,6 +452,8 @@ Lets assume initial state of data tree for ``PATH`` is ``A``. ``Futures#addCallback(ListenableFuture, FutureCallback)`` to listen asynchronously for result. +.. _commit_failure_scenarios: + Commit failure scenarios ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -455,7 +467,7 @@ Optimistic Lock Failure It is the responsibility of the caller to create a new transaction and submit the same modification again in order to update data tree. - **Warning** + .. warning:: ``OptimisticLockFailedException`` usually exposes **multiple writers** to the same data subtree, which may conflict on same @@ -486,11 +498,11 @@ same initial state of data tree and proposes conflicting modifications. WriteTransaction txA = broker.newWriteTransaction(); WriteTransaction txB = broker.newWriteTransaction(); - txA.put(CONFIGURATION, PATH, A); - txB.put(CONFIGURATION, PATH, B); + txA.put(CONFIGURATION, PATH, A); + txB.put(CONFIGURATION, PATH, B); - CheckedFuture futureA = txA.submit(); - CheckedFuture futureB = txB.submit(); + CheckedFuture futureA = txA.submit(); + CheckedFuture futureB = txB.submit(); - Updates ``PATH`` to value ``A`` using ``txA`` @@ -708,7 +720,7 @@ be routed. Declaring a routing context type ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. code:: yang +.. code:: identity node-context { description "Identity used to mark node context"; @@ -725,7 +737,7 @@ In order to define possible values of **context instances** for routed RPCs, we need to model that set accordingly using ``context-instance`` extension from the ``yang-ext`` model. -.. code:: yang +.. code:: import yang-ext { prefix ext; } @@ -770,7 +782,7 @@ reference**. This is achieved using YANG extension ``context-reference`` from ``yang-ext`` model on leaf, which will be used for RPC routing. -.. code:: yang +.. code:: rpc example-routed-rpc { input { @@ -841,11 +853,22 @@ Line 112: We register salFlowService1 as implementation for nodeOne. The salFlowService1 will be executed only for RPCs which contains Instance Identifier for foo:node:1. +RPCs and cluster +^^^^^^^^^^^^^^^^ + +In case there is is only a single provider of an RPC in the cluster +the RPC registration is propagated to other nodes via Gossip protocol +and the RPC calls from other nodes are correctly routed to the +provider. Since the registrations are not expected to change rapidly +there is a latency of about 1 second until the registration is reflected +on the remote nodes. + + OpenDaylight Controller MD-SAL: RESTCONF ---------------------------------------- -RESCONF operations overview -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +RESTCONF operations overview +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | RESTCONF allows access to datastores in the controller. | There are two datastores: @@ -1386,7 +1409,7 @@ provide three parameters to this RPC: - SUBTREE: changes anywhere in the subtree starting at the node will be reported -The RPC to create the stream can be invoked via RESCONF like this: +The RPC to create the stream can be invoked via RESTCONF like this: - URI: http://{odlAddress}:{odlPort}/restconf/operations/sal-remote:create-data-change-event-subscription @@ -1413,7 +1436,7 @@ The response should look something like this: { "output": { - "stream-name": "toaster:toaster/toaster:toasterStatus/datastore=CONFIGURATION/scope=SUBTREE" + "stream-name": "data-change-event-subscription/toaster:toaster/toaster:toasterStatus/datastore=CONFIGURATION/scope=SUBTREE" } } @@ -1436,10 +1459,25 @@ response from *create-data-change-event-subscription* RPC from the previous step. - URI: - http://{odlAddress}:{odlPort}/restconf/streams/stream/toaster:toaster/datastore=CONFIGURATION/scope=SUBTREE + http://{odlAddress}:{odlPort}/restconf/streams/stream/data-change-event-subscription/toaster:toaster/datastore=CONFIGURATION/scope=SUBTREE - OPERATION: GET +The subscription call may be modified with the following query parameters defined in the RESTCONF RFC: + +- `filter `__ + +- `start-time `__ + +- `end-time `__ + +In addition, the following ODL extension query parameter is supported: + +:odl-leaf-nodes-only: + If this parameter is set to "true", create and update notifications will only + contain the leaf nodes modified instead of the entire subscription subtree. + This can help in reducing the size of the notifications. + The expected response status is 200 OK and response body should be empty. You will get your WebSocket location from **Location** header of response. For example in our particular toaster example location header @@ -1640,6 +1678,8 @@ RESTCONF. WebSocket client applications `__ +.. _config_subsystem: + Config Subsystem ---------------- @@ -1865,4 +1905,3 @@ It can be acquired from, for example, environment variables. After the creation of a default instance, it acts as a regular instance and fully participates in the configuration subsystem (It can be reconfigured or deleted in following transactions.). -