Bug 560: Fixed Mount Point RPC registration service 55/8655/3
authorLukas Sedlak <lsedlak@cisco.com>
Fri, 4 Jul 2014 07:25:13 +0000 (09:25 +0200)
committerLukas Sedlak <lsedlak@cisco.com>
Fri, 4 Jul 2014 11:47:24 +0000 (13:47 +0200)
The RPC Services can now be correctly registered for Mount Points. The RPCs are able to
correctly propagate between Binding Independent Broker and Binding Aware Broker.

This commit is dependant on commit: https://git.opendaylight.org/gerrit/#/c/8654/

Change-Id: I6c3c3e1f648d1faa8b4d43a24eacaf014123b880
Signed-off-by: Lukas Sedlak <lsedlak@cisco.com>
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java
opendaylight/md-sal/sal-binding-dom-it/pom.xml
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/DOMRpcServiceTestBugfix560.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareRpcBroker.java
opendaylight/md-sal/sal-test-model/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-test-model/src/main/yang/opendaylight-test-rpc-service.yang [new file with mode: 0644]

index 24dcfad..d3f6d2d 100644 (file)
     <!--sal-protocolbuffer-encoding-->
     <module>sal-protocolbuffer-encoding</module>
 
-      <!--  Karaf feature -->
-      <module>feature</module>
+    <!--  Karaf feature -->
+    <module>feature</module>
 
+    <!-- Yang Test Models for MD-SAL -->
+    <module>sal-test-model</module>
   </modules>
 
   <build>
index d247266..c45cb90 100644 (file)
@@ -28,6 +28,7 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
+import com.google.common.base.Optional;
 import org.opendaylight.controller.md.sal.binding.impl.AbstractForwardedDataBroker;
 import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
@@ -57,6 +58,7 @@ import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
 import org.opendaylight.controller.sal.core.api.Provider;
 import org.opendaylight.controller.sal.core.api.RpcImplementation;
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
 import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
