+.. _controller-dev-guide:
+
Controller
==========
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 <mdsal_dev_guide>` - 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
manipulate YANG modeled data and invoke YANG modeled RPCs, using XML
or JSON as payload format.
+.. _mdsal_dev_guide:
+
MD-SAL Overview
---------------
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 <transaction_isolation>` from other currently running
transactions. The state of running transaction and underlying data tree
is not affected by other concurrently running transactions.
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 <submitting_transaction>` it to be processed.
4. application observes the result of the transaction commit using
either blocking or asynchronous calls.
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 <transaction_local_state>`
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 <commit_failure_scenarios>` due
to failing verification of data or concurrent transaction modifying and
affected data in an incompatible way.
Removes a whole subtree from a specified path.
+.. _submitting_transaction:
+
Submitting transaction
^^^^^^^^^^^^^^^^^^^^^^
.. code:: java
- Futures.addCallback( writeTx.submit(), new FutureCallback<Void>() {
- public void onSuccess( Void result ) {
+ Futures.addCallback( writeTx.submit(), new FutureCallback<Void>() {
+ 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);
}
});
.. code:: java
try {
- writeTx.submit().checkedGet();
- } catch (TransactionCommitFailedException e) {
+ writeTx.submit().checkedGet();
+ } catch (TransactionCommitFailedException e) {
LOG.error("Commit failed.",e);
}
- Catches ``TransactionCommitFailedException`` and logs it.
+.. _transaction_local_state:
+
Transaction local state
^^^^^^^^^^^^^^^^^^^^^^^
.. 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``.
- Read will return value ``C`` for ``PATH``, since previous write
occurred in same transaction.
+.. _transaction_isolation:
+
Transaction isolation
~~~~~~~~~~~~~~~~~~~~~
.. 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``.
``Futures#addCallback(ListenableFuture, FutureCallback)`` to listen
asynchronously for result.
+.. _commit_failure_scenarios:
+
Commit failure scenarios
~~~~~~~~~~~~~~~~~~~~~~~~
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
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``
Declaring a routing context type
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. code:: yang
+.. code::
identity node-context {
description "Identity used to mark node context";
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; }
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 {
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:
- 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
{
"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"
}
}
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 <https://tools.ietf.org/html/draft-ietf-netconf-restconf-05#section-4.8.6>`__
+
+- `start-time <https://tools.ietf.org/html/draft-ietf-netconf-restconf-05#section-4.8.7>`__
+
+- `end-time <https://tools.ietf.org/html/draft-ietf-netconf-restconf-05#section-4.8.8>`__
+
+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
WebSocket client
applications <https://developer.mozilla.org/en-US/docs/WebSockets/Writing_WebSocket_client_applications>`__
+.. _config_subsystem:
+
Config Subsystem
----------------
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.).
-