As the main open-source SDN project, opendaylight adopts the osgi framework and has been supported by many vendors. The helium version is also coming soon.
The following describes how to implement RPC in odl. odl uses Yang as the model definition file. The Yang specification was first used for netconf. Later, restconf implemented restful on the HTTP protocol, while Yang defined the model.
The implementation is divided into two steps: 1. Use Yang to define the model and implement the API jar package. 2. Implement the RPC service implementation class and register it to the session.
Two Java project directory structures.
Step 1: Define the Yang file and Its Pom. xml
Define XP test. Yang in the directory XP test \ SRC \ main \ Yang
module xptest { yang-version 1; namespace "http://startsky.com/ns/xptest"; prefix xps; organization "xpstudio Netconf Central"; contact "xinping <[email protected]>"; description "YANG version of the xptest-MIB."; revision "2014-10-3" { description "xptest module in progress."; } typedef DispString { type string { length "0 .. 255"; } description "YANG version of the SMIv2 DisplayString TEXTUAL-CONVENTION."; reference "RFC 2579, section 2."; } container xptester { leaf name { type string; } leaf age { type uint32; default 99; } leaf homeaddress { type string; } } // container toaster rpc make-order { input { leaf name { type string; } leaf days { type uint32; default 1; } } output { leaf name { type string; } leaf orderno { type uint32; } } } // make-order rpc cancel-order { input { leaf orderno { type uint32; } } output { leaf name { type string; } leaf order-status { type enumeration { enum "success" { value 1; } enum "fail" { value 2; } } } } } // cancel-order } // module xptest
Define the Pom. xml of Yang, and define Pom. xml under xptest.
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.opendaylight.controller.samples</groupId> <artifactId>sal-samples</artifactId> <version>1.1-SNAPSHOT</version> </parent> <artifactId>sample-xptest</artifactId> <packaging>bundle</packaging> <dependencies> <dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>yang-binding</artifactId> </dependency> <dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>yang-common</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.opendaylight.yangtools</groupId> <artifactId>yang-maven-plugin</artifactId> <dependencies> <dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>maven-sal-api-gen-plugin</artifactId> <version>${yangtools.version}</version> <type>jar</type> </dependency> </dependencies> <executions> <execution> <goals> <goal>generate-sources</goal> </goals> <configuration> <yangFilesRootDir>src/main/yang</yangFilesRootDir> <codeGenerators> <generator> <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass> <outputBaseDir>${salGeneratorPath}</outputBaseDir> </generator> </codeGenerators> <inspectDependencies>true</inspectDependencies> </configuration> </execution> </executions> </plugin> </plugins> </build> <scm> <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection> <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection> <tag>HEAD</tag> <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url> </scm></project>
The above Yang file defines two RPC.
Run MVN install to compile xptest. Yang. an RPC service xptestservice interface is generated. The two methods correspond to two RPC functions.
Step 2: Define the RPC implementation file xptestprovider and its Activator
This project is defined as xpprovider.
RPC implementation class XP testprovider
package org.opendaylight.controller.xptest.impl;import java.util.concurrent.Future;import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.CancelOrderInput;import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.CancelOrderOutput;import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.CancelOrderOutput.OrderStatus;import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.CancelOrderOutputBuilder;import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.MakeOrderInput;import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.MakeOrderOutput;import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.MakeOrderOutputBuilder;import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.XptestService;import org.opendaylight.yangtools.yang.common.RpcResult;import org.opendaylight.yangtools.yang.common.RpcResultBuilder;import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;import com.google.common.util.concurrent.Futures;public class XpTestProvider implements XptestService { @Override public Future<RpcResult<CancelOrderOutput>> cancelOrder( CancelOrderInput input) { // TODO Auto-generated method stub RpcResult<CancelOrderOutput> ret=null; if(input.getOrderno() >10) { ret=RpcResultBuilder.<CancelOrderOutput>failed().withError( ErrorType.APPLICATION, "resource-denied", "days > 10,failed!!" ).build(); }else { CancelOrderOutputBuilder builder=new CancelOrderOutputBuilder(); builder.setName("name"+input.getOrderno()); builder.setOrderStatus(OrderStatus.Success); ret=RpcResultBuilder.<CancelOrderOutput>success(builder.build()).build(); } return Futures.immediateFuture(ret); } @Override public Future<RpcResult<MakeOrderOutput>> makeOrder(MakeOrderInput input) { // TODO Auto-generated method stub RpcResult<MakeOrderOutput> ret=null; if(input.getDays()>10) { ret=RpcResultBuilder.<MakeOrderOutput>failed().withError( ErrorType.APPLICATION, "resource-denied", "days > 10,failed!!" ).build(); }else { MakeOrderOutputBuilder builder=new MakeOrderOutputBuilder(); builder.setName(input.getName()); builder.setOrderno((long) 112233); ret=RpcResultBuilder.<MakeOrderOutput>success(builder.build()).build(); } return Futures.immediateFuture(ret); }}
Implement the plug-in entry class activator, and implement the command line interface by the way. You can customize command line test commands.
/** * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */package org.opendaylight.controller.xptest;import org.eclipse.osgi.framework.console.CommandInterpreter;import org.eclipse.osgi.framework.console.CommandProvider;import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;import org.opendaylight.controller.xptest.impl.XpTestProvider;import org.opendaylight.yang.gen.v1.http.startsky.com.ns.xptest.rev141003.XptestService;import org.osgi.framework.BundleContext;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Forwarding Rules Manager Activator * * Activator {@link ForwardingRulesManager}. * It registers all listeners (DataChangeEvent, ReconcilNotification) * in the Session Initialization phase. * * @author <a href="mailto:[email protected]">Vaclav Demcak</a> * * */public class Activator extends AbstractBindingAwareProvider implements CommandProvider { private final static Logger LOG = LoggerFactory.getLogger(Activator.class); @Override public void onSessionInitiated(ProviderContext session) { LOG.info("FRMActivator initialization."); try { // final DataBroker dataBroker = session.getSALService(DataBroker.class);// this.manager = new ForwardingRulesManagerImpl(dataBroker, session);// this.manager.start(); XpTestProvider rpcins=new XpTestProvider(); session.addRpcImplementation(XptestService.class,rpcins); LOG.info("FRMActivator initialization successfull."); } catch (Exception e) { LOG.error("Unexpected error by FRM initialization!", e); this.stopImpl(null); } } @Override protected void startImpl(BundleContext context) { // TODO Auto-generated method stub super.startImpl(context); context.registerService(CommandProvider.class.getName(), this, null); } @Override protected void stopImpl(final BundleContext context) { /* if (manager != null) { try { manager.close(); } catch (Exception e) { LOG.error("Unexpected error by stopping FRMActivator", e); } manager = null; }*/ LOG.info("FRMActivator stopped."); } public void _gettpsbyne(CommandInterpreter ci) { ci.println("gettpsbyne:" + ci.nextArgument()); } @Override public String getHelp() { return "\tgettpsbyne neid– say what you input\n"; } }
The Pom. xml file of the xpprovider.
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.opendaylight.controller.samples</groupId> <artifactId>sal-samples</artifactId> <version>1.1-SNAPSHOT</version> </parent> <artifactId>sample-xptest-provider</artifactId> <packaging>bundle</packaging> <dependencies> <dependency> <groupId>${project.groupId}</groupId> <artifactId>sample-xptest</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>equinoxSDK381</groupId> <artifactId>org.eclipse.osgi</artifactId> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>config-api</artifactId> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>sal-binding-api</artifactId> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>sal-binding-config</artifactId> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>sal-common-util</artifactId> </dependency> <dependency> <groupId>org.osgi</groupId> <artifactId>org.osgi.core</artifactId> </dependency> <!-- dependencies to use AbstractDataBrokerTest --> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>sal-binding-broker-impl</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>sal-binding-broker-impl</artifactId> <type>test-jar</type> <scope>test</scope> </dependency> <dependency> <artifactId>junit</artifactId> <groupId>junit</groupId> <scope>test</scope> </dependency> <!-- used to mock up classes --> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>sal-binding-api</artifactId> </dependency> <dependency> <groupId>org.opendaylight.controller.model</groupId> <artifactId>model-flow-service</artifactId> </dependency> <dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>yang-common</artifactId> </dependency> <dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>sal-binding-broker-impl</artifactId> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <configuration> <instructions> <Bundle-Activator>org.opendaylight.controller.xptest.Activator</Bundle-Activator> </instructions> </configuration> </plugin> </plugins> </build> <scm> <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection> <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection> <tag>HEAD</tag> <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url> </scm></project>
Step 3: perform the test.
Run run. bat, start odl, and run the following test case in restclient. Tools that support restclient include chrome plug-in postman and Firefox restclient. There is also a separate jar package restclient on the Internet.
HTTP method => post
Url => http: // localhost: 8080/restconf/Operations/xptest: Make-order
Header => Content-Type: Application/yang. Data + JSON
Body =>
{
"Input ":
{
"Xptest: Name": "3", "xptest: Days": 3
}
}
The XML data is returned. How to add accept: Application/yang. Data + JSON in the header will return JSON data.
The failure test cases can be constructed according to the figure in the above Code.
I hope that anyone interested in odl will be able to help me.
How to Implement RPC in odl