====== ODL Development Old ====== ====== ODL ====== * http://sdnhub.org/tutorials/opendaylight/ * http://sdnhub.org/tutorials/pox/ * https://wiki.opendaylight.org/view/Controller_Core_Functionality_Tutorials:Tutorials:Starting_A_Project * https://developer.cisco.com/site/openSDN/documents/design-guide/#how-to-deploy-your-feature ===== Learning Path ===== ODL Developer Guide: * https://wiki.opendaylight.org/view/OpenDaylight_Controller:Programmer_Guide * Look at other links on this site. * MD-SAL : https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL * yang model reference: https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Model_Reference * MD-SAL Architecture : https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Architecture * Datastore: https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Architecture:DOM_DataStore * search wiki for MD-SAL:Architecture * Config subsystem: https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:MD-SAL_Document_Review:Config_SubSystem * Tutorial: * https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Toaster_Tutorial * TODO: https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:MD-SAL_App_Tutorial * TODO: https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:FAQ * TODO Southbound Plugin: https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Southbound_Plugin_Development_Guide * l2switch, md-sal implementation of l2 functionalities: https://wiki.opendaylight.org/view/L2_Switch https://wiki.opendaylight.org/view/L2_Switch:Main OVSDB Integration: * https://wiki.opendaylight.org/view/OVSDB:Developer_Guide#OpenStack_OpenDaylight_OVSDB_Integration * https://wiki.opendaylight.org/view/OVSDB_Integration:Design * http://sdntutorials.com/qa/ General * https://wiki.opendaylight.org/view/Tech_Work_Stream:Main Other wiki resources. * https://github.com/BRCDcomm/BVC/wiki/Sample-MD-SAL-Solution * https://wiki.opendaylight.org/view/Karaf:Step_by_Step_Guide * https://wiki.opendaylight.org/view/GettingStarted:Development_Environment_Setup * https://wiki.opendaylight.org/view/GettingStarted:Starter_Parent_and_Distribution_Projects * http://books.sonatype.com/mvnref-book/reference/pom-relationships-sect-pom-best-practice.html * https://wiki.opendaylight.org/view/Controller_Core_Functionality_Tutorials:Tutorials:Starting_A_Project:ch1 * https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Toaster_Step-By-Step_krb ===== Dev Environment ===== ==== Karaf Java Heap ==== (At least) in karaf 2.2.10: If running karaf through bin/start Memory values could be configured in the bin/setenv file: export JAVA_MIN_MEM=256M # Minimum memory for the JVM export JAVA_MAX_MEM=1024M # Maximum memory for the JVM export JAVA_PERM_MEM=128M # Minimum perm memory for the JVM export JAVA_MAX_PERM_MEM=256M # Maximum memory for the JVM If running karaf as a service (karaf-service) In this case any exported variable seems to be ignored. The maximum java heap size could be defined in the etc/karaf-wrapper.conf: Maximum Java Heap Size (in MB) wrapper.java.maxmemory=1024 ==== Dev env ==== * https://wiki.opendaylight.org/view/GettingStarted:Development_Environment_Setup#Edit_your_.7E.2F.m2.2Fsettings.xml ==== Maven Java Dev ==== mvn help:effective-pom # skip IT (integration test) nsu (no snapshot update) mvn clean install -DskipIT -DskipTests -nsu dependency:analyze mvn dependency:tree ===== Archetype ===== * http://sdnhub.org/tutorials/opendaylight-tutorial/opendaylight-toolkit-roll-your-own-opendaylight-app-development/ * Helloworld: https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Startup_Project_Archetype * MD-SAL: https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Archetype_Tutorial ==== Project Structure ==== * https://wiki.opendaylight.org/view/CrossProject:HouseKeeping_Best_Practices_Group:Project_layout * ====== MD-SAL Concepts ====== * https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:FAQ ** SAL Plugin ** Every bundle in MD-SAL is plugin (openflow plugin, ovsdb plugin, Package handler, Topology manager, Flow Programmer...). The plugin may write data to data store (provider) or read data from data store (consumer). Southbound / Northbound plugins are programmers' view. ** Registration Subsystem ** When loaded Providers register RPCs they implement with SAL, Consumers register with SAL for configuration data notification. The SAL components responsible for this is call Configuration Subsystem, which consists of RPC-Registry, Notification-Service, Data Broker (https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Toaster_Tutorial#Config-subsystem_Context). ** Sample Interaction ** https://wiki.opendaylight.org/view/File:Add_Flow_use_case.png - OF Plugin register its RPC, Flow Programmer register for Flow Model Data notification. - AddFlow request comes from rest. And new Flow added to Flow Service Model Datastore. - Flow Programmer Service gets notification from Datastore. It want to tell OF Plugin to add flow to the appropriate switch. - Flow Programmer Service tell SAL to give it a reference to the Addflow RPC. - The AddFlow RPC request is routed to the OF Plugin, and the implementation method of the “AddFlow” RPC is invoked. There is the sequence diagram for that usecase (learning switch) here. ====== Plugin Lifecycle ====== https://wiki.opendaylight.org/view/File:Plugin_design_process.png ====== Starting Project ====== This document the step to start a project. ===== Project Structure ===== mkdir dmm ==== Scaffolding Project ==== Use odl toolkit to generate basic project structure. Install it: git clone https://git.opendaylight.org/gerrit/p/toolkit.git && cd toolkit && mvn clean install -D skipTests ** Alternative ** Generate project: mvn archetype:generate -DarchetypeGroupId=org.opendaylight.controller \ -DarchetypeRepository=http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/ \ -DarchetypeCatalog=http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/archetype-catalog.xml choose archetype: archetype-md-sal-app-simple ==== Generate some code ==== cd into the /generate project. Run mvn clean install -Dgen This will copy a number of additional files to the remaining four projects and finishes the initialization. cd up one directory (i.e. cd ..). Now run a complete build (i.e. mvn clean install). You should see that the parent project (named after your artifact id), and four child projects (consumer, model, provider, and web) all compile successfully. Delete the generate folder as it is no longer needed. You now have a fully functional MD-SAL application template which provides a number of capabilities. Read on for more information about what each project provides a template for, and which you can discard. At this point you can import your projects into eclipse or other IDE’s as you desire. See Getting Started: Eclipse. ===== Top pom.xml ===== cat pom.xml 4.0.0 de.dailab.nemo.dmm commons 1.0.0-SNAPSHOT commons/parent pom de.dailab.nemo.dmm dmm ${project.artifactId} 1.0-SNAPSHOT dav:http://nexus.opendaylight.org/content/sites/site 3.8.1.v20120830-144521 2010.09.24.4-SNAPSHOT 2010.09.24.4-SNAPSHOT src/main/yang-gen-config src/main/yang-gen-sal 0.3.0-SNAPSHOT etc/opendaylight/karaf commons/parent distribution/opendaylight-karaf features/dmm model provider consumer web scm:git:ssh://git.opendaylight.org:29418/controller.git scm:git:ssh://git.opendaylight.org:29418/controller.git https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL HEAD opendaylight-release ${nexusproxy}/repositories/opendaylight.release/ opendaylight-snapshot ${nexusproxy}/repositories/opendaylight.snapshot/ website ${sitedeploy} maven-deploy-plugin true org.codehaus.mojo build-helper-maven-plugin 1.8 add-source add-source generate-sources src/main/yang ${jmxGeneratorPath} ${salGeneratorPath} maven-clean-plugin ${jmxGeneratorPath} ** ${salGeneratorPath} ** org.eclipse.m2e lifecycle-mapping 1.0.0 org.codehaus.mojo properties-maven-plugin [0.0,) set-system-properties org.codehaus.enunciate maven-enunciate-plugin [0.0,) docs org.jacoco jacoco-maven-plugin [0.0,) prepare-agent pre-test post-test org.ops4j.pax.exam maven-paxexam-plugin [1.2.4,) generate-depends-file false org.apache.maven.plugins maven-checkstyle-plugin [2.0,) check org.opendaylight.yangtools yang-maven-plugin [0.5,) generate-sources org.codehaus.groovy.maven gmaven-plugin 1.0 execute org.apache.maven.plugins maven-enforcer-plugin ${enforcer.version} enforce org.codehaus.mojo build-helper-maven-plugin ===== Parent Pom: commons/parent/pom.xml ===== Common parent for all child project, with specification of dependencies. Pom defines * options: version definition * dependencies: jars that need to be downloaded Providers, consumers pom.xml specifies what they are dependent on. Features pom.xml specifies the dependent features. **Move common dependency up level!** ===== Feature Bundle: features ===== * https://wiki.opendaylight.org/view/Controller_Core_Functionality_Tutorials:Tutorials:Starting_A_Project:ch0 mkdir features/dmm mv features/* features/dmm ==== Include The Parent pom ==== specify commons pom artifact as parent: de.dailab.nemo.dmm commons 1.0.0-SNAPSHOT ../../commons/parent features-dmm 1.0.0-SNAPSHOT jar ==== features/dmm/pom.xml ==== 4.0.0 org.opendaylight.toaster toaster-parent ../parent 0.0.1-SNAPSHOT features-toaster ${project.artifactId} jar features.xml org.opendaylight.yangtools features-yangtools features xml org.opendaylight.controller features-mdsal features xml org.opendaylight.toaster toaster-impl org.opendaylight.toaster toaster-consumer org.opendaylight.yangtools features-test test org.opendaylight.controller opendaylight-karaf-empty ${karaf.empty.version} zip src/main/resources true org.apache.maven.plugins maven-resources-plugin filter generate-resources resources org.codehaus.mojo build-helper-maven-plugin attach-artifacts package attach-artifact ${project.build.directory}/classes/${features.file} xml features org.apache.maven.plugins maven-surefire-plugin ${surefire.version} org.opendaylight.controller opendaylight-karaf-empty ${karaf.empty.version} org.opendaylight.yangtools:features-test ==== Meta-feature ==== An example meta-feature. The version paramerters are defined in commons/parent/pom.xml mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features mvn:org.opendaylight.controller/features-mdsal/${controller.mdsal.version}/xml/features odl-adsal-core odl-adsal-networkconfiguration odl-adsal-connection odl-adsal-clustering odl-adsal-configuration odl-yangtools-common odl-yangtools-binding mvn:org.opendaylight.toaster/toaster-api/${project.version} odl-mdsal-broker odl-toaster-api mvn:org.opendaylight.toaster/toaster-impl/${project.version} mvn:org.opendaylight.toaster/toaster-impl/${project.version}/xml/config odl-mdsal-broker odl-toaster-api mvn:org.opendaylight.toaster/toaster-consumer/${project.version} ==== Configfile Tag ==== Provider, consumer config.xml must match the ones generated (attach resource) with provider/consumer pom.xml. mvn:de.dailab.nemo.dmm/dmm-provider/${project.version}/xml/config # generated config.xml is here: ~/.m2/repository/de/dailab/nemo/dmm/dmm-provider/1.0.0-SNAPSHOT/dmm-provider-1.0.0-SNAPSHOT-config.xml ==== Update Dependencies in Feature pom ==== All feature, bundle in dependency list of a local feature must be add in dependencies of feature-dmm/pom.xml: org.opendaylight.yangtools features-yangtools features xml ${yangtools.version} org.opendaylight.controller features-mdsal features xml ${controller.mdsal.version} org.opendaylight.controller features-restconf features xml ${controller.restconf.version} ==== Install Features in Local Distribution ==== distribution-karaf/pom.xml ... ... ... org.apache.karaf.tooling karaf-maven-plugin ${karaf.version} true standard ... ==== Install Features From Maven Repo ==== When feature bundle is installed in maven repo, it can be loaded to opendaylight: cd distribution-karaf/target/assembly/bin repo-add mvn:com.cisco.controller.samples/6-coffee-maker-features/1.0.0-SNAPSHOT/xml/features # real path is: /home/fedora/.m2/repository/de/dailab/nemo/dmm/features-dmm/1.0.0-SNAPSHOT/features-dmm-1.0.0-SNAPSHOT-features.xml repo-add mvn:de.dailab.nemo.dmm/features-dmm/1.0.0-SNAPSHOT/xml/features feature:install dmm-task-all ==== Conclusion: Features Workflow ==== * In src/fetures.xml, declare local bundle, its config file, and dependant features in the feature definition. 14 15 odl-yangtools-common 16 odl-yangtools-binding 17 odl-mdsal-broker 18 mvn:de.dailab.nemo.ima.controller/ima-controller-main/${project.version} 19 mvn:de.dailab.nemo.ima.controller/ima-controller-main/${project.version}/xml /config 20 * Add repository on top where the dependant features are located. mvn:org.opendaylight.controller/features-restconf/${mdsal.version}/xml/features * In features.pom, add the dependant repository to the dependency list: 30 org.opendaylight.controller 31 features-mdsal 32 features 33 xml 34 ===== Local controller: distribution/distribution-karaf ===== mkdir -p distribution cd distribution mvn archetype:generate -DarchetypeGroupId=org.opendaylight.controller \ -DarchetypeRepository=http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/ \ -DarchetypeCatalog=http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/archetype-catalog.xml Select karaf-distro... ==== Parent pom ==== Specify commons pom artifact as parent de.dailab.nemo.dmm commons 1.0.0-SNAPSHOT ../../commons/parent de.dailab.nemo.dmm distribution-karaf 1.0.0-SNAPSHOT jar ==== bootFeature ==== Currently now feature is loaded at boot: org.apache.karaf.tooling karaf-maven-plugin ${karaf.version} true standard ===== Model ===== The Java DTO generated from yang model. ===== Provider ===== * https://wiki.opendaylight.org/view/YANG_Tools:Helium:How-To%27s/Tutorials * http://sdntutorials.com/yang-to-java-conversion-how-to-create-maven-project-in-eclipse/ * http://docs.inocybe.com/dev-guide/content/_updating_the_maven_configuration_in_pom_xml.html ==== Config Subsystem Service ==== To wire the provider or consumer with SAL framework. The service dependencies are specified in a yang file inside provider source code, "provider/src/main/yang/task-provider-impl.yang". This YANG file is specifically used to generate bundle initialization code that will help provide Java dependencies. We will provide details to wire a module into the config subsystem in the next section. This configuration file is read by the YANG Code Generator, which autogenerates Java files to help with wiring into the config subsystem. The plugin needed to perform code generation: ==== Yang Based API & Configuration ==== In provider/pom.xml, yang-to-java is done by yang-maven-plugin. The generated plugin configuration: 19 33 .......................... 34 org.opendaylight.yangtools 35 yang-maven-plugin 36 ${yangtools.version} 37 38 39 config <-------- ????? 40 41 generate-sources 42 43 44 45 46 org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator 47 ${jmxGeneratorPath} 48 49 urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang 50 51 52 53 org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl 54 ${salGeneratorPath} 55 56 57 true 58 59 60 61 62 63 org.opendaylight.yangtools 64 maven-sal-api-gen-plugin 65 ${yangtools.version} 66 jar 67 68 69 org.opendaylight.controller 70 yang-jmx-generator-plugin 71 0.2.5-SNAPSHOT 72 73 74 **ERROR** The above code run code generation **twice**, one to the specified ${salGeneratorPath}, under execution id "config". The other as default to target/generated-sources. --> Duplicate class error. Do a mvn help:effective-pom to see details. If this is from the md-sal archetype --> TODO bug report!!!! How to fix? remove "id" from "execution" ==== Eclipse m2e-build-helper plugin ==== Source not detected by eclipse. No problem with mvn console!!! * http://stackoverflow.com/questions/7409823/m2e-lifecycle-mapping-not-found The org.eclipse.m2e:lifecycle-mapping plugin doesn't exist actually. It should be used from the section of your pom. That way, it's not resolved by Maven but can be read by m2e. But a more practical solution to your problem would be to install the m2e build-helper connector in eclipse. You can install it from the Window > Preferences > Maven > Discovery > open catalog. That way build-helper-maven-plugin:add-sources would be called in eclipse without having you to change your pom.xml. ==== Config Subsystem Dependency ==== Besides the plugin contained in pom.xml, we add code in the coffee-maker-provider-impl.yang file to wire ** RPC, notification and MD-SAL data broker dependencies **. 28 // Augments the 'configuration' choice node under modules/module. 29 // We consume the three main services, RPCs, DataStore, and Notifications 30 augment "/config:modules/config:module/config:configuration" { 31 case task-provider-impl { 32 when "/config:modules/config:module/config:type = 'task-provider-impl'"; 33 34 container rpc-registry { 35 uses config:service-ref { 36 refine type { 37 mandatory true; 38 config:required-identity mdsal:binding-rpc-registry; 39 } 40 } 41 } 42 43 container notification-service { 44 uses config:service-ref { 45 refine type { 46 mandatory true; 47 config:required-identity mdsal:binding-notification-service; 48 } 49 } 50 } 51 52 container data-broker { 53 uses config:service-ref { 54 refine type { 55 mandatory false; 56 config:required-identity mdsal:binding-async-data-broker; 57 } 58 } 59 } 60 } 61 } When you run mvn clean install, you will see a list of files generated under src/main/yang-gen-config and src/main/yang-gen-sal directories. Do not make any changes in the java files generated in those directories, and do commit them to your git/svn repository. There are two more files generated under src/main/java: Model*ProviderModule.java and Model*ProviderModuleFactory.java. Update these files to wire MD-SAL dependencies. provider/src/main/java/org/opendaylight/controller/config/yang/config/task_provider/impl/ ├── TaskProviderModuleFactory.java └── TaskProviderModule.java ==== Wiring a module into the Config Subsystem ==== The ModuleFactory.java is used when MD-SAL create an instance of the producer service. To initialize a module in the config subsystem and make it available for use in a controller environment, you must specify the module information within an XML-formatted configuration file. This file is also auto generated from yang file? or from archetype?, provider/src/main/resources/configuration/initial/05-provider-config.xml. In this example the module name and type use the namespace specified in task-provider-impl.yang. We add dependencies on rpc-registry, data-broker, and notification-service, which are required at runtime. ==== Registrate ServiceProvider Implementation With Global RPC ==== In TaskProviderModule: 14 public class TaskProviderModule extends org.opendaylight.controller.config.yang.config.task_provider.impl.AbstractTaskProviderModule { ... 30 @Override 31 public AutoCloseable createInstance() { 32 final TaskProvider appProvider = new TaskProvider(); 33 // Need data brocker to read/write to MD-SAL Config? and Operational Datastore 34 DataBroker dataBrokerService = getDataBrokerDependency(); 35 appProvider.setDataService(dataBrokerService); 36 // Registration with global RPC 37 RpcProviderRegistry rpcRegistryDependency = getRpcRegistryDependency(); 38 final BindingAwareBroker.RpcRegistration rpcRegistration = 39 rpcRegistryDependency 40 .addRpcImplementation(TaskService.class, appProvider); 41 42 //retrieves the notification service for publishing notifications 43 NotificationProviderService notificationService = getNotificationServiceDependency(); 44 45 46 // Wrap toaster as AutoCloseable and close registrations to md-sal at 47 // close() 48 final class CloseResources implements AutoCloseable { 49 50 @Override 51 public void close() throws Exception { 52 rpcRegistration.close(); 53 appProvider.close(); 54 log.info("TaskProvider (instance {}) torn down.", this); 55 } 56 } 57 58 AutoCloseable ret = new CloseResources(); 59 log.info("TaskProvider (instance {}) initialized.", ret); 60 return ret; 61 } ==== Implement The Service ==== The RPC registration above tells SAL to create an instance fo the service implementation when invoked: 31 public AutoCloseable createInstance() { 32 final TaskProvider appProvider = new TaskProvider(); The service implemenation is here: 12 import de.dailab.nemo.dmm.provider.TaskProvider; So all custom Provider implementation should be done with in this namespace. ===== Consumer ===== Consumer Plugin is also specified by yang file. ==== Initialize Consumer Instance with a Provider Instance ==== 13 public class TaskConsumerModule extends org.opendaylight.controller.config.yang.config.task_consumer.impl.AbstractTaskConsumerModule { 14 private static final Logger log = LoggerFactory.getLogger(TaskConsumerModule.class); 15 ... 28 29 @Override 30 public AutoCloseable createInstance() { 31 TaskService service = getRpcRegistryDependency().getRpcService(TaskService.class); <--------- Here it is 32 33 final TaskConsumerImpl consumerImpl = new TaskConsumerImpl(service); 34 35 36 final class AutoCloseableService implements TaskConsumerService, AutoCloseable { 37 38 @Override 39 public void close() throws Exception { 40 log.info("TaskConsumerService (instance {}) torn down.", this); 41 } 42 43 @Override 44 public void createEntry(Map data) { 45 consumerImpl.createEntry(data); 46 } 47 } 48 49 AutoCloseable ret = new AutoCloseableService(); 50 log.info("TaskConsumerService (instance {}) initialized.", ret ); 51 return ret; 52 } ===== Data Store ===== ===== Binding Independent Context ===== Binding Independent are the API that is not generated or provided by the producer or consumer. They a derived directly from yang model by Restconf service. ==== Load dependent Bundles ==== feature:install dmm-task-all odl-mdsal-apidocs odl-netconf-mdsal ==== RESTConf and the DataStore ==== ==== Background on Restconf, Mapping ==== Ref: * http://sdntutorials.com/what-is-restconf/ * https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Restconf Listing supported Yang module by restconf (karaf web): http://192.168.201.43:8181/restconf/modules === Restconf operations overview === * http://docs.inocybe.com/dev-guide/content/_restconf_operations_overview.html * https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Concepts#Instance_Identifier Restconf allows access to datastores in the controller. There are two datastores: Config: Contains data inserted via controller Operational: Contains other data Each request must start with the URI /restconf. Restconf listens on port 8080 for HTTP requests. Restconf supports OPTIONS, GET, PUT, POST, and DELETE operations. Request and response data can either be in the XML or JSON format. XML structures according to yang are defined at: XML-YANG. JSON structures are defined at: JSON-YANG. Data in the request must have a correctly set Content-Type field in the http header with the allowed value of the media type. The media type of the requested data has to be set in the Accept field. Get the media types for each resource by calling the OPTIONS operation. Most of the paths of the pathsRestconf endpoints use Instance Identifier. is used in the explanation of the operations. It must start with : where is a name of the module and is the name of a node in the module. It is sufficient to just use after :. Each has to be separated by /. can represent a data node which is a list or container yang built-in type. If the data node is a list, there must be defined keys of the list behind the data node name for example, //. The format : has to be used in this case as well: Module A has node A1. Module B augments node A1 by adding node X. Module C augments node A1 by adding node X. For clarity, it has to be known which node is X (for example: C:X). For more details about encoding, see: Restconf 02 - Encoding YANG Instance Identifiers in the Request URI. ====== Configuration Subsystem: Hybrid SAL, Activators ====== ===== How To Load Bundles The Hybrid Way? ===== * See the Transition plan here: https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Architecture#Transition_Plan * https://lists.opendaylight.org/pipermail/controller-dev/2013-October/001614.html Load Bundle with Activator: * Bundle Activator defined in pom.xml * Activator class either inherits from AbstractBindingAwareConsumer or ComponentActivatorAbstractBase Using Config Subsystem: * Use yang modeling language as a language for modelling the configuration, dependencies and state data for Modules * In l2switch repo there are xml files that describe the different modules, dependencies and sequence of loading. ===== Sample ===== ==== Instance Identifier ==== The Instance Identifier is a unique identifier of an element (location) in the yang data tree; basically it is the path to the node that uniquely identifies all the node's parent nodes. For unique identification of list elements it is required to specify key values as well. MD-SAL currently provides three different APIs to access data in the common data store: Binding APIs (Java generated DTOs) DOM APIs HTTP Restconf APIs ==== Example ==== Consider the following simple YANG model for inventory: module inventory { namespace "urn:opendaylight:inventory"; prefix inv; revision "2013-06-07"; container nodes { list node { key "id"; leaf "id" { type "string"; } } } } And having one instance of node with name foo; Lets asume we want to create instance identifier for node foo, in following bindings/ formats: YANG / XML / XPath version /inv:nodes/inv:node[id="foo"] Binding-Aware version (generated APIs) import org.opendaylight.yang.gen.urn.opendaylight.inventory.rev130607.Nodes; import org.opendaylight.yang.gen.urn.opendaylight.inventory.rev130607.nodes.Node; import org.opendaylight.yang.gen.urn.opendaylight.inventory.rev130607.nodes.NodeKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; InstanceIdentifier identifier = InstanceIdentifier.builder(Nodes.class).child(Node.class,new NodeKey("foo")).toInstance(); Note: Last call toInstance() does not return an instance of node, but Java version of Instance identifier of Instance identifier which uniquely identifies node "foo"; Binding Independent version (yang-data-api) import org.opendaylight.yang.common.QName; import org.opendaylight.yang.data.api.InstanceIdentifier; QName nodes = QName.create("urn:opendaylight:inventory","2013-06-07","nodes"); QName node = QName.create("urn:opendaylight:inventory","2013-06-07","node"); QName idName = QName.create("urn:opendaylight:inventory","2013-06-07","id"); InstanceIdentifier = InstanceIdentifier.builder() .node(nodes) .nodeWithKey(node,idName,"foo") .toInstance(); Note: Last call toInstance() does not return an instance of node, but Java version of Instance identifier which uniquely identifies node "foo"; HTTP Restconf APIs http://localhost:8080/restconf/config/inventory:nodes/node/foo Note: We assume that HTTP APIs are exposed on localhost, port 8080 ==== . ==== === Create a task via Restconf === To create the controller you will do a REST post (you will need a rest client such as PostMan for google chrome). HTTP Method => POST URL => http://localhost:8080/restconf/config Header => Content-Type: application/yang.data+json Body => { "toaster:toaster" : { "toaster:toasterManufacturer" : "General Electric", "toaster:toasterModelNumber" : "123", "toaster:toasterStatus" : "up" } } # my body Body => { "task:task": {"entry": [ { "entry-id":"12", "title":"cool title", "desc":"this is it" } ] } } ====== Source Code & Tutorials ====== ===== Programming tools ===== * http://sdnhub.org/tutorials/opendaylight-tutorial/opendaylight-development-with-eclipse/ * http://sdnhub.org/releases/sdn-starter-kit-ryu/ * http://sdnhub.org/tutorials/app-pseudo-code/ ===== ODL Network Visualization ===== * http://plvision.eu/blog/opendaylight-vtn-coordinator-enabling-webui-and-cli/ * ====== Mininet ====== * http://mininet.org/walkthrough/ * https://github.com/mininet/openflow-tutorial/wiki/Create-a-Learning-Switch * http://sdnhub.org/tutorials/pox/ ===== Install Mininet ===== Install OVS packages first: openstack-neutron-openvswitch.noarch : Neutron openvswitch plugin openvswitch.x86_64 : Open vSwitch daemon/database/utilities openvswitch-controller.x86_64 : Open vSwitch OpenFlow controller openvswitch-devel.i686 : Open vSwitch OpenFlow development package (library, headers) openvswitch-devel.x86_64 : Open vSwitch OpenFlow development package (library, headers) openvswitch-test.noarch : Open vSwitch testing utilities python-openvswitch.noarch : Open vSwitch python bindings **openvswitch-controller** the default controller. Install mininet from GIT as instructed: ===== Start mininet ===== sudo mn --controller=remote,ip=172.16.102.161 --topo tree,3 sudo mn --topo single,3 --mac --switch ovsk,protocols=OpenFlow13 --controller remote ====== OVSDB Mininet ====== * At the end, modify miniet with ovsdb: https://wiki.opendaylight.org/view/OVSDB_Integration:Mininet_OVSDB_Tutorial