@@ -321,7 +323,10 @@ public class BindingIndependentConnector implements //
     public void startRpcForwarding() {
         if (biRpcRegistry != null && baRpcRegistry instanceof RouteChangePublisher<?, ?>) {
             checkState(!rpcForwarding, "Connector is already forwarding RPCs");
-            domToBindingRpcManager = baRpcRegistry.registerRouteChangeListener(new DomToBindingRpcForwardingManager());
+            final DomToBindingRpcForwardingManager biFwdManager = new DomToBindingRpcForwardingManager();
+
+            domToBindingRpcManager = baRpcRegistry.registerRouteChangeListener(biFwdManager);
+            biRpcRegistry.addRpcRegistrationListener(biFwdManager);
             if (baRpcRegistry instanceof RpcProviderRegistryImpl) {
                 baRpcRegistryImpl = (RpcProviderRegistryImpl) baRpcRegistry;
                 baRpcRegistryImpl.registerRouterInstantiationListener(domToBindingRpcManager.getInstance());
@@ -528,7 +533,7 @@ public class BindingIndependentConnector implements //
      */
     private class DomToBindingRpcForwardingManager implements
             RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>, RouterInstantiationListener,
-            GlobalRpcRegistrationListener {
+            GlobalRpcRegistrationListener, RpcRegistrationListener {
 
         private final Map<Class<? extends RpcService>, DomToBindingRpcForwarder> forwarders = new WeakHashMap<>();
         private RpcProviderRegistryImpl registryImpl;
@@ -543,7 +548,7 @@ public class BindingIndependentConnector implements //
 
         @Override
         public void onGlobalRpcRegistered(final Class<? extends RpcService> cls) {
-            getRpcForwarder(cls, null);
+            getRpcForwarder(cls, null).registerToDOMBroker();
         }
 
         @Override
@@ -588,31 +593,39 @@ public class BindingIndependentConnector implements //
             return potential;
         }
 
+        @Override
+        public void onRpcImplementationAdded(QName name) {
+
+            final Optional<Class<? extends RpcService>> rpcInterface = mappingService.getRpcServiceClassFor(
+                    name.getNamespace().toString(), name.getFormattedRevision());
+            if (rpcInterface.isPresent()) {
+                getRpcForwarder(rpcInterface.get(), null).registerToBidningBroker();
+            }
+        }
+
+        @Override
+        public void onRpcImplementationRemoved(QName name) {
+
+        }
     }
 
     private class DomToBindingRpcForwarder implements RpcImplementation, InvocationHandler {
 
         private final Set<QName> supportedRpcs;
         private final WeakReference<Class<? extends RpcService>> rpcServiceType;
-        private final Set<org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration> registrations;
+        private Set<org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration> registrations;
         private final Map<QName, RpcInvocationStrategy> strategiesByQName = new HashMap<>();
         private final WeakHashMap<Method, RpcInvocationStrategy> strategiesByMethod = new WeakHashMap<>();
+        private final RpcService proxy;
 
         public DomToBindingRpcForwarder(final Class<? extends RpcService> service) {
             this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
             this.supportedRpcs = mappingService.getRpcQNamesFor(service);
-            try {
-                for (QName rpc : supportedRpcs) {
-                    RpcInvocationStrategy strategy = createInvocationStrategy(rpc, service);
-                    strategiesByMethod.put(strategy.targetMethod, strategy);
-                    strategiesByQName.put(rpc, strategy);
-                    biRpcRegistry.addRpcImplementation(rpc, this);
-                }
 
-            } catch (Exception e) {
-                LOG.error("Could not forward Rpcs of type {}", service.getName(), e);
-            }
-            registrations = ImmutableSet.of();
+            Class<?> cls = rpcServiceType.get();
+            ClassLoader clsLoader = cls.getClassLoader();
+            proxy =(RpcService) Proxy.newProxyInstance(clsLoader, new Class<?>[] { cls }, this);
+            createStrategies();
         }
 
         /**
@@ -622,16 +635,12 @@ public class BindingIndependentConnector implements //
          * @param context
          */
         public DomToBindingRpcForwarder(final Class<? extends RpcService> service,
-                final Class<? extends BaseIdentity> context) {
-            this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
-            this.supportedRpcs = mappingService.getRpcQNamesFor(service);
+                                        final Class<? extends BaseIdentity> context) {
+            this(service);
             Builder<RoutedRpcRegistration> registrationsBuilder = ImmutableSet
                     .<org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration> builder();
             try {
                 for (QName rpc : supportedRpcs) {
-                    RpcInvocationStrategy strategy = createInvocationStrategy(rpc, service);
-                    strategiesByMethod.put(strategy.targetMethod, strategy);
-                    strategiesByQName.put(rpc, strategy);
                     registrationsBuilder.add(biRpcRegistry.addRoutedRpcImplementation(rpc, this));
                 }
                 createDefaultDomForwarder();
@@ -641,6 +650,32 @@ public class BindingIndependentConnector implements //
             registrations = registrationsBuilder.build();
         }
 
+
+
+        private void createStrategies() {
+            try {
+                for (QName rpc : supportedRpcs) {
+                    RpcInvocationStrategy strategy = createInvocationStrategy(rpc, rpcServiceType.get());
+                    strategiesByMethod.put(strategy.targetMethod, strategy);
+                    strategiesByQName.put(rpc, strategy);
+                }
+            } catch (Exception e) {
+                LOG.error("Could not forward Rpcs of type {}", rpcServiceType.get(), e);
+            }
+
+        }
+
+        public void registerToDOMBroker() {
+            try {
+                for (QName rpc : supportedRpcs) {
+                    biRpcRegistry.addRpcImplementation(rpc, this);
+                }
+            } catch (Exception e) {
+                LOG.error("Could not forward Rpcs of type {}", rpcServiceType.get(), e);
+            }
+        }
+
+
         public void registerPaths(final Class<? extends BaseIdentity> context,
                 final Class<? extends RpcService> service, final Set<InstanceIdentifier<?>> set) {
             QName ctx = BindingReflections.findQName(context);
@@ -737,6 +772,10 @@ public class BindingIndependentConnector implements //
 
             });
         }
+
+        public void registerToBidningBroker() {
+               baRpcRegistry.addRpcImplementation((Class)rpcServiceType.get(), proxy);
+        }
     }
 
     public boolean isRpcForwarding() {
index fd5c5be..46971ca 100644 (file)
       <artifactId>pax-exam-container-native</artifactId>
       <scope>test</scope>
     </dependency>
-
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-simple</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-parser-impl</artifactId>
+      <scope>test</scope>
+    </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-test-model</artifactId>
+          <version>1.1-SNAPSHOT</version>
+      </dependency>
   </dependencies>
   <build>
     <plugins>
diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/DOMRpcServiceTestBugfix560.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/DOMRpcServiceTestBugfix560.java
new file mode 100644 (file)
index 0000000..6a6af06
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * 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.sal.binding.test.connect.dom;
+
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.sal.binding.api.mount.MountProviderInstance;
+import org.opendaylight.controller.sal.binding.api.mount.MountProviderService;
+import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory;
+import org.opendaylight.controller.sal.binding.test.util.BindingTestContext;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.bi.ba.rpcservice.rev140701.OpendaylightTestRpcServiceService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.bi.ba.rpcservice.rev140701.RockTheHouseInputBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+
+/**
+ * Test case for reported bug 560
+ *
+ * @author Lukas Sedlak
+ * @see <a
+ *      href="https://bugs.opendaylight.org/show_bug.cgi?id=560">https://bugs.opendaylight.org/show_bug.cgi?id=560</a>
+ */
+public class DOMRpcServiceTestBugfix560 {
+
+    private final static String RPC_SERVICE_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:test:bi:ba:rpcservice";
+    private final static String REVISION_DATE = "2014-07-01";
+    private final static QName RPC_NAME = QName.create(RPC_SERVICE_NAMESPACE,
+            REVISION_DATE, "rock-the-house");
+
+    private static final NodeId MOUNT_NODE = new NodeId("id");
+    private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
+
+    private static final InstanceIdentifier<Node> BA_MOUNT_ID = createBANodeIdentifier(MOUNT_NODE);
+    private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier BI_MOUNT_ID = createBINodeIdentifier(MOUNT_NODE);
+
+    private BindingTestContext testContext;
+    private MountProvisionService domMountPointService;
+    private MountProviderService bindingMountPointService;
+    private SchemaContext schemaContext;
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @Before
+    public void setUp() throws Exception {
+        BindingBrokerTestFactory testFactory = new BindingBrokerTestFactory();
+        testFactory.setExecutor(MoreExecutors.sameThreadExecutor());
+        testFactory.setStartWithParsedSchema(true);
+        testContext = testFactory.getTestContext();
+
+        testContext.start();
+        domMountPointService = testContext.getDomMountProviderService();
+        bindingMountPointService = testContext.getBindingMountProviderService();
+        assertNotNull(domMountPointService);
+
+        final YangContextParser parser = new YangParserImpl();
+        final InputStream moduleStream = BindingReflections.getModuleInfo(
+                OpendaylightTestRpcServiceService.class)
+                .getModuleSourceStream();
+
+        assertNotNull(moduleStream);
+        List<InputStream> rpcModels = Collections.singletonList(moduleStream);
+        Set<Module> modules = parser.parseYangModelsFromStreams(rpcModels);
+        schemaContext = parser.resolveSchemaContext(modules);
+    }
+
+    private static org.opendaylight.yangtools.yang.data.api.InstanceIdentifier createBINodeIdentifier(
+            NodeId mountNode) {
+        return org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+                .builder().node(Nodes.QNAME)
+                .nodeWithKey(Node.QNAME, NODE_ID_QNAME, mountNode.getValue())
+                .toInstance();
+    }
+
+    private static InstanceIdentifier<Node> createBANodeIdentifier(
+            NodeId mountNode) {
+        return InstanceIdentifier.builder(Nodes.class)
+                .child(Node.class, new NodeKey(mountNode)).toInstance();
+    }
+
+    @Test
+    public void test() throws ExecutionException, InterruptedException {
+        testContext.getBindingDataBroker().readOperationalData(BA_MOUNT_ID);
+        final MountProvisionInstance mountPoint = domMountPointService
+                .createMountPoint(BI_MOUNT_ID);
+        mountPoint.setSchemaContext(schemaContext);
+        assertNotNull(mountPoint);
+
+        mountPoint.addRpcImplementation(RPC_NAME, new RpcImplementation() {
+
+            @Override
+            public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(
+                    QName rpc, CompositeNode input) {
+
+                return Futures.immediateFuture(Rpcs
+                        .<CompositeNode> getRpcResult(true));
+            }
+
+            @Override
+            public Set<QName> getSupportedRpcs() {
+                return ImmutableSet.of(RPC_NAME);
+            }
+        });
+
+        final Set<QName> biSupportedRpcs = mountPoint.getSupportedRpcs();
+        assertNotNull(biSupportedRpcs);
+        assertTrue(!biSupportedRpcs.isEmpty());
+
+        MountProviderInstance mountInstance = bindingMountPointService
+                .getMountPoint(BA_MOUNT_ID);
+        assertNotNull(mountInstance);
+        final OpendaylightTestRpcServiceService rpcService = mountInstance
+                .getRpcService(OpendaylightTestRpcServiceService.class);
+        assertNotNull(rpcService);
+
+        try {
+            Future<RpcResult<Void>> result = rpcService
+                    .rockTheHouse(new RockTheHouseInputBuilder().build());
+            assertTrue(result.get().isSuccessful());
+        } catch (IllegalStateException ex) {
+            fail("OpendaylightTestRpcServiceService class doesn't contain rockTheHouse method!");
+        }
+    }
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @After
+    public void teardown() throws Exception {
+        testContext.close();
+    }
+}
index 8fc6fe2..3213930 100644 (file)
@@ -14,6 +14,7 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import com.google.common.base.Preconditions;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
 import org.opendaylight.controller.md.sal.common.impl.routing.RoutingUtils;
@@ -140,17 +141,34 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
         RpcDefinition definition = findRpcDefinition(rpcType);
         checkArgument(!isRoutedRpc(definition), "RPC Type must not be routed.");
         GlobalRpcRegistration reg = new GlobalRpcRegistration(rpcType, implementation, this);
-        implementations.putIfAbsent(rpcType, implementation);
+        final RpcImplementation previous = implementations.putIfAbsent(rpcType, implementation);
+        Preconditions.checkState(previous == null, "Rpc %s is already registered.",rpcType);
+        notifyRpcAdded(rpcType);
         return reg;
     }
 
+    private void notifyRpcAdded(QName rpcType) {
+        for (ListenerRegistration<RpcRegistrationListener> listener : rpcRegistrationListeners) {
+            try {
+                listener.getInstance().onRpcImplementationAdded(rpcType);
+            } catch (Exception ex) {
+                LOG.error("Unhandled exception during invoking listener {}", listener.getInstance(), ex);
+            }
+
+        }
+    }
+
     private boolean isRoutedRpc(RpcDefinition definition) {
         return getRoutingStrategy(definition) instanceof RoutedRpcStrategy;
     }
 
     @Override
     public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(RpcRegistrationListener listener) {
-        return rpcRegistrationListeners.register(listener);
+        ListenerRegistration<RpcRegistrationListener> reg = rpcRegistrationListeners.register(listener);
+        for (QName impl : implementations.keySet()) {
+            listener.onRpcImplementationAdded(impl);
+        }
+        return reg;
     }
 
     @Override
diff --git a/opendaylight/md-sal/sal-test-model/pom.xml b/opendaylight/md-sal/sal-test-model/pom.xml
new file mode 100644 (file)
index 0000000..8d29b98
--- /dev/null
@@ -0,0 +1,77 @@
+<?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">
+    <parent>
+        <artifactId>sal-parent</artifactId>
+        <groupId>org.opendaylight.controller</groupId>
+        <version>1.1-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+    </dependencies>
+
+    <artifactId>sal-test-model</artifactId>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <configuration>
+                    <includes>
+                        <include>org.opendaylight.controller.*</include>
+                    </includes>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>pre-test</id>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>post-test</id>
+                        <goals>
+                            <goal>report</goal>
+                        </goals>
+                        <phase>test</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <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>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-test-model/src/main/yang/opendaylight-test-rpc-service.yang b/opendaylight/md-sal/sal-test-model/src/main/yang/opendaylight-test-rpc-service.yang
new file mode 100644 (file)
index 0000000..3412eb5
--- /dev/null
@@ -0,0 +1,22 @@
+module opendaylight-test-rpc-service {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:test:bi:ba:rpcservice";
+    prefix "rpc";
+
+    description
+        "Test model for testing of registering rpc service on binding independent mount point 
+        and retrieving rpc service via binding aware mount point.";
+
+    revision "2014-07-01" {
+        description
+            "Initial revision";
+    }
+
+    rpc rock-the-house {
+        input {
+            leaf zip-code {
+                type string;
+            }
+        }
+    }
+}
\ No newline at end of file

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.