Merge "Fixed headline nesting in config and restconf."
[docs.git] / manuals / developer-guide / src / main / asciidoc / controller / config.adoc
1 === OpenDaylight Controller Configuration: Java Code Generator
2
3 ==== YANG to Java code generator
4
5 The Java code for the configuration system is generated by the yang-maven-plugin and the yang-jmx-generator-plugin.
6 The input Yang module files are converted to java files by the definition of the module and the specified templates. the generated java code can represent interfaces, classes, or abstract classes used for configuration.
7
8 ===== Service interfaces generating
9
10 Service interfaces (SI) are generated from YANG "service-types". Each SI must be defined as "identity" with a "base" statement set to "config:service-type", or another SI. This is because a service must have a globally unique name.
11  Each SI must be annotated with @ServiceInterfaceAnnotation, and must extend AbstractServiceInterface.
12
13 *Sample YANG module representing service interface* +
14
15 ----
16 module config-test {
17     yang-version 1;
18     namespace "urn:opendaylight:params:xml:ns:yang:controller:test";
19     prefix "test";
20
21     import config { prefix config; revision-date 2013-04-05; }
22
23     description
24         "Testing API";
25
26     revision "2013-06-13" {
27         description
28             "Initial revision";
29     }
30
31     identity testing {
32         description
33             "Test api";
34
35         base "config:service-type";
36         config:java-class "java.lang.AutoCloseable";
37     }
38 }
39 ----
40 The "description" node of identity is generated as javadoc in the service interface. +
41 The "config:java-class" is generated as *ServiceInterfaceAnnotation*. It specifies java classes or interfaces in the "osgiRegistrationTypes" parameter. The module implementing this service interface must instantiate a java object that can be cast to any of the java types defined in "osgiRegistrationTypes".
42
43 *Generated java source file: AutoCloseableServiceInterface* +
44 ----
45 package %prefix%.test;
46
47 /**
48 * Test api
49 */
50 @org.opendaylight.controller.config.api.annotations.Description(value = "Test api")
51 @org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation(value = "testing", osgiRegistrationType = java.lang.AutoCloseable.class)
52 public interface AutoCloseableServiceInterface extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface
53 {
54
55 }
56 ----
57
58 ====== Module stubs generating
59
60 Modules are constructed during configuration transaction. A module implements the ModuleMXBean interface. The ModuleMXBean interface represents getters and setters for attributes that will be exposed to the configuration registry by means of JMX. Attributes can either be simple types, or composite types.
61
62 Each ModuleMXBean must be defined in yang as "identity" with the base statement set to "config:module-type". Not only are ModuleMXBeans generated, but also ModuleFactory and Module stubs. Both are first generated as abstract classes with almost full functionality. Then their implementations, which are allowed to be modified by users, are generated, but only once.
63
64 ===== Runtime beans generating
65
66 Runtime JMX beans are purposed to be the auditors: they capture data about running module instances. A module can have zero or more runtime beans. Runtime beans are hierarchically ordered, and each must be uniquely identified.
67  A runtime bean is defined as a configuration augment of a module, from which interface RuntimeMXBean, RuntimeRegistrator, and RuntimeRegistretion are generated. Augment definition contains arguments representing the data of a module that must be watched.
68
69 ===== RPCs
70
71 Method calls in yang must be specified as top level elements. The context, where an RPC operation exits, must be defined in the RPC definition itself, and in the runtime bean that provides method implementation.
72
73
74 ===== OpenDaylight Controller: Configuration
75 The Controller configuration operation has three stages:
76
77 * First, a Proposed configuration is created. Its target is to replace the old configuration.
78 * Second, the Proposed configuration is validated, and then committed. If it passes validation successfully, the Proposed configuration state will be changed to Validated.
79 * Finally, a Validated configuration can be Committed, and the affected modules can be reconfigured.
80
81 In fact, each configuration operation is wrapped in a transaction. Once a transaction is created, it can be configured, that is to say, a user can abort the transaction during this stage. After the transaction configuration is done, it is committed to the validation stage. In this stage, the validation procedures are invoked.
82  If one or more validations fail, the transaction can be reconfigured. Upon success, the second phase commit is invoked.
83  If this commit is successful, the transaction enters the last stage, committed. After that, the desired modules are reconfigured. If the second phase commit fails, it means that the transaction is unhealthy - basically, a new configuration instance creation failed, and the application can be in an inconsistent state.
84
85 .Configuration states
86 image::configuration.jpg[width=500]
87
88 .Transaction states
89 image::Transaction.jpg[width=500]
90
91 ==== Validation
92 To secure the consistency and safety of the new configuration and to avoid conflicts, the configuration validation process is necessary.
93 Usually, validation checks the input parameters of a new configuration, and mostly verifies module-specific relationships.
94 The validation procedure results in a decision on whether the proposed configuration is healthy.
95
96 ==== Dependency resolver
97 Since there can be dependencies between modules, a change in a module configuration can affect the state of other modules. Therefore, we need to verify whether dependencies on other modules can be resolved.
98 The Dependency Resolver acts in a manner similar to dependency injectors. Basically, a dependency tree is built.
99
100 ==== APIs and SPIs
101 This section describes configuration system APIs and SPIs.
102
103
104 ===== SPIs
105 *Module* org.opendaylight.controller.config.spi. Module is the common interface for all modules: every module must implement it. The module is designated to hold configuration attributes, validate them, and create instances of service based on the attributes.
106 This instance must implement the AutoCloseable interface, owing to resources clean up. If the module was created from an already running instance, it contains an old instance of the module. A module can implement multiple services. If the module depends on other modules, setters need to be annotated with @RequireInterface.
107
108 *Module creation*
109
110 . The module needs to be configured, set with all required attributes.
111 . The module is then moved to the commit stage for validation. If the validation fails, the module attributes can be reconfigured. Otherwise, a new instance is either created, or an old instance is reconfigured.
112 A module instance is identified by ModuleIdentifier, consisting of the factory name and instance name.
113
114 *ModuleFactory* org.opendaylight.controller.config.spi. The ModuleFactory interface must be implemented by each module factory. +
115 A module factory can create a new module instance in two ways: +
116
117 * From an existing module instance
118 * An entirely new instance +
119 ModuleFactory can also return default modules, useful for populating registry with already existing configurations.
120 A module factory implementation must have a globally unique name.
121
122 ===== APIs
123
124 |===
125 | ConfigRegistry | Represents functionality provided by a configuration transaction (create, destroy module, validate, or abort transaction).
126 | ConfigTransactionController | Represents functionality for manipulating with configuration transactions (begin, commit config).
127 | RuntimeBeanRegistratorAwareConfiBean | The module implementing this interface will receive RuntimeBeanRegistrator before getInstance is invoked.
128 |===
129
130 ===== Runtime APIs
131
132 |===
133 | RuntimeBean | Common interface for all runtime beans
134 | RootRuntimeBeanRegistrator | Represents functionality for root runtime bean registration, which subsequently allows hierarchical registrations
135 | HierarchicalRuntimeBeanRegistration | Represents functionality for runtime bean registration and unreregistration from hierarchy
136 |===
137
138 ===== JMX APIs
139
140 JMX API is purposed as a transition between the Client API and the JMX platform. +
141
142 |===
143 | ConfigTransactionControllerMXBean | Extends ConfigTransactionController, executed by Jolokia clients on configuration transaction.
144 | ConfigRegistryMXBean | Represents entry point of configuration management for MXBeans.
145 | Object names | Object Name is the pattern used in JMX to locate JMX beans. It consists of domain and key properties (at least one key-value pair). Domain is defined as "org.opendaylight.controller". The only mandatory property is "type".
146 |===
147
148 ===== Use case scenarios
149
150 A few samples of successful and unsuccessful transaction scenarios follow: +
151
152 *Successful commit scenario*
153
154 . The user creates a transaction calling creteTransaction() method on ConfigRegistry.
155 . ConfigRegisty creates a transaction controller, and registers the transaction as a new bean.
156 . Runtime configurations are copied to the transaction. The user can create modules and set their attributes.
157 . The configuration transaction is to be committed.
158 . The validation process is performed.
159 . After successful validation, the second phase commit begins.
160 . Modules proposed to be destroyed are destroyed, and their service instances are closed.
161 . Runtime beans are set to registrator.
162 . The transaction controller invokes the method getInstance on each module.
163 . The transaction is committed, and resources are either closed or released.
164
165 *Validation failure scenario* +
166 The transaction is the same as the previous case until the validation process. +
167
168 . If validation fails, (that is to day, illegal input attributes values or dependency resolver failure), the validationException is thrown and exposed to the user.
169 . The user can decide to reconfigure the transaction and commit again, or abort the current transaction.
170 . On aborted transactions, TransactionController and JMXRegistrator are properly closed.
171 . Unregistration event is sent to ConfigRegistry.
172
173 ===== Default module instances
174 The configuration subsystem provides a way for modules to create default instances. A default instance is an instance of a module, that is created at the module bundle start-up (module becomes visible for
175 configuration subsystem, for example, its bundle is activated in the OSGi environment). By default, no default instances are produced.
176
177 The default instance does not differ from instances created later in the module life-cycle. The only difference is that the configuration for the default instance cannot be provided by the configuration subsystem.
178 The module has to acquire the configuration for these instances on its own. It can be acquired from, for example, environment variables.
179 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.).
180
181 === OpenDaylight Controller configuration: Initial
182 The Initial configuration of the controller involves two methods.
183
184 === Initial configuration for controller
185 The two ways of configuring the controller: +
186
187 * Using the https://wiki.opendaylight.org/view/OpenDaylight_Controller:Config:config.ini[config.ini] property file to pass configuration properties to the OSGi bundles besides the config subsystem.
188 * Using the https://wiki.opendaylight.org/view/OpenDaylight_Controller:Config:Configuration:Initial#Configuration_Persister[configuration persister] to push the initial configuration for modules managed by the config subsystem.
189
190 ==== Using the config.ini property file
191
192 The config.ini property file can be used to provide a set of properties for any OSGi bundle deployed to the controller. It is usually used to configure bundles that are not managed by the config subsystem. For details, see <<_opendaylight_controller_configuration_config_ini>>.
193
194 ==== Using configuration persister
195
196 Configuration persister is a default service in the controller, and is started automatically using the OSGi Activator. Its purpose is to load the initial configuration for the config subsystem and store a snapshot for every new configuration state pushed to the config-subsystem from external clients.
197 For details, see <<_opendaylight_controller_configuration_persister>>.
198
199 === OpenDaylight Controller configuration: config.ini
200
201 Various parts of the system that are not under the configuration subsystem use the file config.ini. Changes to this file apply after a server restart. The tabulation of several important configuration keys and values follows:
202
203 [cols="2*", width="75%"]
204 |===
205
206 |Setting | Description
207 | yangstore.blacklist=.\*controller.model.* | This regular expression (can be OR-ed using pipe character) tells netconf to exclude the yang files found in the matching bundle symbolic name from the hello message. This is helpful when dealing with a netconf client that has parsing problems.
208 | netconf.config.persister.* settings  | See <<_opendaylight_controller_configuration_initial>>.
209 | netconf.tcp.address=0.0.0.0 netconf.tcp.port=8383 +
210
211 netconf.ssh.address=0.0.0.0 netconf.ssh.port=1830 netconf.ssh.pk.path = ./configuration/RSA.pk +
212
213 netconf.tcp.client.address=127.0.0.1 netconf.tcp.client.port=8383 | These settings specify the netconf server bindings. IP address 0.0.0.0 is used when all available network interfaces must be used by the netconf server. When starting the ssh server, the user must provide a private key. The actual authentication is done in the user admin module. By default, users admin:admin and netconf:netconf can be used to connect by means of ssh. Since the ssh bridge acts as a proxy, one needs to specify the netconf plaintext TCP address and port. These settings must normally be identical to those specified by netconf.tcp.* .
214 |===
215 === OpenDaylight Controller: Configuration Persister
216 One way of configuring the controller is to use the configuration persister to push the initial configuration for modules managed by the config subsystem.
217
218 ==== Using configuration persister
219
220 The configuration persister is a default service in the controller, and is started automatically using the OSGi Activator.
221 Its purpose: +
222
223 * Load the initial configuration for the config subsystem.
224 * Store a snapshot for every new configuration state pushed to the config-subsystem from external clients. +
225
226 It retrieves the base configuration from the config.ini property file, and tries to load the configuration for the config subsystem.
227 The configuration for the config subsystem is pushed as a set of edit-config netconf rpcs followed by a commit rpc since the config persister acts as a netconf client.
228
229 *Configuration persister lifecycle:* +
230
231 . Start the config persister service at _config-persister-impl_ bundle startup.
232 . Retrieve the base configuration of the adapters from the config.ini property file.
233 . Initialize the backing storage adapters.
234 . Initialize the netconf client, and connect to the netconf endpoint of the config subsystem.
235 . Load the initial configuration snapshots from the latest storage adapter.
236 . Send the edit-config rpc with the initial configuration snapshots.
237 . Send the commit rpc.
238 . Listen for any of the following changes to the configuration and persist a snapshot.
239
240 *Configuration Persister interactions:* +
241
242 .Persister
243 image::Persister.jpg[width=500]
244
245 === Current configuration for controller distribution
246
247 The _config.ini_ property file contains the following configuration for the configuration persister: +
248 ----
249 netconf.config.persister.active=1,2
250
251 netconf.config.persister.1.storageAdapterClass=org.opendaylight.controller.config.persist.storage.directory.autodetect.AutodetectDirectoryStorageAdapter
252
253 netconf.config.persister.1.properties.directoryStorage=configuration/initial/
254
255 netconf.config.persister.1.readonly=true
256
257
258 netconf.config.persister.2.storageAdapterClass=org.opendaylight.controller.config.persist.storage.file.xml.XmlFileStorageAdapter
259
260 netconf.config.persister.2.properties.fileStorage=configuration/current/controller.currentconfig.xml
261
262 netconf.config.persister.2.properties.numberOfBackups=1
263 ----
264
265 With this configuration, the configuration persister initializes two adapters: +
266
267 * AutodetectDirectoryStorageAdapter to load the initial configuration files from the _configuration/initial/_ folder. These files will be pushed as the initial configuration for the config subsystem. Since this adapter is Read only, it will not store any configuration snapshot during the controller lifecycle.
268 * XmlFileStorageAdapter to store snapshots of the current configuration after any change in the file _configuration/current/controller.currentconfig.xml_ (Only 1 snapshot backup is kept; every new change overwrites the previous one). +
269 The initial configuration in the controller distribution consists of 2 files in the https://wiki.opendaylight.org/view/OpenDaylight_Controller:Config:Configuration:Initial#Persisted_snapshot_format[xml format]. +
270 * configuration/initial/00-netty.xml: +
271 ----
272 <snapshot>
273     <required-capabilities>
274         <capability>urn:opendaylight:params:xml:ns:yang:controller:netty?module=netty&amp;revision=2013-11-19</capability>
275         <capability>urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&amp;revision=2013-11-12</capability>
276         <capability>urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup?module=threadgroup&amp;revision=2013-11-07</capability>
277         <capability>urn:opendaylight:params:xml:ns:yang:controller:netty:timer?module=netty-timer&amp;revision=2013-11-19</capability>
278     </required-capabilities>
279     <configuration>
280
281         <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
282             <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
283                 <module>
284                     <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup">netty:netty-threadgroup-fixed</type>
285                     <name>global-boss-group</name>
286                 </module>
287                 <module>
288                     <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup">netty:netty-threadgroup-fixed</type>
289                     <name>global-worker-group</name>
290                 </module>
291                 <module>
292                     <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty:timer">netty:netty-hashed-wheel-timer</type>
293                     <name>global-timer</name>
294                 </module>
295                 <module>
296                     <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor">netty:netty-global-event-executor</type>
297                     <name>global-event-executor</name>
298                 </module>
299             </modules>
300
301             <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
302                 <service>
303                     <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-threadgroup</type>
304                     <instance>
305                         <name>global-boss-group</name>
306                         <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-boss-group']</provider>
307                     </instance>
308                     <instance>
309                         <name>global-worker-group</name>
310                         <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-worker-group']</provider>
311                     </instance>
312                 </service>
313                 <service>
314                     <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-event-executor</type>
315                     <instance>
316                         <name>global-event-executor</name>
317                         <provider>/modules/module[type='netty-global-event-executor'][name='global-event-executor']</provider>
318                     </instance>
319                 </service>
320                 <service>
321                     <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-timer</type>
322                     <instance>
323                         <name>global-timer</name>
324                         <provider>/modules/module[type='netty-hashed-wheel-timer'][name='global-timer']</provider>
325                     </instance>
326                 </service>
327             </services>
328         </data>
329
330     </configuration>
331 </snapshot>
332 ----
333 This configuration snapshot instantiates netty utilities, which will be utilized by the controller components that use netty internally. +
334
335 *configuration/initial/01-md-sal.xml:* +
336 ----
337 <snapshot>
338
339     <configuration>
340
341         <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
342             <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
343                 <module>
344                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</type>
345                     <name>yang-schema-service</name>
346                 </module>
347                 <module>
348                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:hash-map-data-store</type>
349                     <name>hash-map-data-store</name>
350                 </module>
351                 <module>
352                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
353                     <name>dom-broker</name>
354                     <data-store xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
355                         <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
356                         <!-- to switch to the clustered data store, comment out the hash-map-data-store <name> and uncomment the cluster-data-store one -->
357                         <name>hash-map-data-store</name>
358                         <!-- <name>cluster-data-store</name> -->
359                     </data-store>
360                 </module>
361                 <module>
362                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
363                     <name>binding-broker-impl</name>
364                     <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
365                         <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
366                         <name>binding-notification-broker</name>
367                     </notification-service>
368                     <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
369                         <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
370                         <name>binding-data-broker</name>
371                     </data-broker>
372                 </module>
373                 <module>
374                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</type>
375                     <name>runtime-mapping-singleton</name>
376                 </module>
377                 <module>
378                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</type>
379                     <name>binding-notification-broker</name>
380                 </module>
381                 <module>
382                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-broker</type>
383                     <name>binding-data-broker</name>
384                     <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
385                         <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
386                         <name>dom-broker</name>
387                     </dom-broker>
388                     <mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
389                         <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
390                         <name>runtime-mapping-singleton</name>
391                     </mapping-service>
392                 </module>
393
394             </modules>
395
396             <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
397                         <service>
398                                 <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
399                                 <instance>
400                                         <name>yang-schema-service</name>
401                                         <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
402                                 </instance>
403                         </service>
404                         <service>
405                                 <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
406                                 <instance>
407                                         <name>binding-notification-broker</name>
408                                         <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
409                                 </instance>
410                         </service>
411                         <service>
412                                 <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
413                                 <instance>
414                                         <name>hash-map-data-store</name>
415                                         <provider>/modules/module[type='hash-map-data-store'][name='hash-map-data-store']</provider>
416                                 </instance>
417                         </service>
418                         <service>
419                                 <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
420                                 <instance>
421                                         <name>binding-osgi-broker</name>
422                                         <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
423                                 </instance>
424                         </service>
425                         <service>
426                                 <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
427                                 <instance>
428                                         <name>binding-rpc-broker</name>
429                                         <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
430                                 </instance>
431                         </service>
432                         <service>
433                                 <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
434                                 <instance>
435                                         <name>runtime-mapping-singleton</name>
436                                         <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
437                                 </instance>
438                         </service>
439                         <service>
440                         <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
441                                 <instance>
442                                         <name>dom-broker</name>
443                                         <provider>/modules/module[type='dom-broker-impl'][name='dom-broker']</provider>
444                                 </instance>
445                         </service>
446                         <service>
447                                 <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
448                                 <instance>
449                                         <name>binding-data-broker</name>
450                                         <provider>/modules/module[type='binding-data-broker'][name='binding-data-broker']</provider>
451                                 </instance>
452                         </service>
453
454             </services>
455         </data>
456
457     </configuration>
458
459     <required-capabilities>
460         <capability>urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&amp;revision=2013-11-12</capability>
461         <capability>urn:opendaylight:params:xml:ns:yang:controller:threadpool?module=threadpool&amp;revision=2013-04-09</capability>
462         <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
463         <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&amp;revision=2013-10-28</capability>
464         <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&amp;revision=2013-10-28</capability>
465         <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&amp;revision=2013-10-28</capability>
466         <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&amp;revision=2013-10-28</capability>
467     </required-capabilities>
468
469 </snapshot>
470 ----
471 This configuration snapshot instantiates md-sal modules.
472
473 After the controller is started, all these modules will be instantiated and configured. They can be further referenced from the new modules as dependencies, reconfigured, or even deleted.
474 These modules are considered to be the base configuration for the controller and the purpose of them being configured automatically is to simplify the process of controller configuration for users, since the base modules will already be ready for use.
475
476 === Adding custom initial configuration
477
478 There are multiple ways to add the custom initial confguration to the controller distribution:
479
480 . Manually create the config file, and put it in the initial configuration folder.
481 . Reconfigure the running controller using the yuma yangcli tool. The XmlFileStorageAdapter adapter will store the current snapshot, and on the next startup of the controller (assuming it was not rebuilt since), it will load the configuration containing the changes.
482
483 ==== Custom initial configuration in bgpcep distribution
484
485 The BGPCEP project will serve as an example for adding the custom initial configuration. The bgpcep project contains the custom initial configuration that is based on the initial configuration from the controller. It adds new modules, which depend on MD-SAL and netty modules created with the initial config files of the controller. There are multiple config files in the bgpcep project. Only the 30-programming.xml file located under the programming-parent/controller-config project will be described in this section. This file contains the configuration for an instance of the instruction-scheduler module:
486
487 ----
488 <?xml version="1.0" encoding="UTF-8"?>
489 <!-- vi: set et smarttab sw=4 tabstop=4: -->
490 <!--
491       Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
492
493  This program and the accompanying materials are made available under the
494  terms of the Eclipse Public License v1.0 which accompanies this distribution,
495  and is available at http://www.eclipse.org/legal/epl-v10.html.
496 -->
497 <snapshot>
498         <required-capabilities>
499                 <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
500                 <capability>urn:opendaylight:params:xml:ns:yang:controller:netty?module=netty&amp;revision=2013-11-19</capability>
501                 <capability>urn:opendaylight:params:xml:ns:yang:controller:programming:impl?module=config-programming-impl&amp;revision=2013-11-15</capability>
502                 <capability>urn:opendaylight:params:xml:ns:yang:controller:programming:spi?module=config-programming-spi&amp;revision=2013-11-15</capability>
503         </required-capabilities>
504         <configuration>
505
506                 <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
507                         <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
508                                 <module>
509                                         <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:programming:impl">prefix:instruction-scheduler-impl</type>
510                                         <name>global-instruction-scheduler</name>
511                                         <data-provider>
512                                                 <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
513                                                 <name>binding-data-broker</name>
514                                         </data-provider>
515                                         <notification-service>
516                                                 <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
517                                                 <name>binding-notification-broker</name>
518                                         </notification-service>
519                                         <rpc-registry>
520                                                 <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
521                                                 <name>binding-rpc-broker</name>
522                                         </rpc-registry>
523                                         <timer>
524                                                 <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-timer</type>
525                                                 <name>global-timer</name>
526                                         </timer>
527                                 </module>
528                         </modules>
529
530                         <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
531                                 <service>
532                                         <type xmlns:pgmspi="urn:opendaylight:params:xml:ns:yang:controller:programming:spi">pgmspi:instruction-scheduler</type>
533                                         <instance>
534                                                 <name>global-instruction-scheduler</name>
535                                                 <provider>/modules/module[type='instruction-scheduler-impl'][name='global-instruction-scheduler']</provider>
536                                         </instance>
537                                 </service>
538                         </services>
539                 </data>
540
541         </configuration>
542 </snapshot>
543 ----
544 Instruction-scheduler is instantiated as a module of type _instruction-scheduler-impl_ with the name *global-instruction-scheduler:* +
545 ----
546 <module>
547        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:programming:impl">prefix:instruction-scheduler-impl</type>
548        <name>global-instruction-scheduler</name>
549        ...
550 ----
551 There is also an alias created for this module instancfe, and the alias is *global-instruction-scheduler* of type _instruction-scheduler_: +
552 ----
553 ...
554 <service>
555         <type xmlns:pgmspi="urn:opendaylight:params:xml:ns:yang:controller:programming:spi">pgmspi:instruction-scheduler</type>
556         <instance>
557                 <name>global-instruction-scheduler</name>
558                 <provider>/modules/module[type='instruction-scheduler-impl'][name='global-instruction-scheduler']</provider>
559         </instance>
560 </service>
561 ...
562 ----
563 The type of the alias is instruction-scheduler. This type refers to a certain service that is implemented by the instruction-scheduler-impl module. With this service type, the global-instruction-scheduler instance can be injected into any other module that requires instruction-scheduler as a dependency.
564 One module can provide (implement) multiple services, and each of these services can be assigned an alias. This alias can be later used to reference the implementation it is pointing to.
565 If no alias is assigned by the user, a default alias will be assigned for each provided service.
566 The default alias is constructed from the name of the module instance with a prefix *ref_* and a possible suffix containing a number to resolve name clashes.
567 It is recommended that users provide aliases for each service of every module instance, and use these aliases for dependency injection. References to the alias global-instruction-scheduler can be found in subsequent config files in the bgpcep project for example, _32-pcep.xml_ located under the _pcep-parent/pcep-controller-config_ project.
568
569 The configuration contains four dependencies on the MD-SAL and the netty modules: +
570 ----
571 ...
572 <data-provider>
573         <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
574         <name>binding-data-broker</name>
575 </data-provider>
576 <notification-service>
577         <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
578         <name>binding-notification-broker</name>
579 </notification-service>
580 <rpc-registry>
581         <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
582         <name>binding-rpc-broker</name>
583 </rpc-registry>
584 <timer>
585         <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-timer</type>
586         <name>global-timer</name>
587 </timer>
588 ...
589 ----
590
591 MD-SAL dependencies: +
592
593 * Data-provider dependency
594 * Notification-service dependency
595 * Rpc-registry dependency
596
597 All MD-SAL dependencies can be found in the https://wiki.opendaylight.org/view/OpenDaylight_Controller:Config:Configuration:Initial#Current_configuration_for_controller_distribution[MD-SAL initial configuration file]. For example, rpc-registry dependency points to an alias binding-rpc-broker of the type binding-rpc-registry. This alias further points to an instance of the binding-broker-impl named binding-broker-impl.
598 The Yang module that defines the binding-broker-impl module : https://git.opendaylight.org/gerrit/gitweb?p=controller.git;f=opendaylight/md-sal/sal-binding-broker/src/main/yang/opendaylight-binding-broker-impl.yang;a=blob[opendaylight-binding-broker-impl.yang].
599
600 *Netty dependencies:* +
601
602 * Timer dependency
603
604 This configuration expects these dependencies to be already up and ready. It is the responsibility of the configuration subsystem to find the dependency and inject it.
605 If the configuration of a module points to a non-existing dependency, the configuration subsystem will produce an exception during the validation phase.
606 Every user-created configuration needs to point to existing dependencies. In the case of multiple initial configuration files that depend on one another, the resolution order can be ensured by the names of the files. Files are sorted by their names in ascending order. This means that every configuration file will have the visibility of modules from all previous configuration files by means of aliases.
607
608 NOTE: The configuration provided by initial config files can also be pushed to the controller at runtime using netconf client. The whole configuration located under the data tag needs to be inserted into the config tag in the edit-config rpc. For more information, see https://wiki.opendaylight.org/view/OpenDaylight_Controller:Config:Main#Examples[Examples].
609
610 ==== Configuration Persister
611
612 As a part of the configuration subsystem, the purpose of the persister is to save and load a permanent copy of a configuration. The Persister interface represents basic operations over a storage - persist configuration and load last config, configuration snapshot is represented as string and set of it's capabilities. StorageAdapter represents an adapter interface to the ConfigProvider - subset of BundleContext, allowing access to the OSGi framework system properties.
613
614 ===== Persister implementation
615
616 Configuration persister implementation is part of the Controller Netconf. PersisterAggregator class is the implementation of the Presister interface. The functionality is delegated to the storage adapters. Storage adapters are low level persisters that do the heavy lifting for this class. Instances of storage adapters can be injected directly by means of the constructor, or instantiated from a full name of its class provided in a properties file. There can be many persisters configured, and varying numbers of them can be used.
617
618 *Example of presisters configuration:* +
619 ----
620 netconf.config.persister.active=2,3
621  # read startup configuration
622  netconf.config.persister.1.storageAdapterClass=org.opendaylight.controller.config.persist.storage.directory.xml.XmlDirectoryStorageAdapter
623  netconf.config.persister.1.properties.fileStorage=configuration/initial/
624
625  netconf.config.persister.2.storageAdapterClass=org.opendaylight.controller.config.persist.storage.file.FileStorageAdapter
626  netconf.config.persister.2.readonly=true
627  netconf.config.persister.2.properties.fileStorage=configuration/current/controller.config.1.txt
628
629  netconf.config.persister.3.storageAdapterClass=org.opendaylight.controller.config.persist.storage.file.FileStorageAdapter
630  netconf.config.persister.3.properties.fileStorage=configuration/current/controller.config.2.txt
631  netconf.config.persister.3.properties.numberOfBackups=3
632 ----
633
634 During server startup, ConfigPersisterNotificationHandler requests the last snapshot from the underlying storages. Each storage can respond by giving a snapshot or an absent response. The PersisterAggregator#loadLastConfigs() will search for the first non-absent response from storages ordered backwards as user specified (first '3', then '2'). When a commit notification is received, '2' will be omitted because the read-only flag is set to true, so only '3' will have a chance to persist the new configuration.
635 If read-only was false, or not specified, both storage adapters would be called in the order specified by 'netconf.config.persister' property.
636
637 === Persister Notification Handler
638
639 ConfigPersisterNotificationHandler class is responsible for listening for netconf notifications containing the latest committed configuration.
640 The listener can handle incoming notifications, or delegates the configuration saving or loading to the persister.
641
642 ==== Storage Adapter implementations
643
644 *XML File Storage* +
645
646 The XmlFileStorageAdapter implementation stores configuration in an xml file.
647
648 *XML Directory Storage* +
649
650 XmlDirectoryStorageAdapter retrieves the initial configuration from a directory. If multiple xml files are present, files are ordered based on the file names and pushed in this order (for example, 00.xml, then 01.xml..) Each file defines its required capabilities, so it will be pushed when those capabilities are advertized by ODL. Writing to this persister is not supported.
651
652 *No-Operation Storage* +
653
654 NoOpStorageAdapter serves as a dummy implementation of the storage adapter.
655
656 *Obsolete storage adapters* +
657
658 * File Storage
659
660 * FileStorageAdapter implements StorageAdapter, and provides file based configuration persisting.
661 File path and name is stored as a property and a number of stored backups, expressing the count of the last configurations to be persisted too.
662 The implementation can handle persisting input configuration, and load the last configuration.
663
664 * Directory Storage
665
666 * DirectoryStorageAdapter retrieves initial configurations from a directory. If multiple files are present, snapshot and required capabilities will be merged together. See configuration later on this page for details. Writing to this persister is not supported.
667
668 * Autodetect Directory Storage
669
670 * AutodetectDirectoryStorageAdapter retrieves initial configuration from a directory (exactly as Xml Directory Storage) but supports xml as well as plaintext format for configuration files. Xml and plaintext files can be combined in one directory. Purpose of this persister is to keep backwards compatibility for plaintext configuration files.
671
672 IMPORTANT: This functionality will be removed in later releases since Plaintext File/Directory adapters are deprecated, and will be fully replaced by xml storage adapters.
673
674 ===== Persisted snapshot format
675
676 Configuration snapshots are persisted in xml files for both file and directory adapters. They share the same format: +
677 ----
678 <snapshot>
679     <required-capabilities>
680         <capability>urn:opendaylight:params:xml:ns:yang:controller:netty?module=netty&amp;revision=2013-11-19</capability>
681         ...
682     </required-capabilities>
683     <configuration>
684
685         <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
686             <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
687              ...
688             </modules>
689
690             <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
691              ...
692             </services>
693
694         </data>
695
696     </configuration>
697 </snapshot>
698 ----
699 The whole snapshot is encapsulated in the snapshot tag that contains two children elements: +
700
701 * The required-capabilities tag contains the list of yang capabilities that are required to push configurations located under the configuration tag. The config persister will not push the configuration before the netconf endpoint for the config subsystem reports all needed capabilities. Every yang model that is referenced within this xml file (as namespace for xml tag) must be referenced as a capability in this list.
702 * The configuration tag contains the configurations to be pushed to the config subsystem. It is wrapped in a data tag with the base netconf namespace. The whole data tag, with all its child elements, will be inserted into an edit-config rpc as config tag. For more information about the structure of configuration data, see  base yang model for the config subsystem and all the configuration yang files for the controller modules as well as those provided examples. Examples contain multiple explained edit-config rpcs that change the configuration.
703
704 NOTE:  XML File adapter adds additional tags to the xml format since it supports multiple snapshots per file.
705
706 The xml format for xml file adapter: +
707 ----
708 <persisted-snapshots>
709    <snapshots>
710       <snapshot>
711          <required-capabilities>
712             <capability>urn:opendaylight:params:xml:ns:yang:controller:shutdown:impl?module=shutdown-impl&amp;revision=2013-12-18</capability>
713          </required-capabilities>
714          <configuration>
715             <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
716                <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
717                  ....
718                </modules>
719                <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
720                  ...
721                </services>
722             </data>
723          </configuration>
724       </snapshot>
725       <snapshot>
726          <required-capabilities>
727             <capability>urn:opendaylight:params:xml:ns:yang:controller:shutdown:impl?module=shutdown-impl&amp;revision=2013-12-18</capability>
728          </required-capabilities>
729          <configuration>
730             <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
731                <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
732                  ....
733                </modules>
734                <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
735                  ...
736                </services>
737             </data>
738          </configuration>
739       </snapshot>
740    </snapshots>
741 </persisted-snapshots>
742 ----
743
744
745 === OpenDaylight Controller configuration: FAQs
746 ====  Generic questions about the configuration subsystem
747 *There is already JMX. Why do we need another system?*
748
749 Java Management Extensions (JMX) provides programmatic access to management data, defining a clear structure on the level of a single object (MBeans). It provides the mechanism to query and set information exposed from these MBeans, too. It is adequate for replacing properties, but it does not treat the JVM container for what it is: a collection of applications working in concert. When the configuration problem is taken to the level of an entire system, there are multiple issues which JMX does not solve:
750
751 * The need to validate that a proposed system is semantically valid before an attempt to change is made
752 * The ability to synchronize modification multiple properties at the same time, such that both occur at the same time
753 * The ability to express dependencies between applications
754 * Machine-readable descriptions of layouts of configuration data
755
756 *Why use YANG?*
757
758 The problem of configuring a device has been tackled in https://ietf.org/[IETF] for many years now, initially using https://en.wikipedia.org/wiki/Simple_Network_Management_Protocol[SNMP] (with https://en.wikipedia.org/wiki/Management_information_base[MIB] as the data definition language). While the protocol has been successful for monitoring devices, it has never gained traction as the unified way of configuring devices. The reasons for this have been https://tools.ietf.org/html/rfc3535[analyzed] and https://datatracker.ietf.org/doc/rfc6241/[NETCONF] was standardized as the successor protocol. NETCONF provides the abstractions to deal with configuration validation, and relies on http://tools.ietf.org/html/rfc6020[YANG] as its data modeling language. The configuration subsystem is designed to completely align with NETCONF such that it can be used as the native transport with minimal translation.
759
760 === OpenDaylight Controller configuration: Component map
761 [cols="5,5a",^,options="header",width="75%"]
762 |===
763 | Component | Description
764 | config-subsystem-core | Config subsystem core.
765                         Manages the configuration of the controller.
766
767 Responsibilities:
768
769
770 * Scanning of bundles for ModuleFactories.
771
772 * Transactional management of lifecycle and dependency injection for config modules.
773
774 * Exposure of modules and their configuration into JMX.
775 | netty-config| Config modules for netty related resources, for example, netty-threadgroup, netty-timer and others.
776
777 Contains config module definition in the form of yang schemas + generated code binding for the config subsystem.
778 | controller-shutdown | Controller shutdown mechanism.
779
780 Brings down the whole OSGi container of the controller.
781
782 Authorization required in the form of a "secret string".
783
784 Also contains config module definition in the form of yang schemas + generated code binding for the config subsystem. This makes it possible to invoke shutdown by means of the config-subsystem.
785 | threadpool-config | Config modules for threading related resources, for example, threadfactories, fixed-threadpool, and others.
786
787 Contains config module definition in the form of yang schemas + generated code binding for the config subsystem.
788 | logback-config | Config modules for logging (logback) related resources, for example, loggers, appenders, and others.
789
790 Contains config module definition in the form of yang schemas + generated code binding for the config subsystem.
791 | netconf-config-dispatcher-config | Config modules for netconf-dispatcher(from netconf subsystem).
792
793 Contains config module definition in the form of yang schemas + generated code binding for the config subsystem.
794 | yang-jmx-config-generator | Maven plugin that generates the config subsystem code binding from provided yang schemas. This binding is required when the bundles want to participate in the config subsystem.
795 | yang-jmx-config-generator-testing-modules | Testing resources for the maven plugin.
796 | config-persister | Contains the api definition for an extensible configuration persister(database for controller configuration).
797
798 The persister (re)stores the configuration for the controller. Persister implementation can be found in the netconf subsystem.
799
800 The adapter bundles contain concrete implementations of storage extension. They store the config as xml files on the filesystem.
801 | config-module-archetype | Maven archetype for "config subsystem aware" bundles.
802
803 This archetype contains blueprints for yang-schemas, java classes, and other files(for example, pom.xml) required for a bundle to participate in the config subsystem.
804
805 This archetype generates a bundle skeleton that can be developed into a full blown "config subsystem aware" bundle.
806 |===
807
808 === OpenDaylight Controller: Netconf component map
809
810 [cols="2", options="header", width="75%"]
811 |===
812 |Component | Description
813
814 | netconf-server | Implementation of the generic (extensible) netconf server over tcp/ssh. Handles the general communication over the network, and forwards the rpcs to its extensions that implement the specific netconf rpc handles (For example: get-config).
815 | netconf-to-config-mapping | API definition for the netconf server extension with the base implementation that transforms the netconf rpcs to java calls for the config-subsystem (config-subsystem netconf extension).
816 | netconf-client | Netconf client basic implementation. Simple netconf client that supports netconf communication with remote netconf devices using xml format.
817 | netconf-monitoring | Netconf-monitoring yang schemas with the implementation of a netconf server extension that handles the netconf-monitoring related handlers (For example: adding netconf-state to get rpc)
818 | config-persister-impl | Extensible implementation of the config persister that persists the configuration in the form of xml,(easy to inject to edit-config rpc) and loads the initial configuration from the persisted files. The configuration is stored after every successful commit rpc.
819 | netconf-cli | Prototype of a netconf cli.
820 |===
821
822 === OpenDaylight Controller Configuration: Examples sample project
823 *Sample maven project* +
824
825 In this example, we will create a maven project that provides two modules, each implementing one service. We will design a simple configuration, as well as runtime data for each module using yang.
826 A sample maven project called config-demo was created. This project contains two Java interfaces: Foo and Bar. Each interface has one default implementation per interface, FooImpl and BarImpl. Bar is the producer in our example and produces integers when the method getNextEvent() is called. Foo is the consumer, and its implementation depends on a Bar instance. Both implementations require some configuration that is injected by means of constructors.
827
828 * Bar.java:
829 ----
830 package org.opendaylight.controller.config.demo;
831
832 public interface Bar {
833
834     int getNextEvent();
835
836 }
837 ----
838 * BarImpl.java:
839 ----
840 package org.opendaylight.controller.config.demo;
841
842 public class BarImpl implements Bar {
843
844     private final int l1, l2;
845     private final boolean b;
846
847     public BarImpl(int l1, int l2, boolean b) {
848         this.l1 = l1;
849         this.currentL = l1;
850         this.l2 = l2;
851         this.b = b;
852     }
853
854     private int currentL;
855
856     @Override
857     public int getNextEvent() {
858         if(currentL==l2)
859             return -1;
860         return currentL++;
861     }
862 }
863 ----
864 * Foo.java:
865 ----
866 package org.opendaylight.controller.config.demo;
867
868 public interface Foo {
869
870     int getEventCount();
871 }
872 ----
873 * FooImpl.java:
874 ----
875 package org.opendaylight.controller.config.demo;
876
877 public class FooImpl implements Foo {
878
879     private final String strAttribute;
880     private final Bar barDependency;
881     private final int intAttribute;
882
883     public FooImpl(String strAttribute, int intAttribute, Bar barDependency) {
884         this.strAttribute = strAttribute;
885         this.barDependency = barDependency;
886         this.intAttribute = intAttribute;
887     }
888
889     @Override
890     public int getEventCount() {
891         int count = 0;
892         while(barDependency.getNextEvent() != intAttribute) {
893             count++;
894         }
895         return count;
896     }
897 }
898 ----
899 * pom.xml (config-demo project is defined as a sub-module of the controller project, and at this point contains only the configuration for maven-bundle-plugin):
900 ----
901 <?xml version="1.0" encoding="UTF-8"?>
902 <project xmlns="http://maven.apache.org/POM/4.0.0"
903          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
904          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
905     <modelVersion>4.0.0</modelVersion>
906
907     <parent>
908         <artifactId>commons.opendaylight</artifactId>
909         <groupId>org.opendaylight.controller</groupId>
910         <version>1.4.1-SNAPSHOT</version>
911         <relativePath>../commons/opendaylight/pom.xml</relativePath>
912     </parent>
913     <groupId>org.opendaylight.controller</groupId>
914     <version>0.1.1-SNAPSHOT</version>
915     <artifactId>config-demo</artifactId>
916     <packaging>bundle</packaging>
917     <name>${project.artifactId}</name>
918     <prerequisites>
919         <maven>3.0.4</maven>
920     </prerequisites>
921
922     <build>
923         <plugins>
924             <plugin>
925                 <groupId>org.apache.felix</groupId>
926                 <artifactId>maven-bundle-plugin</artifactId>
927                 <version>2.4.0</version>
928                 <extensions>true</extensions>
929                 <configuration>
930                     <instructions>
931                         <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
932                         <Export-Package>
933                             org.opendaylight.controller.config.demo,
934                         </Export-Package>
935                     </instructions>
936                 </configuration>
937             </plugin>
938         </plugins>
939     </build>
940
941 </project>
942 ----
943
944 ==== Describing the module configuration using yang
945 In order to fully leverage the utilities of the configuration subsystem, we need to describe the services, modules, their configurations, and the runtime state using the yang modeling language. We will define two services and two modules, which will be used to configure the instances of FooImpl and BarImpl. This definition will be split into two yang files: config-demo.yang (service definition) and config-demo-impl.yang (module definition).
946
947 * config-demo.yang
948 ----
949 module config-demo {
950     yang-version 1;
951     namespace "urn:opendaylight:params:xml:ns:yang:controller:config:demo";
952     prefix "demo";
953
954     import config { prefix config; revision-date 2013-04-05; }
955
956     description
957         "Service definition for config-demo";
958
959     revision "2013-10-14" {
960         description
961             "Initial revision";
962     }
963
964     // Service definition for service foo that encapsulates instances of org.opendaylight.controller.config.demo.Foo
965     identity foo {
966         description
967             "Foo service definition";
968
969         base "config:service-type";
970         config:java-class "org.opendaylight.controller.config.demo.Foo";
971     }
972
973     identity bar {
974         description
975             "Bar service definition";
976
977         base "config:service-type";
978         config:java-class "org.opendaylight.controller.config.demo.Bar";
979     }
980 }
981 ----
982 The config yang module needs to be imported in order to define the services. There are two services defined, and these services correspond to the Java interfaces Foo and Bar (specified by the config:java-class extension).
983
984 * config-demo-impl.yang
985 ----
986 module config-demo-impl {
987
988     yang-version 1;
989     namespace "urn:opendaylight:params:xml:ns:yang:controller:config:demo:java";
990     prefix "demo-java";
991
992     // Dependency on service definition for config-demo
993     /* Service definitions could be also located in this yang file or even
994      * in a separate maven project that is marked as maven dependency
995      */
996     import config-demo { prefix demo; revision-date 2013-10-14;}
997
998     // Dependencies on config subsystem definition
999     import config { prefix config; revision-date 2013-04-05; }
1000     import rpc-context { prefix rpcx; revision-date 2013-06-17; }
1001
1002
1003     description
1004         "Service implementation for config-demo";
1005
1006     revision "2013-10-14" {
1007         description
1008             "Initial revision";
1009     }
1010                                                                       //----- module foo-impl ----- //
1011     // Module implementing foo service                                                              //
1012     identity foo-impl {                                                                             //
1013         base config:module-type;                                                                    //
1014         config:provided-service demo:foo;                                                           //
1015         config:java-name-prefix FooImpl;                                                            //
1016     }                                                                                               //
1017                                                                                                     //
1018     // Configuration for foo-impl module                                                            //
1019     augment "/config:modules/config:module/config:configuration" {                                  //
1020         case foo-impl {                                                                             //
1021             when "/config:modules/config:module/config:type = 'foo-impl'";                          //
1022                                                                                                     //
1023             leaf str-attribute {                                                                    //
1024                 type string;                                                                        //
1025             }                                                                                       //
1026                                                                                                     //
1027             leaf int-attribute {                                                                    //
1028                 type int32;                                                                         //
1029             }                                                                                       //
1030                                                                                                     //
1031                                                                                                     //
1032             // Dependency on bar service instance                                                   //
1033             container bar-dependency {                                                              //
1034                 uses config:service-ref {                                                           //
1035                     refine type {                                                                   //
1036                         mandatory true;                                                             //
1037                         config:required-identity demo:bar;                                          //
1038                     }                                                                               //
1039                 }                                                                                   //
1040             }                                                                                       //
1041                                                                                                     //
1042         }                                                                                           //
1043     }                                                                                               //
1044                                                                                                     //
1045     // Runtime state definition for foo-impl module                                                 //
1046     augment "/config:modules/config:module/config:state" {                                          //
1047         case foo-impl {                                                                             //
1048             when "/config:modules/config:module/config:type = 'foo-impl'";                          //
1049                                                                                                     //
1050                                                                                                     //
1051         }                                                                                           //
1052     }                                                                                               //
1053                                                                                       // ---------- //
1054     // Module implementing bar service
1055     identity bar-impl {
1056         base config:module-type;
1057         config:provided-service demo:bar;
1058         config:java-name-prefix BarImpl;
1059     }
1060
1061     augment "/config:modules/config:module/config:configuration" {
1062         case bar-impl {
1063             when "/config:modules/config:module/config:type = 'bar-impl'";
1064
1065             container dto-attribute {
1066                 leaf int-attribute {
1067                     type int32;
1068                 }
1069
1070                 leaf int-attribute2 {
1071                     type int32;
1072                 }
1073
1074                 leaf bool-attribute {
1075                     type boolean;
1076                 }
1077             }
1078
1079         }
1080     }
1081
1082     augment "/config:modules/config:module/config:state" {
1083         case bar-impl {
1084             when "/config:modules/config:module/config:type = 'bar-impl'";
1085
1086         }
1087     }
1088
1089 }
1090 ----
1091 The config yang module as well as the config-demo yang module need to be imported. There are two modules defined: foo-impl and bar-impl. Their configuration (defined in the augment "/config:modules/config:module/config:configuration" block) corresponds to the configuration of the FooImpl and BarImpl Java classes. In the constructor of FooImpl.java, we see that the configuration of foo-impl module defines three similar attributes. These arguments are used to instantiate the FooImpl class. These yang files are placed under the src/main/yang folder.
1092
1093 ==== Updating the maven configuration in pom.xml
1094
1095 The yang-maven-plugin must be added to the pom.xml. This plugin will process the yang files, and generate the configuration code for the defined modules. Plugin configuration: +
1096 ----
1097 <plugin>
1098     <groupId>org.opendaylight.yangtools</groupId>
1099     <artifactId>yang-maven-plugin</artifactId>
1100     <version>${yangtools.version}</version>
1101     <executions>
1102         <execution>
1103             <goals>
1104                 <goal>generate-sources</goal>
1105             </goals>
1106             <configuration>
1107                 <codeGenerators>
1108                     <generator>
1109                         <codeGeneratorClass>
1110                             org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
1111                         </codeGeneratorClass>
1112                         <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
1113                         <additionalConfiguration>
1114                             <namespaceToPackage1>
1115                                 urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
1116                             </namespaceToPackage1>
1117                         </additionalConfiguration>
1118                     </generator>
1119                 </codeGenerators>
1120                 <inspectDependencies>true</inspectDependencies>
1121             </configuration>
1122         </execution>
1123     </executions>
1124     <dependencies>
1125         <dependency>
1126             <groupId>org.opendaylight.controller</groupId>
1127             <artifactId>yang-jmx-generator-plugin</artifactId>
1128             <version>${config.version}</version>
1129         </dependency>
1130     </dependencies>
1131 </plugin>
1132 ----
1133 The configuration important for the plugin: the output folder for the generated files, and the mapping between the yang namespaces and the java packages (Inspect dependencies must be set to true.). The default location for the yang files is under the src/main/yang folder. This plugin is backed by the artifact yang-jmx-generator-plugin and its class org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator is responsible for code generation. This artifact is part of the configuration subsystem.
1134
1135 In addition to the yang-maven-plugin, it is neccessary to add the build-helper-maven-plugin in order to add the generated sources to the build process:
1136 ----
1137 <plugin>
1138    <groupId>org.codehaus.mojo</groupId>
1139    <artifactId>build-helper-maven-plugin</artifactId>
1140    <version>1.8</version>
1141    <executions>
1142        <execution>
1143            <id>add-source</id>
1144            <phase>generate-sources</phase>
1145            <goals>
1146                <goal>add-source</goal>
1147            </goals>
1148            <configuration>
1149                <sources>
1150                   <source>${project.build.directory}/generated-sources/config</source>;
1151                </sources>
1152            </configuration>
1153        </execution>
1154    </executions>
1155 </plugin>
1156 ----
1157 Earlier, the configuration yang module in the yang files was imported. In order to acquire this yang module, we need to add a dependency to the pom file:
1158 ----
1159 <dependency>
1160     <groupId>org.opendaylight.controller</groupId>
1161     <artifactId>config-api</artifactId>
1162     <version>${config.version}</version>
1163 </dependency>
1164 ----
1165 In addition, a couple of utility dependencies must be added:
1166 ----
1167 <dependency>
1168     <groupId>org.slf4j</groupId>
1169     <artifactId>slf4j-api</artifactId>
1170 </dependency>
1171 <dependency>
1172     <groupId>com.google.guava</groupId>
1173     <artifactId>guava</artifactId>
1174 </dependency>
1175 ----
1176 Run *mvn clean install*.
1177
1178 ==== Generated java files
1179
1180 A set of new source files divided into two groups is seen. The first group is located under the ${project.build.directory}/generated-sources/config directory, which was specified in the yang-maven-plugin configuration. The second group is located under the src/main/java directory. Both groups then define the package org.opendaylight.controller.config.yang.config.demo.impl. The first group contains code that must not be edited in any way, since this code can be regenerated by the plugin if necessary. The code that needs to be edited belongs to the second group and is located under src/main/java.
1181
1182 ===== Generated config source files examples
1183
1184 * BarImplModuleMXBean.java
1185 ----
1186 public interface BarImplModuleMXBean
1187 {
1188     public org.opendaylight.controller.config.yang.config.demo.java.DtoAttribute getDtoAttribute();
1189
1190     public void setDtoAttribute(org.opendaylight.controller.config.yang.config.demo.java.DtoAttribute dtoAttribute);
1191
1192 }
1193 ----
1194 The BarImplModuleMXBean interface represents the getter and the setter for dtoAttribute that will be exported to the configuration registry by means of JMX. The attribute was defined in the yang model: in this case, it is the composite type which was converted to OpenType.
1195
1196 * Attribute definition from config-demo-impl.yang
1197 ----
1198 // Module implementing bar service
1199     identity bar-impl {
1200         base config:module-type;
1201         config:provided-service demo:foo;
1202         config:java-name-prefix BarImpl;
1203     }
1204
1205     augment "/config:modules/config:module/config:configuration" {
1206         case bar-impl {
1207             when "/config:modules/config:module/config:type = 'bar-impl'";
1208
1209             container dto-attribute {
1210                 leaf int-attribute {
1211                     type int32;
1212                 }
1213
1214                 leaf int-attribute2 {
1215                     type int32;
1216                 }
1217
1218                 leaf bool-attribute {
1219                     type boolean;
1220                 }
1221             }
1222
1223         }
1224     }
1225 ----
1226 From the container dto-attribute, the DtoAttribute java file was generated. The Class contains the plain constructor, and the getters and setters for the attributes defined as container leaves.
1227 Not only is ModuleMXBean generated from this module definition, but also BarImplModuleFactory and BarImplModule stubs (in fact AbstractBarImplModuleFactory and AbstractBarImplModule are generated too.).
1228
1229 * AbstractBarImplModule.java +
1230 This abstract class is almost fully generated: only the method validate() has an empty body and the method createInstance() is abstract. The user must implement both methods by user. AbstractBarImplModule implements its ModuleMXBean, Module, RuntimeBeanRegistratorAwareModule, and the dependent service interface as defined in yang. Moreover, the class contains two types of constructors: one for the module created from the old module instance, and the second for module creation from scratch.
1231
1232 * AbstractBarImplModuleFactory.java +
1233 Unlike AbstractModule, AbstractFactory is fully generated, but it is still an abstract class. The factory is responsible for module instances creation, and provides two type of instantiateModule methods for both module constructor types. It implements the ModuleFactory interface.
1234
1235 Next, create the runtime bean for FooImplModule. Runtime beans are designated to capture data about the running module.
1236
1237 * Add runtime bean definition to config-demo-impl.yang +
1238
1239 ===== Modifying generated sources
1240
1241 Generated source files: +
1242
1243 * src/main/java/**/BarImplModule
1244 * src/main/java/**/BarImplModuleFactory
1245 * src/main/java/**/FooImplModule
1246 * src/main/java/**/FooImplModuleFactory
1247
1248 *BarImplModule* +
1249 We will start by modifying BarImplModule. Two constructors and two generated methods are seen:
1250 ----
1251 @Override
1252     public void validate(){
1253         super.validate();
1254         // Add custom validation for module attributes here.
1255     }
1256
1257     @Override
1258     public java.lang.AutoCloseable createInstance() {
1259         //TODO:implement
1260         throw new java.lang.UnsupportedOperationException("Unimplemented stub method");
1261     }
1262 ----
1263 In *validate*, specify the validation for configuration attributes, for example:
1264 ----
1265 @Override
1266     public void validate(){
1267         super.validate();
1268         Preconditions.checkNotNull(getDtoAttribute());
1269         Preconditions.checkNotNull(getDtoAttribute().getBoolAttribute());
1270         Preconditions.checkNotNull(getDtoAttribute().getIntAttribute());
1271         Preconditions.checkNotNull(getDtoAttribute().getIntAttribute2());
1272         Preconditions.checkState(getDtoAttribute().getIntAttribute() > getDtoAttribute().getIntAttribute2());
1273     }
1274 ----
1275 In *createInstance* you need to create a new instance of the bar service => Bar interface, for example:
1276 ----
1277 @Override
1278     public java.lang.AutoCloseable createInstance() {
1279         return new BarImpl(getDtoAttribute().getIntAttribute(), getDtoAttribute().getIntAttribute2(), getDtoAttribute()
1280                 .getBoolAttribute());
1281     }
1282 ----
1283 ===== Notes:
1284
1285 * createInstance returns AutoCloseable so the returned type needs to implement it. (You can make BarImpl implement AutoCloseable, or create a Wrapper class around the BarImpl instance that implements AutoCloseable, or even extend the BarImpl class and make it implement it.)
1286 * You can access all the configuration attributes by means of the getter methods.
1287 * In config-demo-impl.yang, we defined the bar-impl configuration as a container dto-attribute. The code generator creates a transfer object DtoAttribute that you can access by means of the getDtoAttribute() method, and retrieve configuration data from it. You can even add a new constructor to BarImpl that takes this transfer object, and reduces the number of arguments.
1288
1289 *FooImplModule* +
1290 We will not add any custom validation in this module. The createInstance method will look as follows: +
1291 ----
1292  @Override
1293     public java.lang.AutoCloseable createInstance() {
1294         return new FooImpl(getStrAttribute(), getIntAttribute(), getBarDependencyDependency());
1295     }
1296 ----
1297 ===== Adding support for default instances
1298
1299 In order to provide a default instance of module bar-impl, we need to further modify the generated code by the overriding method getDefaultModules in src/main/java/**/BarImplModuleFactory class. The body of this class is empty thus far, and it inherits the default behaviour from its parent abstract factory. Use the following code to replace the empty body:
1300 ----
1301 public static final ModuleIdentifier defaultInstance1Id = new ModuleIdentifier(NAME, "defaultInstance1");
1302
1303     @Override
1304     public Set<BarImplModule> getDefaultModules(DependencyResolverFactory dependencyResolverFactory, BundleContext bundleContext) {
1305         DependencyResolver depResolver1 = dependencyResolverFactory.createDependencyResolver(defaultInstance1Id);
1306         BarImplModule defaultModule1 = new BarImplModule(defaultInstance1Id, depResolver1);
1307         defaultModule1.setDtoAttribute(getDefaultConfiguration(bundleContext));
1308
1309         return Sets.newHashSet(defaultModule1);
1310     }
1311
1312     private DtoAttribute getDefaultConfiguration(BundleContext bundleContext) {
1313         DtoAttribute defaultConfiguration = new DtoAttribute();
1314
1315         String property = bundleContext.getProperty("default.bool");
1316         defaultConfiguration.setBoolAttribute(property == null ? false : Boolean.parseBoolean(property));
1317
1318         property = bundleContext.getProperty("default.int1");
1319         defaultConfiguration.setIntAttribute(property == null ? 55 : Integer.parseInt(property));
1320
1321         property = bundleContext.getProperty("default.int2");
1322         defaultConfiguration.setIntAttribute2(property == null ? 0 : Integer.parseInt(property));
1323
1324         return defaultConfiguration;
1325     }
1326 ----
1327 The _getDefaultModules_ method now produces an instance of the bar-impl module with the name _defaultInstance1_. (It is possible to produce multiple default instances since the return type is a Set of module instances.) Note the getDefaultConfiguration method. It provides the default configuration for default instances by trying to retrieve system properties from bundleContext (or provides hardcoded values in case the system property is not present).
1328
1329 For the controller distribution, system properties can be fed by means of _config.ini_ file.
1330
1331 The method _getDefaultModules_ is called automatically after a bundle containing this factory is started in the OSGi environment. Its default implementation returns an empty Set.
1332
1333 The default instances approach is similar to the Activator class approach in OSGi with the advantage of default instances being managed by the configuration subsystem. This approach can either replace the Activator class approach, or be used along with it.
1334
1335 *Verifying the default instances in distribution* +
1336
1337 If we add the config-demo bundle to the opendaylight distribution, we can verify the presence of the default instance. The file pom.xml under the opendaylight/distribution/opendaylight folder needs to be modified by adding the config-demo dependency:
1338 ----
1339 <dependency>
1340     <groupId>${project.groupId}</groupId>
1341     <artifactId>config-demo</artifactId>
1342     <version>0.1.1-SNAPSHOT</version>
1343 </dependency>
1344 ----
1345 Now we need to rebuild the conf-demo module using mvn clean install. Then, we can build the distribution using the same mvn command under the _opendaylight/distribution/opendaylight_ folder. If we go to the _opendaylight/distribution/opendaylight/target/distribution.opendaylight-osgipackage/opendaylight_ folder, and execute run.sh, the opendaylight distribution should start.
1346
1347 We can check the presence of the default instances by means of JMX using a tool such as _jvisualvm_.
1348
1349 === OpenDaylight Controller:Configuration examples user guide
1350 ==== Configuring thread pools with yangcli-pro
1351 Requirements: yangcli-pro version 13.04-9.2 or later +
1352
1353 ===== Connecting to plaintext TCP socket and ssh
1354 Currently SSH is exposed by the controller. The network interface and port are configured in configuration/config.ini . The current configuration of netconf is as follows: +
1355 ----
1356 # Netconf startup configuration
1357 #netconf.tcp.address=127.0.0.l
1358 #netconf.tcp.port=8383
1359
1360 netconf.ssh.address=0.0.0.0
1361 netconf.ssh.port=1830
1362 ----
1363 To connect the yangcli-pro client, use the following syntax: +
1364 ----
1365 yangcli-pro --user=admin --password=admin --transport=ssh --ncport=1830 --server=localhost
1366 ----
1367 If the plaintext TCP port is not commented out, one can use the following: +
1368 ----
1369 yangcli-pro --user=a --password=a --transport=tcp --ncport=8383 --server=localhost
1370 ----
1371 Authentication in this case is ignored.
1372
1373 For better debugging, include following arguments: +
1374 ----
1375 --log=/tmp/yuma.log --log-level=debug4 --log-console
1376 ----
1377
1378 NOTE:  When the log file is set, the output will not appear on stdout.
1379
1380 ===== Configuring threadfactory
1381 The threadfactory is a service interface that can be plugged into threadpools, defined in config-threadpool-api (see the https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blob;f=opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang;h=8f3064822be319dfee6fd7c7061c8bee14db268f;hb=refs/heads/master[yang file].
1382 The implementation to be used is called threadfactory-naming. This implementation will set a name for each thread created using a configurable prefix and auto incremented index. See the https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blob;f=opendaylight/config/threadpool-config-impl/src/main/yang/threadpool-impl.yang;h=a2366f285a0c0b8682b1093f18fb5ee184c9cde3;hb=refs/heads/master[Yang file].
1383
1384 . Launch yangcli-pro and connect to the server.
1385 . Enter *get-config source=running* to see the current configuration. +
1386 Example output: +
1387 ----
1388 rpc-reply {
1389   data {
1390     modules {
1391       module  binding-broker-singleton {
1392         type binding-impl:binding-broker-impl-singleton
1393         name binding-broker-singleton
1394       }
1395     }
1396     services {
1397       service  md-sal-binding:binding-broker-osgi-registry {
1398         type md-sal-binding:binding-broker-osgi-registry
1399         instance  ref_binding-broker-singleton {
1400           name ref_binding-broker-singleton
1401           provider /modules/module[type='binding-broker-impl-singleton'][name='binding-broker-singleton']
1402         }
1403       }
1404     }
1405   }
1406 }
1407 ----
1408 [start=3]
1409 . Enter the merge /modules/module.
1410 . At the prompt, enter the string value for the leaf <name>. This is the name of the config module. Enter threadfactory-bgp.
1411 . Set the identityref for the leaf <type>. Press Tab to see a list of available module names. Enter threadfactory-naming.
1412 . At the prompt, choose the case statement. Example output:
1413 ----
1414  1: case netty-threadgroup-fixed:
1415        leaf thread-count
1416   2: case netty-hashed-wheel-timer:
1417        leaf tick-duration
1418        leaf ticks-per-wheel
1419        container thread-factory
1420   3: case async-eventbus:
1421        container threadpool
1422   4: case threadfactory-naming:
1423        leaf name-prefix
1424   5: case threadpool-fixed:
1425        leaf max-thread-count
1426        container threadFactory
1427   6: case threadpool-flexible:
1428        leaf max-thread-count
1429        leaf minThreadCount
1430        leaf keepAliveMillis
1431        container threadFactory
1432   7: case threadpool-scheduled:
1433        leaf max-thread-count
1434        container threadFactory
1435   8: case logback:
1436        list file-appenders
1437        list rolling-appenders
1438        list console-appenders
1439        list loggers
1440 ----
1441 In this case, we chose 4. +
1442 [start=7]
1443 . Next fill in the string value for the leaf <name-prefix>. Enter bgp.
1444 : (You should get an OK response from the server.)
1445 [start=8]
1446 . Optionally issue get-config source=candidate to verify the change.
1447 . Issue commit.
1448 . Issue get-config source=running. Example output: +
1449 ----
1450 rpc-reply {
1451   data {
1452     modules {
1453       module  binding-broker-singleton {
1454         type binding-impl:binding-broker-impl-singleton
1455         name binding-broker-singleton
1456       }
1457       module  threadfactory-bgp {
1458         type th-java:threadfactory-naming
1459         name threadfactory-bgp
1460         name-prefix bgp
1461       }
1462     }
1463     services {
1464       service  th:threadfactory {
1465         type th:threadfactory
1466         instance  ref_threadfactory-bgp {
1467           name ref_threadfactory-bgp
1468           provider /modules/module[type='threadfactory-naming'][name='threadfactory-bgp']
1469         }
1470       }
1471       service  md-sal-binding:binding-broker-osgi-registry {
1472         type md-sal-binding:binding-broker-osgi-registry
1473         instance  ref_binding-broker-singleton {
1474           name ref_binding-broker-singleton
1475           provider /modules/module[type='binding-broker-impl-singleton'][name='binding-broker-singleton']
1476         }
1477       }
1478     }
1479   }
1480 }
1481 ----
1482 ==== Configuring fixed threadpool
1483
1484 Service interface threadpool is defined in the config-threadpool-api. The implementation used is called threadpool-fixed that is defined in config-threadpool-impl. This implementation creates a threadpool of fixed size. There are two mandatory attributes: size and dependency on a threadfactory.
1485
1486 . Issue get-config source=running. As you can see in the last step of configuring threadfactory, /services/service, the node associated with it has instance name ref_threadfactory-bgp.
1487 . Issue merge /modules/module.
1488 . Enter the name bgp-threadpool.
1489 . Enter the type threadpool.
1490 . Select the appropriate case statement.
1491 . Enter the value for leaf <max-thread-count>: 100.
1492 . Enter the threadfactory for attribute threadfactory/type. This is with reference to /services/service/type, in other words, the service interface.
1493 . Enter ref_threadfactory-bgp.
1494 Server response must be an OK message.
1495 [start=9]
1496 . Issue commit.
1497 . Issue get-config source=running.
1498 Example output: +
1499 ----
1500 rpc-reply {
1501   data {
1502     modules {
1503       module  binding-broker-singleton {
1504         type binding-impl:binding-broker-impl-singleton
1505         name binding-broker-singleton
1506       }
1507       module  bgp-threadpool {
1508         type th-java:threadpool-fixed
1509         name bgp-threadpool
1510         threadFactory {
1511           type th:threadfactory
1512           name ref_threadfactory-bgp
1513         }
1514         max-thread-count 100
1515       }
1516       module  threadfactory-bgp {
1517         type th-java:threadfactory-naming
1518         name threadfactory-bgp
1519         name-prefix bgp
1520       }
1521     }
1522     services {
1523       service  th:threadpool {
1524         type th:threadpool
1525         instance  ref_bgp-threadpool {
1526           name ref_bgp-threadpool
1527           provider /modules/module[type='threadpool-fixed'][name='bgp-threadpool']
1528         }
1529       }
1530       service  th:threadfactory {
1531         type th:threadfactory
1532         instance  ref_threadfactory-bgp {
1533           name ref_threadfactory-bgp
1534           provider /modules/module[type='threadfactory-naming'][name='threadfactory-bgp']
1535         }
1536       }
1537       service  md-sal-binding:binding-broker-osgi-registry {
1538         type md-sal-binding:binding-broker-osgi-registry
1539         instance  ref_binding-broker-singleton {
1540           name ref_binding-broker-singleton
1541           provider /modules/module[type='binding-broker-impl-singleton'][name='binding-broker-singleton']
1542         }
1543       }
1544     }
1545   }
1546 }
1547 ----
1548 To see the actual netconf messages, use the logging arguments described at the top of this page. To validate that a threadpool has been created, a tool like VisualVM can be used.
1549
1550 ==== Logback configuration - Yuma
1551 This approach to configure logback will utilize a 3rd party cli netconf client from Yuma. We will modify existing console appender in logback and then call reset rpc on logback to clear its status list.
1552
1553 For initial configuration of the controller and startup parameters for yuma, see the threadpool example: https://wiki.opendaylight.org/view/OpenDaylight_Controller:Config:Examples:Threadpool[Threadpool configuration using Yuma].
1554
1555 Start the controller and yuma cli client as in the previous example.
1556
1557 There is no need to initialize the configuration module wrapping logback manually, since it creates a default instance. Therefore you should see the output containing logback configuration after the execution of get-config source=running command in yuma:
1558 ----
1559 rpc-reply {
1560   data {
1561     modules {
1562       module  singleton {
1563         type logging:logback
1564         name singleton
1565         console-appenders {
1566           threshold-filter ERROR
1567           name STDOUT
1568           encoder-pattern '%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n'
1569         }
1570         file-appenders {
1571           append true
1572           file-name logs/audit.log
1573           name audit-file
1574           encoder-pattern '%date{"yyyy-MM-dd HH:mm:ss.SSS z"} %msg %n'
1575         }
1576         loggers {
1577           level WARN
1578           logger-name org.opendaylight.controller.logging.bridge
1579         }
1580         loggers {
1581           level INFO
1582           logger-name audit
1583           appenders audit-file
1584         }
1585         loggers {
1586           level ERROR
1587           logger-name ROOT
1588           appenders STDOUT
1589           appenders opendaylight.log
1590         }
1591         loggers {
1592           level INFO
1593           logger-name org.opendaylight
1594         }
1595         loggers {
1596           level WARN
1597           logger-name io.netty
1598         }
1599         rolling-appenders {
1600           append true
1601           max-file-size 10MB
1602           file-name logs/opendaylight.log
1603           name opendaylight.log
1604           file-name-pattern logs/opendaylight.%d.log.zip
1605           encoder-pattern '%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{35} - %msg%n'
1606           clean-history-on-start false
1607           max-history 1
1608           rolling-policy-type TimeBasedRollingPolicy
1609         }
1610       }
1611       module  binding-broker-singleton {
1612         type binding-impl:binding-broker-impl-singleton
1613         name binding-broker-singleton
1614       }
1615     }
1616     services {
1617       service  md-sal-binding:binding-broker-osgi-registry {
1618         type md-sal-binding:binding-broker-osgi-registry
1619         instance  ref_binding-broker-singleton {
1620           name ref_binding-broker-singleton
1621           provider /modules/module[type='binding-broker-impl-singleton'][name='binding-broker-singleton']
1622         }
1623       }
1624     }
1625   }
1626 }
1627 ----
1628
1629 ===== Modifying existing console appender in logback
1630 . Start edit-config with merge option:
1631 ----
1632 merge /modules/module
1633 ----
1634 [start=2]
1635 . For Name of the module, enter *singleton*.
1636 . For Type, enter *logback*.
1637 . Pick the corresponding case statement with the name logback.
1638 We do not want to modify file-appenders, rolling-appenders and loggers lists, so the answer to questions from yuma is N (for no):
1639 ----
1640 Filling optional case /modules/module/configuration/logback:
1641 Add optional list 'file-appenders'?
1642 Enter Y for yes, N for no, or C to cancel: [default: Y]
1643 ----
1644 [start=5]
1645 . As we want to modify console-appenders, the answer to the question from Yuma is Y:
1646 ----
1647 Filling optional case /modules/module/configuration/logback:
1648 Add optional list 'console-appenders'?
1649 Enter Y for yes, N for no, or C to cancel: [default: Y]
1650 ----
1651 [start=6]
1652 . This will start a new configuration process for console appender and we will fill following values:
1653
1654 * <encoder-pattern> %date{"yyyy-MM-dd HH:mm:ss.SSS z"} %msg %n
1655 * <threshold-filter> INFO
1656 * <name> STDOUT
1657 [start=7]
1658 . Answer N to the next question.
1659 ----
1660 Add another list?
1661 Enter Y for yes, N for no, or C to cancel: [default: N]
1662 ----
1663 Notice that we changed the level for threshold-filter for STDOUT console appender from ERROR to INFO. Now issue a commit command to commit the changed configuration, and the response from get-config source=running command should look like this:
1664 ----
1665 rpc-reply {
1666   data {
1667     modules {
1668       module  singleton {
1669         type logging:logback
1670         name singleton
1671         console-appenders {
1672           threshold-filter INFO
1673           name STDOUT
1674           encoder-pattern '%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n'
1675         }
1676         file-appenders {
1677           append true
1678           file-name logs/audit.log
1679           name audit-file
1680           encoder-pattern '%date{"yyyy-MM-dd HH:mm:ss.SSS z"} %msg %n'
1681         }
1682         loggers {
1683           level WARN
1684           logger-name org.opendaylight.controller.logging.bridge
1685         }
1686         loggers {
1687           level INFO
1688           logger-name audit
1689           appenders audit-file
1690         }
1691         loggers {
1692           level ERROR
1693           logger-name ROOT
1694           appenders STDOUT
1695           appenders opendaylight.log
1696         }
1697         loggers {
1698           level INFO
1699           logger-name org.opendaylight
1700         }
1701         loggers {
1702           level WARN
1703           logger-name io.netty
1704         }
1705         rolling-appenders {
1706           append true
1707           max-file-size 10MB
1708           file-name logs/opendaylight.log
1709           name opendaylight.log
1710           file-name-pattern logs/opendaylight.%d.log.zip
1711           encoder-pattern '%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{35} - %msg%n'
1712           clean-history-on-start false
1713           max-history 1
1714           rolling-policy-type TimeBasedRollingPolicy
1715         }
1716       }
1717       module  binding-broker-singleton {
1718         type binding-impl:binding-broker-impl-singleton
1719         name binding-broker-singleton
1720       }
1721     }
1722     services {
1723       service  md-sal-binding:binding-broker-osgi-registry {
1724         type md-sal-binding:binding-broker-osgi-registry
1725         instance  ref_binding-broker-singleton {
1726           name ref_binding-broker-singleton
1727           provider /modules/module[type='binding-broker-impl-singleton'][name='binding-broker-singleton']
1728         }
1729       }
1730     }
1731   }
1732 }
1733 ----
1734 ==== Invoking RPCs
1735 *Invoking Reset RPC on logback* +
1736 The configuration module for logback exposes some information about its current state(list of logback status messages). This information can be accessed using get netconf operation or get command from yuma. Example response after issuing get command in yuma:
1737 ----
1738 rpc-reply {
1739   data {
1740     modules {
1741       module  singleton {
1742         type logging:logback
1743         name singleton
1744         status {
1745           message 'Found resource [configuration/logback.xml] at
1746 [file:/.../controller/opendaylight/distribution/opendaylight/target/distribution.opendaylight-
1747 osgipackage/opendaylight/configuration/logback.xml]'
1748           level INFO
1749           date 2479534352
1750         }
1751         status {
1752           message 'debug attribute not set'
1753           level INFO
1754           date 2479534441
1755         }
1756         status {
1757           message 'Will scan for changes in
1758 [[/.../controller/opendaylight/distribution/opendaylight/target/distribution.opendaylight-
1759 osgipackage/opendaylight/configuration/logback.xml]]
1760 every 60 seconds.'
1761           level INFO
1762           date 2479534448
1763         }
1764         status {
1765           message 'Adding ReconfigureOnChangeFilter as a turbo filter'
1766           level INFO
1767           date 2479534448
1768         }
1769  ...
1770 ----
1771 Logback also exposes an rpc called reset that wipes out the list of logback status messages and to invoke an rpc with name reset on module named singleton of type logback, following command needs to be issued in yuma:
1772 ----
1773 reset context-instance="/modules/module[type='logback' and name='singleton']"
1774 ----
1775 After an ok response, issuing get command should produce response with empty logback status message list:
1776 ----
1777 rpc-reply {
1778   data {
1779     modules {
1780       module  singleton {
1781         type logging:logback
1782         name singleton
1783       }
1784     }
1785   }
1786 }
1787 ----
1788 This response confirms successful execution of the reset rpc on logback.
1789
1790 *Invoking shutdown RPC* +
1791 This command entered in yuma will shut down the server. If all bundles do not stop correctly within 10 seconds, it will force the process to exit.
1792 ----
1793 shutdown context-instance="/modules/module[type='shutdown' and name='shutdown']",input-secret="",max-wait-time="10000",reason="reason"
1794 ----
1795 === OpenDaylight Controller Configuration: Logback Examples
1796 ==== Logback Configuration Example
1797
1798 The Logback logger configuration is part of the config subsystem. This module allows changes to the Logback configuration at runtime. It is used here as an example to demonstrate the YANG to Java code generator and to show how the configuration transaction works.
1799
1800 ==== Java code generation
1801 The logging configuration YANG module definition can be found in the config-logging.yang file. The code is generated by the yang-maven-plugin and yang-jmx-generator-plugin. The output java files are located as defined in the plugin configuration, where additional configuration parameters can be set. The logback module is defined as identity, with the base "config:module-type"; it does not provide or depend on any service interface.
1802 ----
1803 identity logback {
1804     description
1805         "Actual state of logback configuration.";
1806     base config:module-type;
1807     config:java-name-prefix Logback;
1808 }
1809 ----
1810 The next logback module attributes are defined in the "/config:modules/config:module/config:configuration" augment as the snippet below shows.
1811 ----
1812 augment "/config:modules/config:module/config:configuration" {
1813     case logback {
1814         when "/config:modules/config:module/config:type = 'logback'";
1815
1816         list console-appenders {
1817
1818             leaf encoder-pattern {
1819                 type string;
1820                 mandatory true;
1821             }
1822
1823             leaf threshold-filter {
1824                 type string;
1825                 default 'ALL';
1826             }
1827
1828             leaf name {
1829                 type string;
1830                 mandatory true;
1831             }
1832             config:java-name-prefix ConsoleAppenderTO;
1833         }
1834          ...
1835 ----
1836 Now LogbackModule and LogbackModuleFactory can be generated. In fact, three more java files related to this module will be generated. By the augment definition, TypeObjects too are generated (that is to say, ConsoleAppenderTO). They are regular java classes with getters and setters for arguments defined as leaves.
1837
1838 * *LogbackModuleMXBean* is the interface containing getters and setters for attributes defined in the configuration augment.
1839 * *AbstractLogbackModule* is the abstract java class, which implements Module, RuntimeBeanRegistratorAwareModule, and LogbackModuleMXBean. It contains almost all functionality, except validate and createInstance methods.
1840 * *AbstractLogbackModuleFactory* is the abstract java class responsible for creating module instances. It implements the ModuleFactory interface.
1841 * *LogbackModule* class extends AbstractLogbackModule. It is located in a different place (source/main/java) and can be modified by the user, so that the abstract method is implemented and the validate method is overridden.
1842 * *LogbackModuleFactory* class extends AbstractLogbackModuleFactory and overrides its instantiateModule methods.
1843 Next, the runtime bean is defined in the "/config:modules/config:module/config:state" augment. +
1844 ----
1845 augment "/config:modules/config:module/config:state" {
1846     case logback {
1847         when "/config:modules/config:module/config:type = 'logback'";
1848
1849         rpcx:rpc-context-instance "logback-rpc";
1850
1851         list status {
1852             config:java-name-prefix StatusTO;
1853
1854             leaf level {
1855                 type string;
1856             }
1857
1858             leaf message {
1859                 type string;
1860             }
1861
1862             leaf date {
1863                 type uint32;
1864             }
1865         }
1866     }
1867 }
1868 ----
1869 * The *Generator* plugin creates another set of java files.
1870 * *LogbackRuntimeMXBean* is the interface extending RuntimeBean. It contains the getter method for the argument defined in the augment.
1871 * *LogbackRuntimeRegistrator* class serves as the registrator for runtime beans.
1872 * *LogbackRuntimeRegistration* class serves as the registration ticket. An instance is returned after registration.
1873
1874 The Logback config also defines logback-rpc with the reset method. It is also defined in the state augment, owing to the context.
1875 ----
1876 identity logback-rpc;
1877 rpc reset {
1878     input {
1879         uses rpcx:rpc-context-ref {
1880             refine context-instance {
1881                 rpcx:rpc-context-instance logback-rpc;
1882             }
1883         }
1884     }
1885 }
1886 ----
1887 The Reset method is defined in the LogbackRuntimeMXBean interface.
1888
1889 ==== Logback configuration: Jolokia
1890
1891 To create configuration on the running OSGi server: Jolokia (http://www.jolokia.org/) is used as a JMX-HTTP bridge, which listens at http://localhost:8080/controller/nb/v2/jolokia and curl to request over HTTP.
1892
1893 . Start the controller. Find more here: https://wiki.opendaylight.org/view/OpenDaylight_Controller:Pulling,_Hacking,_and_Pushing_the_Code_from_the_CLI
1894 . Request Jolokia:
1895 ----
1896 curl http://localhost:8080/controller/nb/v2/jolokia --user admin:admin
1897 ----
1898 The response must resemble the following: +
1899 ----
1900 {
1901     "timestamp": 1382425537,
1902     "status": 200,
1903     "request": {
1904         "type": "version"
1905     },
1906     "value": {
1907         "protocol": "7.0",
1908         "agent": "1.1.1",
1909         "info": {
1910             "product": "equinox",
1911             "vendor": "Eclipse",
1912             "version": "3.8.1.v20120830-144521"
1913         }
1914     }
1915 }
1916 ----
1917 Jolokia is working.
1918 To configure Logback, first, create a configuration transaction. ConfigResgistryModule offers the operation beginConfig(), and to invoke it:
1919 ----
1920 curl -X POST -H "Content-Type: application/json" -d '{"type":"exec","mbean":"org.opendaylight.controller:type=ConfigRegistry","arguments":[],"operation":"beginConfig"}' http://localhost:8080/controller/nb/v2/jolokia --user admin:admin
1921 ----
1922 The configuration transaction was created. The response received: +
1923 ----
1924 {
1925     "timestamp": 1383034210,
1926     "status": 200,
1927     "request": {
1928         "operation": "beginConfig",
1929         "mbean": "org.opendaylight.controller:type=ConfigRegistry",
1930         "type": "exec"
1931     },
1932     "value": {
1933         "objectName": "org.opendaylight.controller:TransactionName=ConfigTransaction-1-2,type=ConfigTransaction"
1934     }
1935 }
1936 ----
1937 At this stage, the transaction can be aborted, but we want to create the module bean to be configured. In the created ConfigTransaction call createModule method, the module identifier is logback, and the name must be singleton as only one instance of the Logback configuration is needed.
1938 ----
1939 curl -X POST -H "Content-Type: application/json" -d '{"type":"exec","mbean":"org.opendaylight.controller:TransactionName=ConfigTransaction-1-2,type=ConfigTransaction","arguments":["logback","singleton"],"operation":"createModule"}' http://localhost:8080/controller/nb/v2/jolokia --user admin:admin
1940 ----
1941 The LogbackModule bean was created. The response returned:
1942 ----
1943 {
1944     "timestamp": 1383034580,
1945     "status": 200,
1946     "request": {
1947         "operation": "createModule",
1948         "mbean": "org.opendaylight.controller:TransactionName=ConfigTransaction-1-2,type=ConfigTransaction",
1949         "arguments": [
1950             "logback",
1951             "singleton"
1952         ],
1953         "type": "exec"
1954     },
1955     "value": {
1956         "objectName": "org.opendaylight.controller:TransactionName=ConfigTransaction-1-2,instanceName=singleton,moduleFactoryName=logback,type=Module"
1957     }
1958 }
1959 ----
1960 * The configuration bean attributes are set to values obtained from the loggers configuration, with which the server was started. To see attributes, request:
1961 ----
1962 curl -X POST -H "Content-Type: application/json" -d '{"type":"read", "mbean":"org.opendaylight.controller:instanceName=singleton,TransactionName=ConfigTransaction-1-2,type=Module,moduleFactoryName=logback"}' http://localhost:8080/controller/nb/v2/jolokia --user admin:admin
1963 ----
1964 In the response body, the value contains all attributes (CompositeData) and its nested attribute values.
1965 * Now, the proposed configuration can be committed.
1966 ----
1967 curl -X POST -H "Content-Type: application/json" -d '{"type":"exec","mbean":"org.opendaylight.controller:type=ConfigRegistry","arguments":["org.opendaylight.controller:instanceName=singleton,TransactionName=ConfigTransaction-1-2,type=Module,moduleFactoryName=logback"],"operation":"commitConfig"}' http://localhost:8080/controller/nb/v2/jolokia --user admin:admin
1968 ----
1969 The configuration was successfully validated and committed, and the module instance created.
1970 ----
1971 {
1972     "timestamp": 1383034793,
1973     "status": 200,
1974     "request": {
1975         "operation": "commitConfig",
1976         "mbean": "org.opendaylight.controller:type=ConfigRegistry",
1977         "arguments": [
1978             "org.opendaylight.controller:instanceName=singleton,TransactionName=ConfigTransaction-1-2,type=Module,moduleFactoryName=logback"
1979         ],
1980         "type": "exec"
1981     },
1982     "value": {
1983         "newInstances": [
1984             {
1985                 "objectName": "org.opendaylight.controller:instanceName=singleton,moduleFactoryName=logback,type=Module"
1986             }
1987         ],
1988         "reusedInstances": [],
1989         "recreatedInstances": []
1990     }
1991 }
1992 ----
1993 * The runtime bean was registered, and can provide the status information of the configuration and rpc operation reset. To see the status, try requesting:
1994 ----
1995 curl -X POST -H "Content-Type: application/json" -d '{"type":"read","mbean":"org.opendaylight.controller:instanceName=singleton,type=RuntimeBean,moduleFactoryName=logback"}' http://localhost:8080/controller/nb/v2/jolokia --user admin:admin
1996 ----
1997 The entire logback status is in the response body.
1998
1999 * To invoke the rpc method reset:
2000 ----
2001 curl -X POST -H "Content-Type: application/json" -d '{"type":"exec",
2002 "mbean":"org.opendaylight.controller:instanceName=singleton,type=RuntimeBean,moduleFactoryName=logback",
2003 "operation":"reset","arguments":[]}' http://localhost:8080/controller/nb/v2/jolokia --user admin:admin
2004 ----
2005 The answer:
2006 ----
2007 {
2008     "timestamp": 1383035001,
2009     "status": 200,
2010     "request": {
2011         "operation": "reset",
2012         "mbean": "org.opendaylight.controller:instanceName=singleton,moduleFactoryName=logback,type=RuntimeBean",
2013         "type": "exec"
2014     },
2015     "value": null
2016 }
2017 ----
2018 Now, the runtime bean status attribute will be empty:
2019 ----
2020 {
2021     "timestamp": 1383035126,
2022     "status": 200,
2023     "request": {
2024         "mbean": "org.opendaylight.controller:instanceName=singleton,moduleFactoryName=logback,type=RuntimeBean",
2025         "type": "read"
2026     },
2027     "value": {
2028         "StatusTO": []
2029     }
2030 }
2031 ----
2032 ==== Logback configuration: Netconf
2033
2034 In this case, NETCONF RPCs are used to configure logback. The Netconf server listens at port 8383. To communicate over TCP, telnet is used. More about NETCONF is available at: http://tools.ietf.org/html/rfc6241. Netconf implementation is a part of the Controller - netconf-subsystem. The RPCs of Netconf are XML, and the operations are mapped to JMX operations.
2035 * A server re-start is required. The procedure is the same as above.
2036 * Open a terminal and connect to the server:
2037 ----
2038 telnet localhost 8383
2039 ----
2040 A Hello message received from the server contains the server capabilities and session-id. To establish connection to the client,send a hello message:
2041 ----
2042 <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
2043     <capabilities>
2044         <capability>urn:ietf:params:netconf:base:1.0</capability>
2045     </capabilities>
2046 </hello>
2047 ]]>]]>
2048 ----
2049 * With the connection created, the client and server can communicate. To see the running modules and services, send an RPC to the server:
2050 ----
2051 <rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
2052     <get-config>
2053         <source>
2054             <running/>
2055         </source>
2056     </get-config>
2057 </rpc>
2058 ]]>]]>
2059 ----
2060
2061 * To configure logback, create a configuration transaction, and create a configuration module. It can be done in one step (in client point of view):
2062 ----
2063 <rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
2064     <edit-config>
2065         <target>
2066             <candidate/>
2067         </target>
2068         <default-operation>merge</default-operation>
2069         <config>
2070             <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
2071                 <module>
2072                     <name>singleton</name>
2073                     <type xmlns:logging="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
2074                         logging:logback
2075                     </type>
2076                 </module>
2077             </modules>
2078         </config>
2079     </edit-config>
2080 </rpc>
2081 ]]>]]>
2082 ----
2083
2084 If the configuration worked, the client receives a positive response:
2085
2086 ----
2087 <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
2088 <ok/>
2089 </rpc-reply>
2090 ]]>]]>
2091 ----
2092
2093 * The Logback configuration bean attributes contain values loaded from the running Logback configuration. Send a request to the server with an RPC:
2094 ----
2095 <rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
2096     <get-config>
2097         <source>
2098             <candidate/>
2099         </source>
2100     </get-config>
2101 </rpc>
2102 ]]>]]>
2103 ----
2104
2105 * The reply includes the entire configuration that started the server. Assume that we want to change the RollingFileAppender named opendaylight.log attributes - maxFileSize, filename, and maxHistory. ( attribute of TimeBasedRollingPolicy). The proposed configuration:
2106
2107 ----
2108 <rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
2109     <edit-config>
2110         <target>
2111             <candidate/>
2112         </target>
2113         <default-operation>merge</default-operation>
2114         <config>
2115             <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
2116                 <module>
2117                     <name>singleton</name>
2118                     <type xmlns:logging="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
2119                         logging:logback
2120                     </type>
2121                     <rolling-appenders xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
2122                         <append>true</append>
2123                         <max-file-size>5MB</max-file-size>
2124                         <file-name>logs/opendaylight-new.log</file-name>
2125                         <name>opendaylight.log</name>
2126                         <file-name-pattern>logs/opendaylight.%d.log.zip</file-name-pattern>
2127                         <encoder-pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{35} - %msg%n</encoder-pattern>
2128                         <clean-history-on-start>false</clean-history-on-start>
2129                         <max-history>7</max-history>
2130                         <rolling-policy-type>TimeBasedRollingPolicy</rolling-policy-type>
2131                     </rolling-appenders>
2132                 </module>
2133             </modules>
2134         </config>
2135     </edit-config>
2136 </rpc>
2137 ]]>]]>
2138 ----
2139 This configuration is merged with the proposed module configuration. If it passes the validation process successfully, an "ok" reply is received.
2140
2141 * The configuration bean is ready to be committed:
2142 ----
2143 <rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
2144     <commit></commit>
2145 </rpc>
2146 ]]>]]>
2147 ----
2148 If successful, the ok message is received obtained, and the logback configuration is set. To verify, look into the logs directory to find a new log file named opendaylight-new.log
2149
2150 * Correctly close the session with the session-id:
2151 ----
2152 <rpc message-id="2" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
2153     <close-session xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/>
2154 </rpc>
2155 ]]>]]>
2156 ----
2157 ===== Logback configuration - Yuma
2158
2159 For a yangcli-pro example, see the https://wiki.opendaylight.org/view/OpenDaylight_Controller:Config:Examples:User_guide[user guide].
2160
2161 === Opendaylight Controller: Configuration Logback.xml
2162 Logging in ODL container is done by means of http://logback.qos.ch/[Logback]. Comprehensive documentation is available at http://logback.qos.ch/documentation.html.
2163
2164 By default, logging messages are appended to stdout of the java process and to file logs/opendaylight.log. When debugging a problem it might be useful to increase logging level:
2165 ----
2166 <logger name="org.opendaylight.controller" level="DEBUG"/>
2167 ----
2168 Logger tags can be appended under root node <configuration/>. Name of logger is used to select all loggers to which specified rules should apply. Loggers are usually named after class in which they reside. The example above matches all loggers in controller - they all are starting with org.opendaylight.controller . There are 5 logging levels: TRACE,DEBUG,INFO, WARN, ERROR. Additionally one can specify which appenders should be used for given loggers. This might be helpful to redirect certain log messages to another file or send them to syslog or over SMTP.
2169 == OpenDaylight Controller Configuration: Examples of Threadpool
2170
2171 === Configuration example of thread pools using yangcli-pro
2172
2173 For a yangcli-pro example, see the https://wiki.opendaylight.org/view/OpenDaylight_Controller:Config:Examples:User_guide[Examples User Guide].
2174
2175 === Configuration example of thread pools using telnet
2176 It is also possible to manipulate the configuration without the yuma cli. With just a telnet or ssh connection, it is possible to send the plain text containing netconf rpcs encoded in the xml format and achieve the same results as with yuma cli.
2177
2178 This example reproduces the configuration of a threadpool and a threadfactory from the previous example using just a telnet connection. We can also use ssh connection, with the netconf rpcs sending procedure remaining the same. For detailed information about initial configuration for the controller as well as the configuration process, see the example using yuma cli.
2179
2180 === Connecting to plaintext TCP socket
2181
2182 . Open a telnet connection:
2183 ----
2184 telnet 127.0.0.1 8383
2185 ----
2186 [start=2]
2187 . Open an ssh connection:
2188 ----
2189 ssh netconf@127.0.0.1 -p 1830 -s netconf
2190 ----
2191 The password for user netconf is : netconf, and the separator for the messages is: +
2192 ----
2193 ]]>]]>
2194 ----
2195 Every message needs end with these 6 characters.
2196
2197 The server sends a hello message: +
2198 ----
2199 <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
2200 <capabilities>
2201 <capability>urn:ietf:params:netconf:base:1.0</capability>
2202 <capability>urn:ietf:params:netconf:capability:exi:1.0</capability>
2203 <capability>urn:opendaylight:l2:types?module=opendaylight-l2-types&amp;revision=2013-08-27</capability>
2204 <capability>urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup?module=threadgroup&amp;revision=2013-11-07</capability>
2205 <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
2206 <capability>urn:opendaylight:params:xml:ns:yang:controller:threadpool?module=threadpool&amp;revision=2013-04-09</capability>
2207 <capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>
2208 <capability>urn:opendaylight:params:xml:ns:yang:controller:config?module=config&amp;revision=2013-04-05</capability>
2209 <capability>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&amp;revision=2010-10-04</capability>
2210 <capability>urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&amp;revision=2013-11-12</capability>
2211 <capability>urn:ietf:params:xml:ns:yang:rpc-context?module=rpc-context&amp;revision=2013-06-17</capability>
2212 <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&amp;revision=2013-10-28</capability>
2213 <capability>urn:opendaylight:params:xml:ns:yang:controller:netty:timer?module=netty-timer&amp;revision=2013-11-19</capability>
2214 <capability>urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&amp;revision=2010-09-24</capability>
2215 <capability>urn:ietf:params:netconf:capability:rollback-on-error:1.0</capability>
2216 <capability>urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl?module=threadpool-impl&amp;revision=2013-04-05</capability>
2217 <capability>urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&amp;revision=2010-09-24</capability>
2218 <capability>urn:opendaylight:params:xml:ns:yang:controller:logback:config?module=config-logging&amp;revision=2013-07-16</capability>
2219 <capability>urn:opendaylight:params:xml:ns:yang:iana?module=iana&amp;revision=2013-08-16</capability>
2220 <capability>urn:opendaylight:yang:extension:yang-ext?module=yang-ext&amp;revision=2013-07-09</capability>
2221 <capability>urn:opendaylight:params:xml:ns:yang:controller:netty?module=netty&amp;revision=2013-11-19</capability>
2222 <capability>http://netconfcentral.org/ns/toaster?module=toaster&amp;revision=2009-11-20</capability>
2223 <capability>urn:opendaylight:params:xml:ns:yang:ieee754?module=ieee754&amp;revision=2013-08-19</capability>
2224 <capability>urn:opendaylight:params:xml:ns:yang:nps-concepts?module=nps-concepts&amp;revision=2013-09-30</capability>
2225 </capabilities>
2226
2227 <session-id>4</session-id>
2228 </hello>
2229 ]]>]]>
2230 ----
2231 [start=3]
2232 . As the client, you must respond with a hello message:
2233 ----
2234 <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
2235     <capabilities>
2236         <capability>urn:ietf:params:netconf:base:1.0</capability>
2237     </capabilities>
2238 </hello>
2239 ]]>]]>
2240 ----
2241 Although there is no response to the hello message, the session is already established.
2242
2243 === Configuring threadfactory
2244
2245 . The following is the Xml equivalent to *get-config source=running*: +
2246 ----
2247 <rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
2248     <get-config>
2249         <source>
2250             <running/>
2251         </source>
2252     </get-config>
2253 </rpc>
2254 ]]>]]>
2255 ----
2256 The response containing the current configuration: +
2257 ----
2258 <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
2259         <data>
2260                 <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
2261                         <module>
2262                                 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl-singleton</type>
2263                                 <name>binding-broker-singleton</name>
2264                         </module>
2265                 </modules>
2266                 <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
2267                         <service>
2268                                 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-broker-osgi-registry</type>
2269                                 <instance>
2270                                         <name>ref_binding-broker-singleton</name>
2271                                         <provider>/modules/module[type='binding-broker-impl-singleton'][name='binding-broker-singleton']</provider>
2272                                 </instance>
2273                         </service>
2274                 </services>
2275         </data>
2276 </rpc-reply>]]>]]>
2277 ----
2278 [start=2]
2279 . To create an instance of threadfactory-naming with the name threadfactory-bgp, and the attribute name-prefix set to bgp, send the message:
2280 ----
2281 <rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
2282         <edit-config>
2283                 <target>
2284                         <candidate/>
2285                 </target>
2286                 <default-operation>merge</default-operation>
2287                 <config>
2288                         <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
2289                                 <module xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="merge">
2290                                         <name>threadfactory-bgp</name>
2291                                         <type xmlns:th-java="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">th-java:threadfactory-naming</type>
2292                                         <name-prefix xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">bgp</name-prefix>
2293                                 </module>
2294                         </modules>
2295                 </config>
2296         </edit-config>
2297 </rpc>]]>]]>
2298 ----
2299 [start=3]
2300 . To commit the threadfactory instance, send a commit message:
2301 ----
2302 <rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
2303         <commit/>
2304 </rpc>]]>]]>
2305 ----
2306 The Netconf endpoint should respond with ok to edit-config, as well as the commit message: +
2307
2308 ----
2309 <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
2310         <ok/>
2311 </rpc-reply>]]>]]>
2312 ----
2313 [start=4]
2314 . The response to the get-config message (the same as the first message sent in this example) should contain the commited instance of threadfactory-naming:
2315 ----
2316 <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
2317         <data>
2318                 <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
2319                         <module>
2320                                 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl-singleton</type>
2321                                 <name>binding-broker-singleton</name>
2322                         </module>
2323
2324                         <module>
2325                                 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">prefix:threadfactory-naming</type>
2326                                 <name>threadfactory-bgp</name>
2327                                 <name-prefix xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">bgp</name-prefix>
2328                         </module>
2329                 </modules>
2330
2331                 <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
2332                         <service>
2333                                 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadfactory</type>
2334                                 <instance>
2335                                         <name>ref_threadfactory-bgp</name>
2336                                         <provider>/modules/module[type='threadfactory-naming'][name='threadfactory-bgp']</provider>
2337                                 </instance>
2338                         </service>
2339                         <service>
2340                                 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-broker-osgi-registry</type>
2341                                 <instance>
2342                                         <name>ref_binding-broker-singleton</name>
2343                                         <provider>/modules/module[type='binding-broker-impl-singleton'][name='binding-broker-singleton']</provider>
2344                                 </instance>
2345                         </service>
2346                 </services>
2347         </data>
2348 </rpc-reply>]]>]]>
2349 ----
2350 === Configuring fixed threadpool
2351
2352 * To create an instance of *threadpool-fixed* , with the same configuration and the same dependency as before, send the following message:
2353
2354 ----
2355 <rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
2356         <edit-config>
2357                 <target>
2358                         <candidate/>
2359                 </target>
2360                 <default-operation>merge</default-operation>
2361                 <config>
2362                         <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
2363                                 <module xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="merge">
2364                                         <name>bgp-threadpool</name>
2365                                         <type xmlns:th-java="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">th-java:threadpool-fixed</type>
2366                                         <max-thread-count xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">100</max-thread-count>
2367                                         <threadFactory xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">
2368                                                 <type xmlns:th="urn:opendaylight:params:xml:ns:yang:controller:threadpool">th:threadfactory</type>
2369                                                 <name>ref_th-bgp</name>
2370                                         </threadFactory>
2371                                 </module>
2372                         </modules>
2373
2374                         <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
2375                         <service>
2376                                 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadfactory</type>
2377                                 <instance>
2378                                         <name>ref_th-bgp</name>
2379                                         <provider>/modules/module[type='threadfactory-naming'][name='threadfactory-bgp']</provider>
2380                                 </instance>
2381                         </service>
2382                 </services>
2383                 </config>
2384         </edit-config>
2385 </rpc>]]>]]>
2386 ----
2387 Notice the _services_ tag. If an instance is to be referenced as a dependency by another module, it needs to be placed under this tag as a service instance with a unique reference name. Tag _provider_ points to a unique instance that is already present in the config subsystem, or is created within the current edit-config operation.
2388 The tag _name_ contains the reference name that can be referenced by other modules to create a dependency. In this case, a new instance of threadpool uses this reference in its configuration under the _threadFactory_ tag).
2389
2390 You should get an ok response again, and the configuration subsystem will inject the dependency into the threadpool. Now you can commit the configuration (ok response once more) and the process is finished. The config subsystem is now in the same state as it was at the end of the previous example.