Merge "Fixed deserialization of IdentityRefs in Restconf URI."
authorEd Warnicke <eaw@cisco.com>
Tue, 10 Dec 2013 20:01:51 +0000 (20:01 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 10 Dec 2013 20:01:51 +0000 (20:01 +0000)
141 files changed:
opendaylight/config/logback-config/src/main/yang/config-logging.yang
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/TemplateFactory.java
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/Field.java
opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java
opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ModuleMXBeanEntryTemplatesTest.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntry.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/TypeProviderWrapper.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/JavaAttribute.java
opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryNameConflictTest.java
opendaylight/config/yang-jmx-generator/src/test/resources/duplicates/config-test-duplicate-attribute-in-runtime-and-mxbean.yang [new file with mode: 0644]
opendaylight/config/yang-test/src/main/yang/config-test-impl.yang
opendaylight/distribution/opendaylight/pom.xml
opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/00-netty.conf
opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.conf
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java
opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestFromSalConversionsUtils.java
opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestToSalConversionsUtils.java
opendaylight/md-sal/forwardingrules-manager/pom.xml
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/FRMUtil.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractTransaction.xtend [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FRMActivator.xtend [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowCommitHandler.xtend [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.xtend [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransaction.xtend [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransactionValidator.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupCommitHandler.xtend [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.xtend [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransaction.xtend [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransactionValidator.java [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterCommitHandler.xtend [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.xtend [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransaction.xtend [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransactionValidator.java [new file with mode: 0644]
opendaylight/md-sal/model/model-flow-base/src/main/yang/action-types.yang [deleted file]
opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/match-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-action-types.yang [new file with mode: 0644]
opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-flow-types.yang [moved from opendaylight/md-sal/model/model-flow-base/src/main/yang/flow-types.yang with 73% similarity]
opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang
opendaylight/md-sal/model/model-inventory/src/main/yang/opendaylight-inventory-config.yang [new file with mode: 0644]
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-binding-broker/pom.xml
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AugmentationVerifier.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/BindingTestUtilities.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/MultipleAugmentationPuts.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java
opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/AbstractTest.java
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/Rpcs.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractConsumer.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractProvider.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend
opendaylight/md-sal/sal-remoterpc-connector/implementation/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/remote/rpc/ZeroMQServerModule.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/remote/rpc/ZeroMQServerModuleFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Client.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Context.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcClient.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProvider.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcServer.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RoutingTableProvider.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RpcSocket.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Sender.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ServerImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/SocketManager.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/SocketPair.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/CompositeNodeImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/Message.java [moved from opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/Message.java with 88% similarity]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/MessageWrapper.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/RouteIdentifierImpl.java [moved from opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/RouteIdentifierImpl.java with 54% similarity]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/RpcRequestImpl.java [moved from opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/RpcRequestImpl.java with 94% similarity]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/util/XmlUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/scala/org/opendaylight/controller/sal/connector/remoterpc/Client.scala [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/yang/odl-sal-dom-rpc-remote-cfg.yang [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/RouteIdentifierImplTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/RpcSocketTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/SerilizationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/SocketManagerTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/resources/FourSimpleChildren.xml [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/pom.xml [moved from opendaylight/md-sal/test/zeromq-test-consumer/pom.xml with 87% similarity]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/java/org/opendaylight/controller/sample/zeromq/consumer/ExampleConsumer.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/FourSimpleChildren.xml [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/InvalidCompositeChild.xml [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/InvalidSimpleChild.xml [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/OneSimpleChild.xml [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/OneSimpleOneCompositeChild.xml [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/TwoCompositeChildren.xml [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/TwoSimpleChildren.xml [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/provider-service/pom.xml [moved from opendaylight/md-sal/test/zeromq-test-provider/pom.xml with 89% similarity]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/provider-service/src/main/java/org/opendaylight/controller/sample/zeromq/provider/ExampleProvider.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/RouterTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/resources/controller.config [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/resources/logback.xml [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqrouter/rest/Router.java [new file with mode: 0644]
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java
opendaylight/md-sal/sal-zeromq-connector/pom.xml [deleted file]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChange.java [deleted file]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/Activator.java [deleted file]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/ZeroMqRpcRouter.java [deleted file]
opendaylight/md-sal/test/pom.xml [deleted file]
opendaylight/md-sal/test/zeromq-test-consumer/src/main/java/org/opendaylight/controller/sample/zeromq/consumer/ExampleConsumer.java [deleted file]
opendaylight/md-sal/test/zeromq-test-it/pom.xml [deleted file]
opendaylight/md-sal/test/zeromq-test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/ServiceConsumerController.java [deleted file]
opendaylight/md-sal/test/zeromq-test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/ServiceProviderController.java [deleted file]
opendaylight/md-sal/test/zeromq-test-provider/src/main/java/org/opendaylight/controller/sample/zeromq/provider/ExampleProvider.java [deleted file]
opendaylight/md-sal/zeromq-routingtable/implementation/pom.xml
opendaylight/netconf/config-netconf-connector/pom.xml
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AbstractAttributeReadingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeConfigElement.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleAttributeReadingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleBinaryAttributeReadingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleCompositeAttributeReadingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/CompositeAttributeResolvingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleBinaryAttributeWritingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_differentNamespaceTO.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_typeNameConfigAttributeMatching.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised7.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised8.xml
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeTableStatistics.java
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java
opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/UserConfig.java
opendaylight/web/flows/src/main/java/org/opendaylight/controller/flows/web/Flows.java
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/UserBean.java [new file with mode: 0644]

index 7f4ea39dd4ccb66d5e65979ce994848b884d2dd0..3b28b574696683540391dd53ab041b0b40dd7ebb 100644 (file)
@@ -51,6 +51,7 @@ module config-logging {
                     type string;
                     mandatory true;
                 }
+                key name;
                 config:java-name-prefix FileAppenderTO;
             }
             
@@ -89,6 +90,7 @@ module config-logging {
                     type string;
                     mandatory true;
                 }
+                key name;
 
                 leaf file-name-pattern {
                     type string;
@@ -107,7 +109,7 @@ module config-logging {
                 
                 leaf clean-history-on-start {
                     type boolean;
-                    default 0;
+                    default false;
                 }
                 config:java-name-prefix RollingFileAppenderTO;
             }
@@ -128,6 +130,8 @@ module config-logging {
                     type string;
                     mandatory true;
                 }
+                key name;
+
                 config:java-name-prefix ConsoleAppenderTO;
             }
 
@@ -136,6 +140,7 @@ module config-logging {
                     type string;
                     mandatory true;
                 }
+                key logger-name;
 
                 leaf level {
                     type string;
index 6da68018f2ff92e3795c017b9ddadb2628a7e625..115bb85b618020b61282c83c3c692c9dafca6251 100644 (file)
@@ -129,7 +129,7 @@ public class TemplateFactory {
                 for (JavaAttribute ja : rpc.getParameters()) {
                     Field field = new Field(Collections.<String> emptyList(),
                             ja.getType().getFullyQualifiedName(),
-                            ja.getLowerCaseCammelCase());
+                            ja.getLowerCaseCammelCase(), ja.getNullableDefaultWrappedForCode());
                     fields.add(field);
                 }
                 MethodDeclaration operation = new MethodDeclaration(
@@ -433,15 +433,18 @@ public class TemplateFactory {
                     String varName = BindingGeneratorUtil
                             .parseToValidParamName(attrEntry.getKey());
 
-                    String fullyQualifiedName;
+                    String fullyQualifiedName, nullableDefault = null;
                     if (attrEntry.getValue() instanceof TypedAttribute) {
                         Type type = ((TypedAttribute) attrEntry.getValue()).getType();
                         fullyQualifiedName = serializeType(type);
+                        if(attrEntry.getValue() instanceof JavaAttribute) {
+                            nullableDefault = ((JavaAttribute)attrEntry.getValue()).getNullableDefaultWrappedForCode();
+                        }
                     } else {
                         fullyQualifiedName = FullyQualifiedNameHelper
                                 .getFullyQualifiedName(packageName, attrEntry.getValue().getUpperCaseCammelCase());
                     }
-                    fields.add(new Field(fullyQualifiedName, varName));
+                    fields.add(new Field(fullyQualifiedName, varName, nullableDefault));
 
                     String getterName = "get" + innerName;
                     MethodDefinition getter = new MethodDefinition(
@@ -531,6 +534,7 @@ public class TemplateFactory {
                 String packageName) {
             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
                 String type;
+                String nullableDefaultWrapped = null;
                 AttributeIfc attributeIfc = attrEntry.getValue();
 
                 if (attributeIfc instanceof TypedAttribute) {
@@ -548,6 +552,7 @@ public class TemplateFactory {
                     if (innerAttr instanceof JavaAttribute) {
                         fullyQualifiedName = ((JavaAttribute) innerAttr)
                                 .getType().getFullyQualifiedName();
+                        nullableDefaultWrapped = ((JavaAttribute) innerAttr).getNullableDefaultWrappedForCode();
                     } else if (innerAttr instanceof TOAttribute) {
                         fullyQualifiedName = FullyQualifiedNameHelper
                                 .getFullyQualifiedName(packageName, innerAttr.getUpperCaseCammelCase());
@@ -563,7 +568,7 @@ public class TemplateFactory {
                 }
 
                 fields.add(new Field(type, attributeIfc
-                        .getUpperCaseCammelCase()));
+                        .getUpperCaseCammelCase(), nullableDefaultWrapped));
             }
         }
 
@@ -582,12 +587,16 @@ public class TemplateFactory {
         void processAttributes(Map<String, AttributeIfc> attributes,
                 String packageName) {
             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
-                String type;
+                String type, nullableDefaultWrapped = null;
                 AttributeIfc attributeIfc = attrEntry.getValue();
 
                 if (attributeIfc instanceof TypedAttribute) {
                     TypedAttribute typedAttribute = (TypedAttribute) attributeIfc;
                     type = serializeType(typedAttribute.getType());
+                    if (attributeIfc instanceof JavaAttribute) {
+                        nullableDefaultWrapped = ((JavaAttribute) attributeIfc).getNullableDefaultWrappedForCode();
+                    }
+
                 } else if (attributeIfc instanceof TOAttribute) {
                     String fullyQualifiedName = FullyQualifiedNameHelper
                             .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
@@ -600,6 +609,7 @@ public class TemplateFactory {
                     if (innerAttr instanceof JavaAttribute) {
                         fullyQualifiedName = ((JavaAttribute) innerAttr)
                                 .getType().getFullyQualifiedName();
+                        nullableDefaultWrapped = ((JavaAttribute) innerAttr).getNullableDefaultWrappedForCode();
                     } else if (innerAttr instanceof TOAttribute) {
                         fullyQualifiedName = FullyQualifiedNameHelper
                                 .getFullyQualifiedName(packageName, innerAttr.getUpperCaseCammelCase());
@@ -631,8 +641,7 @@ public class TemplateFactory {
                 String varName = BindingGeneratorUtil
                         .parseToValidParamName(attrEntry.getKey());
                 moduleFields.add(new ModuleField(type, varName, attributeIfc
-                        .getUpperCaseCammelCase(), attributeIfc
-                        .getNullableDefault(), isDependency, dependency));
+                        .getUpperCaseCammelCase(), nullableDefaultWrapped, isDependency, dependency));
 
                 String getterName = "get"
                         + attributeIfc.getUpperCaseCammelCase();
index fe9e885b6fab8edcc457008b479f534512073386..0857ec6f8da64e16e64119d44d78834fd477cb9c 100644 (file)
@@ -7,10 +7,10 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model;
 
-import java.util.List;
-
 import com.google.common.collect.Lists;
 
+import java.util.List;
+
 public class Field {
     private final String type;
     private final String name;
@@ -21,6 +21,10 @@ public class Field {
         this(Lists.<String> newArrayList(), type, name, null);
     }
 
+    public Field(String type, String name, String definition) {
+        this(Lists.<String> newArrayList(), type, name, definition);
+    }
+
     public Field(List<String> modifiers, String type, String name) {
         this(modifiers, type, name, null);
     }
index 2f1437404a7d49f7673d0c6ae34637f597be6847..1945cac1c270919d10b59481139581e848c87f0a 100644 (file)
@@ -534,7 +534,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
         assertDeclaredField(fieldDeclarations,
                 "private java.util.concurrent.ThreadFactory threadfactoryDependency");
         assertDeclaredField(fieldDeclarations,
-                "private java.lang.Long keepAlive=10");
+                "private java.lang.Long keepAlive=new java.lang.Long(\"10\")");
         assertDeclaredField(fieldDeclarations,
                 "private java.lang.Long coreSize");
         assertDeclaredField(fieldDeclarations, "private byte[] binary");
index 3c479318968e35cc6a132e9c6b88ae8d6700ff72..48d5b30eb282731bc7adabe46427384352272bf4 100644 (file)
@@ -7,14 +7,7 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator.plugin;
 
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-
-import java.util.Collections;
-import java.util.Map;
-
+import com.google.common.collect.Maps;
 import org.junit.Test;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
@@ -23,7 +16,13 @@ import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.AbstractFa
 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
 
-import com.google.common.collect.Maps;
+import java.util.Collections;
+import java.util.Map;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 
 public class ModuleMXBeanEntryTemplatesTest {
 
@@ -61,6 +60,7 @@ public class ModuleMXBeanEntryTemplatesTest {
         doReturn("package.type").when(typeA).getFullyQualifiedName();
         doReturn(typeA).when(attr).getType();
         doReturn("Type").when(attr).getUpperCaseCammelCase();
+        doReturn("new Default()").when(attr).getNullableDefault();
         return attr;
     }
 
index a7110b874c829e00cfaccf4386abf97fb9c7b556..4eba739b469d52b675b7208e0621c9ddc9f4a845 100644 (file)
@@ -7,9 +7,21 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static java.lang.String.format;
+import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AbstractDependencyAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
@@ -41,20 +53,9 @@ import org.opendaylight.yangtools.yang.model.api.UsesNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static java.lang.String.format;
-import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
 
 /**
  * Represents part of yang model that describes a module.
@@ -184,8 +185,9 @@ public class ModuleMXBeanEntry extends AbstractEntry {
     }
 
     /**
-     * @return services implemented by this module. Keys are fully qualified java names of generated
-     * ServiceInterface classes, values are identity local names.
+     * @return services implemented by this module. Keys are fully qualified
+     *         java names of generated ServiceInterface classes, values are
+     *         identity local names.
      */
     public Map<String, QName> getProvidedServices() {
         return providedServices;
@@ -360,7 +362,6 @@ public class ModuleMXBeanEntry extends AbstractEntry {
                                     e.getConflictingName(), when.getQName(),
                                     when.getQName());
                         }
-
                         checkUniqueRuntimeBeansGeneratedClasses(
                                 uniqueGeneratedClassesNames, when, runtimeBeans);
                         Set<RuntimeBeanEntry> runtimeBeanEntryValues = Sets
@@ -415,6 +416,11 @@ public class ModuleMXBeanEntry extends AbstractEntry {
                         .<RuntimeBeanEntry> emptyList());
             }
         }
+        // check attributes name uniqueness
+        for (Entry<String, ModuleMXBeanEntry> entry : result.entrySet()) {
+            checkUniqueRuntimeBeanAttributesName(entry.getValue(),
+                    uniqueGeneratedClassesNames);
+        }
         if (unaugmentedModuleIdentities.size() > 0) {
             logger.warn("Augmentation not found for all module identities: {}",
                     unaugmentedModuleIdentities.keySet());
@@ -443,6 +449,25 @@ public class ModuleMXBeanEntry extends AbstractEntry {
         }
     }
 
+    private static void checkUniqueRuntimeBeanAttributesName(
+            ModuleMXBeanEntry mxBeanEntry,
+            Map<String, QName> uniqueGeneratedClassesNames) {
+        for (RuntimeBeanEntry runtimeBeanEntry : mxBeanEntry.getRuntimeBeans()) {
+            for (String runtimeAttName : runtimeBeanEntry
+                    .getYangPropertiesToTypesMap().keySet()) {
+                if (mxBeanEntry.getAttributes().keySet()
+                        .contains(runtimeAttName)) {
+                    QName qName1 = uniqueGeneratedClassesNames
+                            .get(runtimeBeanEntry.getJavaNameOfRuntimeMXBean());
+                    QName qName2 = uniqueGeneratedClassesNames.get(mxBeanEntry
+                            .getGloballyUniqueName());
+                    throw new NameConflictException(runtimeAttName, qName1,
+                            qName2);
+                }
+            }
+        }
+    }
+
     private static void checkUniqueAttributesWithGeneratedClass(
             Map<String, QName> uniqueGeneratedClassNames, QName parentQName,
             Map<String, AttributeIfc> yangToAttributes) {
@@ -566,7 +591,8 @@ public class ModuleMXBeanEntry extends AbstractEntry {
     private static AttributeIfc getAttributeValue(DataSchemaNode attrNode,
             Module currentModule,
             Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
-            TypeProviderWrapper typeProviderWrapper, SchemaContext schemaContext, String packageName) {
+            TypeProviderWrapper typeProviderWrapper,
+            SchemaContext schemaContext, String packageName) {
 
         if (attrNode instanceof LeafSchemaNode) {
             // simple type
@@ -575,12 +601,14 @@ public class ModuleMXBeanEntry extends AbstractEntry {
         } else if (attrNode instanceof ContainerSchemaNode) {
             // reference or TO
             ContainerSchemaNode containerSchemaNode = (ContainerSchemaNode) attrNode;
-            Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(containerSchemaNode,
-                    attrNode, currentModule, qNamesToSIEs, schemaContext);
+            Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(
+                    containerSchemaNode, attrNode, currentModule, qNamesToSIEs,
+                    schemaContext);
             if (dependencyAttributeOptional.isPresent()) {
                 return dependencyAttributeOptional.get();
             } else {
-                return TOAttribute.create(containerSchemaNode, typeProviderWrapper, packageName);
+                return TOAttribute.create(containerSchemaNode,
+                        typeProviderWrapper, packageName);
             }
 
         } else if (attrNode instanceof LeafListSchemaNode) {
@@ -588,12 +616,14 @@ public class ModuleMXBeanEntry extends AbstractEntry {
                     typeProviderWrapper);
         } else if (attrNode instanceof ListSchemaNode) {
             ListSchemaNode listSchemaNode = (ListSchemaNode) attrNode;
-            Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(listSchemaNode,
-                    attrNode, currentModule, qNamesToSIEs, schemaContext);
+            Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(
+                    listSchemaNode, attrNode, currentModule, qNamesToSIEs,
+                    schemaContext);
             if (dependencyAttributeOptional.isPresent()) {
                 return dependencyAttributeOptional.get();
             } else {
-                return ListAttribute.create(listSchemaNode, typeProviderWrapper, packageName);
+                return ListAttribute.create(listSchemaNode,
+                        typeProviderWrapper, packageName);
             }
         } else {
             throw new UnsupportedOperationException(
@@ -601,16 +631,15 @@ public class ModuleMXBeanEntry extends AbstractEntry {
         }
     }
 
-    private static Optional<? extends AbstractDependencyAttribute> extractDependency(DataNodeContainer dataNodeContainer,
-                                                            DataSchemaNode attrNode,
-                                                            Module currentModule,
-                                                            Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
-                                                            SchemaContext schemaContext) {
+    private static Optional<? extends AbstractDependencyAttribute> extractDependency(
+            DataNodeContainer dataNodeContainer, DataSchemaNode attrNode,
+            Module currentModule,
+            Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
+            SchemaContext schemaContext) {
         if (dataNodeContainer.getUses().size() == 1
                 && getChildNodeSizeWithoutUses(dataNodeContainer) == 0) {
             // reference
-            UsesNode usesNode = dataNodeContainer.getUses().iterator()
-                    .next();
+            UsesNode usesNode = dataNodeContainer.getUses().iterator().next();
             checkState(usesNode.getRefines().size() == 1,
                     "Unexpected 'refine' child node size of "
                             + dataNodeContainer);
@@ -618,26 +647,28 @@ public class ModuleMXBeanEntry extends AbstractEntry {
                     .values().iterator().next();
             checkState(refine.getUnknownSchemaNodes().size() == 1,
                     "Unexpected unknown schema node size of " + refine);
-            UnknownSchemaNode requiredIdentity = refine
-                    .getUnknownSchemaNodes().iterator().next();
+            UnknownSchemaNode requiredIdentity = refine.getUnknownSchemaNodes()
+                    .iterator().next();
             checkState(
                     ConfigConstants.REQUIRED_IDENTITY_EXTENSION_QNAME.equals(requiredIdentity
-                            .getNodeType()),
-                    "Unexpected language extension " + requiredIdentity);
+                            .getNodeType()), "Unexpected language extension "
+                            + requiredIdentity);
             String prefixAndIdentityLocalName = requiredIdentity
                     .getNodeParameter();
             // import should point to a module
             ServiceInterfaceEntry serviceInterfaceEntry = findSIE(
-                    prefixAndIdentityLocalName, currentModule,
-                    qNamesToSIEs, schemaContext);
+                    prefixAndIdentityLocalName, currentModule, qNamesToSIEs,
+                    schemaContext);
             boolean mandatory = refine.getConstraints().isMandatory();
             AbstractDependencyAttribute reference;
-            if (dataNodeContainer instanceof ContainerSchemaNode ){
-                reference = new DependencyAttribute(attrNode, serviceInterfaceEntry,
-                    mandatory, attrNode.getDescription());
+            if (dataNodeContainer instanceof ContainerSchemaNode) {
+                reference = new DependencyAttribute(attrNode,
+                        serviceInterfaceEntry, mandatory,
+                        attrNode.getDescription());
             } else {
-                reference = new ListDependenciesAttribute(attrNode, serviceInterfaceEntry,
-                        mandatory, attrNode.getDescription());
+                reference = new ListDependenciesAttribute(attrNode,
+                        serviceInterfaceEntry, mandatory,
+                        attrNode.getDescription());
             }
             return Optional.of(reference);
         }
index a2238d1a13da854c07df8278c697e8fddd15bdd2..764ecd38868c7b224c1c8e0065d7989f8126fa37 100644 (file)
@@ -26,6 +26,10 @@ public class TypeProviderWrapper {
         return getType(leaf, type);
     }
 
+    public String getDefault(LeafSchemaNode node) {
+        return typeProvider.getTypeDefaultConstruction(node);
+    }
+
     public Type getType(SchemaNode leaf, TypeDefinition<?> type) {
         Type javaType;
         try {
index 325ca9ee06fd1bd9d29d56a94cedc0871aac77c7..3e20e4a55ad47f58e538a33594d1f5d4f0e70d32 100644 (file)
@@ -22,7 +22,7 @@ import javax.management.openmbean.SimpleType;
 public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
 
     private final Type type;
-    private final String nullableDescription, nullableDefault;
+    private final String nullableDescription, nullableDefault, nullableDefaultWrappedForCode;
     private final TypeProviderWrapper typeProviderWrapper;
     private final TypeDefinition<?> typeDefinition;
 
@@ -33,6 +33,7 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
         this.typeDefinition = leaf.getType();
         this.typeProviderWrapper = typeProviderWrapper;
         this.nullableDefault = leaf.getDefault();
+        this.nullableDefaultWrappedForCode = leaf.getDefault() == null ? null : typeProviderWrapper.getDefault(leaf);
         this.nullableDescription = leaf.getDescription();
     }
 
@@ -42,10 +43,14 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
         this.type = typeProviderWrapper.getType(leaf);
         this.typeDefinition = leaf.getType();
         this.typeProviderWrapper = typeProviderWrapper;
-        this.nullableDefault = null;
+        this.nullableDefault = nullableDefaultWrappedForCode = null;
         this.nullableDescription = leaf.getDescription();
     }
 
+    public TypeDefinition<?> getTypeDefinition() {
+        return typeDefinition;
+    }
+
     /**
      * Returns the most base type
      */
@@ -56,6 +61,10 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
         return baseType;
     }
 
+    public String getNullableDefaultWrappedForCode() {
+        return nullableDefaultWrappedForCode;
+    }
+
     @Override
     public Type getType() {
         return type;
index deef08a292e6d5a7853796effeaa85fc5096773e..9032a2c9306ca38f537028984f05812ca24f6e2a 100644 (file)
@@ -100,6 +100,9 @@ public class ModuleMXBeanEntryNameConflictTest extends AbstractYangTest {
         testedYangModulesToExpectedConflictingName.put(
                 "config-test-runtime-bean-name-conflict2",
                 "StateARuntimeMXBean");
+        testedYangModulesToExpectedConflictingName.put(
+                "config-test-duplicate-attribute-in-runtime-and-mxbean",
+                "port");
     }
 
     private String getYangModuleName(String name) {
diff --git a/opendaylight/config/yang-jmx-generator/src/test/resources/duplicates/config-test-duplicate-attribute-in-runtime-and-mxbean.yang b/opendaylight/config/yang-jmx-generator/src/test/resources/duplicates/config-test-duplicate-attribute-in-runtime-and-mxbean.yang
new file mode 100644 (file)
index 0000000..58c3af2
--- /dev/null
@@ -0,0 +1,57 @@
+// vi: set smarttab et sw=4 tabstop=4:
+module config-test-duplicate-attribute-in-runtime-and-mxbean {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:jmx:duplicate:runtime";
+    prefix "th-java";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import rpc-context { prefix rpcx; revision-date 2013-06-17; }
+    import ietf-inet-types { prefix inet; revision-date 2010-09-24;}
+
+
+    description
+        "This module contains the base YANG definitions for NS-OS
+         thread services pure Java implementation.";
+
+    revision "2013-04-05" {
+        description
+            "Updated to work with new anchors.";
+    }
+
+    revision "2013-04-03" {
+        description
+            "Initial revision.";
+    }
+
+   identity async-eventbus {
+        base config:module-type;
+        config:java-name-prefix AsyncEventBus;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case async-eventbus {
+            when "/config:modules/config:module/config:type = 'async-eventbus'";
+            leaf port {
+                type string;
+            }
+            leaf core-size {
+                type uint32;
+            }
+            leaf simple-int3 {
+                type uint16;
+            }
+        }
+    }
+
+    augment "/config:modules/config:module/config:state" {
+        case async-eventbus {
+            when "/config:modules/config:module/config:type = 'async-eventbus'";
+            leaf simple-arg {
+                type uint32;
+            }
+            leaf port {
+                type inet:port-number;
+            }
+        }
+    }
+}
\ No newline at end of file
index bd83a4cc701c358fc85829e1098fb21d73806505..9ad7a44915b15bdfbce7a64cbdaf2eb02f8bba14 100644 (file)
@@ -48,28 +48,40 @@ module config-test-impl {
            container dto-a {
                 leaf simple-arg {
                     type uint32;
+                    default 1;
                 }
 
                 leaf port {
                     type inet:port-number;
+                    default 8080;
                 }
 
+                leaf ip4 {
+                    type inet:ipv4-address;
+                    default 127.0.0.1;
+                }
+
+                leaf ip {
+                    type inet:ip-address;
+                    // TODO defaults for union default 0:0:0:0:0:0:0:1;
+                }
             }
 
             leaf as-number {
-                mandatory true;
                 type inet:as-number;
+                default 44;
             }
 
 
             leaf simpleInt {
                 type uint32;
-                default 99L;
+                default 99;
             }
 
             container dto_b {
                 leaf simple-int1 {
                     type uint32;
+                    default 32;
                 }
 
                 leaf simple-int2 {
@@ -101,28 +113,34 @@ module config-test-impl {
             when "/config:modules/config:module/config:type = 'impl-netconf'";
             leaf binaryLeaf {
                 type binary;
+                default ZGVmYXVsdEJpbg==;
             }
 
             leaf type {
                 type string;
+                default "default-string";
             }
 
             leaf extended {
                 type tt:extend-once;
+                default 1;
             }
 
             leaf extended-twice {
                 type tt:extend-twice;
+                default 2;
             }
 
             leaf extended-enum {
                 type tt:extend-enum;
+                default ONE;
             }
 
             leaf sleep-factor {
                 type decimal64 {
                     fraction-digits 2;
                 }
+                default 2.00;
             }
 
            container dto-c {
@@ -153,23 +171,28 @@ module config-test-impl {
             }
 
             leaf simple-long {
-                type int64  ;
+                type int64;
+                default -45;
             }
 
             leaf simple-long-2 {
                 type uint32;
+                default 445;
             }
 
             leaf simple-BigInteger {
                 type uint64;
+                default 545454;
             }
 
             leaf simple-byte {
                 type int8;
+                default -4;
             }
 
             leaf simple-short {
                 type uint8;
+                default 45;
             }
 
             leaf simple-test {
@@ -209,6 +232,7 @@ module config-test-impl {
                     container deep {
                         leaf simple-int3 {
                             type uint16;
+                            default 0;
                         }
                     }
                 }
@@ -393,6 +417,7 @@ module config-test-impl {
             container retValContainer {
                 leaf v1 {
                     type string;
+                    default "from rpc";
                 }
 
                 leaf v2 {
index adc0c0973f76309d60b474c5e1dfbddc5fa23e9d..4c0b81f7d71a4e4ce9a15c527050bfe23977740c 100644 (file)
          <groupId>org.opendaylight.controller.thirdparty</groupId>
          <artifactId>ganymed</artifactId>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-remoterpc-connector</artifactId>
+          <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+              <groupId>org.opendaylight.controller</groupId>
+              <artifactId>
+                  zeromq-routingtable.implementation
+              </artifactId>
+              <version>0.4.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+              <groupId>org.zeromq</groupId>
+              <artifactId>jeromq</artifactId>
+              <version>0.3.1</version>
+          </dependency>
       </dependencies>
     </profile>
     <profile>
index e83fdcc5c885eac73f9d9837e0f5758ea2240499..c2f9bc311dc18b8cbde89c2c964c1fde73ad5939 100644 (file)
                <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-threadgroup</type>
                <instance>
                        <name>global-boss-group</name>
-                       <provider>/config/modules/module[name='netty-threadgroup-fixed']/instance[name='global-boss-group']</provider>
+                       <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-boss-group']</provider>
                </instance>
                <instance>
                        <name>global-worker-group</name>
-                       <provider>/config/modules/module[name='netty-threadgroup-fixed']/instance[name='global-worker-group']</provider>
+                       <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-worker-group']</provider>
                </instance>
        </service>
        <service>
                <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-event-executor</type>
                <instance>
                        <name>global-event-executor</name>
-                       <provider>/config/modules/module[name='netty-global-event-executor']/instance[name='global-event-executor']</provider>
+                       <provider>/modules/module[type='netty-global-event-executor'][name='global-event-executor']</provider>
                </instance>
        </service>
        <service>
                <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-timer</type>
                <instance>
                        <name>global-timer</name>
-                       <provider>/config/modules/module[name='netty-hashed-wheel-timer']/instance[name='global-timer']</provider>
+                       <provider>/modules/module[type='netty-hashed-wheel-timer'][name='global-timer']</provider>
                </instance>
        </service>
 //CAPABILITIES START
index 430a278a6061b332e885df89094b3ac4271b7ac8..fa33215ea6e9454d5c016e5e2f2fb58474099b55 100644 (file)
                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
                <instance>
                        <name>ref_yang-schema-service</name>
-                       <provider>/config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service']</provider>
+                       <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
                </instance>
        </service>
        <service>
                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
                <instance>
                        <name>ref_binding-notification-broker</name>
-                       <provider>/config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker']</provider>
+                       <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
                </instance>
        </service>
        <service>
                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
                <instance>
                        <name>ref_hash-map-data-store</name>
-                       <provider>/config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store']</provider>
+                       <provider>/modules/module[type='hash-map-data-store'][name='hash-map-data-store']</provider>
                </instance>
                <instance>
-            <name>ref_cluster-data-store</name>
-            <provider>/config/modules/module[name='dom-clustered-store-impl']/instance[name='cluster-data-store']</provider>
-        </instance>
+                       <name>ref_cluster-data-store</name>
+                       <provider>/modules/module[type='dom-clustered-store-impl'][name='cluster-data-store']</provider>
+               </instance>
        </service>
        <service>
                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
                <instance>
                        <name>ref_binding-broker-impl</name>
-                       <provider>/config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl']</provider>
+                       <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
                </instance>
        </service>
        <service>
                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
                <instance>
-                       <name>ref_binding-rpc-broker</name>
-                       <provider>/config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl']</provider>
+                       <name>binding-rpc-broker</name>
+                       <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
                </instance>
        </service>
        <service>
                <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
                <instance>
                        <name>ref_runtime-mapping-singleton</name>
-                       <provider>/config/modules/module[name='runtime-generated-mapping']/instance[name='runtime-mapping-singleton']</provider>
+                       <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
                </instance>
        </service>
        <service>
        <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
                <instance>
                        <name>ref_dom-broker</name>
-                       <provider>/config/modules/module[name='dom-broker-impl']/instance[name='dom-broker']</provider>
+                       <provider>/modules/module[type='dom-broker-impl'][name='dom-broker']</provider>
                </instance>
        </service>
        <service>
                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
                <instance>
                        <name>ref_binding-data-broker</name>
-                       <provider>/config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker']</provider>
+                       <provider>/modules/module[type='binding-data-broker'][name='binding-data-broker']</provider>
                </instance>
        </service>
 //CAPABILITIES START
index 1e33481e70a7dae49b1646014f77d422f50648cf..6cf728cde967d2ca1ed250dc93198a061a226795 100644 (file)
@@ -42,28 +42,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.Remo
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsInputBuilder
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodAllActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.HwPathActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.LoopbackActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlTypeActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNextHopActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTosActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanCfiActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SwPathActionBuilder
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv6Builder
@@ -80,9 +58,54 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder
 import java.util.Collections
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.controller.action._case.ControllerActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.flood.action._case.FloodActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.flood.all.action._case.FloodAllActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.hw.path.action._case.HwPathActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.loopback.action._case.LoopbackActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.dst.action._case.SetDlDstActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.src.action._case.SetDlSrcActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.type.action._case.SetDlTypeActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.next.hop.action._case.SetNextHopActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.tos.action._case.SetNwTosActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.tp.dst.action._case.SetTpDstActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.tp.src.action._case.SetTpSrcActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.cfi.action._case.SetVlanCfiActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.id.action._case.SetVlanIdActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.pcp.action._case.SetVlanPcpActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.sw.path.action._case.SwPathActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTosActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNextHopActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlTypeActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodAllActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.HwPathActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.LoopbackActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanCfiActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SwPathActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder
 
 public class MDFlowMapping {
 
@@ -114,7 +137,7 @@ public class MDFlowMapping {
     public static def Instructions toApplyInstruction(ArrayList<Action> actions) {
         val it = new InstructionsBuilder;
         val applyActions = new InstructionBuilder;
-        applyActions.instruction = new ApplyActionsBuilder().setAction(actions).build()
+        applyActions.instruction = new ApplyActionsCaseBuilder().setApplyActions(new ApplyActionsBuilder().setAction(actions).build()).build()
         instruction = Collections.<Instruction>singletonList(applyActions.build)
         return it.build;
     }
@@ -153,37 +176,37 @@ public class MDFlowMapping {
 
     public static dispatch def toAction(Controller sourceAction) {
         val actionBuilder = new ActionBuilder();
-        actionBuilder.action = new ControllerActionBuilder().build();
+        actionBuilder.action = new ControllerActionCaseBuilder().setControllerAction(new ControllerActionBuilder().build()).build();
         return actionBuilder.build();
     }
 
     public static dispatch def toAction(Drop sourceAction) {
         val actionBuilder = new ActionBuilder();
-        actionBuilder.action = new DropActionBuilder().build();
+        actionBuilder.action = new DropActionCaseBuilder().setDropAction(new DropActionBuilder().build()).build();
         return actionBuilder.build();
     }
 
     public static dispatch def toAction(Flood sourceAction) {
         val actionBuilder = new ActionBuilder();
-        actionBuilder.action = new FloodActionBuilder().build();
+        actionBuilder.action = new FloodActionCaseBuilder().setFloodAction(new FloodActionBuilder().build).build();
         return actionBuilder.build();
     }
 
     public static dispatch def toAction(FloodAll sourceAction) {
         val actionBuilder = new ActionBuilder();
-        actionBuilder.action = new FloodAllActionBuilder().build();
+        actionBuilder.action = new FloodAllActionCaseBuilder().setFloodAllAction(new FloodAllActionBuilder().build()).build();
         return actionBuilder.build();
     }
 
     public static dispatch def toAction(HwPath sourceAction) {
         val actionBuilder = new ActionBuilder();
-        actionBuilder.action = new HwPathActionBuilder().build();
+        actionBuilder.action = new HwPathActionCaseBuilder().setHwPathAction(new HwPathActionBuilder().build()).build();
         return actionBuilder.build();
     }
 
     public static dispatch def toAction(Loopback sourceAction) {
         val actionBuilder = new ActionBuilder();
-        actionBuilder.action = new LoopbackActionBuilder().build();
+        actionBuilder.action = new LoopbackActionCaseBuilder().setLoopbackAction(new LoopbackActionBuilder().build()).build();
         return actionBuilder.build();
     }
 
@@ -191,14 +214,14 @@ public class MDFlowMapping {
         val actionBuilder = new ActionBuilder();
         val it = new OutputActionBuilder();
         outputNodeConnector = sourceAction.port.toUri;
-        actionBuilder.action = it.build();
+        actionBuilder.action = new OutputActionCaseBuilder().setOutputAction(it.build()).build();
         return actionBuilder.build();
 
     }
 
     public static dispatch def toAction(PopVlan sourceAction) {
         val actionBuilder = new ActionBuilder();
-        actionBuilder.action = new PopVlanActionBuilder().build();
+        actionBuilder.action = new PopVlanActionCaseBuilder().build();
         return actionBuilder.build();
     }
 
@@ -209,7 +232,7 @@ public class MDFlowMapping {
         vlanId = new VlanId(sourceAction.vlanId);
         pcp = sourceAction.pcp;
         tag = sourceAction.tag;
-        actionBuilder.action = it.build();
+        actionBuilder.action = new PushVlanActionCaseBuilder().setPushVlanAction(it.build()).build();
         return actionBuilder.build();
     }
 
@@ -217,7 +240,7 @@ public class MDFlowMapping {
         val actionBuilder = new ActionBuilder();
         val it = new SetDlDstActionBuilder();
         address = sourceAction.dlAddress.toMacAddress();
-        actionBuilder.action = it.build();
+        actionBuilder.action = new SetDlDstActionCaseBuilder().setSetDlDstAction(it.build()).build;
         return actionBuilder.build();
     }
 
@@ -225,7 +248,7 @@ public class MDFlowMapping {
         val actionBuilder = new ActionBuilder();
         val it = new SetDlSrcActionBuilder();
         address = sourceAction.dlAddress.toMacAddress;
-        actionBuilder.action = it.build();
+        actionBuilder.action = new SetDlSrcActionCaseBuilder().setSetDlSrcAction(it.build()).build;
         return actionBuilder.build();
     }
 
@@ -233,7 +256,7 @@ public class MDFlowMapping {
         val actionBuilder = new ActionBuilder();
         val it = new SetDlTypeActionBuilder();
         dlType = new EtherType(sourceAction.dlType as long);
-        actionBuilder.action = it.build();
+        actionBuilder.action = new SetDlTypeActionCaseBuilder().setSetDlTypeAction(it.build()).build();
         return actionBuilder.build();
     }
 
@@ -242,7 +265,7 @@ public class MDFlowMapping {
         val it = new SetNextHopActionBuilder();
         val inetAddress = sourceAction.address;
         address = inetAddress.toInetAddress;
-        actionBuilder.action = it.build();
+        actionBuilder.action = new SetNextHopActionCaseBuilder().setSetNextHopAction(it.build).build();
         return actionBuilder.build();
     }
 
@@ -251,7 +274,7 @@ public class MDFlowMapping {
         val it = new SetNwDstActionBuilder();
         val inetAddress = sourceAction.address;
         address = inetAddress.toInetAddress;
-        actionBuilder.action = it.build();
+        actionBuilder.action = new SetNwDstActionCaseBuilder().setSetNwDstAction(it.build()).build();
         return actionBuilder.build();
     }
 
@@ -260,7 +283,7 @@ public class MDFlowMapping {
         val it = new SetNwSrcActionBuilder();
         val inetAddress = sourceAction.address;
         address = inetAddress.toInetAddress;
-        actionBuilder.action = it.build();
+        actionBuilder.action = new SetNwSrcActionCaseBuilder().setSetNwSrcAction(it.build()).build();
         return actionBuilder.build();
     }
 
@@ -268,7 +291,7 @@ public class MDFlowMapping {
         val actionBuilder = new ActionBuilder();
         val it = new SetNwTosActionBuilder();
         tos = sourceAction.nwTos;
-        actionBuilder.action = it.build();
+        actionBuilder.action = new SetNwTosActionCaseBuilder().setSetNwTosAction(it.build).build;
         return actionBuilder.build();
     }
 
@@ -276,7 +299,7 @@ public class MDFlowMapping {
         val actionBuilder = new ActionBuilder();
         val it = new SetTpDstActionBuilder();
         port = new PortNumber(sourceAction.port);
-        actionBuilder.action = it.build();
+        actionBuilder.action = new SetTpDstActionCaseBuilder().setSetTpDstAction(it.build()).build();
         return actionBuilder.build();
     }
 
@@ -284,7 +307,7 @@ public class MDFlowMapping {
         val actionBuilder = new ActionBuilder();
         val it = new SetTpSrcActionBuilder();
         port = new PortNumber(sourceAction.port);
-        actionBuilder.action = it.build();
+        actionBuilder.action = new SetTpSrcActionCaseBuilder().setSetTpSrcAction(it.build()).build();
         return actionBuilder.build();
     }
 
@@ -292,7 +315,7 @@ public class MDFlowMapping {
         val actionBuilder = new ActionBuilder();
         val it = new SetVlanCfiActionBuilder();
         vlanCfi = new VlanCfi(sourceAction.cfi);
-        actionBuilder.action = it.build();
+        actionBuilder.action = new SetVlanCfiActionCaseBuilder().setSetVlanCfiAction(it.build()).build();
         return actionBuilder.build();
     }
 
@@ -301,7 +324,7 @@ public class MDFlowMapping {
 
         val it = new SetVlanIdActionBuilder();
         vlanId = new VlanId(sourceAction.vlanId);
-        actionBuilder.action = it.build();
+        actionBuilder.action = new SetVlanIdActionCaseBuilder().setSetVlanIdAction(it.build()).build();
         return actionBuilder.build();
     }
 
@@ -309,13 +332,13 @@ public class MDFlowMapping {
         val actionBuilder = new ActionBuilder();
         val it = new SetVlanPcpActionBuilder();
         vlanPcp = new VlanPcp(sourceAction.pcp as short);
-        actionBuilder.action = it.build();
+        actionBuilder.action = new SetVlanPcpActionCaseBuilder().setSetVlanPcpAction(it.build).build;
         return actionBuilder.build();
     }
 
     public static dispatch def toAction(SwPath sourceAction) {
         val actionBuilder = new ActionBuilder();
-        actionBuilder.action = new SwPathActionBuilder().build();
+        actionBuilder.action = new SwPathActionCaseBuilder().setSwPathAction(new SwPathActionBuilder().build()).build();
         return actionBuilder.build();
     }
 
index b5ed3fe4c2ca0c1979fd50d5f2580927c51c6b81..a8349be1b410f2abcd3714de6ba141e8257c02d0 100644 (file)
@@ -35,38 +35,39 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.ActionList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodAllAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.HwPathAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.LoopbackAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlTypeAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetMplsTtlAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNextHopAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTosAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTtlAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetQueueAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanCfiAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SwPathAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodAllActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.HwPathActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.LoopbackActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlTypeActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetMplsTtlActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNextHopActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTosActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTtlActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetQueueActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanCfiActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SwPathActionCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp;
@@ -147,8 +148,8 @@ public class ToSalConversionsUtils {
             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow source) {
         if (source.getInstructions() != null) {
             for (Instruction instruction : source.getInstructions().getInstruction()) {
-                if (instruction.getInstruction() instanceof ActionList) {
-                    return (((ActionList) instruction.getInstruction()).getAction());
+                if (instruction.getInstruction() instanceof ApplyActionsCase) {
+                    return (((ApplyActionsCase) instruction.getInstruction()).getApplyActions().getAction());
                 }
             }
         }
@@ -162,119 +163,119 @@ public class ToSalConversionsUtils {
                org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action sourceAction = action
                     .getAction();
 
-            if (sourceAction instanceof ControllerAction) {
+            if (sourceAction instanceof ControllerActionCase) {
                 targetAction.add(new Controller());
-            } else if (sourceAction instanceof OutputAction) {
+            } else if (sourceAction instanceof OutputActionCase) {
 
-                Uri nodeConnector = ((OutputAction) sourceAction).getOutputNodeConnector();
+                Uri nodeConnector = ((OutputActionCase) sourceAction).getOutputAction().getOutputNodeConnector();
                 if (nodeConnector != null) {
                     //for (Uri uri : nodeConnectors) {
                         targetAction.add(new Output(fromNodeConnectorRef(nodeConnector)));
                     //}
                 }
-            } else if (sourceAction instanceof PopMplsAction) {
+            } else if (sourceAction instanceof PopMplsActionCase) {
                 // TODO: define maping
-            } else if (sourceAction instanceof PushMplsAction) {
+            } else if (sourceAction instanceof PushMplsActionCase) {
                 // TODO: define maping
-            } else if (sourceAction instanceof PushPbbAction) {
+            } else if (sourceAction instanceof PushPbbActionCase) {
                 // TODO: define maping
-            } else if (sourceAction instanceof SetMplsTtlAction) {
+            } else if (sourceAction instanceof SetMplsTtlActionCase) {
                 // TODO: define maping
                 // targetAction = //no action to map
-            } else if (sourceAction instanceof SetNwTtlAction) {
+            } else if (sourceAction instanceof SetNwTtlActionCase) {
                 // TODO: define maping
-            } else if (sourceAction instanceof SetQueueAction) {
+            } else if (sourceAction instanceof SetQueueActionCase) {
                 // TODO: define maping
                 // targetAction = //no action to map
-            } else if (sourceAction instanceof DropAction) {
+            } else if (sourceAction instanceof DropActionCase) {
                 targetAction.add(new Drop());
-            } else if (sourceAction instanceof FloodAction) {
+            } else if (sourceAction instanceof FloodActionCase) {
                 targetAction.add(new Flood());
-            } else if (sourceAction instanceof FloodAllAction) {
+            } else if (sourceAction instanceof FloodAllActionCase) {
                 targetAction.add(new FloodAll());
-            } else if (sourceAction instanceof HwPathAction) {
+            } else if (sourceAction instanceof HwPathActionCase) {
                 targetAction.add(new HwPath());
-            } else if (sourceAction instanceof LoopbackAction) {
+            } else if (sourceAction instanceof LoopbackActionCase) {
                 targetAction.add(new Loopback());
-            } else if (sourceAction instanceof PopVlanAction) {
+            } else if (sourceAction instanceof PopVlanActionCase) {
                 targetAction.add(new PopVlan());
-            } else if (sourceAction instanceof PushVlanAction) {
-                PushVlanAction pushVlanAction = (PushVlanAction) sourceAction;
-                PushVlan pushVlan = pushVlanFrom(pushVlanAction);
+            } else if (sourceAction instanceof PushVlanActionCase) {
+                PushVlanActionCase pushVlanAction = (PushVlanActionCase) sourceAction;
+                PushVlan pushVlan = pushVlanFrom(pushVlanAction.getPushVlanAction());
                 if (pushVlan != null) {
                     targetAction.add(pushVlan);
                 }
-            } else if (sourceAction instanceof SetDlDstAction) {
-                MacAddress addressL2Dest = ((SetDlDstAction) sourceAction).getAddress();
+            } else if (sourceAction instanceof SetDlDstActionCase) {
+                MacAddress addressL2Dest = ((SetDlDstActionCase) sourceAction).getSetDlDstAction().getAddress();
                 if (addressL2Dest != null) {
                     targetAction.add(new SetDlDst(bytesFrom(addressL2Dest)));
                 }
-            } else if (sourceAction instanceof SetDlSrcAction) {
-                MacAddress addressL2Src = ((SetDlSrcAction) sourceAction).getAddress();
+            } else if (sourceAction instanceof SetDlSrcActionCase) {
+                MacAddress addressL2Src = ((SetDlSrcActionCase) sourceAction).getSetDlSrcAction().getAddress();
                 if (addressL2Src != null) {
                     targetAction.add(new SetDlSrc(bytesFrom(addressL2Src)));
 
                 }
-            } else if (sourceAction instanceof SetDlTypeAction) {
-                EtherType dlType = ((SetDlTypeAction) sourceAction).getDlType();
+            } else if (sourceAction instanceof SetDlTypeActionCase) {
+                EtherType dlType = ((SetDlTypeActionCase) sourceAction).getSetDlTypeAction().getDlType();
                 if (dlType != null) {
                     Long dlTypeValue = dlType.getValue();
                     if (dlTypeValue != null) {
                         targetAction.add(new SetDlType(dlTypeValue.intValue()));
                     }
                 }
-            } else if (sourceAction instanceof SetNextHopAction) {
-                Address addressL3 = ((SetNextHopAction) sourceAction).getAddress();
+            } else if (sourceAction instanceof SetNextHopActionCase) {
+                Address addressL3 = ((SetNextHopActionCase) sourceAction).getSetNextHopAction().getAddress();
 
                 InetAddress inetAddress = inetAddressFrom(addressL3);
                 if (inetAddress != null) {
                     targetAction.add(new SetNextHop(inetAddress));
                 }
-            } else if (sourceAction instanceof SetNwDstAction) {
-                Address addressL3 = ((SetNwDstAction) sourceAction).getAddress();
+            } else if (sourceAction instanceof SetNwDstActionCase) {
+                Address addressL3 = ((SetNwDstActionCase) sourceAction).getSetNwDstAction().getAddress();
 
                 InetAddress inetAddress = inetAddressFrom(addressL3);
                 if (inetAddress != null) {
                     targetAction.add(new SetNwDst(inetAddress));
                 }
-            } else if (sourceAction instanceof SetNwSrcAction) {
-                Address addressL3 = ((SetNwSrcAction) sourceAction).getAddress();
+            } else if (sourceAction instanceof SetNwSrcActionCase) {
+                Address addressL3 = ((SetNwSrcActionCase) sourceAction).getSetNwSrcAction().getAddress();
 
                 InetAddress inetAddress = inetAddressFrom(addressL3);
                 if (inetAddress != null) {
                     targetAction.add(new SetNwSrc(inetAddress));
                 }
-            } else if (sourceAction instanceof SetNwTosAction) {
-                Integer tos = ((SetNwTosAction) sourceAction).getTos();
+            } else if (sourceAction instanceof SetNwTosActionCase) {
+                Integer tos = ((SetNwTosActionCase) sourceAction).getSetNwTosAction().getTos();
                 if (tos != null) {
                     targetAction.add(new SetNwTos(tos));
                 }
-            } else if (sourceAction instanceof SetTpDstAction) {
-                PortNumber port = ((SetTpDstAction) sourceAction).getPort();
+            } else if (sourceAction instanceof SetTpDstActionCase) {
+                PortNumber port = ((SetTpDstActionCase) sourceAction).getSetTpDstAction().getPort();
                 if (port != null) {
                     Integer portValue = port.getValue();
                     if (port.getValue() != null) {
                         targetAction.add(new SetTpDst(portValue));
                     }
                 }
-            } else if (sourceAction instanceof SetTpSrcAction) {
-                PortNumber port = ((SetTpSrcAction) sourceAction).getPort();
+            } else if (sourceAction instanceof SetTpSrcActionCase) {
+                PortNumber port = ((SetTpSrcActionCase) sourceAction).getSetTpSrcAction().getPort();
                 if (port != null) {
                     Integer portValue = port.getValue();
                     if (port.getValue() != null) {
                         targetAction.add(new SetTpSrc(portValue));
                     }
                 }
-            } else if (sourceAction instanceof SetVlanCfiAction) {
-                VlanCfi vlanCfi = ((SetVlanCfiAction) sourceAction).getVlanCfi();
+            } else if (sourceAction instanceof SetVlanCfiActionCase) {
+                VlanCfi vlanCfi = ((SetVlanCfiActionCase) sourceAction).getSetVlanCfiAction().getVlanCfi();
                 if (vlanCfi != null) {
                     Integer vlanCfiValue = vlanCfi.getValue();
                     if (vlanCfiValue != null) {
                         targetAction.add(new SetVlanCfi(vlanCfiValue));
                     }
                 }
-            } else if (sourceAction instanceof SetVlanIdAction) {
-                org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId vlanID = ((SetVlanIdAction) sourceAction)
+            } else if (sourceAction instanceof SetVlanIdActionCase) {
+                org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId vlanID = ((SetVlanIdActionCase) sourceAction).getSetVlanIdAction()
                         .getVlanId();
                 if (vlanID != null) {
                     Integer vlanIdValue = vlanID.getValue();
@@ -282,15 +283,15 @@ public class ToSalConversionsUtils {
                         targetAction.add(new SetVlanId(vlanIdValue));
                     }
                 }
-            } else if (sourceAction instanceof SetVlanPcpAction) {
-                VlanPcp vlanPcp = ((SetVlanPcpAction) sourceAction).getVlanPcp();
+            } else if (sourceAction instanceof SetVlanPcpActionCase) {
+                VlanPcp vlanPcp = ((SetVlanPcpActionCase) sourceAction).getSetVlanPcpAction().getVlanPcp();
                 if (vlanPcp != null) {
                     Short vlanPcpValue = vlanPcp.getValue();
                     if (vlanPcpValue != null) {
                         targetAction.add(new SetVlanPcp(vlanPcpValue));
                     }
                 }
-            } else if (sourceAction instanceof SwPathAction) {
+            } else if (sourceAction instanceof SwPathActionCase) {
                 targetAction.add(new SwPath());
             }
         }
@@ -315,7 +316,7 @@ public class ToSalConversionsUtils {
         return null;
     }
 
-    private static PushVlan pushVlanFrom(PushVlanAction pushVlanAction) {
+    private static PushVlan pushVlanFrom(org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanAction pushVlanAction) {
         final int tag;
         final int pcp;
         final int cfi;
index cb70174103802005e9cd0d73d88da9344138697d..b062b0016d54340040dc6a827b5cf6eb745f4076 100644 (file)
@@ -27,6 +27,7 @@ import org.opendaylight.controller.sal.match.Match;
 import org.opendaylight.controller.sal.match.MatchType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanAction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
@@ -186,25 +187,25 @@ public class TestFromSalConversionsUtils {
 
     private void checkOdActions(
             List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actions) {
-        checkOdAction(actions, FloodAction.class, false);
-        checkOdAction(actions, FloodAllAction.class, false);
-        checkOdAction(actions, HwPathAction.class, false);
-        checkOdAction(actions, LoopbackAction.class, false);
-        checkOdAction(actions, PopVlanAction.class, false);
-        checkOdAction(actions, PushVlanAction.class, true);
-        checkOdAction(actions, SetDlDstAction.class, true);
-        checkOdAction(actions, SetDlSrcAction.class, true);
-        checkOdAction(actions, SetDlTypeAction.class, true);
-        checkOdAction(actions, SetNwTosAction.class, true);
-        checkOdAction(actions, SetNwDstAction.class, true);
-        checkOdAction(actions, SetNwSrcAction.class, true);
-        checkOdAction(actions, SetNextHopAction.class, true);
-        checkOdAction(actions, SetTpDstAction.class, true);
-        checkOdAction(actions, SetTpSrcAction.class, true);
-        checkOdAction(actions, SetVlanCfiAction.class, true);
-        checkOdAction(actions, SetVlanIdAction.class, true);
-        checkOdAction(actions, SetVlanPcpAction.class, true);
-        checkOdAction(actions, SwPathAction.class, false);
+        checkOdAction(actions, FloodActionCase.class, false);
+        checkOdAction(actions, FloodAllActionCase.class, false);
+        checkOdAction(actions, HwPathActionCase.class, false);
+        checkOdAction(actions, LoopbackActionCase.class, false);
+        checkOdAction(actions, PopVlanActionCase.class, false);
+        checkOdAction(actions, PushVlanActionCase.class, true);
+        checkOdAction(actions, SetDlDstActionCase.class, true);
+        checkOdAction(actions, SetDlSrcActionCase.class, true);
+        checkOdAction(actions, SetDlTypeActionCase.class, true);
+        checkOdAction(actions, SetNwTosActionCase.class, true);
+        checkOdAction(actions, SetNwDstActionCase.class, true);
+        checkOdAction(actions, SetNwSrcActionCase.class, true);
+        checkOdAction(actions, SetNextHopActionCase.class, true);
+        checkOdAction(actions, SetTpDstActionCase.class, true);
+        checkOdAction(actions, SetTpSrcActionCase.class, true);
+        checkOdAction(actions, SetVlanCfiActionCase.class, true);
+        checkOdAction(actions, SetVlanIdActionCase.class, true);
+        checkOdAction(actions, SetVlanPcpActionCase.class, true);
+        checkOdAction(actions, SwPathActionCase.class, false);
     }
 
     private void checkOdAction(
@@ -216,26 +217,26 @@ public class TestFromSalConversionsUtils {
                     .getAction();
             if (cl.isInstance(innerAction)) {
                 numOfFoundActions++;
-                if (innerAction instanceof PushVlanAction) {
-                    assertEquals("Wrong value of cfi in PushVlanAction.", (Integer) 1, ((PushVlanAction) innerAction)
+                if (innerAction instanceof PushVlanActionCase) {
+                    assertEquals("Wrong value of cfi in PushVlanAction.", (Integer) 1, ((PushVlanActionCase) innerAction).getPushVlanAction()
                             .getCfi().getValue());
                     assertEquals("Wrong value of pcp in PushVlanAction.", (Integer) 7,
-                            ((PushVlanAction) innerAction).getPcp());
+                            ((PushVlanActionCase) innerAction).getPushVlanAction().getPcp());
                     assertEquals("Wrong value of tag in PushVlanAction.", (Integer) 0x8100,
-                            ((PushVlanAction) innerAction).getTag());
+                            ((PushVlanActionCase) innerAction).getPushVlanAction().getTag());
                     assertEquals("Wrong value of vlad ID in PushVlanAction.", (Integer) 4095,
-                            ((PushVlanAction) innerAction).getVlanId().getValue());
-                } else if (innerAction instanceof SetDlDstAction) {
+                            ((PushVlanActionCase) innerAction).getPushVlanAction().getVlanId().getValue());
+                } else if (innerAction instanceof SetDlDstActionCase) {
                     assertEquals("Wrong MAC destination address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa", 
-                            ((SetDlDstAction) innerAction).getAddress().getValue());
-                } else if (innerAction instanceof SetDlSrcAction) {
+                            ((SetDlDstActionCase) innerAction).getSetDlDstAction().getAddress().getValue());
+                } else if (innerAction instanceof SetDlSrcActionCase) {
                     assertEquals("Wrong MAC source address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa", 
-                            ((SetDlSrcAction) innerAction).getAddress().getValue());
-                } else if (innerAction instanceof SetDlTypeAction) {
+                            ((SetDlSrcActionCase) innerAction).getSetDlSrcAction().getAddress().getValue());
+                } else if (innerAction instanceof SetDlTypeActionCase) {
                     assertEquals("Wrong data link type in SetDlTypeAction.", (long) 513,
-                            (long) ((SetDlTypeAction) innerAction).getDlType().getValue());
-                } else if (innerAction instanceof SetNextHopAction) {
-                    Address address = ((SetNextHopAction) innerAction).getAddress();
+                            (long) ((SetDlTypeActionCase) innerAction).getSetDlTypeAction().getDlType().getValue());
+                } else if (innerAction instanceof SetNextHopActionCase) {
+                    Address address = ((SetNextHopActionCase) innerAction).getSetNextHopAction().getAddress();
                     boolean ipv4AddressFound = false;
                     if (address instanceof Ipv4) {
                         ipv4AddressFound = true;
@@ -243,10 +244,10 @@ public class TestFromSalConversionsUtils {
                                 .getIpv4Address().getValue());
                     }
                     assertTrue("Ipv4 address wasn't found.", ipv4AddressFound);
-                } else if (innerAction instanceof SetNwTosAction) {
-                    assertEquals("Wrong TOS in SetNwTosAction.", (Integer) 63, ((SetNwTosAction) innerAction).getTos());
-                } else if (innerAction instanceof SetNwDstAction) {
-                    Address address = ((SetNwDstAction) innerAction).getAddress();
+                } else if (innerAction instanceof SetNwTosActionCase) {
+                    assertEquals("Wrong TOS in SetNwTosAction.", (Integer) 63, ((SetNwTosActionCase) innerAction).getSetNwTosAction().getTos());
+                } else if (innerAction instanceof SetNwDstActionCase) {
+                    Address address = ((SetNwDstActionCase) innerAction).getSetNwDstAction().getAddress();
                     boolean ipv4AddressFound = false;
                     if (address instanceof Ipv4) {
                         ipv4AddressFound = true;
@@ -254,8 +255,8 @@ public class TestFromSalConversionsUtils {
                                 .getIpv4Address().getValue());
                     }
                     assertTrue("Ipv4 address wasn't found.", ipv4AddressFound);
-                } else if (innerAction instanceof SetNwSrcAction) {
-                    Address address = ((SetNwSrcAction) innerAction).getAddress();
+                } else if (innerAction instanceof SetNwSrcActionCase) {
+                    Address address = ((SetNwSrcActionCase) innerAction).getSetNwSrcAction().getAddress();
                     boolean ipv4AddressFound = false;
                     if (address instanceof Ipv4) {
                         ipv4AddressFound = true;
@@ -263,21 +264,21 @@ public class TestFromSalConversionsUtils {
                                 .getIpv4Address().getValue());
                     }
                     assertTrue("Ipv4 address wasn't found.", ipv4AddressFound);
-                } else if (innerAction instanceof SetTpDstAction) {
+                } else if (innerAction instanceof SetTpDstActionCase) {
                     assertEquals("Port number is incorrect in SetTpDstAction.", (Integer) 65534,
-                            ((SetTpDstAction) innerAction).getPort().getValue());
-                } else if (innerAction instanceof SetTpSrcAction) {
+                            ((SetTpDstActionCase) innerAction).getSetTpDstAction().getPort().getValue());
+                } else if (innerAction instanceof SetTpSrcActionCase) {
                     assertEquals("Port number is incorrect in SetTpSrcAction.", (Integer) 65535,
-                            ((SetTpSrcAction) innerAction).getPort().getValue());
-                } else if (innerAction instanceof SetVlanCfiAction) {
+                            ((SetTpSrcActionCase) innerAction).getSetTpSrcAction().getPort().getValue());
+                } else if (innerAction instanceof SetVlanCfiActionCase) {
                     assertEquals("Vlan cfi number is incorrect in SetVlanCfiAction.", (Integer) 1,
-                            ((SetVlanCfiAction) innerAction).getVlanCfi().getValue());
-                } else if (innerAction instanceof SetVlanIdAction) {
+                            ((SetVlanCfiActionCase) innerAction).getSetVlanCfiAction().getVlanCfi().getValue());
+                } else if (innerAction instanceof SetVlanIdActionCase) {
                     assertEquals("Vlan id number is incorrect in SetVlanIdAction.", (Integer) 4095,
-                            ((SetVlanIdAction) innerAction).getVlanId().getValue());
-                } else if (innerAction instanceof SetVlanPcpAction) {
+                            ((SetVlanIdActionCase) innerAction).getSetVlanIdAction().getVlanId().getValue());
+                } else if (innerAction instanceof SetVlanPcpActionCase) {
                     assertEquals("Vlan pcp number is incorrect in SetVlanPcpAction.", new Short((short) 7),
-                            ((SetVlanPcpAction) innerAction).getVlanPcp().getValue());
+                            ((SetVlanPcpActionCase) innerAction).getSetVlanPcpAction().getVlanPcp().getValue());
                 }
             }
         }
index 97e1660443449bbb7ff8ce4364b844ab23b65c0f..793f3cc3955bb82e97ba3bf28cf3b9ca679c6c00 100644 (file)
@@ -29,6 +29,34 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.Flow
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.controller.action._case.ControllerActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.flood.action._case.FloodActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.flood.all.action._case.FloodAllActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.hw.path.action._case.HwPathActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.loopback.action._case.LoopbackActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.mpls.action._case.PushMplsActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.pbb.action._case.PushPbbActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.dst.action._case.SetDlDstActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.src.action._case.SetDlSrcActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.type.action._case.SetDlTypeActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.mpls.ttl.action._case.SetMplsTtlActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.next.hop.action._case.SetNextHopActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.tos.action._case.SetNwTosActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.ttl.action._case.SetNwTtlActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.queue.action._case.SetQueueActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.tp.dst.action._case.SetTpDstActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.tp.src.action._case.SetTpSrcActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.cfi.action._case.SetVlanCfiActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.id.action._case.SetVlanIdActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.pcp.action._case.SetVlanPcpActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.sw.path.action._case.SwPathActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv6Builder;
@@ -54,8 +82,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActions;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
 
 import com.google.common.net.InetAddresses;
 
@@ -282,31 +311,31 @@ public class TestToSalConversionsUtils {
     private Instructions prepareOdActions() {
         List<Action> odActions = new ArrayList<>();
 
-        ControllerActionBuilder controllerActionBuilder = new ControllerActionBuilder();
-        DropActionBuilder dropActionBuilder = new DropActionBuilder();
-        FloodActionBuilder floodActionBuilder = new FloodActionBuilder();
-        FloodAllActionBuilder floodAllActionBuilder = new FloodAllActionBuilder();
-        HwPathActionBuilder hwPathActionBuilder = new HwPathActionBuilder();
-        LoopbackActionBuilder loopbackActionBuilder = new LoopbackActionBuilder();
-        OutputActionBuilder outputActionBuilder = new OutputActionBuilder();
-        PopMplsActionBuilder popMplsActionBuilder = new PopMplsActionBuilder();
-        PopVlanActionBuilder popVlanActionBuilder = new PopVlanActionBuilder();
-        PushMplsActionBuilder pushMplsActionBuilder = new PushMplsActionBuilder();
-        PushPbbActionBuilder pushPbbActionBuilder = new PushPbbActionBuilder();
-        PushVlanActionBuilder pushVlanActionBuilder = new PushVlanActionBuilder();
-        SetDlDstActionBuilder setDlDstActionBuilder = new SetDlDstActionBuilder();
-        SetDlSrcActionBuilder setDlSrcActionBuilder = new SetDlSrcActionBuilder();
-        SetDlTypeActionBuilder setDlTypeActionBuilder = new SetDlTypeActionBuilder();
-        SetMplsTtlActionBuilder setMplsTtlActionBuilder = new SetMplsTtlActionBuilder();
-        SetNwTosActionBuilder setNwTosActionBuilder = new SetNwTosActionBuilder();
-        SetNwTtlActionBuilder setNwTtlActionBuilder = new SetNwTtlActionBuilder();
-        SetQueueActionBuilder setQueueActionBuilder = new SetQueueActionBuilder();
-        SetTpDstActionBuilder setTpDstActionBuilder = new SetTpDstActionBuilder();
-        SetTpSrcActionBuilder setTpSrcActionBuilder = new SetTpSrcActionBuilder();
-        SetVlanCfiActionBuilder setVlanCfiActionBuilder = new SetVlanCfiActionBuilder();
-        SetVlanIdActionBuilder setVlanIdActionBuilder = new SetVlanIdActionBuilder();
-        SetVlanPcpActionBuilder setVlanPcpActionBuilder = new SetVlanPcpActionBuilder();
-        SwPathActionBuilder swPathActionBuilder = new SwPathActionBuilder();
+        ControllerActionCaseBuilder controllerActionBuilder = new ControllerActionCaseBuilder();
+        DropActionCaseBuilder dropActionBuilder = new DropActionCaseBuilder();
+        FloodActionCaseBuilder floodActionBuilder = new FloodActionCaseBuilder();
+        FloodAllActionCaseBuilder floodAllActionBuilder = new FloodAllActionCaseBuilder();
+        HwPathActionCaseBuilder hwPathActionBuilder = new HwPathActionCaseBuilder();
+        LoopbackActionCaseBuilder loopbackActionBuilder = new LoopbackActionCaseBuilder();
+        OutputActionCaseBuilder outputActionBuilder = new OutputActionCaseBuilder();
+        PopMplsActionCaseBuilder popMplsActionBuilder = new PopMplsActionCaseBuilder();
+        PopVlanActionCaseBuilder popVlanActionBuilder = new PopVlanActionCaseBuilder();
+        PushMplsActionCaseBuilder pushMplsActionBuilder = new PushMplsActionCaseBuilder();
+        PushPbbActionCaseBuilder pushPbbActionBuilder = new PushPbbActionCaseBuilder();
+        PushVlanActionCaseBuilder pushVlanActionBuilder = new PushVlanActionCaseBuilder();
+        SetDlDstActionCaseBuilder setDlDstActionBuilder = new SetDlDstActionCaseBuilder();
+        SetDlSrcActionCaseBuilder setDlSrcActionBuilder = new SetDlSrcActionCaseBuilder();
+        SetDlTypeActionCaseBuilder setDlTypeActionBuilder = new SetDlTypeActionCaseBuilder();
+        SetMplsTtlActionCaseBuilder setMplsTtlActionBuilder = new SetMplsTtlActionCaseBuilder();
+        SetNwTosActionCaseBuilder setNwTosActionBuilder = new SetNwTosActionCaseBuilder();
+        SetNwTtlActionCaseBuilder setNwTtlActionBuilder = new SetNwTtlActionCaseBuilder();
+        SetQueueActionCaseBuilder setQueueActionBuilder = new SetQueueActionCaseBuilder();
+        SetTpDstActionCaseBuilder setTpDstActionBuilder = new SetTpDstActionCaseBuilder();
+        SetTpSrcActionCaseBuilder setTpSrcActionBuilder = new SetTpSrcActionCaseBuilder();
+        SetVlanCfiActionCaseBuilder setVlanCfiActionBuilder = new SetVlanCfiActionCaseBuilder();
+        SetVlanIdActionCaseBuilder setVlanIdActionBuilder = new SetVlanIdActionCaseBuilder();
+        SetVlanPcpActionCaseBuilder setVlanPcpActionBuilder = new SetVlanPcpActionCaseBuilder();
+        SwPathActionCaseBuilder swPathActionBuilder = new SwPathActionCaseBuilder();
 
         prepareActionOutput(outputActionBuilder);
         prepareActionPushVlan(pushVlanActionBuilder);
@@ -350,7 +379,7 @@ public class TestToSalConversionsUtils {
         odActions.add(new ActionBuilder().setAction(swPathActionBuilder.build()).build());
 
         
-        ApplyActions innerInst = new ApplyActionsBuilder().setAction(odActions).build();
+        ApplyActionsCase innerInst = new ApplyActionsCaseBuilder().setApplyActions(new ApplyActionsBuilder().setAction(odActions).build()).build();
         Instruction applyActions = new InstructionBuilder().setInstruction(innerInst).build();
         List<Instruction> instructions = Collections.singletonList(applyActions );
         InstructionsBuilder instBuilder = new InstructionsBuilder();
@@ -360,64 +389,77 @@ public class TestToSalConversionsUtils {
         return instBuilder.build();
     }
 
-    private void prepareActionSetVlanPcp(SetVlanPcpActionBuilder setVlanPcpActionBuilder) {
+    private void prepareActionSetVlanPcp(SetVlanPcpActionCaseBuilder wrapper) {
+        SetVlanPcpActionBuilder setVlanPcpActionBuilder = new SetVlanPcpActionBuilder();
         setVlanPcpActionBuilder.setVlanPcp(new VlanPcp((short) 7));
+        wrapper.setSetVlanPcpAction(setVlanPcpActionBuilder.build());
     }
 
-    private void prepareActionSetVladId(SetVlanIdActionBuilder setVlanIdActionBuilder) {
+    private void prepareActionSetVladId(SetVlanIdActionCaseBuilder wrapper) {
+        SetVlanIdActionBuilder setVlanIdActionBuilder = new SetVlanIdActionBuilder();
         setVlanIdActionBuilder.setVlanId(new VlanId(4095));
+        wrapper.setSetVlanIdAction(setVlanIdActionBuilder.build());
     }
 
-    private void prepareActionSetVlanCfi(SetVlanCfiActionBuilder setVlanCfiActionBuilder) {
+    private void prepareActionSetVlanCfi(SetVlanCfiActionCaseBuilder wrapper) {
+        SetVlanCfiActionBuilder setVlanCfiActionBuilder = new SetVlanCfiActionBuilder();
         setVlanCfiActionBuilder.setVlanCfi(new VlanCfi(1));
+        wrapper.setSetVlanCfiAction(setVlanCfiActionBuilder.build());
     }
 
-    private void prepareActionSetTpDst(SetTpDstActionBuilder setTpDstActionBuilder) {
+    private void prepareActionSetTpDst(SetTpDstActionCaseBuilder wrapper) {
+        SetTpDstActionBuilder setTpDstActionBuilder = new SetTpDstActionBuilder();
         setTpDstActionBuilder.setPort(new PortNumber(65535));
+        wrapper.setSetTpDstAction(setTpDstActionBuilder.build());
     }
 
-    private void prepareActionSetTpSrc(SetTpSrcActionBuilder setTpSrcActionBuilder) {
+    private void prepareActionSetTpSrc(SetTpSrcActionCaseBuilder wrapper) {
+        SetTpSrcActionBuilder setTpSrcActionBuilder = new SetTpSrcActionBuilder();
         setTpSrcActionBuilder.setPort(new PortNumber(65535));
+        wrapper.setSetTpSrcAction(setTpSrcActionBuilder.build());
     }
 
-    private void prepareActionSetNwTos(SetNwTosActionBuilder setNwTosActionBuilder) {
+    private void prepareActionSetNwTos(SetNwTosActionCaseBuilder wrapper) {
+        SetNwTosActionBuilder setNwTosActionBuilder = new SetNwTosActionBuilder();
         setNwTosActionBuilder.setTos(63);
+        wrapper.setSetNwTosAction(setNwTosActionBuilder.build());
     }
 
     private void prepareActionSetNwSrc(List<Action> odActions) {
         // test case for IPv4
         SetNwSrcActionBuilder setNwSrcActionBuilderIpv4 = new SetNwSrcActionBuilder();
         setNwSrcActionBuilderIpv4.setAddress(prapareIpv4Address("192.168.100.102"));
-        odActions.add(new ActionBuilder().setAction(setNwSrcActionBuilderIpv4.build()).build());
+        odActions.add(new ActionBuilder().setAction(new SetNwSrcActionCaseBuilder().setSetNwSrcAction(setNwSrcActionBuilderIpv4.build()).build()).build());
 
         // test case for IPv6
         SetNwSrcActionBuilder setNwSrcActionBuilderIpv6 = new SetNwSrcActionBuilder();
         setNwSrcActionBuilderIpv6.setAddress(prapareIpv6Address("2001:0db8:85a3:0000:0000:8a2e:0370:7336"));
-        odActions.add(new ActionBuilder().setAction(setNwSrcActionBuilderIpv6.build()).build());
+        odActions.add(new ActionBuilder().setAction(new SetNwSrcActionCaseBuilder().setSetNwSrcAction(setNwSrcActionBuilderIpv6.build()).build()).build());
     }
 
     private void prepareActionSetNwDst(List<Action> odActions) {
         // test case for IPv4
+        
         SetNwDstActionBuilder setNwDstActionBuilderIpv4 = new SetNwDstActionBuilder();
         setNwDstActionBuilderIpv4.setAddress(prapareIpv4Address("192.168.100.101"));
-        odActions.add(new ActionBuilder().setAction(setNwDstActionBuilderIpv4.build()).build());
+        odActions.add(new ActionBuilder().setAction(new SetNwDstActionCaseBuilder().setSetNwDstAction(setNwDstActionBuilderIpv4.build()).build()).build());
 
         // test case for IPv6
         SetNwDstActionBuilder setNwDstActionBuilderIpv6 = new SetNwDstActionBuilder();
         setNwDstActionBuilderIpv6.setAddress(prapareIpv6Address("2001:0db8:85a3:0000:0000:8a2e:0370:7335"));
-        odActions.add(new ActionBuilder().setAction(setNwDstActionBuilderIpv6.build()).build());
+        odActions.add(new ActionBuilder().setAction(new SetNwDstActionCaseBuilder().setSetNwDstAction(setNwDstActionBuilderIpv6.build()).build()).build());
     }
 
     private void prepareActionNextHop(List<Action> odActions) {
         // test case for IPv4
         SetNextHopActionBuilder setNextHopActionBuilderIpv4 = new SetNextHopActionBuilder();
         setNextHopActionBuilderIpv4.setAddress(prapareIpv4Address("192.168.100.100"));
-        odActions.add(new ActionBuilder().setAction(setNextHopActionBuilderIpv4.build()).build());
+        odActions.add(new ActionBuilder().setAction(new SetNextHopActionCaseBuilder().setSetNextHopAction(setNextHopActionBuilderIpv4.build()).build()).build());
 
         // test case for IPv6
         SetNextHopActionBuilder setNextHopActionBuilderIpv6 = new SetNextHopActionBuilder();
         setNextHopActionBuilderIpv6.setAddress(prapareIpv6Address("2001:0db8:85a3:0000:0000:8a2e:0370:7334"));
-        odActions.add(new ActionBuilder().setAction(setNextHopActionBuilderIpv6.build()).build());
+        odActions.add(new ActionBuilder().setAction(new SetNextHopActionCaseBuilder().setSetNextHopAction(setNextHopActionBuilderIpv6.build()).build()).build());
     }
 
     private Address prapareIpv4Address(String ipv4Address) {
@@ -432,27 +474,37 @@ public class TestToSalConversionsUtils {
         return ipv6Builder.build();
     }
 
-    private void prepareActionSetDlType(SetDlTypeActionBuilder setDlTypeActionBuilder) {
+    private void prepareActionSetDlType(SetDlTypeActionCaseBuilder wrapper) {
+        SetDlTypeActionBuilder setDlTypeActionBuilder = new SetDlTypeActionBuilder();
         setDlTypeActionBuilder.setDlType(new EtherType(513l));
+        wrapper.setSetDlTypeAction(setDlTypeActionBuilder.build());
     }
 
-    private void prepareActionSetDlSrc(SetDlSrcActionBuilder setDlSrcActionBuilder) {
+    private void prepareActionSetDlSrc(SetDlSrcActionCaseBuilder wrapper) {
+        SetDlSrcActionBuilder setDlSrcActionBuilder = new SetDlSrcActionBuilder();
         setDlSrcActionBuilder.setAddress(new MacAddress("24:77:03:7C:C5:F1"));
+        wrapper.setSetDlSrcAction(setDlSrcActionBuilder.build());
     }
 
-    private void prepareActionSetDlDst(SetDlDstActionBuilder setDlDstActionBuilder) {
+    private void prepareActionSetDlDst(SetDlDstActionCaseBuilder wrapper) {
+        SetDlDstActionBuilder setDlDstActionBuilder = new SetDlDstActionBuilder();
         setDlDstActionBuilder.setAddress(new MacAddress("3C:A9:F4:00:E0:C8"));
+        wrapper.setSetDlDstAction(setDlDstActionBuilder.build());
     }
 
-    private void prepareActionPushVlan(PushVlanActionBuilder pushVlanActionBuilder) {
+    private void prepareActionPushVlan(PushVlanActionCaseBuilder wrapper) {
+        PushVlanActionBuilder pushVlanActionBuilder = new PushVlanActionBuilder();
         pushVlanActionBuilder.setPcp(7); // 3 bits
         pushVlanActionBuilder.setCfi(new VlanCfi(1)); // 1 bit
         pushVlanActionBuilder.setVlanId(new VlanId(4095));
         pushVlanActionBuilder.setTag(0x8100); // 12 bit
+        wrapper.setPushVlanAction(pushVlanActionBuilder.build());
     }
 
-    private void prepareActionOutput(OutputActionBuilder outputActionBuilder) {       
+    private void prepareActionOutput(OutputActionCaseBuilder wrapper) {
+        OutputActionBuilder outputActionBuilder = new OutputActionBuilder();
         outputActionBuilder.setOutputNodeConnector(new Uri("uri1"));
+        wrapper.setOutputAction(outputActionBuilder.build());
     }
 
     private Match prepOdMatch(MtchType mt) {
index 597483ef6541456b4e417c255e71465e8fa0fe79..e2948fd54e59818352d9eff4c51bec8d2ac9a293 100644 (file)
@@ -23,7 +23,7 @@
                 <artifactId>maven-bundle-plugin</artifactId>
                 <configuration>
                     <instructions>
-                        <Bundle-Activator>org.opendaylight.controller.forwardingrulesmanager.consumer.impl.FRMConsumerImpl</Bundle-Activator>
+                        <Bundle-Activator>org.opendaylight.controller.frm.FRMActivator</Bundle-Activator>
                     </instructions>
                 </configuration>
             </plugin>
index 24bfc4fdf4c09079230189c43e9d33a428ab0cbf..ab2e19e9d4db3e915217e17203a6ac903e607c7d 100644 (file)
@@ -11,29 +11,23 @@ import org.opendaylight.controller.sal.utils.NetUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetQueueAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetQueueActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpActionCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActions;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActions;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTable;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.Meter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActions;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
@@ -43,6 +37,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 
 public class FRMUtil {
     protected static final Logger logger = LoggerFactory.getLogger(FRMUtil.class);
@@ -207,15 +208,15 @@ public class FRMUtil {
         for (Action curaction : actions) {
             org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action action = curaction
                     .getAction();
-            if (action instanceof ControllerAction) {
-                Integer length = ((ControllerAction) action).getMaxLength();
+            if (action instanceof ControllerActionCase) {
+                Integer length = ((ControllerActionCase) action).getControllerAction().getMaxLength();
                 if (length < 0 || length > 65294) {
                     logger.error("Controller: MaxLength is not valid");
                     return false;
                 }
-            } else if (action instanceof OutputAction) {
-                Integer length = ((OutputAction) action).getMaxLength();
-                Uri outputnodeconnector = ((OutputAction) action).getOutputNodeConnector();
+            } else if (action instanceof OutputActionCase) {
+                Integer length = ((OutputActionCase) action).getOutputAction().getMaxLength();
+                Uri outputnodeconnector = ((OutputActionCase) action).getOutputAction().getOutputNodeConnector();
                 if (length < 0 || length > 65294) {
                     logger.error("OutputAction: MaxLength is not valid");
                     return false;
@@ -240,62 +241,62 @@ public class FRMUtil {
                     }
 
                 }
-            } else if (action instanceof PushMplsAction) {
-                Integer ethertype = ((PushMplsAction) action).getEthernetType();
+            } else if (action instanceof PushMplsActionCase) {
+                Integer ethertype = ((PushMplsActionCase) action).getPushMplsAction().getEthernetType();
                 if (ethertype != null && ethertype != 0x8847 && ethertype != 0x8848) {
                     logger.error("Ether Type is not valid for PushMplsAction");
                     return false;
                 }
-            } else if (action instanceof PushPbbAction) {
-                Integer ethertype = ((PushPbbAction) action).getEthernetType();
+            } else if (action instanceof PushPbbActionCase) {
+                Integer ethertype = ((PushPbbActionCase) action).getPushPbbAction().getEthernetType();
                 if (ethertype != null && ethertype != 0x88E7) {
                     logger.error("Ether type is not valid for PushPbbAction");
                     return false;
                 }
-            } else if (action instanceof PushVlanAction) {
-                Integer ethertype = ((PushVlanAction) action).getEthernetType();
+            } else if (action instanceof PushVlanActionCase) {
+                Integer ethertype = ((PushVlanActionCase) action).getPushVlanAction().getEthernetType();
                 if (ethertype != null && ethertype != 0x8100 && ethertype != 0x88a8) {
                     logger.error("Ether Type is not valid for PushVlanAction");
                     return false;
                 }
-            } else if (action instanceof SetDlDstAction) {
-                MacAddress address = ((SetDlDstAction) action).getAddress();
-                if (address != null && !isL2AddressValid(address.toString())) {
+            } else if (action instanceof SetDlDstActionCase || action instanceof SetDlSrcActionCase) {
+                MacAddress address = ((SetDlDstActionCase) action).getSetDlDstAction().getAddress();
+                if (address != null && !isL2AddressValid(address.getValue())) {
                     logger.error("SetDlDstAction: Address not valid");
                     return false;
                 }
-            } else if (action instanceof SetDlSrcAction) {
-                MacAddress address = ((SetDlSrcAction) action).getAddress();
-                if (address != null && !isL2AddressValid(address.toString())) {
+            } else if (action instanceof SetDlSrcActionCase) {
+                MacAddress address = ((SetDlSrcActionCase) action).getSetDlSrcAction().getAddress();
+                if (address != null && !isL2AddressValid(address.getValue())) {
                     logger.error("SetDlSrcAction: Address not valid");
                     return false;
                 }
-            } else if (action instanceof SetQueueAction) {
-                String queue = ((SetQueueAction) action).getQueue();
+            } else if (action instanceof SetQueueActionCase) {
+                String queue = ((SetQueueActionCase) action).getSetQueueAction().getQueue();
                 if (queue != null && !isQueueValid(queue)) {
                     logger.error("Queue Id not valid");
                     return false;
                 }
-            } else if (action instanceof SetTpDstAction) {
-                PortNumber port = ((SetTpDstAction) action).getPort();
+            } else if (action instanceof SetTpDstActionCase) {
+                PortNumber port = ((SetTpDstActionCase) action).getSetTpDstAction().getPort();
                 if (port != null && !isPortValid(port)) {
                     logger.error("Port not valid");
                 }
-            } else if (action instanceof SetTpSrcAction) {
-                PortNumber port = ((SetTpSrcAction) action).getPort();
+            } else if (action instanceof SetTpSrcActionCase) {
+                PortNumber port = ((SetTpSrcActionCase) action).getSetTpSrcAction().getPort();
                 if (port != null && !isPortValid(port)) {
                     logger.error("Port not valid");
                 }
-            } else if (action instanceof SetVlanIdAction) {
-                VlanId vlanid = ((SetVlanIdAction) action).getVlanId();
-                if (vlanid != null && !isVlanIdValid(vlanid.getValue().toString())) {
-                    logger.error("Vlan ID is not in the range 0 - 4095");
+            } else if (action instanceof SetVlanIdActionCase) {
+                VlanId vlanid = ((SetVlanIdActionCase) action).getSetVlanIdAction().getVlanId();
+                if (vlanid != null && !isVlanIdValid(vlanid.toString())) {
+                    logger.error("Vlan ID %s is not in the range 0 - 4095");
                     return false;
                 }
-            } else if (action instanceof SetVlanPcpAction) {
-                VlanPcp vlanpcp = ((SetVlanPcpAction) action).getVlanPcp();
-                if (vlanpcp != null && !isVlanPriorityValid(vlanpcp.getValue().toString())) {
-                    logger.error("Vlan priority is not in the range 0 - 7");
+            } else if (action instanceof SetVlanPcpActionCase) {
+                VlanPcp vlanpcp = ((SetVlanPcpActionCase) action).getSetVlanPcpAction().getVlanPcp();
+                if (vlanpcp != null && !isVlanPriorityValid(vlanpcp.toString())) {
+                    logger.error("Vlan priority %s is not in the range 0 - 7");
                     return false;
                 }
             }
@@ -315,35 +316,35 @@ public class FRMUtil {
         for (Instruction instruction : instructionsList) {
             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
                     .getInstruction();
-            if (curInstruction instanceof GoToTable) {
+            if (curInstruction instanceof GoToTableCase) {
 
-                Short tableid = ((GoToTable) curInstruction).getTableId();
+                Short tableid = ((GoToTableCase) curInstruction).getGoToTable().getTableId();
                 if (tableid < 0) {
                     logger.error("table id is not valid");
                     return false;
                 }
             }
 
-            else if (curInstruction instanceof WriteActions) {
+            else if (curInstruction instanceof WriteActionsCase) {
 
-                List<Action> action = ((WriteActions) curInstruction).getAction();
+                List<Action> action = ((WriteActionsCase) curInstruction).getWriteActions().getAction();
                 validateActions(action);
 
             }
 
-            else if (curInstruction instanceof ApplyActions) {
-                List<Action> action = ((ApplyActions) curInstruction).getAction();
+            else if (curInstruction instanceof ApplyActionsCase) {
+                List<Action> action = ((ApplyActionsCase) curInstruction).getApplyActions().getAction();
                 validateActions(action);
             }
 
-            else if (curInstruction instanceof ClearActions) {
-                List<Action> action = ((ClearActions) curInstruction).getAction();
+            else if (curInstruction instanceof ClearActionsCase) {
+                List<Action> action = ((ClearActionsCase) curInstruction).getClearActions().getAction();
                 validateActions(action);
             }
 
-            else if (curInstruction instanceof Meter) {
+            else if (curInstruction instanceof MeterCase) {
 
-                String meter = ((Meter) curInstruction).getMeter();
+                MeterId meter = ((MeterCase) curInstruction).getMeter().getMeterId();
                 if (meter != null && !isValidMeter(meter)) {
                     logger.error("Meter Id is not valid");
                     return false;
@@ -355,7 +356,7 @@ public class FRMUtil {
         return true;
     }
 
-    public static boolean isValidMeter(String meter) {
+    public static boolean isValidMeter(MeterId meter) {
         // TODO
         return true;
     }
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractTransaction.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractTransaction.xtend
new file mode 100644 (file)
index 0000000..9f45a11
--- /dev/null
@@ -0,0 +1,99 @@
+package org.opendaylight.controller.frm
+
+import java.util.Collections
+import java.util.HashSet
+import java.util.Map.Entry
+import java.util.Set
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.controller.sal.common.util.Rpcs
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.common.RpcError
+
+abstract class AbstractTransaction implements DataCommitTransaction<InstanceIdentifier<?extends DataObject>, DataObject> {
+        
+    @Property
+    val DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
+    
+    new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+        _modification = modification;
+    }
+    
+    def void validate() throws IllegalStateException
+    
+    override finish() throws IllegalStateException {
+        validate()
+        callRpcs();
+        return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());     
+    }
+    
+    override getModification() {
+        return _modification;
+    }
+    
+    override rollback() throws IllegalStateException {
+        rollbackRpcs();
+        return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
+    }
+    
+    def private callRpcs() {
+        val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries = _modification.getCreatedConfigurationData().entrySet();
+
+        /*
+         * This little dance is because updatedEntries contains both created and modified entries
+         * The reason I created a new HashSet is because the collections we are returned are immutable.
+         */
+        val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updatedEntries = new HashSet<Entry<InstanceIdentifier<? extends DataObject>, DataObject>>();
+        updatedEntries.addAll(_modification.getUpdatedConfigurationData().entrySet());
+        updatedEntries.removeAll(createdEntries);
+
+        val Set<InstanceIdentifier<? extends DataObject>> removeEntriesInstanceIdentifiers = _modification.getRemovedConfigurationData();
+        for (Entry<InstanceIdentifier<? extends DataObject >, DataObject> entry : createdEntries) {
+            add(entry.key,entry.value);
+        }
+        for (Entry<InstanceIdentifier<?>, DataObject> entry : updatedEntries) {
+                val originalFlow = _modification.originalConfigurationData.get(entry.key);
+                val updatedFlow = entry.value
+                update(entry.key, originalFlow ,updatedFlow);
+        }
+
+        for (InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers ) {
+            val removeValue = _modification.getOriginalConfigurationData.get(instanceId);
+                remove(instanceId,removeValue);
+        }
+    }
+    
+    def void remove(InstanceIdentifier<?> identifier, DataObject remove)
+    
+    def void update(InstanceIdentifier<?> identifier, DataObject original, DataObject update)
+    
+    def void add(InstanceIdentifier<?> identifier, DataObject add)
+    
+    def private rollbackRpcs() {
+        val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries = _modification.getCreatedConfigurationData().entrySet();
+
+        /*
+         * This little dance is because updatedEntries contains both created and modified entries
+         * The reason I created a new HashSet is because the collections we are returned are immutable.
+         */
+        val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updatedEntries = new HashSet<Entry<InstanceIdentifier<? extends DataObject>, DataObject>>();
+        updatedEntries.addAll(_modification.getUpdatedConfigurationData().entrySet());
+        updatedEntries.removeAll(createdEntries);
+
+        val Set<InstanceIdentifier<? >> removeEntriesInstanceIdentifiers = _modification.getRemovedConfigurationData();
+        for (Entry<InstanceIdentifier<?>, DataObject> entry : createdEntries) {
+            remove(entry.key,entry.value); // because we are rolling back, remove what we would have added.            
+        }
+        for (Entry<InstanceIdentifier<?>, DataObject> entry : updatedEntries) {
+            val originalFlow = _modification.originalConfigurationData.get(entry.key);
+            val updatedFlow = entry.value
+            update(entry.key, updatedFlow ,originalFlow);// because we are rolling back, replace the updated with the original
+        }
+
+        for (InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers ) {
+            val removeValue = _modification.getOriginalConfigurationData.get(instanceId);
+            add(instanceId,removeValue);// because we are rolling back, add what we would have removed.
+        }
+    }    
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FRMActivator.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FRMActivator.xtend
new file mode 100644 (file)
index 0000000..8ec9d79
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013 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.frm
+
+import org.opendaylight.controller.frm.flow.FlowProvider
+import org.opendaylight.controller.frm.group.GroupProvider
+import org.opendaylight.controller.frm.meter.MeterProvider
+import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
+import org.osgi.framework.BundleContext
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService
+
+class FRMActivator extends AbstractBindingAwareProvider {
+
+    static var FlowProvider provider = new FlowProvider();
+    static var GroupProvider groupProvider = new GroupProvider();
+    static var MeterProvider meterProvider = new MeterProvider();
+
+    override onSessionInitiated(ProviderContext session) {
+        provider.dataService = session.getSALService(DataProviderService)
+        provider.salFlowService = session.getRpcService(SalFlowService);
+        provider.start();
+        
+        groupProvider.dataService = session.getSALService(DataProviderService)
+        groupProvider.salGroupService = session.getRpcService(SalGroupService)
+        groupProvider.start();
+        
+        meterProvider.dataService = session.getSALService(DataProviderService)
+        meterProvider.salMeterService = session.getRpcService(SalMeterService)
+        meterProvider.start();
+    }
+
+    override protected stopImpl(BundleContext context) {
+        provider.close();
+        groupProvider.close();
+        meterProvider.close();
+    }
+
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowCommitHandler.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowCommitHandler.xtend
new file mode 100644 (file)
index 0000000..03095fa
--- /dev/null
@@ -0,0 +1,22 @@
+package org.opendaylight.controller.frm.flow
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
+
+class FlowCommitHandler implements DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+       
+    @Property
+    val SalFlowService salFlowService;
+    
+    new(SalFlowService manager) {
+        _salFlowService = manager;
+    }
+    
+    override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+        return new FlowTransaction(modification,salFlowService);
+    }
+    
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.xtend
new file mode 100644 (file)
index 0000000..e664c7b
--- /dev/null
@@ -0,0 +1,50 @@
+package org.opendaylight.controller.frm.flow
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
+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.yangtools.concepts.Registration
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.slf4j.LoggerFactory
+
+class FlowProvider implements AutoCloseable {
+    
+    @Property
+    DataProviderService dataService;
+    
+    @Property
+    SalFlowService salFlowService;
+    
+    FlowCommitHandler commitHandler
+
+    Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject>> commitHandlerRegistration;
+    
+    static val LOG = LoggerFactory.getLogger(FlowProvider);
+    
+    def void start() {
+        commitHandler = new FlowCommitHandler(salFlowService)
+        val InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Nodes)
+            .child(Node)
+            .augmentation(FlowCapableNode)
+            .child(Table)
+            .child(Flow)
+            .toInstance();
+        commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler);
+        LOG.info("Flow Config Provider started.");
+    }
+
+    protected def startChange() {
+        return dataService.beginTransaction;
+    }
+    
+    override close() throws Exception {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+    
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransaction.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransaction.xtend
new file mode 100644 (file)
index 0000000..5203d3c
--- /dev/null
@@ -0,0 +1,72 @@
+package org.opendaylight.controller.frm.flow
+
+import org.opendaylight.controller.frm.AbstractTransaction
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
+
+class FlowTransaction extends AbstractTransaction {
+    
+    @Property
+    val SalFlowService salFlowService;
+    
+    new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalFlowService salFlowService) {
+        super(modification)
+        _salFlowService = salFlowService;
+    }
+    
+    override remove(InstanceIdentifier<?> instanceId, DataObject obj) {
+        if(obj instanceof Flow) {
+            val flow = (obj as Flow)
+            val tableInstanceId = instanceId.firstIdentifierOf(Table);
+            val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+            val builder = new RemoveFlowInputBuilder(flow);
+            builder.setNode(new NodeRef(nodeInstanceId));
+            builder.setFlowTable(new FlowTableRef(tableInstanceId));
+            _salFlowService.removeFlow(builder.build());            
+        }
+    }
+    
+    override update(InstanceIdentifier<?> instanceId, DataObject originalObj, DataObject updatedObj) {
+        if(originalObj instanceof Flow && updatedObj instanceof Flow) {
+            val originalFlow = (originalObj as Flow)
+            val updatedFlow = (updatedObj as Flow)
+            val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+            val builder = new UpdateFlowInputBuilder();
+            builder.setNode(new NodeRef(nodeInstanceId));
+            val ufb = new UpdatedFlowBuilder(updatedFlow);
+            builder.setUpdatedFlow((ufb.build()));
+            val ofb = new OriginalFlowBuilder(originalFlow);
+            builder.setOriginalFlow(ofb.build());      
+            _salFlowService.updateFlow(builder.build());
+           
+        }
+    }
+    
+    override add(InstanceIdentifier<?> instanceId, DataObject obj) {
+        if(obj instanceof Flow) {
+            val flow = (obj as Flow)
+            val tableInstanceId = instanceId.firstIdentifierOf(Table);
+            val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+            val builder = new AddFlowInputBuilder(flow);
+            builder.setNode(new NodeRef(nodeInstanceId));
+            builder.setFlowTable(new FlowTableRef(tableInstanceId));
+            _salFlowService.addFlow(builder.build());            
+        }
+    }
+    
+    override validate() throws IllegalStateException {
+        FlowTransactionValidator.validate(this)
+    }  
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransactionValidator.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransactionValidator.java
new file mode 100644 (file)
index 0000000..f6ffdb8
--- /dev/null
@@ -0,0 +1,9 @@
+package org.opendaylight.controller.frm.flow;
+
+public class FlowTransactionValidator {
+
+    public static void validate(FlowTransaction transaction) throws IllegalStateException {
+        // NOOP
+    }
+
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupCommitHandler.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupCommitHandler.xtend
new file mode 100644 (file)
index 0000000..2c5f42b
--- /dev/null
@@ -0,0 +1,22 @@
+package org.opendaylight.controller.frm.group
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+
+class GroupCommitHandler implements DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+       
+    @Property
+    val SalGroupService groupService;
+    
+    new(SalGroupService groupService) {
+        _groupService = groupService;
+    }
+    
+    override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+        return new GroupTransaction(modification,groupService);
+    }
+    
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.xtend
new file mode 100644 (file)
index 0000000..a75a668
--- /dev/null
@@ -0,0 +1,48 @@
+package org.opendaylight.controller.frm.group
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group
+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.yangtools.concepts.Registration
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.slf4j.LoggerFactory
+
+class GroupProvider implements AutoCloseable {
+    
+    @Property
+    DataProviderService dataService;
+    
+    @Property
+    SalGroupService salGroupService;
+    
+    GroupCommitHandler commitHandler
+
+    Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject>> commitHandlerRegistration;
+    
+    static val LOG = LoggerFactory.getLogger(GroupProvider);
+    
+    def void start() {
+        commitHandler = new GroupCommitHandler(salGroupService)
+        val InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Nodes)
+            .child(Node)
+            .augmentation(FlowCapableNode)
+            .child(Group)
+            .toInstance();
+        commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler);
+        LOG.info("Group Config Provider started.");
+    }
+
+    protected def startChange() {
+        return dataService.beginTransaction;
+    }
+    
+    override close() throws Exception {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+    
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransaction.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransaction.xtend
new file mode 100644 (file)
index 0000000..54382ea
--- /dev/null
@@ -0,0 +1,75 @@
+package org.opendaylight.controller.frm.group
+
+import org.opendaylight.controller.frm.AbstractTransaction
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder
+
+class GroupTransaction extends AbstractTransaction {
+    
+    @Property
+    val SalGroupService groupService;
+    
+    new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalGroupService groupService) {
+        super(modification)
+        _groupService = groupService;
+    }
+    
+    override remove(InstanceIdentifier<?> instanceId, DataObject obj) {
+        if(obj instanceof Group) {
+            val group = (obj as Group)
+            val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+            val builder = new RemoveGroupInputBuilder(group);
+            builder.setNode(new NodeRef(nodeInstanceId));
+            _groupService.removeGroup(builder.build());            
+        }
+    }
+    
+    override update(InstanceIdentifier<?> instanceId, DataObject originalObj, DataObject updatedObj) {
+        if(originalObj instanceof Group && updatedObj instanceof Group) {
+            val originalGroup = (originalObj as Group)
+            val updatedGroup = (updatedObj as Group)
+            val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+            val builder = new UpdateGroupInputBuilder();
+            builder.setNode(new NodeRef(nodeInstanceId));
+            val ufb = new UpdatedGroupBuilder(updatedGroup);
+            builder.setUpdatedGroup((ufb.build()));
+            val ofb = new OriginalGroupBuilder(originalGroup);
+            builder.setOriginalGroup(ofb.build());      
+            _groupService.updateGroup(builder.build());
+           
+        }
+    }
+    
+    override add(InstanceIdentifier<?> instanceId, DataObject obj) {
+        if(obj instanceof Group) {
+            val group = (obj as Group)
+            val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+            val builder = new AddGroupInputBuilder(group);
+            builder.setNode(new NodeRef(nodeInstanceId));
+            _groupService.addGroup(builder.build());            
+        }
+    }
+    
+    override validate() throws IllegalStateException {
+        GroupTransactionValidator.validate(this)
+    }  
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransactionValidator.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransactionValidator.java
new file mode 100644 (file)
index 0000000..a264c33
--- /dev/null
@@ -0,0 +1,9 @@
+package org.opendaylight.controller.frm.group;
+
+public class GroupTransactionValidator {
+
+    public static void validate(GroupTransaction transaction) throws IllegalStateException {
+        // NOOP
+    }
+
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterCommitHandler.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterCommitHandler.xtend
new file mode 100644 (file)
index 0000000..dd8d4c7
--- /dev/null
@@ -0,0 +1,22 @@
+package org.opendaylight.controller.frm.meter
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+
+class FlowCommitHandler implements DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+       
+    @Property
+    val SalMeterService salMeterService;
+    
+    new(SalMeterService manager) {
+        _salMeterService = manager;
+    }
+    
+    override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+        return new MeterTransaction(modification,salMeterService);
+    }
+    
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.xtend
new file mode 100644 (file)
index 0000000..75d29d5
--- /dev/null
@@ -0,0 +1,48 @@
+package org.opendaylight.controller.frm.meter
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter
+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.meter.service.rev130918.SalMeterService
+import org.opendaylight.yangtools.concepts.Registration
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.slf4j.LoggerFactory
+
+class MeterProvider implements AutoCloseable {
+    
+    @Property
+    DataProviderService dataService;
+    
+    @Property
+    SalMeterService salMeterService;
+    
+    FlowCommitHandler commitHandler
+
+    Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject>> commitHandlerRegistration;
+    
+    static val LOG = LoggerFactory.getLogger(MeterProvider);
+    
+    def void start() {
+        commitHandler = new FlowCommitHandler(salMeterService)
+        val InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Nodes)
+            .child(Node)
+            .augmentation(FlowCapableNode)
+            .child(Meter)
+            .toInstance();
+        commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler);
+        LOG.info("Meter Config Provider started.");
+    }
+
+    protected def startChange() {
+        return dataService.beginTransaction;
+    }
+    
+    override close() throws Exception {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+    
+}
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransaction.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransaction.xtend
new file mode 100644 (file)
index 0000000..3ed1f40
--- /dev/null
@@ -0,0 +1,66 @@
+package org.opendaylight.controller.frm.meter
+
+import org.opendaylight.controller.frm.AbstractTransaction
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeterBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+
+class MeterTransaction extends AbstractTransaction {
+    
+    @Property
+    val SalMeterService salMeterService;
+    
+    new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalMeterService salMeterService) {
+        super(modification)
+        _salMeterService = salMeterService;
+    }
+    
+    override remove(InstanceIdentifier<?> instanceId, DataObject obj) {
+        if(obj instanceof Meter) {
+            val meter = (obj as Meter)
+            val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+            val builder = new RemoveMeterInputBuilder(meter);
+            builder.setNode(new NodeRef(nodeInstanceId));
+            _salMeterService.removeMeter(builder.build());            
+        }
+    }
+    
+    override update(InstanceIdentifier<?> instanceId, DataObject originalObj, DataObject updatedObj) {
+        if(originalObj instanceof Meter && updatedObj instanceof Meter) {
+            val originalMeter = (originalObj as Meter)
+            val updatedMeter = (updatedObj as Meter)
+            val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+            val builder = new UpdateMeterInputBuilder();
+            builder.setNode(new NodeRef(nodeInstanceId));
+            val ufb = new UpdatedMeterBuilder(updatedMeter);
+            builder.setUpdatedMeter((ufb.build()));
+            val ofb = new OriginalMeterBuilder(originalMeter);
+            builder.setOriginalMeter(ofb.build());      
+            _salMeterService.updateMeter(builder.build());
+           
+        }
+    }
+    
+    override add(InstanceIdentifier<?> instanceId, DataObject obj) {
+        if(obj instanceof Meter) {
+            val meter = (obj as Meter)
+            val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+            val builder = new AddMeterInputBuilder(meter);
+            builder.setNode(new NodeRef(nodeInstanceId));
+            _salMeterService.addMeter(builder.build());            
+        }
+    }
+    
+    override validate() throws IllegalStateException {
+        MeterTransactionValidator.validate(this)
+    }  
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransactionValidator.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransactionValidator.java
new file mode 100644 (file)
index 0000000..d8afd2a
--- /dev/null
@@ -0,0 +1,9 @@
+package org.opendaylight.controller.frm.meter;
+
+public class MeterTransactionValidator {
+
+    public static void validate(MeterTransaction transaction) throws IllegalStateException {
+        // NOOP
+    }
+
+}
diff --git a/opendaylight/md-sal/model/model-flow-base/src/main/yang/action-types.yang b/opendaylight/md-sal/model/model-flow-base/src/main/yang/action-types.yang
deleted file mode 100644 (file)
index 3850dd5..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-module opendaylight-action-types {
-    namespace "urn:opendaylight:action:types";
-    prefix action;
-
-    import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
-    import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
-    import opendaylight-l2-types {prefix l2t; revision-date "2013-08-27";}
-    import opendaylight-match-types {prefix match; revision-date "2013-10-26";}
-    
-    revision "2013-11-12" {
-        description "Initial revision of action service";
-    }
-    
-    typedef vlan-cfi {
-        type int32;    
-    }
-
-    grouping address {
-        choice address {
-            case ipv4 {
-                leaf ipv4-address {
-                    type inet:ipv4-prefix;
-                }
-            }
-            case ipv6 {
-                leaf ipv6-address {
-                    type inet:ipv6-prefix;
-                }
-            }
-        }
-    }  
-    
-    grouping action-list {
-        list action {
-            key "order";
-            leaf order {
-                type int32;
-            }
-            uses action;
-        }
-    }
-    
-    grouping action {
-        choice action {
-            case output-action {
-                leaf output-node-connector {
-                    type inet:uri;
-                }
-                
-                leaf max-length {
-                    type uint16 {
-                        range "0..65294";
-                    }
-                }                
-            }
-
-            case controller-action {
-                leaf max-length {
-                    type uint16 {
-                        range "0..65294";
-                    }
-                }
-            }
-            
-            case set-field {
-                container match {
-                    uses match:match;
-                }
-            }
-            
-            case set-queue-action {
-                leaf queue {
-                    type string; 
-                }
-                
-                leaf queue-id {
-                    type uint32; 
-                }
-            }
-
-            case pop-mpls-action {
-                leaf ethernet-type {
-                    type uint16; // TODO: define ethertype type
-                }
-            }
-
-            case set-mpls-ttl-action {
-                leaf mpls-ttl {
-                    type uint8;
-                }
-            }
-
-            case set-nw-ttl-action {
-                leaf nw-ttl {
-                    type uint8;
-                }
-            }
-
-            case push-pbb-action {
-                leaf ethernet-type {
-                    type uint16; // TODO: define ethertype type
-                }
-            }
-
-            case pop-pbb-action {
-                
-            }
-            
-            case push-mpls-action {
-                leaf ethernet-type {
-                    type uint16; // TODO: define ethertype type
-                }
-            }
-            
-            case dec-mpls-ttl {
-            }
-            
-            case dec-nw-ttl {
-            }
-            
-            case drop-action {
-            }
-            
-            case flood-action {
-            }
-            
-            case flood-all-action {
-            }
-            
-            case hw-path-action {
-            }
-            
-            case loopback-action {
-            }
-            
-            case pop-vlan-action {
-            }
-            
-            case push-vlan-action {
-                leaf ethernet-type {
-                    type uint16; // TODO: define ethertype type
-                }
-                leaf tag {               // TPID - 16 bits
-                    type int32;
-                } 
-                leaf pcp {               // PCP - 3 bits
-                    type int32;
-                }
-                leaf cfi {               // CFI - 1 bit (drop eligible)
-                    type vlan-cfi;
-                }
-                leaf vlan-id {           // VID - 12 bits
-                    type l2t:vlan-id;
-                }
-//                leaf tci {               //TCI = [PCP + CFI + VID]
-//                }
-//                leaf header {            //header = [TPID + TCI] 
-//                }
-            }
-            
-            case copy-ttl-out {
-            }
-            
-            case copy-ttl-in {
-            }
-            
-            case set-dl-dst-action {
-                leaf address {
-                    type yang:mac-address;
-                }
-            }
-            
-            case set-dl-src-action {
-                leaf address {
-                    type yang:mac-address;
-                }
-            }
-            case group-action {
-                leaf group {
-                    type string;
-                }
-                
-                leaf group-id {
-                    type uint32;
-                }
-            }
-            
-            case set-dl-type-action {
-                leaf dl-type {
-                    type l2t:ether-type;
-                }
-            }
-            
-            case set-next-hop-action {
-                uses address;
-            }
-            
-            case set-nw-dst-action {
-                uses address;            
-            }
-            
-            case set-nw-src-action{
-                uses address;            
-            }
-            
-            case set-nw-tos-action {
-                leaf tos {
-                    type int32;
-                }
-            }
-            
-            case set-tp-dst-action {
-                leaf port {
-                    type inet:port-number;
-                }                
-            }
-            case set-tp-src-action {
-                leaf port {
-                    type inet:port-number;
-                }                
-            }
-            case set-vlan-cfi-action {
-                leaf vlan-cfi {
-                    type vlan-cfi;
-                }
-            }
-            
-            case set-vlan-id-action {
-                leaf vlan-id {
-                    type l2t:vlan-id;
-                } 
-            }
-            
-            case set-vlan-pcp-action {
-                leaf vlan-pcp {
-                    type l2t:vlan-pcp;
-                }            
-            }
-            
-            case sw-path-action {            
-            }  
-        }
-    }
-}
\ No newline at end of file
index f03e28b1108a1dee502b3550fbdfa241d0467d41..8c874e2fe80a60f345f67fe091cde4a883fcc631 100644 (file)
@@ -236,4 +236,12 @@ module opendaylight-group-types {
        uses group-features;
     }
     
+    grouping groups {
+        list group {
+            key "group-id";                  
+        
+            uses group;
+        }
+    }
+    
 }
\ No newline at end of file
index 5ba92aba9d2f242be04e05b11e18892872d53c3f..7dcd254ad7cc751e64d30bf275a8629781f625be 100644 (file)
@@ -91,6 +91,11 @@ module opendaylight-match-types {
             description "IP ECN (2 bits in ToS field).";
             type uint8; 
         }
+        
+        leaf ip-proto {                
+           description "IP Proto (IPv4 or IPv6 Protocol Number).";             
+              type inet:ip-version;            
+               }
     } 
     
     grouping "ipv4-match-fields" {
diff --git a/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-action-types.yang b/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-action-types.yang
new file mode 100644 (file)
index 0000000..81303d6
--- /dev/null
@@ -0,0 +1,343 @@
+module opendaylight-action-types {
+    namespace "urn:opendaylight:action:types";
+    prefix action;
+
+    import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
+    import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
+    import opendaylight-l2-types {prefix l2t; revision-date "2013-08-27";}
+    import opendaylight-match-types {prefix match; revision-date "2013-10-26";}
+    
+    revision "2013-11-12" {
+        description "Initial revision of action service";
+    }
+    
+    typedef vlan-cfi {
+        type int32;    
+    }
+
+    grouping address {
+        choice address {
+            case ipv4 {
+                leaf ipv4-address {
+                    type inet:ipv4-prefix;
+                }
+            }
+            case ipv6 {
+                leaf ipv6-address {
+                    type inet:ipv6-prefix;
+                }
+            }
+        }
+    }  
+    
+    grouping action-list {
+        list action {
+            key "order";
+            leaf order {
+                type int32;
+            }
+            uses action;
+        }
+    }
+    
+    grouping action {
+        choice action {
+            case output-action-case {
+                container output-action {
+                    leaf output-node-connector {
+                        type inet:uri;
+                    }
+                    
+                    leaf max-length {
+                        type uint16 {
+                            range "0..65294";
+                        }
+                    }
+                }
+            }
+
+            case controller-action-case {
+                container controller-action {
+                 leaf max-length {
+                     type uint16 {
+                         range "0..65294";
+                     }
+                 }
+             }
+            }
+             
+
+
+            case set-field-case {
+                container set-field {
+                     uses match:match;
+                 }
+             }
+             
+
+            case set-queue-action-case {
+                container set-queue-action {
+                 leaf queue {
+                     type string; 
+                 }
+                 leaf queue-id {
+                     type uint32; 
+                 }
+             }
+            }
+
+           case pop-mpls-action-case {
+                container pop-mpls-action {
+                 leaf ethernet-type {
+                     type uint16; // TODO: define ethertype type
+                 }
+             }
+            }
+
+            case set-mpls-ttl-action-case {
+                container set-mpls-ttl-action {
+                 leaf mpls-ttl {
+                     type uint8;
+                 }
+             }
+            }
+
+            case set-nw-ttl-action-case {
+                container set-nw-ttl-action {
+                 leaf nw-ttl {
+                     type uint8;
+                 }
+             }
+            }
+
+            case push-pbb-action-case {
+                container push-pbb-action {
+                 leaf ethernet-type {
+                     type uint16; // TODO: define ethertype type
+                 }
+             }
+            }
+
+            case pop-pbb-action-case {
+                container pop-pbb-action {
+                 
+             }
+            }
+             
+
+            case push-mpls-action-case {
+                container push-mpls-action {
+                 leaf ethernet-type {
+                     type uint16; // TODO: define ethertype type
+                 }
+             }
+            }
+             
+
+            case dec-mpls-ttl-case {
+                container dec-mpls-ttl {
+                }
+             }
+             
+
+            case dec-nw-ttl-case {
+                container dec-nw-ttl {
+                }
+             }
+             
+
+            case drop-action-case {
+                container drop-action {
+                }
+             }
+             
+
+            case flood-action-case {
+                container flood-action {
+                }
+             }
+             
+
+            case flood-all-action-case {
+                container flood-all-action {
+                }
+             }
+             
+
+            case hw-path-action-case {
+                container hw-path-action {
+                }
+             }
+             
+
+            case loopback-action-case {
+                container loopback-action {
+                }
+             }
+             
+
+            case pop-vlan-action-case {
+                container pop-vlan-action {
+                }
+             }
+             
+            
+            
+            case push-vlan-action-case {
+                container push-vlan-action {
+                 leaf ethernet-type {
+                     type uint16; // TODO: define ethertype type
+                 }
+                leaf tag {               // TPID - 16 bits
+                    type int32;
+                } 
+                leaf pcp {               // PCP - 3 bits
+                    type int32;
+                }
+                leaf cfi {               // CFI - 1 bit (drop eligible)
+                    type vlan-cfi;
+                }
+                leaf vlan-id {           // VID - 12 bits
+                    type l2t:vlan-id;
+                }
+//                leaf tci {               //TCI = [PCP + CFI + VID]
+//                }
+//                leaf header {            //header = [TPID + TCI] 
+//                }
+                }
+             }
+            
+            case copy-ttl-out-case {
+                container copy-ttl-out {
+                }
+             }
+             
+
+            case copy-ttl-in-case {
+                container copy-ttl-in {
+                }
+             }
+             
+
+            case set-dl-dst-action-case {
+                container set-dl-dst-action {
+                 leaf address {
+                     type yang:mac-address;
+                 }
+             }
+            }
+             
+
+            case set-dl-src-action-case {
+                container set-dl-src-action {
+                 leaf address {
+                     type yang:mac-address;
+                 }
+             }
+
+            }
+            case group-action-case {
+                container group-action {
+                 leaf group {
+                     type string;
+                 }
+                
+                leaf group-id {
+                    type uint32;
+                }
+             }
+            }
+            
+            case set-dl-type-action-case {
+                container set-dl-type-action {
+                 leaf dl-type {
+                     type l2t:ether-type;
+                 }
+             }
+            }
+             
+
+            case set-next-hop-action-case {
+                container set-next-hop-action {
+                 uses address;
+             }
+            }
+             
+
+            case set-nw-dst-action-case {
+                container set-nw-dst-action {
+                 uses address;            
+             }
+            }
+             
+
+            case set-nw-src-action-case {
+                container set-nw-src-action {
+                 uses address;            
+             }
+            }
+             
+
+            case set-nw-tos-action-case {
+                container set-nw-tos-action {
+                 leaf tos {
+                     type int32;
+                 }
+             }
+            }
+             
+
+            case set-tp-dst-action-case {
+                container set-tp-dst-action {
+                 leaf port {
+                     type inet:port-number;
+                 }                
+             }
+
+            }
+            case set-tp-src-action-case {
+                container set-tp-src-action {
+                 leaf port {
+                     type inet:port-number;
+                 }                
+             }
+
+            }
+            case set-vlan-cfi-action-case {
+                container set-vlan-cfi-action {
+                 leaf vlan-cfi {
+                     type vlan-cfi;
+                 }
+             }
+            }
+             
+
+            case set-vlan-id-action-case {
+                container set-vlan-id-action {
+                 leaf vlan-id {
+                     type l2t:vlan-id;
+                 } 
+             }
+            }
+             
+
+            case set-vlan-pcp-action-case {
+                container set-vlan-pcp-action {
+                 leaf vlan-pcp {
+                     type l2t:vlan-pcp;
+                 }            
+             }
+            }
+             
+
+            case sw-path-action-case {            
+                container sw-path-action {
+                }  
+             }  
+         }
+     }
+}
\ No newline at end of file
similarity index 73%
rename from opendaylight/md-sal/model/model-flow-base/src/main/yang/flow-types.yang
rename to opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-flow-types.yang
index 29ea8ddf1889bc8d3cfec6e37d070896fc0bd3ae..e83306db50db1155ab1d9fb7147fd71e2329cfff 100644 (file)
@@ -6,6 +6,7 @@ module opendaylight-flow-types {
     import ietf-yang-types {prefix yang; revision-date "2010-09-24";}    
     import opendaylight-match-types {prefix match; revision-date "2013-10-26";}
     import opendaylight-action-types {prefix action;}
+    import opendaylight-meter-types {prefix meter; revision-date "2013-09-18";}
 
     revision "2013-10-26" {
         description "Initial revision of flow service";
@@ -21,46 +22,54 @@ module opendaylight-flow-types {
         }
     }
 
-    grouping instruction {
-        choice instruction {
-            case go-to-table {
-                leaf table_id {
-                    type uint8;
-                }
+     grouping instruction {
+         choice instruction {
+            case go-to-table-case {
+                container go-to-table {
+                 leaf table_id {
+                     type uint8;
+                 }
+             }
             }
-            
-            case write-metadata {
-                leaf metadata {
-                    type uint64;
-                }
-                
-                leaf metadata-mask {
-                    type uint64;
-                }
+             
+            case write-metadata-case {
+                container write-metadata {
+                 leaf metadata {
+                     type uint64;
+                 }
+                 
+                 leaf metadata-mask {
+                     type uint64;
+                 }
+             }
             }
-            
-            case write-actions {
-                uses action:action-list;
+             
+            case write-actions-case {
+                container write-actions {
+                 uses action:action-list;
+             }
             }
-            
-            case apply-actions {
-                uses action:action-list;
+             
+            case apply-actions-case {
+                container apply-actions {
+                 uses action:action-list;
+             }
             }
-            
-            case clear-actions {
-                uses action:action-list;
+             
+            case clear-actions-case {
+                container clear-actions {
+                 uses action:action-list;
+             }
             }
-            
-            case meter {
-                leaf meter {
-                    type string;
-                }
-                
-                leaf meter-id {
-                    type uint32;
-                }
-            }   
-        }
+             
+            case meter-case {
+                container meter {
+                     leaf meter-id {
+                        type meter:meter-id;
+                     } 
+                 }
+             }
+         }
     }
     
     typedef flow-mod-flags {
@@ -161,7 +170,7 @@ module opendaylight-flow-types {
     grouping flow-statistics {
         leaf packet-count {
             type yang:counter64;
-        } 
+        }
 
         leaf byte-count {
             type yang:counter64;
index 005f7c330daae6405218f1c4ca01d71c30535807..d717e87f761ea5b8c0897d6b4fc87d4fedf89581 100644 (file)
@@ -7,6 +7,10 @@ module flow-node-inventory {
     import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
     import opendaylight-port-types {prefix port;revision-date "2013-09-25";}
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
+    import opendaylight-table-types {prefix table;revision-date "2013-10-26";}
+    import opendaylight-flow-types {prefix flow;revision-date "2013-10-26";}
+    import opendaylight-group-types {prefix group;revision-date "2013-10-18";}
+    import opendaylight-meter-types {prefix meter;revision-date "2013-09-18";}
     
     revision "2013-08-19" {
         description "Flow Capable Node extensions to the Inventory model";
@@ -34,9 +38,37 @@ module flow-node-inventory {
         }
     }
 
-    grouping table {
-
+    typedef flow-id {
+        type uint32; // Note: This doesn't really belong here, and not sure if unint32 is right
+    }
 
+    grouping tables {
+        list table {
+            key "id"; 
+    
+            leaf id {
+                    type uint8;
+            }            
+    
+            uses table:table-features;
+    
+            list flow {
+                key "id"; 
+    
+                leaf id {
+                    type flow-id;
+                }           
+    
+                uses flow:flow;
+            }
+        }
+    }
+    
+    grouping meters {
+        list meter {
+            key "meter-id";
+            uses meter:meter;
+        }
     }
 
     grouping flow-node {
@@ -57,16 +89,10 @@ module flow-node-inventory {
             type string;
         }
 
-        container tables {
-            uses feature;
-            list table {
-                uses table;
-            }
-        }
-        
-        container group-tables {
-            uses feature;
-        }
+        uses tables;
+        uses group:groups;
+        uses meters;
+        // TODO: ports
         
         container supported-match-types {
             list match-type {
diff --git a/opendaylight/md-sal/model/model-inventory/src/main/yang/opendaylight-inventory-config.yang b/opendaylight/md-sal/model/model-inventory/src/main/yang/opendaylight-inventory-config.yang
new file mode 100644 (file)
index 0000000..aaaedc1
--- /dev/null
@@ -0,0 +1,23 @@
+module opendaylight-inventory-config {
+    namespace "urn:opendaylight:inventory:config";
+    prefix inv-config;
+
+    import yang-ext {prefix ext; revision-date "2013-07-09";}
+    import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
+    import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
+    import opendaylight-inventory {prefix inv; revision-date "2013-08-19";}
+
+
+    revision "2013-08-19" {
+        description "Initial revision of Inventory model";
+    }
+    /** Base structure **/
+    container nodes {
+        list node {
+            key "id";
+            ext:context-instance "node-context";
+
+            uses inv:node;
+        }
+    }    
+}
\ No newline at end of file
index 0e78598c1137a339c7368be40b0b7a7e39427b9a..b34621d02d6f8da7a7b24e6e60cff5e641b9a8d4 100644 (file)
@@ -12,7 +12,7 @@
     </scm>
 
     <modules>
-        <!--  Common APIs & Implementation -->
+        <!-- Common APIs & Implementation -->
         <module>sal-common</module>
         <module>sal-common-api</module>
         <module>sal-common-impl</module>
         <module>sal-connector-api</module>
         <module>sal-rest-connector</module>
         <module>sal-netconf-connector</module>
-        
+
+        <module>zeromq-routingtable/implementation</module>
+        <module>sal-remoterpc-connector/implementation</module>
         <!-- Clustered Data Store -->
         <module>clustered-data-store/implementation</module>
 
         <module>inventory-manager</module>
         <module>statistics-manager</module>
         <module>forwardingrules-manager</module>
-        
+
         <!-- Compability Packages -->
         <module>compatibility</module>
-        <module>zeromq-routingtable/implementation</module>
-        <module>sal-zeromq-connector</module>
     </modules>
 
 
     <profiles>
         <profile>
-           <id>integrationtests</id>
-           <activation>
-               <activeByDefault>false</activeByDefault>
-           </activation>
+            <id>integrationtests</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+            </activation>
             <modules>
                 <module>sal-binding-it</module>
-                <module>zeromq-routingtable/integrationtest</module>
                 <module>clustered-data-store/integrationtest</module>
-                <module>test</module>
+                <!--module>zeromq-routingtable/integrationtest</module -->
+                <!--module>sal-remoterpc-connector/integrationtest</module -->
+                <!--module>test/sal-rest-connector-it</modulei -->
             </modules>
         </profile>
         <profile>
-          <id>IDE</id>
-          <activation>
-            <property>
-              <name>m2e.version</name>
-            </property>
-          </activation>
-          <build>
-            <!-- Put the IDE's build output in a folder other than target, so that IDE builds don't interact with Maven builds -->
-            <directory>target-ide</directory>
-          </build>
+            <id>IDE</id>
+            <activation>
+                <property>
+                    <name>m2e.version</name>
+                </property>
+            </activation>
+            <build>
+                <!-- Put the IDE's build output in a folder other than target, 
+                    so that IDE builds don't interact with Maven builds -->
+                <directory>target-ide</directory>
+            </build>
         </profile>
     </profiles>
 
         <guava.version>14.0.1</guava.version>
         <osgi.core.version>5.0.0</osgi.core.version>
         <junit.version>4.8.1</junit.version>
+        <powermock.version>1.5.1</powermock.version>
+        <mockito.version>1.9.5</mockito.version>
         <xtend.version>2.4.3</xtend.version>
         <maven.clean.plugin.version>2.5</maven.clean.plugin.version>
         <jacoco.version>0.5.3.201107060350</jacoco.version>
+        <sal.version>0.5.1-SNAPSHOT</sal.version>  <!-- AD Sal version -->
+
         <!-- Sonar properties using jacoco to retrieve integration test results -->
         <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
         <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
     <pluginRepositories>
         <!-- OpenDayLight Repo Mirror -->
         <pluginRepository>
-          <id>opendaylight-mirror</id>
-          <name>opendaylight-mirror</name>
-          <url>${nexusproxy}/groups/public/</url>
-          <snapshots>
-              <enabled>false</enabled>
-          </snapshots>
-          <releases>
-              <enabled>true</enabled>
-              <updatePolicy>never</updatePolicy>
-          </releases>
+            <id>opendaylight-mirror</id>
+            <name>opendaylight-mirror</name>
+            <url>${nexusproxy}/groups/public/</url>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+            <releases>
+                <enabled>true</enabled>
+                <updatePolicy>never</updatePolicy>
+            </releases>
         </pluginRepository>
         <!-- OpenDayLight Snapshot artifact -->
         <pluginRepository>
-          <id>opendaylight-snapshot</id>
-          <name>opendaylight-snapshot</name>
-          <url> ${nexusproxy}/repositories/opendaylight.snapshot/</url>
-          <snapshots>
-              <enabled>true</enabled>
-          </snapshots>
-          <releases>
-              <enabled>false</enabled>
-          </releases>
+            <id>opendaylight-snapshot</id>
+            <name>opendaylight-snapshot</name>
+            <url> ${nexusproxy}/repositories/opendaylight.snapshot/</url>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
         </pluginRepository>
     </pluginRepositories>
 
     <repositories>
         <!-- OpenDayLight Repo Mirror -->
         <repository>
-          <id>opendaylight-mirror</id>
-          <name>opendaylight-mirror</name>
-          <url>${nexusproxy}/groups/public/</url>
-          <snapshots>
-              <enabled>false</enabled>
-          </snapshots>
-          <releases>
-              <enabled>true</enabled>
-              <updatePolicy>never</updatePolicy>
-          </releases>
+            <id>opendaylight-mirror</id>
+            <name>opendaylight-mirror</name>
+            <url>${nexusproxy}/groups/public/</url>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+            <releases>
+                <enabled>true</enabled>
+                <updatePolicy>never</updatePolicy>
+            </releases>
         </repository>
         <!-- OpenDayLight Snapshot artifact -->
         <repository>
-          <id>opendaylight-snapshot</id>
-          <name>opendaylight-snapshot</name>
-          <url> ${nexusproxy}/repositories/opendaylight.snapshot/</url>
-          <snapshots>
-              <enabled>true</enabled>
-          </snapshots>
-          <releases>
-              <enabled>false</enabled>
-          </releases>
+            <id>opendaylight-snapshot</id>
+            <name>opendaylight-snapshot</name>
+            <url> ${nexusproxy}/repositories/opendaylight.snapshot/</url>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
         </repository>
     </repositories>
 
                 <artifactId>yang-data-api</artifactId>
                 <version>${yang.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-data-impl</artifactId>
+                <version>${yang.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.opendaylight.yangtools</groupId>
                 <artifactId>yang-model-api</artifactId>
                 <artifactId>sal-connector-api</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.opendaylight.controller</groupId>
+                <artifactId>sal</artifactId>
+                <version>${sal.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>org.osgi</groupId>
+                        <artifactId>org.osgi.compendium</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
 
             <!-- Supporting Libraries -->
             <dependency>
                 <artifactId>org.eclipse.xtend.lib</artifactId>
                 <version>${xtend.version}</version>
             </dependency>
-
+            <dependency>
+                <groupId>org.osgi</groupId>
+                <artifactId>org.osgi.core</artifactId>
+                <version>${osgi.core.version}</version>
+            </dependency>
             <!-- Testing Dependencies -->
             <dependency>
                 <groupId>junit</groupId>
             <dependency>
                 <groupId>org.mockito</groupId>
                 <artifactId>mockito-all</artifactId>
-                <version>1.9.5</version>
+                <version>${mockito.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.powermock</groupId>
+                <artifactId>powermock-module-junit4</artifactId>
+                <version>${powermock.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.powermock</groupId>
+                <artifactId>powermock-api-mockito</artifactId>
+                <version>${powermock.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.powermock</groupId>
+                <artifactId>powermock-core</artifactId>
+                <version>${powermock.version}</version>
                 <scope>test</scope>
             </dependency>
         </dependencies>
                     <artifactId>maven-bundle-plugin</artifactId>
                     <version>${bundle.plugin.version}</version>
                     <extensions>true</extensions>
-                    <!--executions>
-                        <execution>
-                            <id>bundle-manifest</id>
-                            <phase>process-classes</phase>
-                            <goals>
-                                <goal>manifest</goal>
-                            </goals>
-                        </execution>
-                    </executions-->
+                    <!--executions> <execution> <id>bundle-manifest</id> 
+                        <phase>process-classes</phase> <goals> <goal>manifest</goal> </goals> </execution> 
+                        </executions -->
                     <configuration>
                         <instructions>
                             <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
                     <artifactId>jacoco-maven-plugin</artifactId>
                     <version>${jacoco.version}</version>
                 </plugin>
-                <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+                <!--This plugin's configuration is used to store Eclipse 
+                    m2e settings only. It has no influence on the Maven build itself. -->
                 <plugin>
                     <groupId>org.eclipse.m2e</groupId>
                     <artifactId>lifecycle-mapping</artifactId>
                                         </goals>
                                     </pluginExecutionFilter>
                                     <action>
-                                        <ignore/>
+                                        <ignore />
                                     </action>
                                 </pluginExecution>
                                 <pluginExecution>
                                         </goals>
                                     </pluginExecutionFilter>
                                     <action>
-                                      <ignore/>
+                                        <ignore />
                                     </action>
                                 </pluginExecution>
                                 <pluginExecution>
                                         </goals>
                                     </pluginExecutionFilter>
                                     <action>
-                                        <ignore/>
+                                        <ignore />
                                     </action>
                                 </pluginExecution>
                             </pluginExecutions>
index ac84aab977783edbebc416d4755379967f70e84c..f9f72094f816d8166c0067f7e1e1aff0829a2aac 100644 (file)
             <version>${slf4j.version}</version>
             <scope>test</scope>
         </dependency>
+            <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-inet-types</artifactId>
+            <version>2010.09.24.2-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+               <groupId>org.opendaylight.controller.model</groupId>
+               <artifactId>model-flow-base</artifactId>
+               <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+               <groupId>org.opendaylight.controller.model</groupId>
+               <artifactId>model-flow-service</artifactId>
+               <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+               <groupId>org.opendaylight.controller.model</groupId>
+               <artifactId>model-flow-statistics</artifactId>
+               <version>1.0-SNAPSHOT</version>
+        </dependency>
     </dependencies>
 </project>
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AugmentationVerifier.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AugmentationVerifier.java
new file mode 100644 (file)
index 0000000..bff77be
--- /dev/null
@@ -0,0 +1,32 @@
+package org.opendaylight.controller.sal.binding.test;
+
+import junit.framework.Assert;
+
+
+import org.opendaylight.yangtools.yang.binding.Augmentable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+public class AugmentationVerifier<T extends Augmentable<T>> {
+
+    private T object;
+
+    public AugmentationVerifier(T objectToVerify) {
+        this.object = objectToVerify;
+    }
+
+    public AugmentationVerifier<T> assertHasAugmentation(Class<? extends Augmentation<T>> augmentation) {
+        assertHasAugmentation(object, augmentation);
+        return (AugmentationVerifier<T>) this;
+    }
+
+    public static <T extends Augmentable<T>> void assertHasAugmentation(T object,
+            Class<? extends Augmentation<T>> augmentation) {
+        Assert.assertNotNull(object);
+        Assert.assertNotNull("Augmentation " + augmentation.getSimpleName() + " is not present.", object.getAugmentation(augmentation));
+    }
+
+    public static <T extends Augmentable<T>> AugmentationVerifier<T> from(T obj) {
+        return new AugmentationVerifier<T>(obj);
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/BindingTestUtilities.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/BindingTestUtilities.java
new file mode 100644 (file)
index 0000000..7d14919
--- /dev/null
@@ -0,0 +1,5 @@
+package org.opendaylight.controller.sal.binding.test;
+
+public class BindingTestUtilities {
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/MultipleAugmentationPuts.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/MultipleAugmentationPuts.java
new file mode 100644 (file)
index 0000000..6d1a699
--- /dev/null
@@ -0,0 +1,210 @@
+package org.opendaylight.controller.sal.binding.test.bugfix;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.sal.binding.test.AugmentationVerifier;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter32;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter64;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+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.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.Duration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.DurationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStatsKey;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+import com.google.common.collect.FluentIterable;
+
+import static org.junit.Assert.*;
+
+public class MultipleAugmentationPuts extends AbstractDataServiceTest implements DataChangeListener {
+
+    private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
+    private static final String NODE_ID = "openflow:1";
+
+    private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
+
+    private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
+            NODE_ID);
+
+    private static final InstanceIdentifier<Nodes> NODES_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) //
+            .toInstance();
+
+    private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier
+            .builder(NODES_INSTANCE_ID_BA) //
+            .child(Node.class, NODE_KEY).toInstance();
+
+    private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODE_INSTANCE_ID_BI = //
+    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+            .node(Nodes.QNAME) //
+            .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
+            .toInstance();
+    private DataChangeEvent<InstanceIdentifier<?>, DataObject> receivedChangeEvent;
+
+    /**
+     * Test for Bug 148
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void testAugmentSerialization() throws Exception {
+
+        baDataService.registerDataChangeListener(NODES_INSTANCE_ID_BA, this);
+
+        Node flowCapableNode = createTestNode(FlowCapableNode.class, flowCapableNodeAugmentation());
+        commitNodeAndVerifyTransaction(flowCapableNode);
+
+        assertNotNull(receivedChangeEvent);
+        verifyNode((Nodes) receivedChangeEvent.getUpdatedOperationalSubtree(), flowCapableNode);
+
+        Nodes nodes = checkForNodes();
+        verifyNode(nodes, flowCapableNode).assertHasAugmentation(FlowCapableNode.class);
+        ;
+        assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
+        Node meterStatsNode = createTestNode(NodeMeterStatistics.class, nodeMeterStatistics());
+        commitNodeAndVerifyTransaction(meterStatsNode);
+
+        assertNotNull(receivedChangeEvent);
+        verifyNode((Nodes) receivedChangeEvent.getUpdatedOperationalSubtree(), meterStatsNode);
+
+        assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
+
+        Node mergedNode = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
+
+        AugmentationVerifier.from(mergedNode) //
+                .assertHasAugmentation(FlowCapableNode.class) //
+                .assertHasAugmentation(NodeMeterStatistics.class);
+
+        assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
+
+        Node meterStatsNodeWithDuration = createTestNode(NodeMeterStatistics.class, nodeMeterStatistics(5, true));
+        commitNodeAndVerifyTransaction(meterStatsNodeWithDuration);
+
+        
+        Node nodeWithUpdatedList = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
+        AugmentationVerifier.from(nodeWithUpdatedList) //
+                .assertHasAugmentation(FlowCapableNode.class) //
+                .assertHasAugmentation(NodeMeterStatistics.class);
+        
+        List<MeterStats> meterStats = nodeWithUpdatedList.getAugmentation(NodeMeterStatistics.class).getMeterStatistics().getMeterStats();
+        assertNotNull(meterStats);
+        assertFalse(meterStats.isEmpty());
+        assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
+        testNodeRemove();
+    }
+
+    private <T extends Augmentation<Node>> Node createTestNode(Class<T> augmentationClass, T augmentation) {
+        NodeBuilder nodeBuilder = new NodeBuilder();
+        nodeBuilder.setId(new NodeId(NODE_ID));
+        nodeBuilder.setKey(NODE_KEY);
+        nodeBuilder.addAugmentation(augmentationClass, augmentation);
+        return nodeBuilder.build();
+    }
+
+    private DataModificationTransaction commitNodeAndVerifyTransaction(Node original) throws Exception {
+        DataModificationTransaction transaction = baDataService.beginTransaction();
+        transaction.putOperationalData(NODE_INSTANCE_ID_BA, original);
+        RpcResult<TransactionStatus> result = transaction.commit().get();
+        assertEquals(TransactionStatus.COMMITED, result.getResult());
+        return transaction;
+    }
+
+    private void testNodeRemove() throws Exception {
+        DataModificationTransaction transaction = baDataService.beginTransaction();
+        transaction.removeOperationalData(NODE_INSTANCE_ID_BA);
+        RpcResult<TransactionStatus> result = transaction.commit().get();
+        assertEquals(TransactionStatus.COMMITED, result.getResult());
+
+        Node node = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
+        assertNull(node);
+    }
+
+    private AugmentationVerifier<Node> verifyNode(Nodes nodes, Node original) {
+        assertNotNull(nodes);
+        assertNotNull(nodes.getNode());
+        assertEquals(1, nodes.getNode().size());
+        Node readedNode = nodes.getNode().get(0);
+        assertEquals(original.getId(), readedNode.getId());
+        assertEquals(original.getKey(), readedNode.getKey());
+        return new AugmentationVerifier<Node>(readedNode);
+    }
+
+    private void assertBindingIndependentVersion(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) {
+        CompositeNode node = biDataService.readOperationalData(nodeId);
+        assertNotNull(node);
+    }
+
+    private Nodes checkForNodes() {
+        return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA);
+    }
+
+    private NodeMeterStatistics nodeMeterStatistics() {
+        return nodeMeterStatistics(10, false);
+    }
+
+    private NodeMeterStatistics nodeMeterStatistics(int count, boolean setDuration) {
+        NodeMeterStatisticsBuilder nmsb = new NodeMeterStatisticsBuilder();
+        MeterStatisticsBuilder meterStats = new MeterStatisticsBuilder();
+
+        List<MeterStats> stats = new ArrayList<>(count);
+        for (int i = 0; i <= count; i++) {
+            MeterStatsBuilder statistic = new MeterStatsBuilder();
+            statistic.setKey(new MeterStatsKey(new MeterId((long) i)));
+            statistic.setByteInCount(new Counter64(BigInteger.valueOf(34590 + i)));
+            statistic.setFlowCount(new Counter32(4569L + i));
+
+            if (setDuration) {
+                DurationBuilder duration = new DurationBuilder();
+                duration.setNanosecond(new Counter32(70L));
+                statistic.setDuration(duration.build());
+            }
+
+            stats.add(statistic.build());
+        }
+        meterStats.setMeterStats(stats);
+        nmsb.setMeterStatistics(meterStats.build());
+        return nmsb.build();
+    }
+
+    private FlowCapableNode flowCapableNodeAugmentation() {
+        FlowCapableNodeBuilder fnub = new FlowCapableNodeBuilder();
+        fnub.setHardware("Hardware Foo");
+        fnub.setManufacturer("Manufacturer Foo");
+        fnub.setSerialNumber("Serial Foo");
+        fnub.setDescription("Description Foo");
+        fnub.setSoftware("JUnit emulated");
+        FlowCapableNode fnu = fnub.build();
+        return fnu;
+    }
+
+    @Override
+    public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        receivedChangeEvent = change;
+    }
+
+}
index 5a98767ff863bc2f446db8566a6ff5505a8312dc..56fbb9a52513c7719d8e156f5319aaeb96996766 100644 (file)
@@ -11,13 +11,16 @@ import java.util.concurrent.Executors;
 
 
 
+
+
+
+
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
@@ -26,7 +29,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
@@ -177,13 +181,11 @@ public class DOMCodecBug01Test extends AbstractDataServiceTest {
         List<Action> actionList = new ArrayList<>();
         PopMplsActionBuilder popMplsAction = new PopMplsActionBuilder();
         popMplsAction.setEthernetType(34);
-        actionList.add(new ActionBuilder().setAction(popMplsAction.build()).setOrder(10).build());
+        actionList.add(new ActionBuilder().setAction(new PopMplsActionCaseBuilder().setPopMplsAction(popMplsAction.build()).build()).setOrder(10).build());
 
         applyActions.setAction(actionList );
-        
-
 
-        instruction.setInstruction(applyActions.build());
+        instruction.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(applyActions.build()).build());
 
 
         List<Instruction> instructionList = Collections.<Instruction>singletonList(instruction.build());
@@ -207,7 +209,6 @@ public class DOMCodecBug01Test extends AbstractDataServiceTest {
         match.setLayer4Match(new TcpMatchBuilder().build());
         flow.setMatch(match.build());
         
-        System.out.println("Putting the configuration Data................");
         path1 = InstanceIdentifier.builder(Flows.class).child(Flow.class, key).toInstance();
        // DataObject cls = (DataObject) modification.readConfigurationData(path1);
         modification.putConfigurationData(path1, flow.build());
index 7111501b5392e174d25b16d456da6493cdfe3d77..ea36f81b0b940d069cc4898e5b2fcad6f2bde5de 100644 (file)
@@ -4,32 +4,12 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
-
-
-
-
-
-
-
-
-
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Future;
 
-
-
-
-
-
-
-
-
-
-
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
@@ -37,16 +17,27 @@ import org.opendaylight.controller.md.sal.common.api.data.DataModification;
 import org.opendaylight.controller.sal.binding.impl.connect.dom.CommitHandlersTransactions;
 import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DecNwTtlCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtlBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpVersion;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
@@ -56,7 +47,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
 import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
@@ -72,13 +66,16 @@ public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest {
     private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
     private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id");
     private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node");
-    private static final long FLOW_ID = 1234;
-    private static final String NODE_ID = "node:1";
-    
-    private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modificationCapture;
+    private static final QName TABLE_ID_QNAME = QName.create(Table.QNAME, "id");
 
+    private static final String NODE_ID = "node:1";
+    private static final FlowId FLOW_ID = new FlowId(1234L);
+    private static final Short TABLE_ID = Short.valueOf((short) 0);
 
     private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
+    private static final FlowKey FLOW_KEY = new FlowKey(FLOW_ID);
+
+    private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modificationCapture;
 
     private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
             NODE_ID);
@@ -93,34 +90,41 @@ public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest {
             .toInstance();
     private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
 
-    private static final FlowKey FLOW_KEY = new FlowKey(FLOW_ID, NODE_REF);
-
     private static final Map<QName, Object> FLOW_KEY_BI = //
-    ImmutableMap.<QName, Object> of(FLOW_ID_QNAME, FLOW_ID, FLOW_NODE_QNAME, NODE_INSTANCE_ID_BI);
+    ImmutableMap.<QName, Object> of(FLOW_ID_QNAME, FLOW_ID.getValue());
+
+    private static final Map<QName, Object> TABLE_KEY_BI = //
+    ImmutableMap.<QName, Object> of(TABLE_ID_QNAME, TABLE_ID);;
 
     private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier FLOW_INSTANCE_ID_BI = //
     org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
-            .node(Flows.QNAME) //
+            .node(Nodes.QNAME) //
+            .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
+            .nodeWithKey(Table.QNAME, TABLE_KEY_BI) //
             .nodeWithKey(Flow.QNAME, FLOW_KEY_BI) //
             .toInstance();
-    
-    private static final InstanceIdentifier<Flows> FLOWS_PATH_BA = //
-            InstanceIdentifier.builder(Flows.class) //
-                    .toInstance();
-            
-    
+    private static final TableKey TABLE_KEY_BA = new TableKey((short) 0);
+
+    private static final InstanceIdentifier<Flow> FLOWS_PATH_BA = //
+    InstanceIdentifier.builder(NODE_INSTANCE_ID_BA) //
+            .augmentation(FlowCapableNode.class) //
+            .child(Table.class, TABLE_KEY_BA) //
+            .child(Flow.class) //
+            .toInstance();
+
     private static final InstanceIdentifier<Flow> FLOW_INSTANCE_ID_BA = //
-    InstanceIdentifier.builder(Flows.class) //
+    InstanceIdentifier.builder(FLOWS_PATH_BA.firstIdentifierOf(Table.class)) //
             .child(Flow.class, FLOW_KEY) //
             .toInstance();
-    
+
     @Test
     public void simpleModifyOperation() throws Exception {
+
         assertNull(biDataService.readConfigurationData(FLOW_INSTANCE_ID_BI));
-        
+
         registerCommitHandler();
-        
-        CompositeNode domflow = createXmlFlow();
+
+        CompositeNode domflow = createTestFlow();
         DataModificationTransaction biTransaction = biDataService.beginTransaction();
         biTransaction.putConfigurationData(FLOW_INSTANCE_ID_BI, domflow);
         RpcResult<TransactionStatus> biResult = biTransaction.commit().get();
@@ -130,62 +134,78 @@ public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest {
         assertNotNull(flow);
         assertNotNull(flow.getMatch());
         assertEquals(TransactionStatus.COMMITED, biResult.getResult());
-        
-    }
 
-    
+    }
 
     private void registerCommitHandler() {
         DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> flowTestCommitHandler = new DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>() {
-            
-            
+
             @Override
             public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
                     DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
                 modificationCapture = modification;
                 return CommitHandlersTransactions.allwaysSuccessfulTransaction(modification);
             }
-            
-            
+
         };
-        Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> registration = baDataService.registerCommitHandler(FLOWS_PATH_BA, flowTestCommitHandler);
+        Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> registration = baDataService
+                .registerCommitHandler(FLOWS_PATH_BA, flowTestCommitHandler);
         assertNotNull(registration);
     }
-    
-    private CompositeNode createXmlFlow() {
-        
-        FlowBuilder flow = new FlowBuilder();
-        MatchBuilder match = new MatchBuilder();
-        VlanMatchBuilder vlanBuilder = new VlanMatchBuilder();
-        VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
-        VlanId vlanId = new VlanId(10);
-        vlanBuilder.setVlanId(vlanIdBuilder.setVlanId(vlanId).build());
-        match.setVlanMatch(vlanBuilder.build());
 
+    private CompositeNode createTestFlow() {
+        FlowBuilder flow = new FlowBuilder();
         flow.setKey(FLOW_KEY);
+        Short tableId = 0;
+        flow.setTableId(tableId);
+        MatchBuilder match = new MatchBuilder();
+        match.setIpMatch(new IpMatchBuilder().setIpProto(IpVersion.Ipv4).build());
+        Ipv4MatchBuilder ipv4Match = new Ipv4MatchBuilder();
+        // ipv4Match.setIpv4Destination(new Ipv4Prefix(cliInput.get(4)));
+        Ipv4Prefix prefix = new Ipv4Prefix("10.0.0.1/24");
+        ipv4Match.setIpv4Destination(prefix);
+        Ipv4Match i4m = ipv4Match.build();
+        match.setLayer3Match(i4m);
         flow.setMatch(match.build());
-        flow.setNode(NODE_REF);
-        InstructionsBuilder instructions = new InstructionsBuilder();
-        InstructionBuilder instruction = new InstructionBuilder();
-        instruction.setOrder(10);
-        ApplyActionsBuilder applyActions = new ApplyActionsBuilder();
-        List<Action> actionList = new ArrayList<>();
-        PopMplsActionBuilder popMplsAction = new PopMplsActionBuilder();
-        popMplsAction.setEthernetType(34);
-        actionList.add(new ActionBuilder().setAction(popMplsAction.build()).setOrder(0).build());
 
-        applyActions.setAction(actionList );
-        
 
 
-        instruction.setInstruction(applyActions.build());
+        // Create a drop action
+        /*
+         * Note: We are mishandling drop actions DropAction dropAction = new
+         * DropActionBuilder().build(); ActionBuilder ab = new ActionBuilder();
+         * ab.setAction(dropAction);
+         */
+
+        DecNwTtl decNwTtl = new DecNwTtlBuilder().build();
+        ActionBuilder ab = new ActionBuilder();
+        ActionKey actionKey = new ActionKey(0);
+        ab.setKey(actionKey );
+        ab.setAction(new DecNwTtlCaseBuilder().setDecNwTtl(decNwTtl).build());
+
+        // Add our drop action to a list
+        List<Action> actionList = new ArrayList<Action>();
+        actionList.add(ab.build());
+
+        // Create an Apply Action
+        ApplyActionsBuilder aab = new ApplyActionsBuilder();
+        aab.setAction(actionList);
+
+        // Wrap our Apply Action in an Instruction
+        InstructionBuilder ib = new InstructionBuilder();
+        ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
 
+        // Put our Instruction in a list of Instructions
+        InstructionsBuilder isb = new InstructionsBuilder();
+        List<Instruction> instructions = new ArrayList<Instruction>();
+        instructions.add(ib.build());
+        isb.setInstruction(instructions);
 
-        List<Instruction> instructionList = Collections.<Instruction>singletonList(instruction.build());
-        instructions.setInstruction(instructionList );
+        // Add our instructions to the flow
+        flow.setInstructions(isb.build());
 
-        flow.setInstructions(instructions.build());
-        
+        flow.setPriority(2);
+        flow.setFlowName("Foo Name");
         CompositeNode domFlow = mappingService.toDataDom(flow.build());
         return domFlow;
     }
index 338561ab48c950da06951c81bdccd033c25869ab..9b814291b934c90bc301a670d448dbb12a47be09 100644 (file)
@@ -59,14 +59,14 @@ public abstract class AbstractTest {
                 mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
                 systemProperty("osgi.bundles.defaultStartLevel").value("4"),
 
-                
-                
                 mdSalCoreBundles(),
 
                 bindingAwareSalBundles(),
                 configMinumumBundles(),
                 // BASE Models
-                baseModelBundles(), flowCapableModelBundles(), junitAndMockitoBundles());
+                baseModelBundles(), 
+                flowCapableModelBundles(), 
+                junitAndMockitoBundles());
     }
     
 }
index e46b566522e26232081cd1fd72a96d873bdebae5..54e1a065f4b45374848bbc53a27b534864d98f7d 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.sal.common.util;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -20,7 +21,7 @@ public class Rpcs {
         return ret;
     }
 
-    private static class RpcResultTO<T> implements RpcResult<T> {
+    private static class RpcResultTO<T> implements RpcResult<T>, Serializable {
 
         private final Collection<RpcError> errors;
         private final T result;
index 1fb73bc9a9fd9a1799a502051bcd1548c3917a1b..99a38ca43a5be68fd3c9bad328e20ab98d0578a4 100644 (file)
@@ -13,17 +13,24 @@ import java.util.Collections;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
 
-public abstract class AbstractConsumer implements Consumer, BundleActivator {
+public abstract class AbstractConsumer implements Consumer, BundleActivator,ServiceTrackerCustomizer<Broker, Broker> {
+
+    
+    
+    
+    private BundleContext context;
+    private ServiceTracker<Broker, Broker> tracker;
+    private Broker broker;
 
-    Broker broker;
-    ServiceReference<Broker> brokerRef;
     @Override
     public final void start(BundleContext context) throws Exception {
+        this.context = context;
         this.startImpl(context);
-        brokerRef = context.getServiceReference(Broker.class);
-        broker = context.getService(brokerRef);
-        broker.registerConsumer(this,context);
+        tracker = new ServiceTracker<>(context, Broker.class, this);
+        tracker.open();
     }
 
 
@@ -32,9 +39,7 @@ public abstract class AbstractConsumer implements Consumer, BundleActivator {
     public final void stop(BundleContext context) throws Exception {
         stopImpl(context);
         broker = null;
-        if(brokerRef != null) {
-            context.ungetService(brokerRef);
-        }
+        tracker.close();
     }
 
     protected void startImpl(BundleContext context) {
@@ -49,4 +54,25 @@ public abstract class AbstractConsumer implements Consumer, BundleActivator {
         return Collections.emptySet();
     }
 
+    
+    @Override
+    public Broker addingService(ServiceReference<Broker> reference) {
+        if(broker == null) {
+            broker = context.getService(reference);
+            broker.registerConsumer(this, context);
+            return broker;
+        }
+        
+        return null;
+    }
+    
+    @Override
+    public void modifiedService(ServiceReference<Broker> reference, Broker service) {
+        // NOOP
+    }
+    
+    @Override
+    public void removedService(ServiceReference<Broker> reference, Broker service) {
+        stopImpl(context);
+    }
 }
index 621ef92132a636aabc347e87b69f6b8ac89c3c8f..1cb1a2bc8522b65301e3f70470e2c41e06d3b32c 100644 (file)
@@ -10,16 +10,20 @@ package org.opendaylight.controller.sal.core.api;
 import java.util.Collection;
 import java.util.Collections;
 
+import javax.naming.Context;
+
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
 
-public abstract class AbstractProvider implements BundleActivator, Provider {
+public abstract class AbstractProvider implements BundleActivator, Provider,ServiceTrackerCustomizer<Broker, Broker> {
 
-    private ServiceReference<Broker> brokerRef;
     private Broker broker;
-
+    private BundleContext context;
+    private ServiceTracker<Broker, Broker> tracker;
     @Override
     public Collection<ProviderFunctionality> getProviderFunctionality() {
         return Collections.emptySet();
@@ -27,12 +31,10 @@ public abstract class AbstractProvider implements BundleActivator, Provider {
 
     @Override
     public final void start(BundleContext context) throws Exception {
-        brokerRef = context.getServiceReference(Broker.class);
-        broker = context.getService(brokerRef);
-
+        this.context = context;
         this.startImpl(context);
-
-        broker.registerProvider(this,context);
+        tracker = new ServiceTracker<>(context, Broker.class, this);
+        tracker.open();
     }
 
     protected void startImpl(BundleContext context) {
@@ -44,7 +46,31 @@ public abstract class AbstractProvider implements BundleActivator, Provider {
 
     @Override
     public final void stop(BundleContext context) throws Exception {
+        broker = null;
+        tracker.close();
+        tracker = null;
         stopImpl(context);
     }
 
+    @Override
+    public Broker addingService(ServiceReference<Broker> reference) {
+        if(broker == null) {
+            broker = context.getService(reference);
+            broker.registerProvider(this, context);
+            return broker;
+        }
+        
+        return null;
+    }
+    
+    @Override
+    public void modifiedService(ServiceReference<Broker> reference, Broker service) {
+        // NOOP
+    }
+    
+    @Override
+    public void removedService(ServiceReference<Broker> reference, Broker service) {
+        stopImpl(context);
+    }
+    
 }
index 482cfa959f2b8e11ce125a53da97d52b5990a808..dc116ca9795537e9d97a7e8de7fac804cda8b041 100644 (file)
@@ -14,6 +14,7 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 import org.opendaylight.controller.sal.core.api.data.DataStore
 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter
 import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
+import org.opendaylight.controller.sal.dom.broker.impl.RpcRouterImpl
 
 class BrokerConfigActivator implements AutoCloseable {
     
@@ -37,7 +38,7 @@ class BrokerConfigActivator implements AutoCloseable {
         val emptyProperties = new Hashtable<String, String>();
         broker.setBundleContext(context);
         
-
+        broker.setRouter(new RpcRouterImpl("Rpc router"))
         schemaService = new SchemaServiceImpl();
         schemaService.setContext(context);
         schemaService.setParser(new YangParserImpl());
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/pom.xml b/opendaylight/md-sal/sal-remoterpc-connector/implementation/pom.xml
new file mode 100644 (file)
index 0000000..b8e0938
--- /dev/null
@@ -0,0 +1,199 @@
+<?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</groupId>
+        <artifactId>sal-parent</artifactId>
+        <relativePath>../..</relativePath>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>sal-remoterpc-connector</artifactId>
+    <packaging>bundle</packaging>
+
+  <properties>
+    <zeromq.version>0.3.1</zeromq.version>
+    <jackson.version>1.9.8</jackson.version>
+    <stax.version>1.0.1</stax.version>
+  </properties>
+
+  <dependencies>
+    <!-- MD Sal interdependencies -->
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>sal-core-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>sal-connector-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>sal-common-util</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>zeromq-routingtable.implementation</artifactId>
+      <!-- TODO: fix the version. Why is it not MD Sal project version?-->
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+
+    <!-- AD Sal -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal</artifactId>
+    </dependency>
+
+    <!-- Yang tools -->
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-data-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-data-impl</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-common</artifactId>
+    </dependency>
+
+    <!-- Third Party -->
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.zeromq</groupId>
+      <artifactId>jeromq</artifactId>
+      <version>${zeromq.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
+    <dependency>
+      <groupId> org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.jackson</groupId>
+      <artifactId>jackson-core-asl</artifactId>
+      <version>${jackson.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.jackson</groupId>
+      <artifactId>jackson-mapper-asl</artifactId>
+      <version>${jackson.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>stax</groupId>
+      <artifactId>stax-api</artifactId>
+      <version>${stax.version}</version>
+    </dependency>
+
+    <!-- Tests -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-module-junit4</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-mockito</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-core</artifactId>
+    </dependency>
+
+  </dependencies>
+
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>${bundle.plugin.version}</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Import-Package>
+                            *,
+                            !org.codehaus.enunciate.jaxrs
+                        </Import-Package>
+                        <Export-Package>
+                            org.opendaylight.controller.config.yang.md.sal.remote.rpc,
+                            org.opendaylight.controller.sal.connector.remoterpc,
+                            org.opendaylight.controller.sal.connector.remoterpc.*
+                        </Export-Package>
+                        <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                    </instructions>
+                </configuration>
+            </plugin>
+           
+
+            <plugin>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <version>0.5.9-SNAPSHOT</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <codeGenerators>
+                                <generator>
+                                    <codeGeneratorClass>
+                                        org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+                                    </codeGeneratorClass>
+                                    <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
+                                    <additionalConfiguration>
+                                        <namespaceToPackage1>
+                                            urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
+                                        </namespaceToPackage1>
+                                    </additionalConfiguration>
+                                </generator>
+                                <generator>
+                                    <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
+                                    <outputBaseDir>target/site/models</outputBaseDir>
+                                </generator>
+                            </codeGenerators>
+                            <inspectDependencies>true</inspectDependencies>
+                        </configuration>
+                    </execution>
+                </executions>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.opendaylight.controller</groupId>
+                        <artifactId>yang-jmx-generator-plugin</artifactId>
+                        <version>0.2.3-SNAPSHOT</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>org.opendaylight.yangtools</groupId>
+                        <artifactId>maven-sal-api-gen-plugin</artifactId>
+                        <version>0.6.0-SNAPSHOT</version>
+                        <type>jar</type>
+                    </dependency>
+                </dependencies>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/remote/rpc/ZeroMQServerModule.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/remote/rpc/ZeroMQServerModule.java
new file mode 100644 (file)
index 0000000..606f282
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+* Generated file
+
+* Generated from: yang module name: odl-sal-dom-rpc-remote-cfg  yang module local name: remote-zeromq-rpc-server
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Dec 05 14:25:21 CET 2013
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.md.sal.remote.rpc;
+
+import org.opendaylight.controller.sal.connector.remoterpc.Client;
+import org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcProvider;
+import org.opendaylight.controller.sal.connector.remoterpc.RoutingTableProvider;
+import org.opendaylight.controller.sal.connector.remoterpc.ServerImpl;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.osgi.framework.BundleContext;
+
+/**
+*
+*/
+public final class ZeroMQServerModule extends org.opendaylight.controller.config.yang.md.sal.remote.rpc.AbstractZeroMQServerModule
+ {
+
+    private static final Integer ZEROMQ_ROUTER_PORT = 5554;
+    private BundleContext bundleContext;
+
+    public ZeroMQServerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public ZeroMQServerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            ZeroMQServerModule oldModule, java.lang.AutoCloseable oldInstance) {
+
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    protected void customValidation(){
+        // Add custom validation for module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        
+        Broker broker = getDomBrokerDependency();
+        RoutingTableProvider provider = new RoutingTableProvider(bundleContext);
+        
+        
+        final int port = getPort() != null ? getPort() : ZEROMQ_ROUTER_PORT;
+
+        ServerImpl serverImpl = new ServerImpl(port);
+        
+        Client clientImpl = new Client();
+        RemoteRpcProvider facade = new RemoteRpcProvider(serverImpl, clientImpl);
+        
+        facade.setRoutingTableProvider(provider );
+        
+        broker.registerProvider(facade, bundleContext);
+        return facade;
+    }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/remote/rpc/ZeroMQServerModuleFactory.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/remote/rpc/ZeroMQServerModuleFactory.java
new file mode 100644 (file)
index 0000000..3cc3ac0
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+* Generated file
+
+* Generated from: yang module name: odl-sal-dom-rpc-remote-cfg  yang module local name: remote-zeromq-rpc-server
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Dec 05 14:25:21 CET 2013
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.md.sal.remote.rpc;
+
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
+import org.opendaylight.controller.config.spi.Module;
+import org.osgi.framework.BundleContext;
+
+/**
+*
+*/
+public class ZeroMQServerModuleFactory extends org.opendaylight.controller.config.yang.md.sal.remote.rpc.AbstractZeroMQServerModuleFactory
+{
+
+    @Override
+    public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
+        ZeroMQServerModule module = (ZeroMQServerModule) super.createModule(instanceName, dependencyResolver, bundleContext);
+        module.setBundleContext(bundleContext);
+        return module;
+    }
+    
+    @Override
+    public Module createModule(String instanceName, DependencyResolver dependencyResolver,
+            DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception {
+        ZeroMQServerModule module = (ZeroMQServerModule) super.createModule(instanceName, dependencyResolver, old,bundleContext);
+        module.setBundleContext(bundleContext);
+        return module;
+    }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Client.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Client.java
new file mode 100644 (file)
index 0000000..ef31623
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2013 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.connector.remoterpc;
+
+import com.google.common.base.Optional;
+
+import org.opendaylight.controller.sal.common.util.RpcErrors;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.MessageWrapper;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
+import org.opendaylight.controller.sal.connector.remoterpc.util.XmlUtils;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.*;
+
+import static com.google.common.base.Preconditions.*;
+
+/**
+ * An implementation of {@link RpcImplementation} that makes remote RPC calls
+ */
+public class Client implements RemoteRpcClient {
+
+    private final Logger _logger = LoggerFactory.getLogger(Client.class);
+
+    private final LinkedBlockingQueue<MessageWrapper> requestQueue = new LinkedBlockingQueue<MessageWrapper>(100);
+
+    private final ExecutorService pool = Executors.newSingleThreadExecutor();
+    private final long TIMEOUT = 5000; // in ms
+
+    private  RoutingTableProvider routingTableProvider;
+
+    public RoutingTableProvider getRoutingTableProvider() {
+        return routingTableProvider;
+    }
+
+    public void setRoutingTableProvider(RoutingTableProvider routingTableProvider) {
+        this.routingTableProvider = routingTableProvider;
+    }
+
+    public LinkedBlockingQueue<MessageWrapper> getRequestQueue() {
+        return requestQueue;
+    }
+
+    @Override
+    public Set<QName> getSupportedRpcs() {
+        // TODO: Find the entries from routing table
+        return Collections.emptySet();
+    }
+
+    public void start() {
+        pool.execute(new Sender(this));
+
+    }
+
+    public void stop() {
+
+        _logger.debug("Client stopping...");
+        Context.getInstance().getZmqContext().term();
+        _logger.debug("ZMQ context terminated");
+
+        pool.shutdown(); // intiate shutdown
+        try {
+            if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
+                pool.shutdownNow();
+                if (!pool.awaitTermination(10, TimeUnit.SECONDS))
+                    _logger.error("Client thread pool did not shut down");
+            }
+        } catch (InterruptedException e) {
+            // (Re-)Cancel if current thread also interrupted
+            pool.shutdownNow();
+            // Preserve interrupt status
+            Thread.currentThread().interrupt();
+        }
+        _logger.debug("Client stopped");
+    }
+
+    @Override
+    public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
+
+        RouteIdentifierImpl routeId = new RouteIdentifierImpl();
+        routeId.setType(rpc);
+
+        String address = lookupRemoteAddress(routeId);
+
+        Message request = new Message.MessageBuilder().type(Message.MessageType.REQUEST)
+                .sender(Context.getInstance().getLocalUri()).recipient(address).route(routeId)
+                .payload(XmlUtils.compositeNodeToXml(input)).build();
+
+        List<RpcError> errors = new ArrayList<RpcError>();
+
+        try (SocketPair pair = new SocketPair()) {
+
+            MessageWrapper messageWrapper = new MessageWrapper(request, pair.getSender());
+            process(messageWrapper);
+            Message response = parseMessage(pair.getReceiver());
+
+            CompositeNode payload = XmlUtils.xmlToCompositeNode((String) response.getPayload());
+
+            return Rpcs.getRpcResult(true, payload, errors);
+
+        } catch (Exception e) {
+            collectErrors(e, errors);
+            return Rpcs.getRpcResult(false, null, errors);
+        }
+
+    }
+
+    public void process(MessageWrapper msg) throws TimeoutException, InterruptedException {
+        _logger.debug("Processing message [{}]", msg);
+
+        boolean success = requestQueue.offer(msg, TIMEOUT, TimeUnit.MILLISECONDS);
+        if (!success)
+            throw new TimeoutException("Queue is full");
+    }
+
+    /**
+     * Block on socket for reply
+     * 
+     * @param receiver
+     * @return
+     */
+    private Message parseMessage(ZMQ.Socket receiver) throws IOException, ClassNotFoundException {
+        return (Message) Message.deserialize(receiver.recv());
+    }
+
+    /**
+     * Find address for the given route identifier in routing table
+     * 
+     * @param routeId
+     *            route identifier
+     * @return remote network address
+     */
+    private String lookupRemoteAddress(RpcRouter.RouteIdentifier routeId) {
+        checkNotNull(routeId, "route must not be null");
+
+        Optional<RoutingTable<String, String>> routingTable = routingTableProvider.getRoutingTable();
+        checkNotNull(routingTable.isPresent(), "Routing table is null");
+
+        Set<String> addresses = routingTable.get().getRoutes(routeId.toString());
+        checkNotNull(addresses, "Address not found for route [%s]", routeId);
+        checkState(addresses.size() == 1, "Multiple remote addresses found for route [%s], \nonly 1 expected", routeId); // its
+                                                                                                                         // a
+                                                                                                                         // global
+                                                                                                                         // service.
+
+        String address = addresses.iterator().next();
+        checkNotNull(address, "Address not found for route [%s]", routeId);
+
+        return address;
+    }
+
+    private void collectErrors(Exception e, List<RpcError> errors) {
+        if (e == null)
+            return;
+        if (errors == null)
+            errors = new ArrayList<RpcError>();
+
+        errors.add(RpcErrors.getRpcError(null, null, null, null, e.getMessage(), null, e.getCause()));
+        for (Throwable t : e.getSuppressed()) {
+            errors.add(RpcErrors.getRpcError(null, null, null, null, t.getMessage(), null, t));
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        stop();
+    }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Context.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Context.java
new file mode 100644 (file)
index 0000000..f0bf12c
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013 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.connector.remoterpc;
+
+import org.zeromq.ZMQ;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Enumeration;
+
+/**
+ * Provides a ZeroMQ Context object
+ */
+public class Context {
+  private ZMQ.Context zmqContext = ZMQ.context(1);
+  private String uri;
+
+  private static Context _instance = new Context();
+
+  private Context() {}
+
+  public static Context getInstance(){
+    return _instance;
+  }
+
+  public ZMQ.Context getZmqContext(){
+    return this.zmqContext;
+  }
+
+  public String getLocalUri(){
+    uri = (uri != null) ? uri
+            : new StringBuilder("tcp://").append(getIpAddress()).append(":")
+              .append(getRpcPort()).toString();
+
+    return uri;
+  }
+
+  public String getRpcPort(){
+    String rpcPort = (System.getProperty("rpc.port") != null)
+        ? System.getProperty("rpc.port")
+        : "5554";
+
+    return rpcPort;
+  }
+
+  private String getIpAddress(){
+    String ipAddress = (System.getProperty("local.ip") != null)
+        ? System.getProperty("local.ip")
+        : findIpAddress();
+
+    return ipAddress;
+  }
+
+  /**
+   * Finds IPv4 address of the local VM
+   * TODO: This method is non-deterministic. There may be more than one IPv4 address. Cant say which
+   * address will be returned. Read IP from a property file or enhance the code to make it deterministic.
+   * Should we use IP or hostname?
+   *
+   * @return
+   */
+  private String findIpAddress() {
+    String hostAddress = null;
+    Enumeration e = null;
+    try {
+      e = NetworkInterface.getNetworkInterfaces();
+    } catch (SocketException e1) {
+      e1.printStackTrace();
+    }
+    while (e.hasMoreElements()) {
+
+      NetworkInterface n = (NetworkInterface) e.nextElement();
+
+      Enumeration ee = n.getInetAddresses();
+      while (ee.hasMoreElements()) {
+        InetAddress i = (InetAddress) ee.nextElement();
+        if ((i instanceof Inet4Address) && (i.isSiteLocalAddress()))
+          hostAddress = i.getHostAddress();
+      }
+    }
+    return hostAddress;
+
+  }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcClient.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcClient.java
new file mode 100644 (file)
index 0000000..6bd123b
--- /dev/null
@@ -0,0 +1,13 @@
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+
+public interface RemoteRpcClient extends RpcImplementation,AutoCloseable{
+
+
+    void setRoutingTableProvider(RoutingTableProvider provider);
+    
+    void stop();
+    
+    void start();
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProvider.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProvider.java
new file mode 100644 (file)
index 0000000..3c2e3b0
--- /dev/null
@@ -0,0 +1,95 @@
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+
+import org.opendaylight.controller.sal.connector.remoterpc.Client;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.Provider.ProviderFunctionality;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public class RemoteRpcProvider implements 
+    RemoteRpcServer,
+    RemoteRpcClient,
+    Provider {
+
+    private final ServerImpl server;
+    private final Client client;
+    private RoutingTableProvider provider;
+
+    @Override
+    public void setRoutingTableProvider(RoutingTableProvider provider) {
+        this.provider = provider;
+        server.setRoutingTableProvider(provider);
+        client.setRoutingTableProvider(provider);
+    }
+    
+    @Override
+    public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
+        return client.invokeRpc(rpc, input);
+    }
+    
+    @Override
+    public Set<QName> getSupportedRpcs() {
+        return client.getSupportedRpcs();
+    }
+    
+    
+    public RemoteRpcProvider(ServerImpl server, Client client) {
+        this.server = server;
+        this.client = client;
+    }
+    
+    public void setBrokerSession(ProviderSession session) {
+        server.setBrokerSession(session);
+    }
+    public void setServerPool(ExecutorService serverPool) {
+        server.setServerPool(serverPool);
+    }
+    public void start() {
+        client.setRoutingTableProvider(provider);
+        server.setRoutingTableProvider(provider);
+        server.start();
+        client.start();
+    }
+    public void onRouteUpdated(String key, Set values) {
+        server.onRouteUpdated(key, values);
+    }
+    public void onRouteDeleted(String key) {
+        server.onRouteDeleted(key);
+    }
+    
+    
+    @Override
+    public Collection<ProviderFunctionality> getProviderFunctionality() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+    
+    
+    @Override
+    public void onSessionInitiated(ProviderSession session) {
+        server.setBrokerSession(session);
+        start();
+    }
+    
+    
+    public void close() throws Exception {
+        server.close();
+        client.close();
+    }
+
+    
+    
+    
+    @Override
+    public void stop() {
+        server.stop();
+        client.stop();
+    }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcServer.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcServer.java
new file mode 100644 (file)
index 0000000..932600f
--- /dev/null
@@ -0,0 +1,6 @@
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+
+public interface RemoteRpcServer extends AutoCloseable {
+
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RoutingTableProvider.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RoutingTableProvider.java
new file mode 100644 (file)
index 0000000..cfdf986
--- /dev/null
@@ -0,0 +1,32 @@
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
+import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
+
+import com.google.common.base.Optional;
+
+public class RoutingTableProvider implements AutoCloseable {
+
+    @SuppressWarnings("rawtypes")
+    final ServiceTracker<RoutingTable,RoutingTable> tracker;
+    
+    
+    public RoutingTableProvider(BundleContext ctx) {
+        @SuppressWarnings("rawtypes")
+        ServiceTracker<RoutingTable, RoutingTable> rawTracker = new ServiceTracker<>(ctx, RoutingTable.class, null);
+        tracker = rawTracker;
+        tracker.open();
+    }
+    
+    public Optional<RoutingTable<String, String>> getRoutingTable() {
+        @SuppressWarnings("unchecked")
+        RoutingTable<String,String> tracked = tracker.getService();
+        return Optional.fromNullable(tracked);
+    }
+
+    @Override
+    public void close() throws Exception {
+        tracker.close();
+    }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RpcSocket.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RpcSocket.java
new file mode 100644 (file)
index 0000000..7e8590a
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2013 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.connector.remoterpc;
+
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.MessageWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
+import java.io.IOException;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * A class encapsulating {@link ZMQ.Socket} of type {@link ZMQ.REQ}.
+ * It adds following capabilities:
+ * <li> Retry logic - Tries 3 times before giving up
+ * <li> Request times out after {@link TIMEOUT} property
+ * <li> The limitation of {@link ZMQ.REQ}/{@link ZMQ.REP} pair is that no 2 requests can be sent before
+ * the response for the 1st request is received. To overcome that, this socket queues all messages until
+ * the previous request has been responded.
+ */
+public class RpcSocket {
+
+  // Constants
+  public static final int TIMEOUT = 2000;
+  public static final int QUEUE_SIZE = 10;
+  public static final int NUM_RETRIES = 3;
+  private static final Logger log = LoggerFactory.getLogger(RpcSocket.class);
+
+  private ZMQ.Socket socket;
+  private ZMQ.Poller poller;
+  private String address;
+  private SocketState state;
+  private long sendTime;
+  private int retriesLeft;
+  private LinkedBlockingQueue<MessageWrapper> inQueue;
+
+
+  public RpcSocket(String address, ZMQ.Poller poller) {
+    this.socket = null;
+    this.state = new IdleSocketState();
+    this.sendTime = -1;
+    this.retriesLeft = NUM_RETRIES;
+    this.inQueue = new LinkedBlockingQueue<MessageWrapper>(QUEUE_SIZE);
+    this.address = address;
+    this.poller = poller;
+    createSocket();
+  }
+
+  public ZMQ.Socket getSocket() {
+    return socket;
+  }
+
+  public String getAddress() {
+    return address;
+  }
+
+  public int getRetriesLeft() {
+    return retriesLeft;
+  }
+
+  public void setRetriesLeft(int retriesLeft) {
+    this.retriesLeft = retriesLeft;
+  }
+
+  public SocketState getState() {
+    return state;
+  }
+
+  public void setState(SocketState state) {
+    this.state = state;
+  }
+
+  public int getQueueSize() {
+    return inQueue.size();
+  }
+
+  public MessageWrapper removeCurrentRequest() {
+    return inQueue.poll();
+  }
+
+  public boolean hasTimedOut() {
+    return (System.currentTimeMillis() - sendTime > RpcSocket.TIMEOUT);
+  }
+
+  public void send(MessageWrapper request) throws TimeoutException {
+    try {
+      boolean success = inQueue.offer(request, TIMEOUT, TimeUnit.MILLISECONDS);    
+      if (!success) {
+        throw new TimeoutException("send :: Queue is full");
+      }
+      process();
+    }
+    catch (InterruptedException e) {
+      log.error("send : Thread interrupted while attempting to add request to inQueue", e);
+    }
+  }
+  
+  public MessageWrapper receive() {
+    Message response = parseMessage();
+    MessageWrapper messageWrapper = inQueue.poll(); //remove the message from queue
+    MessageWrapper responseMessageWrapper = new MessageWrapper(response, messageWrapper.getReceiveSocket());
+
+    state = new IdleSocketState();
+    retriesLeft = NUM_RETRIES;
+    return responseMessageWrapper;
+  }
+  
+  public void process() {
+    if (getQueueSize() > 0) //process if there's message in the queue
+      state.process(this);
+  }
+
+  // Called by IdleSocketState & BusySocketState
+  public void sendMessage() {
+    //Get the message from queue without removing it. For retries
+    MessageWrapper messageWrapper = inQueue.peek();
+    if (messageWrapper != null) {
+      Message message = messageWrapper.getMessage();
+      try {
+        socket.send(Message.serialize(message));
+      }
+      catch (IOException e) {
+        log.debug("Message send failed [{}]", message);
+        log.debug("Exception [{}]", e);
+      }
+      sendTime = System.currentTimeMillis();
+    }
+  }
+  
+  public Message parseMessage() {
+    Message parsedMessage = null;
+    byte[] bytes = socket.recv();
+    log.debug("Received bytes:[{}]", bytes.length);
+    try {
+      parsedMessage = (Message)Message.deserialize(bytes);
+    }
+    catch (IOException|ClassNotFoundException e) {
+      log.debug("parseMessage : Deserializing received bytes failed", e);
+    }
+
+    return parsedMessage;
+  }
+
+  public void recycleSocket() {
+    close();
+  }
+
+  public void close() {
+    socket.setLinger(10);
+    socket.close();
+  }
+
+  private void createSocket() {
+    socket = Context.getInstance().getZmqContext().socket(ZMQ.REQ);
+    socket.connect(address);
+    poller.register(socket, ZMQ.Poller.POLLIN);
+    state = new IdleSocketState();
+  }
+
+
+  /**
+   * Represents the state of a {@link org.opendaylight.controller.sal.connector.remoterpc.RpcSocket}
+   */
+  public static interface SocketState {
+
+    /* The processing actions to be performed in this state
+     */
+    public void process(RpcSocket socket);
+  }
+
+  /**
+   * Represents the idle state of a {@link org.opendaylight.controller.sal.connector.remoterpc.RpcSocket}
+   */
+  public static class IdleSocketState implements SocketState {
+
+    @Override
+    public void process(RpcSocket socket) {
+      socket.sendMessage();
+      socket.setState(new BusySocketState());
+      socket.setRetriesLeft(socket.getRetriesLeft()-1);
+    }
+  }
+
+  /**
+   * Represents the busy state of a {@link org.opendaylight.controller.sal.connector.remoterpc.RpcSocket}
+   */
+  public static class BusySocketState implements SocketState {
+
+    private static Logger log = LoggerFactory.getLogger(BusySocketState.class);
+
+    @Override
+    public void process(RpcSocket socket) {
+      if (socket.hasTimedOut()) {
+        if (socket.getRetriesLeft() > 0) {
+          log.debug("process : Request timed out, retrying now...");
+          socket.sendMessage();
+          socket.setRetriesLeft(socket.getRetriesLeft() - 1);
+        }
+        else {
+          // No more retries for current request, so stop processing the current request
+          MessageWrapper message = socket.removeCurrentRequest();
+          if (message != null) {
+            log.error("Unable to process rpc request [{}]", message);
+            socket.setState(new IdleSocketState());
+            socket.setRetriesLeft(NUM_RETRIES);
+          }
+        }
+      }
+      // Else no timeout, so allow processing to continue
+    }
+  }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Sender.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Sender.java
new file mode 100644 (file)
index 0000000..f53d5ad
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2013 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.connector.remoterpc;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.MessageWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
+import java.io.IOException;
+import java.util.concurrent.TimeoutException;
+
+import static com.google.common.base.Preconditions.*;
+
+/**
+ * Main server thread for sending requests.
+ */
+public class Sender implements Runnable{
+
+  private final static Logger _logger = LoggerFactory.getLogger(Sender.class);
+  private final Client client;
+
+
+  
+  
+  public Sender(Client client) {
+    super();
+    this.client = client;
+  }
+
+@Override
+  public void run() {
+    _logger.info("Starting...");
+
+    try (SocketManager socketManager = new SocketManager()){
+      while (!Thread.currentThread().isInterrupted()) {
+
+        //read incoming messages from blocking queue
+        MessageWrapper request = pollForRequest();
+
+        if (request != null) {
+          processRequest(socketManager, request);
+        }
+
+        flushSockets(socketManager);
+        pollForResponse(socketManager);
+        processResponse(socketManager);
+
+      }
+    } catch(Exception t){
+      _logger.error("Exception: [{}]", t);
+      _logger.error("Stopping...");
+    }
+  }
+
+  private void processResponse(SocketManager socketManager) {
+    for (int i = 0; i < socketManager.getPoller().getSize(); i++) {
+      // If any sockets get a response, process it
+      if (socketManager.getPoller().pollin(i)) {
+        Optional<RpcSocket> socket = socketManager.getManagedSocketFor(
+            socketManager.getPoller().getItem(i).getSocket());
+
+        checkState(socket.isPresent(), "Managed socket not found");
+
+        MessageWrapper response = socket.get().receive();
+        _logger.debug("Received rpc response [{}]", response.getMessage());
+
+        //TODO: handle exception and introduce timeout on receiver side
+        try {
+          response.getReceiveSocket().send(Message.serialize(response.getMessage()));
+        } catch (IOException e) {
+          e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+        }
+      }
+    }
+  }
+
+  private void processRequest(SocketManager socketManager, MessageWrapper request) throws TimeoutException {
+
+    if ((request.getMessage() == null) ||
+        (request.getMessage().getRecipient() == null)) {
+      //invalid message. log and drop
+      _logger.error("Invalid request [{}]", request);
+      return;
+    }
+
+    RpcSocket socket =
+        socketManager.getManagedSocket(request.getMessage().getRecipient());
+
+    socket.send(request);
+  }
+
+  private void flushSockets(SocketManager socketManager){
+    for (RpcSocket socket : socketManager.getManagedSockets()){
+      socket.process();
+    }
+  }
+
+  private MessageWrapper pollForRequest(){
+    return client.getRequestQueue().poll();
+  }
+
+  private void pollForResponse(SocketManager socketManager){
+    try{
+      socketManager.getPoller().poll(10); //poll every 10ms
+    }catch (Throwable t) { /*Ignore and continue*/ }
+  }
+}
+
+
+/*
+SCALA
+
+package org.opendaylight.controller.sal.connector.remoterpc
+
+  import org.slf4j.{LoggerFactory, Logger}
+  import scala.collection.JavaConverters._
+  import scala.Some
+  import org.opendaylight.controller.sal.connector.remoterpc.dto.{MessageWrapper, Message}
+*/
+/**
+ * Main server thread for sending requests. This does not maintain any state. If the
+ * thread dies, it will be restarted
+ */
+/*class Sender extends Runnable {
+  private val _logger: Logger = LoggerFactory.getLogger(Sender.this.getClass())
+
+  override def run = {
+    _logger.info("Sender starting...")
+    val socketManager = new SocketManager()
+
+    try {
+      while (!Thread.currentThread().isInterrupted) {
+        //read incoming messages from blocking queue
+        val request: MessageWrapper = Client.requestQueue.poll()
+
+        if (request != null) {
+          if ((request.message != null) &&
+            (request.message.getRecipient != null)) {
+
+            val socket = socketManager.getManagedSocket(request.message.getRecipient)
+            socket.send(request)
+          } else {
+            //invalid message. log and drop
+            _logger.error("Invalid request [{}]", request)
+          }
+        }
+
+        socketManager.getManagedSockets().asScala.map(s => s.process)
+
+        // Poll all sockets for responses every 1 sec
+        poll(socketManager)
+
+        // If any sockets get a response, process it
+        for (i <- 0 until socketManager.poller.getSize) {
+          if (socketManager.poller.pollin(i)) {
+            val socket = socketManager.getManagedSocketFor(socketManager.poller.getItem(i).getSocket)
+
+            socket match {
+              case None => //{
+                _logger.error("Could not find a managed socket for zmq socket")
+                throw new IllegalStateException("Could not find a managed socket for zmq socket")
+                //}
+              case Some(s) => {
+                val response = s.receive()
+                _logger.debug("Received rpc response [{}]", response.message)
+                response.receiveSocket.send(Message.serialize(response.message))
+              }
+            }
+          }
+        }
+
+      }
+    } catch{
+      case e:Exception => {
+        _logger.debug("Sender stopping due to exception")
+        e.printStackTrace()
+      }
+    } finally {
+      socketManager.stop
+    }
+  }
+
+  def poll(socketManager:SocketManager) = {
+    try{
+      socketManager.poller.poll(10)
+    }catch{
+      case t:Throwable => //ignore and continue
+    }
+  }
+}
+
+
+//    def newThread(r: Runnable): Thread = {
+//      val t = new RequestHandler()
+//      t.setUncaughtExceptionHandler(new RequestProcessorExceptionHandler)
+//      t
+//    }
+
+
+
+/**
+ * Restarts the request processing server in the event of unforeseen exceptions
+ */
+//private class RequestProcessorExceptionHandler extends UncaughtExceptionHandler {
+//  def uncaughtException(t: Thread, e: Throwable) = {
+//    _logger.error("Exception caught during request processing [{}]", e)
+//    _logger.info("Restarting request processor server...")
+//    RequestProcessor.start()
+//  }
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ServerImpl.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ServerImpl.java
new file mode 100644 (file)
index 0000000..83b9385
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2013 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.connector.remoterpc;
+
+import com.google.common.base.Optional;
+
+import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException;
+import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message.MessageType;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
+import org.opendaylight.controller.sal.connector.remoterpc.util.XmlUtils;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+/**
+ * ZeroMq based implementation of RpcRouter TODO: 1. Make rpc request handling
+ * async and non-blocking. Note zmq socket is not thread safe 2. Read properties
+ * from config file using existing(?) ODL properties framework
+ */
+public class ServerImpl implements RemoteRpcServer, RouteChangeListener<String, Set> {
+
+    private Logger _logger = LoggerFactory.getLogger(ServerImpl.class);
+
+    private ExecutorService serverPool;
+
+    // private RoutingTable<RpcRouter.RouteIdentifier, String> routingTable;
+    private RoutingTableProvider routingTable;
+    private Set<QName> remoteServices;
+    private ProviderSession brokerSession;
+    private ZMQ.Context context;
+    private ZMQ.Socket replySocket;
+
+    private final RpcListener listener = new RpcListener();
+
+    private final String localUri = Context.getInstance().getLocalUri();
+
+    private final int rpcPort;
+
+    private RpcImplementation client;
+
+    public RpcImplementation getClient() {
+        return client;
+    }
+
+    public void setClient(RpcImplementation client) {
+        this.client = client;
+    }
+
+    // Prevent instantiation
+    public ServerImpl(int rpcPort) {
+        this.rpcPort = rpcPort;
+    }
+
+    public void setBrokerSession(ProviderSession session) {
+        this.brokerSession = session;
+    }
+
+    public ExecutorService getServerPool() {
+        return serverPool;
+    }
+
+    public void setServerPool(ExecutorService serverPool) {
+        this.serverPool = serverPool;
+    }
+
+    public void start() {
+        context = ZMQ.context(1);
+        serverPool = Executors.newSingleThreadExecutor();
+        remoteServices = new HashSet<QName>();
+
+        // Start listening rpc requests
+        serverPool.execute(receive());
+
+        brokerSession.addRpcRegistrationListener(listener);
+        // routingTable.registerRouteChangeListener(routeChangeListener);
+
+        Set<QName> currentlySupported = brokerSession.getSupportedRpcs();
+        for (QName rpc : currentlySupported) {
+            listener.onRpcImplementationAdded(rpc);
+        }
+
+        _logger.debug("RPC Server started [{}]", localUri);
+    }
+
+    public void stop() {
+        // TODO: un-subscribe
+
+        // if (context != null)
+        // context.term();
+        //
+        // _logger.debug("ZMQ Context is terminated.");
+
+        if (serverPool != null)
+            serverPool.shutdown();
+
+        _logger.debug("Thread pool is closed.");
+    }
+
+    private Runnable receive() {
+        return new Runnable() {
+            public void run() {
+
+                // Bind to RPC reply socket
+                replySocket = context.socket(ZMQ.REP);
+                replySocket.bind("tcp://*:" + Context.getInstance().getRpcPort());
+
+                // Poller enables listening on multiple sockets using a single
+                // thread
+                ZMQ.Poller poller = new ZMQ.Poller(1);
+                poller.register(replySocket, ZMQ.Poller.POLLIN);
+                try {
+                    // TODO: Add code to restart the thread after exception
+                    while (!Thread.currentThread().isInterrupted()) {
+
+                        poller.poll();
+
+                        if (poller.pollin(0)) {
+                            handleRpcCall();
+                        }
+                    }
+                } catch (Exception e) {
+                    // log and continue
+                    _logger.error("Unhandled exception [{}]", e);
+                } finally {
+                    poller.unregister(replySocket);
+                    replySocket.close();
+                }
+
+            }
+        };
+    }
+
+    /**
+     * @throws InterruptedException
+     * @throws ExecutionException
+     */
+    private void handleRpcCall() {
+
+        Message request = parseMessage(replySocket);
+
+        _logger.debug("Received rpc request [{}]", request);
+
+        // Call broker to process the message then reply
+        Future<RpcResult<CompositeNode>> rpc = null;
+        RpcResult<CompositeNode> result = null;
+        try {
+            rpc = brokerSession.rpc((QName) request.getRoute().getType(),
+                    XmlUtils.xmlToCompositeNode((String) request.getPayload()));
+
+            result = (rpc != null) ? rpc.get() : null;
+
+        } catch (Exception e) {
+            _logger.debug("Broker threw  [{}]", e);
+        }
+
+        CompositeNode payload = (result != null) ? result.getResult() : null;
+
+        Message response = new Message.MessageBuilder().type(MessageType.RESPONSE).sender(localUri)
+                .route(request.getRoute()).payload(XmlUtils.compositeNodeToXml(payload)).build();
+
+        _logger.debug("Sending rpc response [{}]", response);
+
+        try {
+            replySocket.send(Message.serialize(response));
+        } catch (Exception e) {
+            _logger.debug("rpc response send failed for message [{}]", response);
+            _logger.debug("{}", e);
+        }
+
+    }
+
+    /**
+     * @param socket
+     * @return
+     */
+    private Message parseMessage(ZMQ.Socket socket) {
+
+        Message msg = null;
+        try {
+            byte[] bytes = socket.recv();
+            _logger.debug("Received bytes:[{}]", bytes.length);
+            msg = (Message) Message.deserialize(bytes);
+        } catch (Throwable t) {
+            t.printStackTrace();
+        }
+        return msg;
+    }
+
+    @Override
+    public void onRouteUpdated(String key, Set values) {
+        RouteIdentifierImpl rId = new RouteIdentifierImpl();
+        try {
+            _logger.debug("Updating key/value {}-{}", key, values);
+            brokerSession.addRpcImplementation((QName) rId.fromString(key).getType(), client);
+
+        } catch (Exception e) {
+            _logger.info("Route update failed {}", e);
+        }
+    }
+
+    @Override
+    public void onRouteDeleted(String key) {
+        // TODO: Broker session needs to be updated to support this
+        throw new UnsupportedOperationException();
+    }
+    
+    /**
+     * Listener for rpc registrations
+     */
+    private class RpcListener implements RpcRegistrationListener {
+
+        
+
+        @Override
+        public void onRpcImplementationAdded(QName name) {
+
+            // if the service name exists in the set, this notice
+            // has bounced back from the broker. It should be ignored
+            if (remoteServices.contains(name))
+                return;
+
+            _logger.debug("Adding registration for [{}]", name);
+            RouteIdentifierImpl routeId = new RouteIdentifierImpl();
+            routeId.setType(name);
+
+            try {
+                routingTable.getRoutingTable().get().addGlobalRoute(routeId.toString(), localUri);
+                _logger.debug("Route added [{}-{}]", name, localUri);
+            } catch (RoutingTableException | SystemException e) {
+                // TODO: This can be thrown when route already exists in the
+                // table. Broker
+                // needs to handle this.
+                _logger.error("Unhandled exception while adding global route to routing table [{}]", e);
+
+            }
+        }
+
+        @Override
+        public void onRpcImplementationRemoved(QName name) {
+
+            _logger.debug("Removing registration for [{}]", name);
+            RouteIdentifierImpl routeId = new RouteIdentifierImpl();
+            routeId.setType(name);
+
+            try {
+                routingTable.getRoutingTable().get().removeGlobalRoute(routeId.toString());
+            } catch (RoutingTableException | SystemException e) {
+                _logger.error("Route delete failed {}", e);
+            }
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        stop();
+    }
+
+    public void setRoutingTableProvider(RoutingTableProvider provider) {
+        this.routingTable = provider;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/SocketManager.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/SocketManager.java
new file mode 100644 (file)
index 0000000..588a299
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013 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.connector.remoterpc;
+
+import com.google.common.base.Optional;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+import java.net.UnknownHostException;
+import java.util.Collection;
+import java.util.concurrent.ConcurrentHashMap;
+
+
+/**
+ * Manages creation of {@link RpcSocket} and their registration with {@link ZMQ.Poller}
+ */
+public class SocketManager implements AutoCloseable{
+  private static final Logger log = LoggerFactory.getLogger(SocketManager.class);
+
+  /*
+   * RpcSockets mapped by network address its connected to
+   */
+  private ConcurrentHashMap<String, RpcSocket> managedSockets = new ConcurrentHashMap<String, RpcSocket>();
+
+  private ZMQ.Poller _poller = new ZMQ.Poller(2); //randomly selected size. Poller grows automatically
+
+  /**
+   * Returns a {@link RpcSocket} for the given address
+   * @param address network address with port eg: 10.199.199.20:5554
+   * @return
+   */
+  public RpcSocket getManagedSocket(String address) throws IllegalArgumentException {
+    //Precondition
+    if (!address.matches("(tcp://)(.*)(:)(\\d*)")) {
+      throw new IllegalArgumentException("Address must of format 'tcp://<ip address>:<port>' but is " + address);
+    }
+
+    if (!managedSockets.containsKey(address)) {
+      log.debug("{} Creating new socket for {}", Thread.currentThread().getName());
+      RpcSocket socket = new RpcSocket(address, _poller);
+      managedSockets.put(address, socket);
+    }
+
+    return managedSockets.get(address);
+  }
+
+  /**
+   * Returns a {@link RpcSocket} for the given {@link ZMQ.Socket}
+   * @param socket
+   * @return
+   */
+  public Optional<RpcSocket> getManagedSocketFor(ZMQ.Socket socket) {
+    for (RpcSocket rpcSocket : managedSockets.values()) {
+      if (rpcSocket.getSocket().equals(socket)) {
+        return Optional.of(rpcSocket);
+      }
+    }
+    return Optional.absent();
+  }
+
+  /**
+   * Return a collection of all managed sockets
+   * @return
+   */
+  public Collection<RpcSocket> getManagedSockets() {
+    return managedSockets.values();
+  }
+
+  /**
+   * Returns the {@link ZMQ.Poller}
+   * @return
+   */
+  public ZMQ.Poller getPoller() {
+    return _poller;
+  }
+
+  /**
+   * This should be called when stopping the server to close all the sockets
+   * @return
+   */
+  @Override
+  public void close() throws Exception {
+    log.debug("Stopping...");
+    for (RpcSocket socket : managedSockets.values()) {
+      socket.close();
+    }
+    managedSockets.clear();
+    log.debug("Stopped");
+  }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/SocketPair.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/SocketPair.java
new file mode 100644 (file)
index 0000000..67b3a83
--- /dev/null
@@ -0,0 +1,41 @@
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+import org.zeromq.ZMQ;
+
+import java.util.UUID;
+
+/**
+ *
+ */
+public class SocketPair implements AutoCloseable{
+  private ZMQ.Socket sender;
+  private ZMQ.Socket receiver;
+
+  private static final String INPROC_PREFIX = "inproc://";
+
+  public SocketPair(){
+    String address = new StringBuilder(INPROC_PREFIX)
+                         .append(UUID.randomUUID())
+                         .toString();
+
+    receiver = Context.getInstance().getZmqContext().socket(ZMQ.PAIR);
+    receiver.bind(address);
+
+    sender = Context.getInstance().getZmqContext().socket(ZMQ.PAIR);
+    sender.connect(address);
+  }
+
+  public ZMQ.Socket getSender(){
+    return this.sender;
+  }
+
+  public ZMQ.Socket getReceiver(){
+    return this.receiver;
+  }
+
+  @Override
+  public void close() throws Exception {
+    sender.close();
+    receiver.close();
+  }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/CompositeNodeImpl.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/CompositeNodeImpl.java
new file mode 100644 (file)
index 0000000..073601a
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2013 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.connector.remoterpc.dto;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.*;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class CompositeNodeImpl implements CompositeNode, Serializable {
+
+  private QName key;
+  private List<Node<?>> children;
+
+  @Override
+  public List<Node<?>> getChildren() {
+    return children;
+  }
+
+  @Override
+  public List<CompositeNode> getCompositesByName(QName children) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public List<CompositeNode> getCompositesByName(String children) {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public List<SimpleNode<?>> getSimpleNodesByName(QName children) {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public List<SimpleNode<?>> getSimpleNodesByName(String children) {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public CompositeNode getFirstCompositeByName(QName container) {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public SimpleNode<?> getFirstSimpleByName(QName leaf) {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public MutableCompositeNode asMutable() {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public QName getKey() {
+    return key;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public List<Node<?>> setValue(List<Node<?>> value) {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public int size() {
+    return 0;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public boolean isEmpty() {
+    return false;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public boolean containsKey(Object key) {
+    return false;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public boolean containsValue(Object value) {
+    return false;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public List<Node<?>> get(Object key) {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public List<Node<?>> put(QName key, List<Node<?>> value) {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public List<Node<?>> remove(Object key) {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public void putAll(Map<? extends QName, ? extends List<Node<?>>> m) {
+    //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public void clear() {
+    //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public Set<QName> keySet() {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public Collection<List<Node<?>>> values() {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public Set<Entry<QName, List<Node<?>>>> entrySet() {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public QName getNodeType() {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public CompositeNode getParent() {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public List<Node<?>> getValue() {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  @Override
+  public ModifyAction getModificationAction() {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+}
@@ -6,10 +6,8 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.controller.sal.connector.remoterpc.router.zeromq;
+package org.opendaylight.controller.sal.connector.remoterpc.dto;
 
-
-import org.codehaus.jackson.map.ObjectMapper;
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 
 import java.io.*;
@@ -20,7 +18,8 @@ public class Message implements Serializable {
     ANNOUNCE((byte) 0),  //TODO: Remove announce, add rpc registration and deregistration
     HEARTBEAT((byte) 1),
     REQUEST((byte) 2),
-    RESPONSE((byte) 3);
+    RESPONSE((byte) 3),
+    ERROR((byte)4);
 
     private final byte type;
 
@@ -35,6 +34,7 @@ public class Message implements Serializable {
 
   private MessageType type;
   private String sender;
+  private String recipient;
   private RpcRouter.RouteIdentifier route;
   private Object payload;
 
@@ -70,11 +70,19 @@ public class Message implements Serializable {
     this.payload = payload;
   }
 
+  public String getRecipient() {
+    return recipient;
+  }
+
+  public void setRecipient(String recipient) {
+    this.recipient = recipient;
+  }
   @Override
   public String toString() {
     return "Message{" +
         "type=" + type +
         ", sender='" + sender + '\'' +
+        ", recipient='" + recipient + '\'' +
         ", route=" + route +
         ", payload=" + payload +
         '}';
@@ -108,17 +116,6 @@ public class Message implements Serializable {
     return o.readObject();
   }
 
-  public static byte[] toJsonBytes(Message m) throws IOException {
-    ObjectMapper o = new ObjectMapper();
-    return o.writeValueAsBytes(m);
-  }
-
-  public static Message fromJsonBytes(byte [] bytes) throws IOException {
-
-    ObjectMapper o = new ObjectMapper();
-    return o.readValue(bytes, Message.class);
-  }
-
   public static class Response extends Message implements RpcRouter.RpcReply {
     private ResponseCode code; // response code
 
@@ -163,6 +160,11 @@ public class Message implements Serializable {
       return this;
     }
 
+    public MessageBuilder recipient(String recipient){
+      message.setRecipient(recipient);
+      return this;
+    }
+
     public MessageBuilder route(RpcRouter.RouteIdentifier route){
       message.setRoute(route);
       return this;
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/MessageWrapper.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/MessageWrapper.java
new file mode 100644 (file)
index 0000000..8d2198c
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 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.connector.remoterpc.dto;
+
+import org.zeromq.ZMQ;
+
+/**
+ * A class encapsulating {@link Message} and the {@link ZMQ.Socket} over which it is transmitted
+ */
+public class MessageWrapper {
+
+  private Message _message;
+  private ZMQ.Socket _receiveSocket;
+  
+  public MessageWrapper(Message message, ZMQ.Socket receiveSocket) {
+    this._message = message;
+    this._receiveSocket = receiveSocket;
+  }
+
+  public Message getMessage() {
+    return _message;
+  }
+
+  public ZMQ.Socket getReceiveSocket() {
+    return _receiveSocket;
+  }
+}
@@ -5,19 +5,21 @@
  * 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.connector.remoterpc.router.zeromq;
+package org.opendaylight.controller.sal.connector.remoterpc.dto;
 
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.ObjectMapper;
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 
 import java.io.Serializable;
+import java.net.URI;
 
-/**
- * User: abhishk2
- */
 public class RouteIdentifierImpl implements RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>,Serializable {
 
+  transient ObjectMapper mapper = new ObjectMapper();
+
   private QName context;
   private QName type;
   private InstanceIdentifier route;
@@ -51,10 +53,35 @@ public class RouteIdentifierImpl implements RpcRouter.RouteIdentifier<QName, QNa
 
   @Override
   public String toString() {
-    return "RouteIdentifierImpl{" +
-        "context=" + context +
-        ", type=" + type +
-        ", route=" + route +
-        '}';
+    try {
+      return mapper.writeValueAsString(this);
+    } catch (Throwable e) {
+      //do nothing
+    }
+
+    return super.toString();
+  }
+
+  public RpcRouter.RouteIdentifier fromString(String input)
+      throws Exception {
+
+    JsonNode root = mapper.readTree(input);
+    this.context  = parseQName(root.get("context"));
+    this.type     = parseQName(root.get("type"));
+
+    return this;
+  }
+
+  private QName parseQName(JsonNode node){
+    if (node == null) return null;
+
+    String namespace = (node.get("namespace") != null) ?
+                       node.get("namespace").asText()  : "";
+
+    String localName = (node.get("localName") != null) ?
+                       node.get("localName").asText() : "";
+
+    URI uri = URI.create(namespace);
+    return new QName(uri, localName);
   }
 }
@@ -5,7 +5,7 @@
  * 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.connector.remoterpc.router.zeromq;
+package org.opendaylight.controller.sal.connector.remoterpc.dto;
 
 import org.opendaylight.controller.sal.connector.api.RpcRouter;
 import org.opendaylight.yangtools.yang.common.QName;
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/util/XmlUtils.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/util/XmlUtils.java
new file mode 100644 (file)
index 0000000..7dab2e3
--- /dev/null
@@ -0,0 +1,63 @@
+package org.opendaylight.controller.sal.connector.remoterpc.util;
+
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeUtils;
+import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.ByteArrayInputStream;
+import java.io.StringWriter;
+
+public class XmlUtils {
+
+  private static final Logger _logger = LoggerFactory.getLogger(XmlUtils.class);
+
+  public static String compositeNodeToXml(CompositeNode cNode){
+    if (cNode == null) return new String();
+
+    Document domTree = NodeUtils.buildShadowDomTree(cNode);
+    StringWriter writer = new StringWriter();
+    try {
+      TransformerFactory tf = TransformerFactory.newInstance();
+      Transformer transformer = tf.newTransformer();
+      transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+      transformer.transform(new DOMSource(domTree), new StreamResult(writer));
+    } catch (TransformerException e) {
+      _logger.error("Error during translation of Document to OutputStream", e);
+    }
+
+    return writer.toString();
+  }
+
+  public static CompositeNode xmlToCompositeNode(String xml){
+    if (xml==null || xml.length()==0) return null;
+
+    Node<?> dataTree;
+    try {
+      dataTree = XmlTreeBuilder.buildDataTree(new ByteArrayInputStream(xml.getBytes()));
+    } catch (XMLStreamException e) {
+      _logger.error("Error during building data tree from XML", e);
+      return null;
+    }
+    if (dataTree == null) {
+      _logger.error("data tree is null");
+      return null;
+    }
+    if (dataTree instanceof SimpleNode) {
+      _logger.error("RPC XML was resolved as SimpleNode");
+      return null;
+    }
+    return (CompositeNode) dataTree;
+  }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/scala/org/opendaylight/controller/sal/connector/remoterpc/Client.scala b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/scala/org/opendaylight/controller/sal/connector/remoterpc/Client.scala
new file mode 100644 (file)
index 0000000..63b6808
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2013 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.connector.remoterpc
+
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.common.{RpcError, RpcResult, QName}
+import org.opendaylight.controller.sal.core.api.RpcImplementation
+import java.util
+import java.util.{UUID, Collections}
+import org.zeromq.ZMQ
+import org.opendaylight.controller.sal.common.util.{RpcErrors, Rpcs}
+import org.slf4j.LoggerFactory
+import org.opendaylight.controller.sal.connector.remoterpc.dto.{MessageWrapper, RouteIdentifierImpl, Message}
+import Message.MessageType
+import java.util.concurrent._
+import java.lang.InterruptedException
+
+
+/**
+ * An implementation of {@link RpcImplementation} that makes
+ * remote RPC calls
+ */
+class Client extends RemoteRpcClient {
+
+  private val _logger = LoggerFactory.getLogger(this.getClass);
+
+  val requestQueue = new LinkedBlockingQueue[MessageWrapper](100)
+  val pool: ExecutorService = Executors.newSingleThreadExecutor()
+  private val TIMEOUT = 5000 //in ms
+  var routingTableProvider: RoutingTableProvider = null
+  
+  
+  def getInstance = this
+
+  
+  def setRoutingTableProvider(provider : RoutingTableProvider) = {
+    routingTableProvider = provider;
+  }
+  
+  def getSupportedRpcs: util.Set[QName] = {
+    Collections.emptySet()
+  }
+
+  def invokeRpc(rpc: QName, input: CompositeNode): RpcResult[CompositeNode] = {
+
+    val routeId = new RouteIdentifierImpl()
+    routeId.setType(rpc)
+
+    //lookup address for the rpc request
+    val routingTable = routingTableProvider.getRoutingTable()
+    require( routingTable != null, "Routing table not found. Exiting" )
+
+    val addresses:util.Set[String] = routingTable.getRoutes(routeId.toString)
+    require(addresses != null, "Address not found for rpc " + rpc);
+    require(addresses.size() == 1) //its a global service.
+
+    val address = addresses.iterator().next()
+    require(address != null, "Address is null")
+
+    //create in-process "pair" socket and pass it to sender thread
+    //Sender replies on this when result is available
+    val inProcAddress = "inproc://" + UUID.randomUUID()
+    val receiver = Context.zmqContext.socket(ZMQ.PAIR)
+    receiver.bind(inProcAddress);
+
+    val sender = Context.zmqContext.socket(ZMQ.PAIR)
+    sender.connect(inProcAddress)
+
+    val requestMessage = new Message.MessageBuilder()
+      .`type`(MessageType.REQUEST)
+      //.sender("tcp://localhost:8081")
+      .recipient(address)
+      .route(routeId)
+      .payload(input)
+      .build()
+
+    _logger.debug("Queuing up request and expecting response on [{}]", inProcAddress)
+
+    val messageWrapper = new MessageWrapper(requestMessage, sender)
+    val errors = new util.ArrayList[RpcError]
+
+    try {
+      process(messageWrapper)
+      val response = parseMessage(receiver)
+
+      return Rpcs.getRpcResult(
+        true, response.getPayload.asInstanceOf[CompositeNode], Collections.emptySet())
+
+    } catch {
+      case e: Exception => {
+        errors.add(RpcErrors.getRpcError(null,null,null,null,e.getMessage,null,e.getCause))
+        return Rpcs.getRpcResult(false, null, errors)
+      }
+    } finally {
+      receiver.close();
+      sender.close();
+    }
+
+  }
+
+  /**
+   * Block on socket for reply
+   * @param receiver
+   * @return
+   */
+  private def parseMessage(receiver:ZMQ.Socket): Message = {
+    val bytes = receiver.recv()
+    return  Message.deserialize(bytes).asInstanceOf[Message]
+  }
+
+  def start() = {
+    pool.execute(new Sender)
+  }
+
+  def process(msg: MessageWrapper) = {
+    _logger.debug("Processing message [{}]", msg)
+    val success = requestQueue.offer(msg, TIMEOUT, TimeUnit.MILLISECONDS)
+
+    if (!success) throw new TimeoutException("Queue is full");
+
+  }
+
+  def stop() = {
+    pool.shutdown() //intiate shutdown
+    _logger.debug("Client stopping...")
+    //    Context.zmqContext.term();
+    //    _logger.debug("ZMQ context terminated")
+
+    try {
+
+      if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
+        pool.shutdownNow();
+        if (!pool.awaitTermination(10, TimeUnit.SECONDS))
+          _logger.error("Client thread pool did not shut down");
+      }
+    } catch {
+      case ie:InterruptedException =>
+        // (Re-)Cancel if current thread also interrupted
+        pool.shutdownNow();
+        // Preserve interrupt status
+        Thread.currentThread().interrupt();
+    }
+    _logger.debug("Client stopped")
+  }
+  
+  def close() = {
+    stop();
+  }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/yang/odl-sal-dom-rpc-remote-cfg.yang b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/yang/odl-sal-dom-rpc-remote-cfg.yang
new file mode 100644 (file)
index 0000000..d20efe5
--- /dev/null
@@ -0,0 +1,52 @@
+module odl-sal-dom-rpc-remote-cfg {
+       yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc";
+    prefix "rpc-cluster";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import opendaylight-md-sal-dom {prefix dom;}
+    
+    description
+        "Service definition for Binding Aware MD-SAL.";
+    revision "2013-10-28" {
+        description
+            "Initial revision";
+    }
+
+    identity remote-rpc-server {
+        base config:service-type;
+        config:java-class "org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcServer";
+    }
+
+    identity remote-rpc-client {
+        base config:service-type;
+        config:java-class "org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcClient";
+    }
+
+    identity remote-zeromq-rpc-server {
+        base config:module-type;
+        config:provided-service remote-rpc-server;
+        config:provided-service remote-rpc-client;
+        config:java-name-prefix ZeroMQServer;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case remote-zeromq-rpc-server {
+            when "/config:modules/config:module/config:type = 'remote-zeromq-rpc-server'";
+            
+            container dom-broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity dom:dom-broker-osgi-registry;
+                    }
+                }
+            }
+            
+            leaf port {
+                type uint16;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientTest.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientTest.java
new file mode 100644 (file)
index 0000000..2e77537
--- /dev/null
@@ -0,0 +1,56 @@
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.MessageWrapper;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+
+import java.util.concurrent.TimeoutException;
+
+public class ClientTest {
+
+    Client client;
+    
+  @Before
+  public void setup(){
+      client = new Client();
+      client.getRequestQueue().clear();
+  }
+
+  @Test
+  public void testStop() throws Exception {
+
+  }
+
+  @Test
+  public void testPool() throws Exception {
+
+  }
+
+  @Test
+  public void process_AddAMessage_ShouldAddToQueue() throws Exception {
+    client.process(getEmptyMessageWrapper());
+    Assert.assertEquals(1, client.getRequestQueue().size());
+  }
+
+  /**
+   * Queue size is 100. Adding 101 message should time out in 2 sec
+   * if server does not process it
+   * @throws Exception
+   */
+  @Test(expected = TimeoutException.class)
+  public void process_Add101Message_ShouldThrow() throws Exception {
+    for (int i=0;i<101;i++){
+      client.process(getEmptyMessageWrapper());
+    }
+  }
+
+  @Test
+  public void testStart() throws Exception {
+  }
+
+  private MessageWrapper getEmptyMessageWrapper(){
+    return new MessageWrapper(new Message(), null);
+  }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/RouteIdentifierImplTest.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/RouteIdentifierImplTest.java
new file mode 100644 (file)
index 0000000..550d9ef
--- /dev/null
@@ -0,0 +1,50 @@
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+import org.codehaus.jackson.JsonParseException;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URI;
+
+public class RouteIdentifierImplTest {
+
+  Logger _logger = LoggerFactory.getLogger(RouteIdentifierImplTest.class);
+
+  private final URI namespace = URI.create("http://cisco.com/example");
+  private final QName QNAME = new QName(namespace, "heartbeat");
+
+  @Test
+  public void testToString() throws Exception {
+    RouteIdentifierImpl rId = new RouteIdentifierImpl();
+    rId.setType(QNAME);
+
+    _logger.debug(rId.toString());
+
+    Assert.assertTrue(true);
+
+  }
+
+  @Test
+  public void testFromString() throws Exception {
+    RouteIdentifierImpl rId = new RouteIdentifierImpl();
+    rId.setType(QNAME);
+
+    _logger.debug("route: " + rId.fromString(rId.toString()));
+
+    Assert.assertTrue(true);
+  }
+
+  @Test(expected = JsonParseException.class)
+  public void testFromInvalidString() throws Exception {
+    String invalidInput = "aklhdgadfa;;;;;;;]]]]=]ag" ;
+    RouteIdentifierImpl rId = new RouteIdentifierImpl();
+    rId.fromString(invalidInput);
+
+    _logger.debug("" + rId);
+    Assert.assertTrue(true);
+  }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/RpcSocketTest.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/RpcSocketTest.java
new file mode 100644 (file)
index 0000000..e23a3ca
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2013 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.connector.remoterpc;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.MessageWrapper;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.zeromq.ZMQ;
+
+import java.util.concurrent.TimeoutException;
+
+import static org.mockito.Mockito.doNothing;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(RpcSocket.class)
+public class RpcSocketTest {
+  RpcSocket rpcSocket = new RpcSocket("tcp://localhost:5554", new ZMQ.Poller(1));
+  RpcSocket spy = PowerMockito.spy(rpcSocket);
+
+  @Test
+  public void testCreateSocket() throws Exception {
+    Assert.assertEquals("tcp://localhost:5554", spy.getAddress());
+    Assert.assertEquals(ZMQ.REQ, spy.getSocket().getType());
+  }
+
+  @Test(expected = TimeoutException.class)
+  public void send_WhenQueueGetsFull_ShouldThrow() throws Exception {
+
+    doNothing().when(spy).process();
+
+    //10 is queue size
+    for (int i=0;i<10;i++){
+      spy.send(getEmptyMessageWrapper());
+    }
+
+    //sending 11th message should throw
+    spy.send(getEmptyMessageWrapper());
+  }
+
+  @Test
+  public void testHasTimedOut() throws Exception {
+    spy.send(getEmptyMessageWrapper());
+    Assert.assertFalse(spy.hasTimedOut());
+    Thread.sleep(1000);
+    Assert.assertFalse(spy.hasTimedOut());
+    Thread.sleep(1000);
+    Assert.assertTrue(spy.hasTimedOut());
+  }
+
+  @Test
+  public void testProcess() throws Exception {
+    PowerMockito.doNothing().when(spy, "sendMessage");
+    spy.send(getEmptyMessageWrapper());
+
+    //Next message should get queued
+    spy.send(getEmptyMessageWrapper());
+
+    //queue size should be 2
+    Assert.assertEquals(2, spy.getQueueSize());
+
+
+    spy.process();
+    //sleep for 2 secs (timeout)
+    //message send would be retried
+    Thread.sleep(2000);
+    spy.process();
+    Thread.sleep(2000);
+    spy.process();
+    Thread.sleep(2000);
+    spy.process(); //retry fails, next message will get picked up
+    Assert.assertEquals(1, spy.getQueueSize());
+  }
+
+  @Test
+  public void testProcessStateTransitions() throws Exception {
+    PowerMockito.doNothing().when(spy, "sendMessage");
+    Assert.assertTrue(spy.getState() instanceof RpcSocket.IdleSocketState);
+    spy.send(getEmptyMessageWrapper());
+    Assert.assertEquals(1, spy.getQueueSize());
+    Thread.sleep(200);
+    Assert.assertTrue(spy.getState() instanceof RpcSocket.BusySocketState);
+    Thread.sleep(1800);
+
+    //1st timeout, 2nd try
+    spy.process();
+    Thread.sleep(200);
+    Assert.assertTrue(spy.getState() instanceof RpcSocket.BusySocketState);
+    Thread.sleep(1800);
+
+    //2nd timeout, 3rd try
+    spy.process();
+    Thread.sleep(200);
+    Assert.assertTrue(spy.getState() instanceof RpcSocket.BusySocketState);
+    Thread.sleep(1800);
+
+    //3rd timeout, no more tries => remove
+    spy.process();
+    Thread.sleep(200);
+    Assert.assertTrue(spy.getState() instanceof RpcSocket.IdleSocketState);
+    Assert.assertEquals(0, spy.getQueueSize());
+  }
+
+  @Test
+  public void testParseMessage() throws Exception {
+    // Write an integration test for parseMessage
+  }
+
+  @Test
+  public void testRecycleSocket() throws Exception {
+    // This will need to be updated in the future...for now, recycleSocket() calls close()
+    Assert.assertTrue(spy.getSocket().base().check_tag());
+    spy.close();
+    Assert.assertEquals(10, spy.getSocket().getLinger());
+    Assert.assertFalse(spy.getSocket().base().check_tag());
+  }
+
+  @Test
+  public void testClose() throws Exception {
+    Assert.assertTrue(spy.getSocket().base().check_tag());
+    spy.close();
+    Assert.assertEquals(10, spy.getSocket().getLinger());
+    Assert.assertFalse(spy.getSocket().base().check_tag());
+  }
+
+  @Test
+  public void testReceive() throws Exception {
+    PowerMockito.doReturn(null).when(spy, "parseMessage");
+    PowerMockito.doNothing().when(spy, "process");
+    spy.send(getEmptyMessageWrapper());
+
+    //There should be 1 message waiting in the queue
+    Assert.assertEquals(1, spy.getQueueSize());
+
+    spy.receive();
+    //This should complete message processing
+    //The message should be removed from the queue
+    Assert.assertEquals(0, spy.getQueueSize());
+    Assert.assertEquals(RpcSocket.NUM_RETRIES, spy.getRetriesLeft());
+
+  }
+
+  @Test
+  public void testReceiveStateTransitions() throws Exception {
+    PowerMockito.doReturn(null).when(spy, "parseMessage");
+    Assert.assertTrue(spy.getState() instanceof RpcSocket.IdleSocketState);
+    spy.send(getEmptyMessageWrapper());
+
+    //There should be 1 message waiting in the queue
+    Assert.assertEquals(1, spy.getQueueSize());
+    Assert.assertTrue(spy.getState() instanceof RpcSocket.BusySocketState);
+
+    spy.receive();
+    //This should complete message processing
+    //The message should be removed from the queue
+    Assert.assertEquals(0, spy.getQueueSize());
+    Assert.assertTrue(spy.getState() instanceof RpcSocket.IdleSocketState);
+  }
+
+  private MessageWrapper getEmptyMessageWrapper(){
+    return new MessageWrapper(new Message(), null);
+  }
+
+  @Test
+  public void testProcessReceiveSequence() throws Exception {
+    PowerMockito.doNothing().when(spy, "sendMessage");
+    PowerMockito.doReturn(null).when(spy, "parseMessage");
+    Assert.assertTrue(spy.getState() instanceof RpcSocket.IdleSocketState);
+    spy.send(getEmptyMessageWrapper());
+    spy.send(getEmptyMessageWrapper());
+    Assert.assertEquals(2, spy.getQueueSize());
+    Assert.assertTrue(spy.getState() instanceof RpcSocket.BusySocketState);
+
+
+    Thread.sleep(2000);
+    Assert.assertTrue(spy.getState() instanceof RpcSocket.BusySocketState);
+    spy.receive();
+    Assert.assertTrue(spy.getState() instanceof RpcSocket.IdleSocketState);
+    Assert.assertEquals(1, spy.getQueueSize());
+
+    spy.process();
+    Assert.assertTrue(spy.getState() instanceof RpcSocket.BusySocketState);
+    spy.receive();
+    Assert.assertTrue(spy.getState() instanceof RpcSocket.IdleSocketState);
+    Assert.assertEquals(0, spy.getQueueSize());
+  }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/SerilizationTest.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/SerilizationTest.java
new file mode 100644 (file)
index 0000000..36a4acd
--- /dev/null
@@ -0,0 +1,79 @@
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeUtils;
+import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.StringWriter;
+
+public class SerilizationTest {
+
+  private static final Logger _logger = LoggerFactory.getLogger(SerilizationTest.class);
+
+  public void fromXml() {
+  }
+
+  @Test
+  public void toXml() throws FileNotFoundException {
+
+    InputStream xmlStream = SerilizationTest.class.getResourceAsStream("/FourSimpleChildren.xml");
+    StringWriter writer = new StringWriter();
+
+    CompositeNode data = loadCompositeNode(xmlStream);
+    Document domTree = NodeUtils.buildShadowDomTree(data);
+    try {
+      TransformerFactory tf = TransformerFactory.newInstance();
+      Transformer transformer = tf.newTransformer();
+      transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+      //transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+      //transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+      //transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+      //transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+      transformer.transform(new DOMSource(domTree), new StreamResult(writer));
+    } catch (TransformerException e) {
+      _logger.error("Error during translation of Document to OutputStream", e);
+    }
+
+    _logger.info("Parsed xml [{}]", writer.toString());
+  }
+
+  //Note to self:  Stolen from TestUtils
+  ///Users/alefan/odl/controller4/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
+  // Figure out how to include TestUtils through pom ...was getting errors
+  private CompositeNode loadCompositeNode(InputStream xmlInputStream) throws FileNotFoundException {
+    if (xmlInputStream == null) {
+      throw new IllegalArgumentException();
+    }
+    Node<?> dataTree;
+    try {
+      dataTree = XmlTreeBuilder.buildDataTree(xmlInputStream);
+    } catch (XMLStreamException e) {
+      _logger.error("Error during building data tree from XML", e);
+      return null;
+    }
+    if (dataTree == null) {
+      _logger.error("data tree is null");
+      return null;
+    }
+    if (dataTree instanceof SimpleNode) {
+      _logger.error("RPC XML was resolved as SimpleNode");
+      return null;
+    }
+    return (CompositeNode) dataTree;
+  }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/SocketManagerTest.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/SocketManagerTest.java
new file mode 100644 (file)
index 0000000..130b30d
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2013 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.connector.remoterpc;
+
+import com.google.common.base.Optional;
+import junit.framework.Assert;
+import org.junit.After;
+import org.junit.Before;
+import org.zeromq.ZMQ;
+import org.opendaylight.controller.sal.connector.remoterpc.SocketManager;
+import org.opendaylight.controller.sal.connector.remoterpc.RpcSocket;
+import org.opendaylight.controller.sal.connector.remoterpc.Context;
+import org.junit.Test;
+
+public class SocketManagerTest {
+
+  SocketManager manager;
+
+  @Before
+  public void setup(){
+    manager = new SocketManager();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    manager.close();
+  }
+
+  @Test
+  public void getManagedSockets_When2NewAdded_ShouldContain2() throws Exception {
+
+    //Prepare data
+    manager.getManagedSocket("tcp://localhost:5554");
+    manager.getManagedSocket("tcp://localhost:5555");
+
+    Assert.assertTrue( 2 == manager.getManagedSockets().size());
+  }
+
+  @Test
+  public void getManagedSockets_When2NewAddedAnd1Existing_ShouldContain2() throws Exception {
+
+    //Prepare data
+    manager.getManagedSocket("tcp://localhost:5554");
+    manager.getManagedSocket("tcp://localhost:5555");
+    manager.getManagedSocket("tcp://localhost:5554"); //ask for the first one
+
+    Assert.assertTrue( 2 == manager.getManagedSockets().size());
+  }
+
+  @Test
+  public void getManagedSocket_WhenPassedAValidAddress_ShouldReturnARpcSocket() throws Exception {
+    String testAddress = "tcp://localhost:5554";
+    RpcSocket rpcSocket = manager.getManagedSocket(testAddress);
+    Assert.assertEquals(testAddress, rpcSocket.getAddress());
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void getManagedSocket_WhenPassedInvalidHostAddress_ShouldThrow() throws Exception {
+    String testAddress = "tcp://nonexistenthost:5554";
+    RpcSocket rpcSocket = manager.getManagedSocket(testAddress);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void getManagedSocket_WhenPassedInvalidAddress_ShouldThrow() throws Exception {
+    String testAddress = "xxx";
+    RpcSocket rpcSocket = manager.getManagedSocket(testAddress);
+  }
+
+  @Test
+  public void getManagedSocket_WhenPassedAValidZmqSocket_ShouldReturnARpcSocket() throws Exception {
+    //Prepare data
+    String firstAddress = "tcp://localhost:5554";
+    RpcSocket firstRpcSocket = manager.getManagedSocket(firstAddress);
+    ZMQ.Socket firstZmqSocket = firstRpcSocket.getSocket();
+
+    String secondAddress = "tcp://localhost:5555";
+    RpcSocket secondRpcSocket = manager.getManagedSocket(secondAddress);
+    ZMQ.Socket secondZmqSocket = secondRpcSocket.getSocket();
+
+    Assert.assertEquals(firstRpcSocket, manager.getManagedSocketFor(firstZmqSocket).get());
+    Assert.assertEquals(secondRpcSocket, manager.getManagedSocketFor(secondZmqSocket).get());
+  }
+
+  @Test
+  public void getManagedSocket_WhenPassedNonManagedZmqSocket_ShouldReturnNone() throws Exception {
+    ZMQ.Socket nonManagedSocket = Context.getInstance().getZmqContext().socket(ZMQ.REQ);
+    nonManagedSocket.connect("tcp://localhost:5000");
+
+    //Prepare data
+    String firstAddress = "tcp://localhost:5554";
+    RpcSocket firstRpcSocket = manager.getManagedSocket(firstAddress);
+    ZMQ.Socket firstZmqSocket = firstRpcSocket.getSocket();
+
+    Assert.assertSame(Optional.<RpcSocket>absent(), manager.getManagedSocketFor(nonManagedSocket) );
+    Assert.assertSame(Optional.<RpcSocket>absent(), manager.getManagedSocketFor(null) );
+  }
+
+  @Test
+  public void stop_WhenCalled_ShouldEmptyManagedSockets() throws Exception {
+    manager.getManagedSocket("tcp://localhost:5554");
+    manager.getManagedSocket("tcp://localhost:5555");
+    Assert.assertTrue( 2 == manager.getManagedSockets().size());
+
+    manager.close();
+    Assert.assertTrue( 0 == manager.getManagedSockets().size());
+  }
+
+  @Test
+  public void poller_WhenCalled_ShouldReturnAnInstanceOfPoller() throws Exception {
+    Assert.assertTrue (manager.getPoller() instanceof ZMQ.Poller);
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/resources/FourSimpleChildren.xml b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/resources/FourSimpleChildren.xml
new file mode 100644 (file)
index 0000000..5ac991b
--- /dev/null
@@ -0,0 +1,6 @@
+<rpc>
+    <name>eth0</name>
+    <type>ethernetCsmacd</type>
+    <enabled>false</enabled>
+    <description>some interface</description>
+</rpc>
similarity index 87%
rename from opendaylight/md-sal/test/zeromq-test-consumer/pom.xml
rename to opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/pom.xml
index 7c6bc21b46f5cdfa08aa1ca294809cd6eb50468a..fa7b73be0e96a7b43e4c1a5952ec8d0b72e9fa77 100644 (file)
@@ -2,11 +2,11 @@
     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>
-        <artifactId>sal-test-parent</artifactId>
+        <artifactId>sal-remoterpc-connector-test-parent</artifactId>
         <groupId>org.opendaylight.controller.tests</groupId>
         <version>1.0-SNAPSHOT</version>
     </parent>
-    <artifactId>zeromq-test-consumer</artifactId>
+    <artifactId>sal-remoterpc-connector-test-consumer</artifactId>
     <packaging>bundle</packaging>
     <scm>
         <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
                 <configuration>
                     <instructions>
                         <Bundle-Activator>org.opendaylight.controller.sample.zeromq.consumer.ExampleConsumer</Bundle-Activator>
-                        <Import-Package>
-                            org.opendaylight.controller.sal.core.api,
-                            org.opendaylight.yangtools.yang.common;version="[0.5,1)",
-                            org.opendaylight.yangtools.yang.data.api,
-                        </Import-Package>
                     </instructions>
                 </configuration>
             </plugin>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-data-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-impl</artifactId>
+            <version>0.5.9-SNAPSHOT</version>
+        </dependency>
 
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/java/org/opendaylight/controller/sample/zeromq/consumer/ExampleConsumer.java b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/java/org/opendaylight/controller/sample/zeromq/consumer/ExampleConsumer.java
new file mode 100644 (file)
index 0000000..87078ea
--- /dev/null
@@ -0,0 +1,122 @@
+package org.opendaylight.controller.sample.zeromq.consumer;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Hashtable;
+import java.util.concurrent.*;
+
+import org.opendaylight.controller.sal.core.api.AbstractConsumer;
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
+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.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+
+import javax.xml.stream.XMLStreamException;
+
+public class ExampleConsumer extends AbstractConsumer {
+
+  private final URI namespace = URI.create("http://cisco.com/example");
+  private final QName QNAME = new QName(namespace, "heartbeat");
+
+  private ConsumerSession session;
+
+  private ServiceRegistration<ExampleConsumer> thisReg;
+  private Logger _logger = LoggerFactory.getLogger(ExampleConsumer.class);
+
+  @Override
+  public void onSessionInitiated(ConsumerSession session) {
+    this.session = session;
+  }
+
+  public RpcResult<CompositeNode> invokeRpc(QName qname, CompositeNode input) {
+    _logger.info("Invoking RPC:[{}] with Input:[{}]", qname.getLocalName(), input);
+    RpcResult<CompositeNode> result = null;
+    Future<RpcResult<CompositeNode>> future = ExampleConsumer.this.session.rpc(qname, input);
+    try {
+      result = future.get();
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    _logger.info("Returning Result:[{}]", result);
+    return result;
+  }
+
+  @Override
+  protected void startImpl(BundleContext context){
+    thisReg = context.registerService(ExampleConsumer.class, this, new Hashtable<String,String>());
+  }
+  @Override
+  protected void stopImpl(BundleContext context) {
+    super.stopImpl(context);
+    thisReg.unregister();
+  }
+
+  public CompositeNode getValidCompositeNodeWithOneSimpleChild() throws FileNotFoundException {
+    InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/OneSimpleChild.xml");
+    return loadCompositeNode(xmlStream);
+  }
+
+  public CompositeNode getValidCompositeNodeWithTwoSimpleChildren() throws FileNotFoundException {
+    InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/TwoSimpleChildren.xml");
+    return loadCompositeNode(xmlStream);
+  }
+
+  public CompositeNode getValidCompositeNodeWithFourSimpleChildren() throws FileNotFoundException {
+    InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/FourSimpleChildren.xml");
+    return loadCompositeNode(xmlStream);
+  }
+
+  public CompositeNode getValidCompositeNodeWithOneSimpleOneCompositeChild() throws FileNotFoundException {
+    InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/OneSimpleOneCompositeChild.xml");
+    return loadCompositeNode(xmlStream);
+  }
+
+  public CompositeNode getValidCompositeNodeWithTwoCompositeChildren() throws FileNotFoundException {
+    InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/TwoCompositeChildren.xml");
+    return loadCompositeNode(xmlStream);
+  }
+
+  public CompositeNode getInvalidCompositeNodeSimpleChild() throws FileNotFoundException {
+    InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/InvalidSimpleChild.xml");
+    return loadCompositeNode(xmlStream);
+  }
+
+  public CompositeNode getInvalidCompositeNodeCompositeChild() throws FileNotFoundException {
+    InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/InvalidCompositeChild.xml");
+    return loadCompositeNode(xmlStream);
+  }
+
+  //Note to self:  Stolen from TestUtils
+  ///Users/alefan/odl/controller4/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
+  // Figure out how to include TestUtils through pom ...was getting errors
+  private CompositeNode loadCompositeNode(InputStream xmlInputStream) throws FileNotFoundException {
+    if (xmlInputStream == null) {
+      throw new IllegalArgumentException();
+    }
+    Node<?> dataTree;
+    try {
+      dataTree = XmlTreeBuilder.buildDataTree(xmlInputStream);
+    } catch (XMLStreamException e) {
+      _logger.error("Error during building data tree from XML", e);
+      return null;
+    }
+    if (dataTree == null) {
+      _logger.error("data tree is null");
+      return null;
+    }
+    if (dataTree instanceof SimpleNode) {
+      _logger.error("RPC XML was resolved as SimpleNode");
+      return null;
+    }
+    return (CompositeNode) dataTree;
+  }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/FourSimpleChildren.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/FourSimpleChildren.xml
new file mode 100644 (file)
index 0000000..5ac991b
--- /dev/null
@@ -0,0 +1,6 @@
+<rpc>
+    <name>eth0</name>
+    <type>ethernetCsmacd</type>
+    <enabled>false</enabled>
+    <description>some interface</description>
+</rpc>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/InvalidCompositeChild.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/InvalidCompositeChild.xml
new file mode 100644 (file)
index 0000000..3979d02
--- /dev/null
@@ -0,0 +1,14 @@
+<rpc>
+    <innerinterface1>
+        <name>eth1</name>
+        <type>ethernet</type>
+        <enabled>false</enabled>
+        <description>some interface</description>
+    </innerinterface1>
+    <innerinterface2>
+        <name>error</name>
+        <type>ethernet</type>
+        <enabled>true</enabled>
+        <description>some interface</description>
+    </innerinterface2>
+</rpc>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/InvalidSimpleChild.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/InvalidSimpleChild.xml
new file mode 100644 (file)
index 0000000..6082d72
--- /dev/null
@@ -0,0 +1,3 @@
+<rpc>
+    <name>error</name>
+</rpc>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/OneSimpleChild.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/OneSimpleChild.xml
new file mode 100644 (file)
index 0000000..f431b04
--- /dev/null
@@ -0,0 +1,3 @@
+<rpc>
+    <name>eth0</name>
+</rpc>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/OneSimpleOneCompositeChild.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/OneSimpleOneCompositeChild.xml
new file mode 100644 (file)
index 0000000..bca7682
--- /dev/null
@@ -0,0 +1,9 @@
+<rpc>
+    <name>eth0</name>
+    <innerinterface>
+        <name>eth1</name>
+        <type>ethernetCsmacd</type>
+        <enabled>false</enabled>
+        <description>some interface</description>
+    </innerinterface>
+</rpc>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/TwoCompositeChildren.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/TwoCompositeChildren.xml
new file mode 100644 (file)
index 0000000..c49407e
--- /dev/null
@@ -0,0 +1,14 @@
+<rpc>
+    <innerinterface1>
+        <name>eth1</name>
+        <type>ethernet</type>
+        <enabled>false</enabled>
+        <description>some interface</description>
+    </innerinterface1>
+    <innerinterface2>
+        <name>eth2</name>
+        <type>ethernet</type>
+        <enabled>true</enabled>
+        <description>some interface</description>
+    </innerinterface2>
+</rpc>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/TwoSimpleChildren.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/TwoSimpleChildren.xml
new file mode 100644 (file)
index 0000000..5f4729c
--- /dev/null
@@ -0,0 +1,4 @@
+<rpc>
+    <name>eth0</name>
+    <type>ethernetCsmacd</type>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/pom.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/pom.xml
new file mode 100644 (file)
index 0000000..5bfbcba
--- /dev/null
@@ -0,0 +1,26 @@
+<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</groupId>
+    <artifactId>sal-parent</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <relativePath>../..</relativePath>
+  </parent>
+  <packaging>pom</packaging>
+  <groupId>org.opendaylight.controller.tests</groupId>
+  <artifactId>sal-remoterpc-connector-test-parent</artifactId>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+  </scm>
+
+  <modules>
+    <module>consumer-service</module>
+    <module>provider-service</module>
+    <module>test-it</module>
+    <module>test-nb</module>
+  </modules>
+
+</project>
similarity index 89%
rename from opendaylight/md-sal/test/zeromq-test-provider/pom.xml
rename to opendaylight/md-sal/sal-remoterpc-connector/integrationtest/provider-service/pom.xml
index 10e15aa9170c04e413086e1210b9cd5772d0803d..a13a5aeba08bfaa15f3ef8713ab0b93fdc411af6 100644 (file)
@@ -2,11 +2,11 @@
          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>
-        <artifactId>sal-test-parent</artifactId>
+        <artifactId>sal-remoterpc-connector-test-parent</artifactId>
         <groupId>org.opendaylight.controller.tests</groupId>
         <version>1.0-SNAPSHOT</version>
   </parent>
-  <artifactId>zeromq-test-provider</artifactId>
+  <artifactId>sal-remoterpc-connector-test-provider</artifactId>
   <packaging>bundle</packaging>
   <scm>
     <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-data-api</artifactId>
     </dependency>
-
+        <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-data-impl</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-common-util</artifactId>
@@ -78,7 +81,7 @@
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-zeromq-connector</artifactId>
+      <artifactId>sal-remoterpc-connector</artifactId>
       <version>1.0-SNAPSHOT</version>
     </dependency>
 
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/provider-service/src/main/java/org/opendaylight/controller/sample/zeromq/provider/ExampleProvider.java b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/provider-service/src/main/java/org/opendaylight/controller/sample/zeromq/provider/ExampleProvider.java
new file mode 100644 (file)
index 0000000..6c294dd
--- /dev/null
@@ -0,0 +1,120 @@
+package org.opendaylight.controller.sample.zeromq.provider;
+
+import org.opendaylight.controller.sal.common.util.RpcErrors;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.CompositeNodeImpl;
+import org.opendaylight.controller.sal.core.api.AbstractProvider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URI;
+import java.util.*;
+
+public class ExampleProvider extends AbstractProvider implements RpcImplementation {
+
+  private final URI namespace = URI.create("http://cisco.com/example");
+  private final QName QNAME = new QName(namespace, "heartbeat");
+  private RpcRegistration reg;
+
+  private ServiceRegistration thisReg;
+
+  private ProviderSession session;
+  private Logger _logger = LoggerFactory.getLogger(ExampleProvider.class);
+
+  @Override
+  public void onSessionInitiated(ProviderSession session) {
+    this.session = session;
+  }
+
+  @Override
+  public Set<QName> getSupportedRpcs() {
+    Set<QName> supportedRpcs = new HashSet<QName>();
+    supportedRpcs.add(QNAME);
+    return supportedRpcs;
+  }
+
+  @Override
+  public RpcResult<CompositeNode> invokeRpc(final QName rpc, CompositeNode input) {
+    boolean success = false;
+    CompositeNode output = null;
+    Collection<RpcError> errors = new ArrayList<>();
+
+    // Only handle supported RPC calls
+    if (getSupportedRpcs().contains(rpc))  {
+      if (input == null) {
+        errors.add(RpcErrors.getRpcError("app", "tag", "info", RpcError.ErrorSeverity.WARNING, "message:null input", RpcError.ErrorType.RPC, null));
+      }
+      else {
+        if (isErroneousInput(input)) {
+          errors.add(RpcErrors.getRpcError("app", "tag", "info", RpcError.ErrorSeverity.ERROR, "message:error", RpcError.ErrorType.RPC, null));
+        }
+        else {
+          success = true;
+          output = addSuccessNode(input);
+        }
+      }
+    }
+    return Rpcs.getRpcResult(success, output, errors);
+  }
+
+  // Examines input -- dives into CompositeNodes and finds any value equal to "error"
+  private boolean isErroneousInput(CompositeNode input) {
+    for (Node<?> n : input.getChildren()) {
+      if (n instanceof CompositeNode) {
+        if (isErroneousInput((CompositeNode)n)) {
+          return true;
+        }
+      }
+      else {  //SimpleNode
+        if ((input.getChildren().get(0).getValue()).equals("error")) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+  
+  // Adds a child SimpleNode containing the value "success" to the input CompositeNode
+  private CompositeNode addSuccessNode(CompositeNode input) {
+    List<Node<?>> list = new ArrayList<Node<?>>(input.getChildren());
+    SimpleNodeTOImpl<String> simpleNode = new SimpleNodeTOImpl<String>(QNAME, input, "success");
+    list.add(simpleNode);
+    return new CompositeNodeTOImpl(QNAME, null, list);
+  }
+
+  @Override
+  protected void startImpl(BundleContext context) {
+    thisReg = context.registerService(ExampleProvider.class, this, new Hashtable<String, String>());
+  }
+
+  @Override
+  protected void stopImpl(BundleContext context) {
+    if (reg != null) {
+      try {
+        reg.close();
+        thisReg.unregister();
+      } catch (Exception e) {
+        // TODO Auto-generated catch block
+        e.printStackTrace();
+      }
+    }
+  }
+
+  public void announce(QName name) {
+    _logger.debug("Announcing [{}]\n\n\n", name);
+    reg = this.session.addRpcImplementation(name, this);
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/pom.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/pom.xml
new file mode 100644 (file)
index 0000000..4305a28
--- /dev/null
@@ -0,0 +1,536 @@
+<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>
+        <artifactId>sal-remoterpc-connector-test-parent</artifactId>
+        <groupId>org.opendaylight.controller.tests</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>sal-remoterpc-connector-test-it</artifactId>
+    <scm>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+    </scm>
+
+    <properties>
+        <exam.version>3.0.0</exam.version>
+        <url.version>1.5.0</url.version>
+        <config.version>0.2.3-SNAPSHOT</config.version>
+        <netconf.version>0.2.3-SNAPSHOT</netconf.version>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>commons-codec</groupId>
+                <artifactId>commons-codec</artifactId>
+                <version>1.7</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.ops4j.pax.exam</groupId>
+                <artifactId>maven-paxexam-plugin</artifactId>
+                <version>1.2.4</version>
+                <executions>
+                    <execution>
+                        <id>generate-config</id>
+                        <goals>
+                            <goal>generate-depends-file</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <pluginManagement>
+            <plugins>
+                <!--This plugin's configuration is used to store Eclipse 
+                    m2e settings only. It has no influence on the Maven build itself. -->
+                <plugin>
+                    <groupId>org.eclipse.m2e</groupId>
+                    <artifactId>lifecycle-mapping</artifactId>
+                    <version>1.0.0</version>
+                    <configuration>
+                        <lifecycleMappingMetadata>
+                            <pluginExecutions>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>
+                                            org.ops4j.pax.exam
+                                        </groupId>
+                                        <artifactId>
+                                            maven-paxexam-plugin
+                                        </artifactId>
+                                        <versionRange>
+                                            [1.2.4,)
+                                        </versionRange>
+                                        <goals>
+                                            <goal>
+                                                generate-depends-file
+                                            </goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore></ignore>
+                                    </action>
+                                </pluginExecution>
+                            </pluginExecutions>
+                        </lifecycleMappingMetadata>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+            <artifactId>xtend-lib-osgi</artifactId>
+            <version>2.4.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.tests</groupId>
+            <artifactId>sal-remoterpc-connector-test-provider</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.tests</groupId>
+            <artifactId>sal-remoterpc-connector-test-consumer</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-broker-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-container-native</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-junit4</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-link-mvn</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.url</groupId>
+            <artifactId>pax-url-aether</artifactId>
+            <version>1.5.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>org.eclipse.osgi</artifactId>
+            <version>3.8.1.v20120830-144521</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>log4j-over-slf4j</artifactId>
+            <version>1.7.2</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-core</artifactId>
+            <version>1.0.9</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.0.9</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-core-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-remoterpc-connector</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>containermanager</artifactId>
+            <version>0.5.1-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.osgi</groupId>
+                    <artifactId>org.osgi.compendium</artifactId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>commons-io</artifactId>
+                    <groupId>commons-io</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-api</artifactId>
+        </dependency>
+        <!--dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>yang-data-impl</artifactId> 
+            <version>0.5.9-SNAPSHOT</version> </dependency -->
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-parser-impl</artifactId>
+            <version>0.5.9-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+            <artifactId>antlr4-runtime-osgi-nohead</artifactId>
+            <version>4.0</version>
+        </dependency>
+
+        <!-- routing table dependencies -->
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>zeromq-routingtable.implementation</artifactId>
+            <version>0.4.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>clustering.services</artifactId>
+            <version>0.4.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal</artifactId>
+            <version>0.5.1-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.osgi</groupId>
+                    <artifactId>org.osgi.compendium</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal.implementation</artifactId>
+            <version>0.4.0-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>commons-io</artifactId>
+                    <groupId>commons-io</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>containermanager</artifactId>
+            <version>0.5.0-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.osgi</groupId>
+                    <artifactId>org.osgi.compendium</artifactId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>commons-io</artifactId>
+                    <groupId>commons-io</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>containermanager.it.implementation</artifactId>
+            <version>0.5.0-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>commons-io</artifactId>
+                    <groupId>commons-io</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>clustering.stub</artifactId>
+            <version>0.4.0-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>commons-io</artifactId>
+                    <groupId>commons-io</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.dependencymanager.shell</artifactId>
+            <version>3.0.1</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.osgi</groupId>
+                    <artifactId>org.osgi.compendium</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>eclipselink</groupId>
+            <artifactId>javax.resource</artifactId>
+            <version>1.5.0.v200906010428</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal</artifactId>
+            <version>0.5.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>ietf-netconf-monitoring</artifactId>
+        <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>yang-ext</artifactId>
+            <version>2013.09.07.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>opendaylight-l2-types</artifactId>
+            <version>2013.08.27.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-it</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-config</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-broker-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-broker-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-inventory</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-connector-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>clustering.services</artifactId>
+            <version>0.4.1-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>org.eclipse.osgi</artifactId>
+            <version>3.8.1.v20120830-144521</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <version>1.9.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+            <version>1.9.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.zeromq</groupId>
+            <artifactId>jeromq</artifactId>
+            <version>0.3.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+            <artifactId>xtend-lib-osgi</artifactId>
+            <version>2.4.3</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-broker-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-container-native</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-junit4</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-netconf-connector</artifactId>
+            <version>${netconf.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>yang-store-impl</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>logback-config</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-persister-impl</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-persister-file-adapter</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-impl</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-client</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam</artifactId>
+            <version>${exam.version}</version>
+            <!-- Compile scope here is intentional, it is used in TestHelper 
+                class which could be downloaded via nexus and reused in other integration 
+                tests. -->
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-link-mvn</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>equinoxSDK381</groupId>
+            <artifactId>org.eclipse.osgi</artifactId>
+            <version>3.8.1.v20120830-144521</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>log4j-over-slf4j</artifactId>
+            <version>1.7.2</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-core</artifactId>
+            <version>1.0.9</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.0.9</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-service</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-manager</artifactId>
+            <version>0.2.3-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>commons-io</artifactId>
+                    <groupId>commons-io</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-management</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+            <artifactId>antlr4-runtime-osgi-nohead</artifactId>
+            <version>4.0</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/RouterTest.java b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/RouterTest.java
new file mode 100644 (file)
index 0000000..62c094d
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 2013 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.sample.zeromq.test.it;
+
+import junit.framework.Assert;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.controller.sal.connector.remoterpc.Client;
+import org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcClient;
+import org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcServer;
+import org.opendaylight.controller.sal.connector.remoterpc.ServerImpl;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sample.zeromq.provider.ExampleProvider;
+import org.opendaylight.controller.sample.zeromq.consumer.ExampleConsumer;
+import org.opendaylight.controller.test.sal.binding.it.TestHelper;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.util.Filter;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
+import javax.inject.Inject;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Hashtable;
+
+import static org.opendaylight.controller.test.sal.binding.it.TestHelper.baseModelBundles;
+import static org.opendaylight.controller.test.sal.binding.it.TestHelper.bindingAwareSalBundles;
+import static org.opendaylight.controller.test.sal.binding.it.TestHelper.configMinumumBundles;
+import static org.opendaylight.controller.test.sal.binding.it.TestHelper.mdSalCoreBundles;
+import static org.ops4j.pax.exam.CoreOptions.*;
+
+@RunWith(PaxExam.class)
+public class RouterTest {
+
+  private Logger _logger = LoggerFactory.getLogger(RouterTest.class);
+
+  public static final String ODL = "org.opendaylight.controller";
+  public static final String YANG = "org.opendaylight.yangtools";
+  public static final String SAMPLE = "org.opendaylight.controller.tests";
+  private final URI namespace = URI.create("http://cisco.com/example");
+  private final QName QNAME = new QName(namespace, "heartbeat");
+
+
+  @Inject
+  org.osgi.framework.BundleContext ctx;
+
+  @Inject
+  @Filter(timeout=60*1000)
+  Broker broker;
+  
+  private ZMQ.Context zmqCtx = ZMQ.context(1);
+  //private Server router;
+  //private ExampleProvider provider;
+
+  //@Test
+  public void testInvokeRpc() throws Exception{
+    //Thread.sleep(1000);
+    //Send announcement
+    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+    Assert.assertNotNull(providerRef);
+
+    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+    Assert.assertNotNull(provider);
+
+    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+    Assert.assertNotNull(consumerRef);
+    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+    Assert.assertNotNull(consumer);
+
+
+    _logger.debug("Provider sends announcement [{}]", "heartbeat");
+    provider.announce(QNAME);
+    ServiceReference routerRef = ctx.getServiceReference(Client.class);
+    Client router = (Client) ctx.getService(routerRef);
+    _logger.debug("Found router[{}]", router);
+    _logger.debug("Invoking RPC [{}]", QNAME);
+    for (int i = 0; i < 3; i++) {
+      RpcResult<CompositeNode> result = router.invokeRpc(QNAME, consumer.getValidCompositeNodeWithOneSimpleChild());
+      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+      Assert.assertNotNull(result);
+    }
+  }
+
+  @Test
+  public void testInvokeRpcWithValidSimpleNode() throws Exception{
+    //Thread.sleep(1500);
+
+    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+    Assert.assertNotNull(providerRef);
+    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+    Assert.assertNotNull(provider);
+    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+    Assert.assertNotNull(consumerRef);
+    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+    Assert.assertNotNull(consumer);
+
+    // Provider sends announcement
+    _logger.debug("Provider sends announcement [{}]", "heartbeat");
+    provider.announce(QNAME);
+    // Consumer invokes RPC
+    _logger.debug("Invoking RPC [{}]", QNAME);
+    CompositeNode input = consumer.getValidCompositeNodeWithOneSimpleChild();
+    for (int i = 0; i < 3; i++) {
+      RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, input);
+      Assert.assertNotNull(result);
+      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+      Assert.assertTrue(result.isSuccessful());
+      Assert.assertNotNull(result.getResult());
+      Assert.assertEquals(0, result.getErrors().size());
+      Assert.assertEquals(input.getChildren().size()+1, result.getResult().getChildren().size());
+    }
+  }
+
+  @Test
+  public void testInvokeRpcWithValidSimpleNodes() throws Exception{
+    //Thread.sleep(1500);
+
+    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+    Assert.assertNotNull(providerRef);
+    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+    Assert.assertNotNull(provider);
+    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+    Assert.assertNotNull(consumerRef);
+    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+    Assert.assertNotNull(consumer);
+
+    // Provider sends announcement
+    _logger.debug("Provider sends announcement [{}]", "heartbeat");
+    provider.announce(QNAME);
+    // Consumer invokes RPC
+    _logger.debug("Invoking RPC [{}]", QNAME);
+    CompositeNode input = consumer.getValidCompositeNodeWithFourSimpleChildren();
+    for (int i = 0; i < 3; i++) {
+      RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, input);
+      Assert.assertNotNull(result);
+      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+      Assert.assertTrue(result.isSuccessful());
+      Assert.assertNotNull(result.getResult());
+      Assert.assertEquals(0, result.getErrors().size());
+      Assert.assertEquals(input.getChildren().size()+1, result.getResult().getChildren().size());
+    }
+  }
+
+  @Test
+  public void testInvokeRpcWithValidCompositeNode() throws Exception{
+    //Thread.sleep(1500);
+
+    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+    Assert.assertNotNull(providerRef);
+    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+    Assert.assertNotNull(provider);
+    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+    Assert.assertNotNull(consumerRef);
+    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+    Assert.assertNotNull(consumer);
+
+    // Provider sends announcement
+    _logger.debug("Provider sends announcement [{}]", "heartbeat");
+    provider.announce(QNAME);
+    // Consumer invokes RPC
+    _logger.debug("Invoking RPC [{}]", QNAME);
+    CompositeNode input = consumer.getValidCompositeNodeWithTwoCompositeChildren();
+    for (int i = 0; i < 3; i++) {
+      RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, input);
+      Assert.assertNotNull(result);
+      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+      Assert.assertTrue(result.isSuccessful());
+      Assert.assertNotNull(result.getResult());
+      Assert.assertEquals(0, result.getErrors().size());
+      Assert.assertEquals(input.getChildren().size()+1, result.getResult().getChildren().size());
+    }
+  }
+
+  @Test
+  public void testInvokeRpcWithNullInput() throws Exception{
+    //Thread.sleep(1500);
+
+    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+    Assert.assertNotNull(providerRef);
+    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+    Assert.assertNotNull(provider);
+    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+    Assert.assertNotNull(consumerRef);
+    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+    Assert.assertNotNull(consumer);
+
+    // Provider sends announcement
+    _logger.debug("Provider sends announcement [{}]", QNAME.getLocalName());
+    provider.announce(QNAME);
+    // Consumer invokes RPC
+    _logger.debug("Invoking RPC [{}]", QNAME);
+    for (int i = 0; i < 3; i++) {
+      RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, null);
+      Assert.assertNotNull(result);
+      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+      Assert.assertFalse(result.isSuccessful());
+      Assert.assertNull(result.getResult());
+      Assert.assertEquals(1, result.getErrors().size());
+      Assert.assertEquals(RpcError.ErrorSeverity.WARNING, ((RpcError)result.getErrors().toArray()[0]).getSeverity());
+    }
+  }
+
+  @Test
+  public void testInvokeRpcWithInvalidSimpleNode() throws Exception{
+    //Thread.sleep(1500);
+
+    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+    Assert.assertNotNull(providerRef);
+    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+    Assert.assertNotNull(provider);
+    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+    Assert.assertNotNull(consumerRef);
+    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+    Assert.assertNotNull(consumer);
+
+    // Provider sends announcement
+    _logger.debug("Provider sends announcement [{}]", QNAME.getLocalName());
+    provider.announce(QNAME);
+    // Consumer invokes RPC
+    _logger.debug("Invoking RPC [{}]", QNAME);
+    CompositeNode input = consumer.getInvalidCompositeNodeSimpleChild();
+    for (int i = 0; i < 3; i++) {
+      RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, input);
+      Assert.assertNotNull(result);
+      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+      Assert.assertFalse(result.isSuccessful());
+      Assert.assertNull(result.getResult());
+      Assert.assertEquals(1, result.getErrors().size());
+      Assert.assertEquals(RpcError.ErrorSeverity.ERROR, ((RpcError)result.getErrors().toArray()[0]).getSeverity());
+    }
+  }
+
+  @Test
+  public void testInvokeRpcWithInvalidCompositeNode() throws Exception{
+    //Thread.sleep(1500);
+
+    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+    Assert.assertNotNull(providerRef);
+    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+    Assert.assertNotNull(provider);
+    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+    Assert.assertNotNull(consumerRef);
+    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+    Assert.assertNotNull(consumer);
+
+    // Provider sends announcement
+    _logger.debug("Provider sends announcement [{}]", QNAME.getLocalName());
+    provider.announce(QNAME);
+    // Consumer invokes RPC
+    _logger.debug("Invoking RPC [{}]", QNAME);
+    CompositeNode input = consumer.getInvalidCompositeNodeCompositeChild();
+    for (int i = 0; i < 3; i++) {
+      RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, input);
+      Assert.assertNotNull(result);
+      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+      Assert.assertFalse(result.isSuccessful());
+      Assert.assertNull(result.getResult());
+      Assert.assertEquals(1, result.getErrors().size());
+      Assert.assertEquals(RpcError.ErrorSeverity.ERROR, ((RpcError)result.getErrors().toArray()[0]).getSeverity());
+    }
+  }
+
+  //@Test
+  // This method is UNTESTED -- need to get around the bundling issues before I know if this even work
+//  public void testInvokeRpcWithValidCompositeNode() throws Exception{
+//    Thread.sleep(10000);
+//    //Send announcement
+//    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+//    Assert.assertNotNull(providerRef);
+//
+//    ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+//    Assert.assertNotNull(provider);
+//
+//    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+//    Assert.assertNotNull(consumerRef);
+//
+//    ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+//    Assert.assertNotNull(consumer);
+//
+//    _logger.debug("Provider sends announcement [{}]", "heartbeat");
+//    provider.announce(QNAME);
+//    ServiceReference routerRef = ctx.getServiceReference(Client.class);
+//    Client router = (Client) ctx.getService(routerRef);
+//    _logger.debug("Found router[{}]", router);
+//    _logger.debug("Invoking RPC [{}]", QNAME);
+//    for (int i = 0; i < 3; i++) {
+//      RpcResult<CompositeNode> result = router.getInstance().invokeRpc(QNAME, consumer.getValidCompositeNodeWithOneSimpleChild());
+//      _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+//      Assert.assertNotNull(result);
+//    }
+//  }
+
+  private Message send(Message msg) throws IOException {
+    ZMQ.Socket reqSocket = zmqCtx.socket(ZMQ.REQ);
+    reqSocket.connect("tcp://localhost:5555");
+    reqSocket.send(Message.serialize(msg));
+    Message response = parseMessage(reqSocket);
+
+    return response;
+  }
+
+  /**
+   * @param socket
+   * @return
+   */
+  private Message parseMessage(ZMQ.Socket socket) {
+
+    Message msg = null;
+    try {
+      byte[] bytes = socket.recv();
+      _logger.debug("Received bytes:[{}]", bytes.length);
+      msg = (Message) Message.deserialize(bytes);
+    } catch (Throwable t) {
+      t.printStackTrace();
+    }
+    return msg;
+  }
+
+  
+  private void printState(){
+    Bundle[] b = ctx.getBundles();
+    _logger.debug("\n\nNumber of bundles [{}]\n\n]", b.length);
+    for (int i=0;i<b.length;i++){
+      _logger.debug("Bundle States {}-{} ",b[i].getSymbolicName(), stateToString(b[i].getState()));
+
+      if ( Bundle.INSTALLED == b[i].getState() || (Bundle.RESOLVED == b[i].getState())){
+        try {
+          b[i].start();
+        } catch (BundleException e) {
+          e.printStackTrace();
+        }
+      }
+    }
+  }
+  private String stateToString(int state) {
+    switch (state) {
+      case Bundle.ACTIVE:
+        return "ACTIVE";
+      case Bundle.INSTALLED:
+        return "INSTALLED";
+      case Bundle.RESOLVED:
+        return "RESOLVED";
+      case Bundle.UNINSTALLED:
+        return "UNINSTALLED";
+      default:
+        return "Not CONVERTED";
+    }
+  }
+
+  @Configuration
+  public Option[] config() {
+    return options(systemProperty("osgi.console").value("2401"),
+        systemProperty("rpc.port").value("5555"),
+        mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(), //
+        mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
+        mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
+        mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
+
+        //mavenBundle(ODL, "sal-binding-broker-impl").versionAsInProject().update(), //
+        mavenBundle(ODL, "sal-common").versionAsInProject(), //
+        mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
+        mavenBundle(ODL, "sal-common-impl").versionAsInProject(), //
+        mavenBundle(ODL, "sal-common-util").versionAsInProject(), //
+        mavenBundle(ODL, "sal-core-api").versionAsInProject().update(), //
+        mavenBundle(ODL, "sal-broker-impl").versionAsInProject(), //
+        mavenBundle(ODL, "sal-core-spi").versionAsInProject().update(), //
+        mavenBundle(ODL, "sal-connector-api").versionAsInProject(), //
+
+
+        
+        baseModelBundles(),
+        bindingAwareSalBundles(),
+        TestHelper.bindingIndependentSalBundles(),
+        TestHelper.configMinumumBundles(),
+        TestHelper.mdSalCoreBundles(),
+        
+      //Added the consumer
+        mavenBundle(SAMPLE, "sal-remoterpc-connector-test-consumer").versionAsInProject(), //
+      //**** These two bundles below are NOT successfully resolved -- some of their dependencies must be missing
+      //**** This causes the "Message" error to occur, the class cannot be found
+        mavenBundle(SAMPLE, "sal-remoterpc-connector-test-provider").versionAsInProject(), //
+        mavenBundle(ODL, "sal-remoterpc-connector").versionAsInProject(), //
+
+        mavenBundle(ODL, "zeromq-routingtable.implementation").versionAsInProject(),
+        mavenBundle(YANG, "concepts").versionAsInProject(),
+        mavenBundle(YANG, "yang-binding").versionAsInProject(), //
+        mavenBundle(YANG, "yang-common").versionAsInProject(), //
+        mavenBundle(YANG, "yang-data-api").versionAsInProject(), //
+        mavenBundle(YANG, "yang-data-impl").versionAsInProject(), //
+        mavenBundle(YANG, "yang-model-api").versionAsInProject(), //
+        mavenBundle(YANG, "yang-parser-api").versionAsInProject(), //
+        mavenBundle(YANG, "yang-parser-impl").versionAsInProject(), //
+        mavenBundle(YANG, "yang-model-util").versionAsInProject(), //
+        mavenBundle(YANG + ".thirdparty", "xtend-lib-osgi").versionAsInProject(), //
+        mavenBundle(YANG + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
+        mavenBundle("com.google.guava", "guava").versionAsInProject(), //
+        mavenBundle("org.zeromq", "jeromq").versionAsInProject(),
+        mavenBundle("org.codehaus.jackson", "jackson-mapper-asl").versionAsInProject(),
+        mavenBundle("org.codehaus.jackson", "jackson-core-asl").versionAsInProject(),
+        //routingtable dependencies
+        systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
+        // List framework bundles
+        mavenBundle("equinoxSDK381", "org.eclipse.equinox.console").versionAsInProject(),
+        mavenBundle("equinoxSDK381", "org.eclipse.equinox.util").versionAsInProject(),
+        mavenBundle("equinoxSDK381", "org.eclipse.osgi.services").versionAsInProject(),
+        mavenBundle("equinoxSDK381", "org.eclipse.equinox.ds").versionAsInProject(),
+        mavenBundle("equinoxSDK381", "org.apache.felix.gogo.command").versionAsInProject(),
+        mavenBundle("equinoxSDK381", "org.apache.felix.gogo.runtime").versionAsInProject(),
+        mavenBundle("equinoxSDK381", "org.apache.felix.gogo.shell").versionAsInProject(),
+        // List logger bundles
+
+        mavenBundle("org.opendaylight.controller", "clustering.services")
+            .versionAsInProject(),
+        mavenBundle("org.opendaylight.controller", "clustering.stub")
+            .versionAsInProject(),
+
+
+        // List all the bundles on which the test case depends
+        mavenBundle("org.opendaylight.controller", "sal")
+            .versionAsInProject(),
+        mavenBundle("org.opendaylight.controller", "sal.implementation")
+            .versionAsInProject(),
+        mavenBundle("org.jboss.spec.javax.transaction",
+            "jboss-transaction-api_1.1_spec").versionAsInProject(),
+        mavenBundle("org.apache.commons", "commons-lang3")
+            .versionAsInProject(),
+        mavenBundle("org.apache.felix",
+            "org.apache.felix.dependencymanager")
+            .versionAsInProject(),
+
+        junitBundles()
+    );
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/resources/controller.config b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/resources/controller.config
new file mode 100644 (file)
index 0000000..0d9cd6a
--- /dev/null
@@ -0,0 +1,123 @@
+//START OF CONFIG-LAST
+<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+       <module>
+               <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</type>
+               <name>yang-schema-service</name>
+       </module>
+       <module>
+               <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:hash-map-data-store</type>
+               <name>hash-map-data-store</name>
+       </module>
+       <module>
+               <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
+               <name>dom-broker</name>
+               <data-store xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+                       <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
+                       <name>ref_hash-map-data-store</name>
+               </data-store>
+       </module>
+       <module>
+               <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
+               <name>binding-broker-impl</name>
+               <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                       <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
+                       <name>ref_binding-notification-broker</name>
+               </notification-service>
+               <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                       <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+                       <name>ref_binding-data-broker</name>
+               </data-broker>
+       </module>
+       <module>
+               <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</type>
+               <name>runtime-mapping-singleton</name>
+       </module>
+       <module>
+               <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</type>
+               <name>binding-notification-broker</name>
+       </module>
+       <module>
+               <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-broker</type>
+               <name>binding-data-broker</name>
+               <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                       <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+                       <name>ref_dom-broker</name>
+               </dom-broker>
+               <mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+               <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
+               <name>ref_runtime-mapping-singleton</name>
+               </mapping-service>
+       </module>
+       <module>
+               <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">prefix:remote-zeromq-rpc-server</type>
+               <name>remoter</name>
+               <port xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">5666</port>
+               <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">
+                       <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</type>
+                       <name>ref_dom-broker</name>
+               </dom-broker>
+       </module>
+</modules>
+<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+       <service>
+       <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+               <instance>
+               <name>ref_yang-schema-service</name>
+               <provider>/config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service']</provider>
+               </instance>
+       </service>
+       <service>
+               <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
+               <instance>
+                       <name>ref_binding-notification-broker</name>
+                       <provider>/config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker']</provider>
+               </instance>
+       </service>
+       <service>
+               <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
+               <instance>
+                       <name>ref_hash-map-data-store</name>
+                       <provider>/config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store']</provider>
+               </instance>
+       </service>
+       <service>
+               <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+               <instance>
+                       <name>ref_binding-broker-impl</name>
+                       <provider>/config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl']</provider>
+               </instance>
+       </service>
+       <service>
+               <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
+               <instance>
+                       <name>ref_runtime-mapping-singleton</name>
+                       <provider>/config/modules/module[name='runtime-generated-mapping']/instance[name='runtime-mapping-singleton']</provider>
+               </instance>
+       </service>
+       <service>
+       <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+               <instance>
+                       <name>ref_dom-broker</name>
+                       <provider>/config/modules/module[name='dom-broker-impl']/instance[name='dom-broker']</provider>
+               </instance>
+       </service>
+       <service>
+               <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+               <instance>
+               <name>ref_binding-data-broker</name>
+               <provider>/config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker']</provider>
+       </instance>
+       </service>
+</services>
+</data>
+
+
+//END OF SNAPSHOT
+urn:opendaylight:params:xml:ns:yang:controller:config?module=config&revision=2013-04-05
+urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28
+urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28
+urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28
+urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28
+urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc?module=odl-sal-dom-rpc-remote-cfg&revision=2013-10-28
+//END OF CONFIG
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/resources/logback.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/resources/logback.xml
new file mode 100644 (file)
index 0000000..1d17796
--- /dev/null
@@ -0,0 +1,16 @@
+<configuration scan="true">
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+      </pattern>
+    </encoder>
+  </appender>
+
+
+  <logger name="org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort" level="ERROR"/>
+
+  <root level="info">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/pom.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/pom.xml
new file mode 100644 (file)
index 0000000..dd7e36c
--- /dev/null
@@ -0,0 +1,109 @@
+<?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>
+    <artifactId>sal-remoterpc-connector-test-parent</artifactId>
+    <groupId>org.opendaylight.controller.tests</groupId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>sal-remoterpc-connector-test-nb</artifactId>
+  <packaging>bundle</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>${bundle.plugin.version}</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Export-Package>
+            </Export-Package>
+            <Import-Package>
+              com.sun.jersey.spi.container.servlet,
+              org.codehaus.jackson.annotate,
+              javax.ws.rs,
+              javax.ws.rs.core,
+              javax.xml.bind,
+              javax.xml.bind.annotation,
+              org.slf4j,
+              org.apache.catalina.filters,
+              org.codehaus.jackson.jaxrs,
+              org.opendaylight.controller.sample.zeromq.provider,
+              org.opendaylight.controller.sample.zeromq.consumer,
+              org.opendaylight.controller.sal.utils,
+              org.opendaylight.yangtools.yang.common,
+              org.opendaylight.controller.sal.connector.api,
+              org.opendaylight.controller.sal.connector.remoterpc.api;version="[0.4,1)",
+              org.opendaylight.controller.sal.connector.remoterpc.impl;version="[0.4,1)",
+              org.opendaylight.controller.sal.connector.remoterpc.dto,
+              org.opendaylight.controller.sal.connector.remoterpc.util,
+              org.osgi.framework,
+              com.google.common.base,
+              org.opendaylight.yangtools.yang.data.api,
+              !org.codehaus.enunciate.jaxrs
+
+            </Import-Package>
+            <Web-ContextPath>/controller/nb/v2/zmqnb</Web-ContextPath>
+            <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
+          </instructions>
+          <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>containermanager</artifactId>
+      <version>0.5.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.northbound</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal</artifactId>
+      <version>0.5.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.tests</groupId>
+      <artifactId>sal-remoterpc-connector-test-provider</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.tests</groupId>
+      <artifactId>sal-remoterpc-connector-test-consumer</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-remoterpc-connector</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <version>5.0.0</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>zeromq-routingtable.implementation</artifactId>
+          <version>0.4.1-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+          <groupId>com.google.guava</groupId>
+          <artifactId>guava</artifactId>
+      </dependency>
+  </dependencies>
+
+ </project>
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqrouter/rest/Router.java b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqrouter/rest/Router.java
new file mode 100644 (file)
index 0000000..6c9ec4e
--- /dev/null
@@ -0,0 +1,246 @@
+package org.opendaylight.controller.tests.zmqrouter.rest;
+
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException;
+import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.CompositeNodeImpl;
+import org.opendaylight.controller.sal.connector.remoterpc.impl.RoutingTableImpl;
+import org.opendaylight.controller.sal.connector.remoterpc.util.XmlUtils;
+import org.opendaylight.controller.sample.zeromq.consumer.ExampleConsumer;
+import org.opendaylight.controller.sample.zeromq.provider.ExampleProvider;
+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.data.api.InstanceIdentifier;
+import org.osgi.framework.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import java.io.Serializable;
+import java.net.URI;
+import java.util.Set;
+
+@Path("router")
+public class Router {
+  private Logger _logger = LoggerFactory.getLogger(Router.class);
+  private final URI namespace = URI.create("http://cisco.com/example");
+  private final QName QNAME = new QName(namespace, "heartbeat");
+
+
+  @GET
+  @Path("/hello")
+  @Produces(MediaType.TEXT_PLAIN)
+  public String hello() {
+    return "Hello";
+  }
+
+  @GET
+  @Path("/announce")
+  @Produces(MediaType.TEXT_PLAIN)
+  public String announce() {
+    _logger.info("Announce request received");
+
+    BundleContext ctx = getBundleContext();
+    ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+    if (providerRef == null) {
+      _logger.debug("Could not get provider reference");
+      return "Could not get provider reference";
+    }
+
+    ExampleProvider provider = (ExampleProvider) ctx.getService(providerRef);
+    if (provider == null) {
+      _logger.info("Could not get provider service");
+      return "Could not get provider service";
+    }
+
+    provider.announce(QNAME);
+    return "Announcement sent ";
+
+  }
+
+  @GET
+  @Path("/rpc")
+  @Produces(MediaType.TEXT_PLAIN)
+  public String invokeRpc() throws Exception {
+    _logger.info("Invoking RPC");
+
+    ExampleConsumer consumer = getConsumer();
+    RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, new CompositeNodeImpl());
+    _logger.info("Result [{}]", result.isSuccessful());
+
+    return stringify(result);
+  }
+
+  @GET
+  @Path("/rpc-success")
+  @Produces(MediaType.TEXT_PLAIN)
+  public String invokeRpcSuccess() throws Exception {
+    ExampleConsumer consumer = getConsumer();
+    RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, consumer.getValidCompositeNodeWithFourSimpleChildren()); //TODO: Change this
+    _logger.info("Result [{}]", result.isSuccessful());
+
+    return stringify(result);
+  }
+
+  @GET
+  @Path("/rpc-failure")
+  @Produces(MediaType.TEXT_PLAIN)
+  public String invokeRpcFailure() throws Exception {
+    ExampleConsumer consumer = getConsumer();
+    //RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, consumer.getInvalidCompositeNodeCompositeChild()); //TODO: Change this
+    RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, null); //TODO: Change this
+    _logger.info("Result [{}]", result.isSuccessful());
+
+    return stringify(result);
+  }
+
+  @GET
+  @Path("/routingtable")
+  @Produces(MediaType.TEXT_PLAIN)
+  public String invokeRoutingTable() {
+    _logger.info("Invoking adding an entry in routing table");
+
+    BundleContext ctx = getBundleContext();
+    ServiceReference routingTableServiceReference = ctx.getServiceReference(RoutingTable.class);
+    if (routingTableServiceReference == null) {
+      _logger.debug("Could not get routing table impl reference");
+      return "Could not get routingtable referen ";
+    }
+    RoutingTable routingTable = (RoutingTableImpl) ctx.getService(routingTableServiceReference);
+    if (routingTable == null) {
+      _logger.info("Could not get routing table service");
+      return "Could not get routing table service";
+    }
+
+
+    RoutingIdentifierImpl rii = new RoutingIdentifierImpl();
+    try {
+      routingTable.addGlobalRoute(rii.toString(), "172.27.12.1:5000");
+    } catch (RoutingTableException e) {
+      _logger.error("error in adding routing identifier" + e.getMessage());
+
+    } catch (SystemException e) {
+      _logger.error("error in adding routing identifier" + e.getMessage());
+    }
+
+    Set<String> routes = routingTable.getRoutes(rii.toString());
+
+    StringBuilder stringBuilder = new StringBuilder();
+    for (String route : routes) {
+      stringBuilder.append(route);
+    }
+
+    _logger.info("Result [{}] routes added for route" + rii + stringBuilder.toString());
+
+    return stringBuilder.toString();
+  }
+
+  @GET
+  @Path("/routingtabledelete")
+  @Produces(MediaType.TEXT_PLAIN)
+  public String invokeDeleteRoutingTable() {
+    _logger.info("Invoking adding an entry in routing table");
+
+    BundleContext ctx = getBundleContext();
+    ServiceReference routingTableServiceReference = ctx.getServiceReference(RoutingTable.class);
+    if (routingTableServiceReference == null) {
+      _logger.debug("Could not get routing table impl reference");
+      return "Could not get routingtable referen ";
+    }
+    RoutingTable routingTable = (RoutingTableImpl) ctx.getService(routingTableServiceReference);
+    if (routingTable == null) {
+      _logger.info("Could not get routing table service");
+      return "Could not get routing table service";
+    }
+
+
+    RoutingIdentifierImpl rii = new RoutingIdentifierImpl();
+    try {
+      routingTable.removeGlobalRoute(rii.toString());
+    } catch (RoutingTableException e) {
+      _logger.error("error in adding routing identifier" + e.getMessage());
+
+    } catch (SystemException e) {
+      _logger.error("error in adding routing identifier" + e.getMessage());
+    }
+
+    Set<String> routes = routingTable.getRoutes(rii.toString());
+
+    StringBuilder stringBuilder = new StringBuilder();
+    if (routes != null) {
+      for (String route : routes) {
+        stringBuilder.append(route);
+      }
+    } else {
+      stringBuilder.append(" successfully");
+    }
+
+    _logger.info("Result [{}] routes removed for route" + rii + stringBuilder.toString());
+
+    return stringBuilder.toString();
+  }
+
+  private String stringify(RpcResult<CompositeNode> result) {
+    CompositeNode node = result.getResult();
+    StringBuilder builder = new StringBuilder("result:").append(XmlUtils.compositeNodeToXml(node)).append("\n")
+        .append("error:").append(result.getErrors()).append("\n");
+
+    return builder.toString();
+  }
+
+  private BundleContext getBundleContext() {
+    ClassLoader tlcl = Thread.currentThread().getContextClassLoader();
+    Bundle bundle = null;
+
+    if (tlcl instanceof BundleReference) {
+      bundle = ((BundleReference) tlcl).getBundle();
+    } else {
+      _logger.info("Unable to determine the bundle context based on " +
+          "thread context classloader.");
+      bundle = FrameworkUtil.getBundle(this.getClass());
+    }
+    return (bundle == null ? null : bundle.getBundleContext());
+  }
+
+  private ExampleConsumer getConsumer() {
+    BundleContext ctx = getBundleContext();
+    ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+    if (consumerRef == null) {
+      _logger.debug("Could not get consumer reference");
+      throw new NullPointerException("Could not get consumer reference");
+    }
+    ExampleConsumer consumer = (ExampleConsumer) ctx.getService(consumerRef);
+    if (consumer == null) {
+      _logger.info("Could not get consumer service");
+      throw new NullPointerException("Could not get consumer service");
+    }
+    return consumer;
+  }
+
+  class RoutingIdentifierImpl implements RpcRouter.RouteIdentifier, Serializable {
+
+    private final URI namespace = URI.create("http://cisco.com/example");
+    private final QName QNAME = new QName(namespace, "global");
+    private final QName instance = new QName(URI.create("127.0.0.1"), "local");
+
+    @Override
+    public QName getContext() {
+      return QNAME;
+    }
+
+    @Override
+    public QName getType() {
+      return QNAME;
+    }
+
+    @Override
+    public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier getRoute() {
+      return InstanceIdentifier.of(instance);
+    }
+  }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/src/main/resources/WEB-INF/web.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/src/main/resources/WEB-INF/web.xml
new file mode 100644 (file)
index 0000000..5bd2139
--- /dev/null
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+        version="3.0">
+  <servlet>
+    <servlet-name>JAXRSZmq</servlet-name>
+    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+    <init-param>
+      <param-name>javax.ws.rs.Application</param-name>
+      <param-value>org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
+    </init-param>
+    <load-on-startup>1</load-on-startup>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>JAXRSZmq</servlet-name>
+    <url-pattern>/*</url-pattern>
+  </servlet-mapping>
+
+
+
+        <security-constraint>
+          <web-resource-collection>
+            <web-resource-name>NB api</web-resource-name>
+            <url-pattern>/*</url-pattern>
+            <http-method>POST</http-method>
+            <http-method>GET</http-method>
+            <http-method>PUT</http-method>
+            <http-method>PATCH</http-method>
+            <http-method>DELETE</http-method>
+            <http-method>HEAD</http-method>
+          </web-resource-collection>
+          <auth-constraint>
+            <role-name>System-Admin</role-name>
+            <role-name>Network-Admin</role-name>
+            <role-name>Network-Operator</role-name>
+            <role-name>Container-User</role-name>
+          </auth-constraint>
+        </security-constraint>
+
+        <security-role>
+                <role-name>System-Admin</role-name>
+        </security-role>
+        <security-role>
+                <role-name>Network-Admin</role-name>
+        </security-role>
+        <security-role>
+                <role-name>Network-Operator</role-name>
+        </security-role>
+        <security-role>
+                <role-name>Container-User</role-name>
+        </security-role>
+
+        <login-config>
+                <auth-method>BASIC</auth-method>
+                <realm-name>opendaylight</realm-name>
+        </login-config>
+</web-app>
index 7022db2bc9bba631b2b21f50f2bb2a20d395d7d5..04114fa0edd3d536cb9eb408663ab3404789d3a3 100644 (file)
@@ -17,6 +17,7 @@ import javax.ws.rs.ext.Provider;
 import org.opendaylight.controller.sal.rest.api.Draft01;
 import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.impl.ResponseException;
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
@@ -45,7 +46,7 @@ public enum StructuredDataToJsonProvider implements MessageBodyWriter<Structured
             throws IOException, WebApplicationException {
         CompositeNode data = t.getData();
         if (data == null) {
-            throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND).build());
+            throw new ResponseException(Response.Status.NOT_FOUND, "No data exists.");
         }
 
         JsonWriter writer = new JsonWriter(new OutputStreamWriter(entityStream, "UTF-8"));
index 35352e0819c9720d4bc23e80f30437b542351633..94a7756da65cefd02adbe3a00eecb69efe9a8dab 100644 (file)
@@ -18,9 +18,10 @@ import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
 import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
+import static javax.ws.rs.core.Response.Status.*
 
 class RestconfImpl implements RestconfService {
-    
+
     val static RestconfImpl INSTANCE = new RestconfImpl
 
     @Property
@@ -28,13 +29,13 @@ class RestconfImpl implements RestconfService {
 
     @Property
     extension ControllerContext controllerContext
-    
+
     private new() {
         if (INSTANCE !== null) {
             throw new IllegalStateException("Already instantiated");
         }
     }
-    
+
     static def getInstance() {
         return INSTANCE
     }
@@ -61,141 +62,148 @@ class RestconfImpl implements RestconfService {
     override createConfigurationData(String identifier, CompositeNode payload) {
         val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
         val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode)
-        val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
+        val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier, value).get();
         switch status.result {
-            case TransactionStatus.COMMITED: Response.status(Response.Status.OK).build
-            default: Response.status(Response.Status.INTERNAL_SERVER_ERROR).build
+            case TransactionStatus.COMMITED: Response.status(NO_CONTENT).build
+            default: Response.status(INTERNAL_SERVER_ERROR).build
         }
     }
 
     override updateConfigurationData(String identifier, CompositeNode payload) {
         val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
         val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode)
-        val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
+        val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier, value).get();
         switch status.result {
-            case TransactionStatus.COMMITED: Response.status(Response.Status.NO_CONTENT).build
-            default: Response.status(Response.Status.INTERNAL_SERVER_ERROR).build
+            case TransactionStatus.COMMITED: Response.status(OK).build
+            default: Response.status(INTERNAL_SERVER_ERROR).build
         }
     }
 
     override invokeRpc(String identifier, CompositeNode payload) {
         val rpc = identifier.rpcDefinition
         if (rpc === null) {
-            throw new ResponseException(Response.Status.NOT_FOUND, "RPC does not exist.");
+            throw new ResponseException(NOT_FOUND, "RPC does not exist.");
         }
         val value = normalizeNode(payload, rpc.input)
         val List<Node<?>> input = new ArrayList
         input.add(value)
         val rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, input, null, null)
         val rpcResult = broker.invokeRpc(rpc.QName, rpcRequest);
-        return new StructuredData(rpcResult.result, rpc.output);
+        if (!rpcResult.successful) {
+            throw new ResponseException(INTERNAL_SERVER_ERROR, "Operation failed")
+        }
+        if (rpcResult.result === null) {
+            return null
+        }
+        return new StructuredData(rpcResult.result, rpc.output)
     }
-    
+
     override readConfigurationData(String identifier) {
         val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
         val data = broker.readConfigurationData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
         return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
     }
-    
+
     override readOperationalData(String identifier) {
         val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
         val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
         return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
     }
-    
+
     override updateConfigurationDataLegacy(String identifier, CompositeNode payload) {
-        updateConfigurationData(identifier,payload);
+        updateConfigurationData(identifier, payload);
     }
-    
+
     override createConfigurationDataLegacy(String identifier, CompositeNode payload) {
-        createConfigurationData(identifier,payload);
+        createConfigurationData(identifier, payload);
     }
-    
+
     private def InstanceIdWithSchemaNode resolveInstanceIdentifier(String identifier) {
         val identifierWithSchemaNode = identifier.toInstanceIdentifier
         if (identifierWithSchemaNode === null) {
-            throw new ResponseException(Response.Status.BAD_REQUEST, "URI has bad format");
+            throw new ResponseException(BAD_REQUEST, "URI has bad format");
         }
         return identifierWithSchemaNode
     }
-    
+
     private def CompositeNode normalizeNode(CompositeNode node, DataSchemaNode schema) {
         if (node instanceof CompositeNodeWrapper) {
-            normalizeNode(node as CompositeNodeWrapper, schema,null)
+            normalizeNode(node as CompositeNodeWrapper, schema, null)
             return (node as CompositeNodeWrapper).unwrap()
         }
         return node
     }
 
-    private def void normalizeNode(NodeWrapper<?> nodeBuilder, DataSchemaNode schema,QName previousAugment) {
+    private def void normalizeNode(NodeWrapper<?> nodeBuilder, DataSchemaNode schema, QName previousAugment) {
         if (schema === null) {
-            throw new ResponseException(Response.Status.BAD_REQUEST,
+            throw new ResponseException(BAD_REQUEST,
                 "Data has bad format\n" + nodeBuilder.localName + " does not exist in yang schema.");
         }
         var validQName = schema.QName
         var currentAugment = previousAugment;
-        if(schema.augmenting) {
+        if (schema.augmenting) {
             currentAugment = schema.QName
-        } else if(previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) {
-            validQName = QName.create(currentAugment,schema.QName.localName);
+        } else if (previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) {
+            validQName = QName.create(currentAugment, schema.QName.localName);
         }
         val moduleName = controllerContext.findModuleByNamespace(validQName.namespace);
         if (nodeBuilder.namespace === null || nodeBuilder.namespace == validQName.namespace ||
             nodeBuilder.namespace.path == moduleName) {
             nodeBuilder.qname = validQName
         } else {
-            throw new ResponseException(Response.Status.BAD_REQUEST,
+            throw new ResponseException(BAD_REQUEST,
                 "Data has bad format\nIf data is in XML format then namespace for " + nodeBuilder.localName +
                     " should be " + schema.QName.namespace + ".\n If data is in Json format then module name for " +
                     nodeBuilder.localName + " should be " + moduleName + ".");
         }
-        
+
         if (nodeBuilder instanceof CompositeNodeWrapper) {
             val List<NodeWrapper<?>> children = (nodeBuilder as CompositeNodeWrapper).getValues
             for (child : children) {
                 normalizeNode(child,
-                    findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes),currentAugment)
+                    findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes),
+                    currentAugment)
             }
         } else if (nodeBuilder instanceof SimpleNodeWrapper) {
             val simpleNode = (nodeBuilder as SimpleNodeWrapper)
             val stringValue = simpleNode.value as String;
-            
+
             val objectValue = TypeDefinitionAwareCodec.from(schema.typeDefinition)?.deserialize(stringValue);
             simpleNode.setValue(objectValue)
         } else if (nodeBuilder instanceof EmptyNodeWrapper) {
             val emptyNodeBuilder = nodeBuilder as EmptyNodeWrapper
-            if(schema instanceof LeafSchemaNode) {
+            if (schema instanceof LeafSchemaNode) {
                 emptyNodeBuilder.setComposite(false);
-            } else if(schema instanceof ContainerSchemaNode) {
+            } else if (schema instanceof ContainerSchemaNode) {
+
                 // FIXME: Add presence check
                 emptyNodeBuilder.setComposite(true);
             }
         }
     }
-    
+
     private def dispatch TypeDefinition<?> typeDefinition(LeafSchemaNode node) {
         node.type
     }
-    
+
     private def dispatch TypeDefinition<?> typeDefinition(LeafListSchemaNode node) {
         node.type
     }
-    
-    
+
     private def DataSchemaNode findFirstSchemaByLocalName(String localName, Set<DataSchemaNode> schemas) {
         for (schema : schemas) {
             if (schema instanceof ChoiceNode) {
                 for (caze : (schema as ChoiceNode).cases) {
-                    val result =  findFirstSchemaByLocalName(localName, caze.childNodes)
+                    val result = findFirstSchemaByLocalName(localName, caze.childNodes)
                     if (result !== null) {
                         return result
                     }
                 }
             } else {
                 val result = schemas.findFirst[n|n.QName.localName.equals(localName)]
-                if(result !== null) {
+                if (result !== null) {
                     return result;
-                
+
                 }
             }
         }
index 103c9ed3cdbe04f3f192180da77d6fd8fc14945e..d58b7e9dab0cecac48f4d5641dd2b6ff9bc8ba3a 100644 (file)
@@ -27,7 +27,7 @@ public class InvokeRpcMethodTest {
         @Override
         public RpcResult<CompositeNode> answer(InvocationOnMock invocation) throws Throwable {
             CompositeNode compNode = (CompositeNode) invocation.getArguments()[1];
-            return new DummyRpcResult.Builder<CompositeNode>().result(compNode).build();
+            return new DummyRpcResult.Builder<CompositeNode>().result(compNode).isSuccessful(true).build();
         }
     }
 
index 5b0eea32126e5f85dc5c95d2c7b0ef52624c9a9d..ec7dba67b9a35392845e93588862411f45362b49 100644 (file)
@@ -133,21 +133,21 @@ public class XmlProvidersTest extends JerseyTest {
 
         String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0");
         Response response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity);
-        assertEquals(204, response.getStatus());
-        response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
         assertEquals(200, response.getStatus());
+        response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
+        assertEquals(204, response.getStatus());
 
         uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0");
         response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity);
-        assertEquals(204, response.getStatus());
-        response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
         assertEquals(200, response.getStatus());
+        response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
+        assertEquals(204, response.getStatus());
 
         uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0");
         response = target(uri).request(MEDIA_TYPE).put(entity);
-        assertEquals(204, response.getStatus());
-        response = target(uri).request(MEDIA_TYPE).post(entity);
         assertEquals(200, response.getStatus());
+        response = target(uri).request(MEDIA_TYPE).post(entity);
+        assertEquals(204, response.getStatus());
     }
 
     @Test
diff --git a/opendaylight/md-sal/sal-zeromq-connector/pom.xml b/opendaylight/md-sal/sal-zeromq-connector/pom.xml
deleted file mode 100644 (file)
index 7859908..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-<?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</groupId>
-    <artifactId>sal-parent</artifactId>
-    <version>1.0-SNAPSHOT</version>
-  </parent>
-
-  <artifactId>sal-zeromq-connector</artifactId>
-  <packaging>bundle</packaging>
-
-  <properties>
-    <scala.version>2.10.3</scala.version>
-  </properties>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Import-Package>
-              org.opendaylight.controller.sal.connector.api,
-              org.opendaylight.controller.sal.core.api,
-              org.opendaylight.yangtools.concepts;version="[0.1,1)",
-              org.opendaylight.yangtools.yang.common;version="[0.5,1)",
-              org.opendaylight.yangtools.yang.data.api;version="[0.5,1)",
-              org.zeromq;version="[0.3,1)"
-            </Import-Package>
-            <Bundle-Activator>org.opendaylight.controller.sal.connector.remoterpc.router.zeromq.Activator</Bundle-Activator>
-          </instructions>
-        </configuration>
-      </plugin>
-
-      <plugin>
-        <groupId>net.alchim31.maven</groupId>
-        <artifactId>scala-maven-plugin</artifactId>
-        <version>3.1.6</version>
-        <configuration>
-          <recompileMode>incremental</recompileMode>
-          <args>
-            <arg>-target:jvm-1.7</arg>
-          </args>
-          <javacArgs>
-            <javacArg>-source</javacArg><javacArg>1.7</javacArg>
-            <javacArg>-target</javacArg><javacArg>1.7</javacArg>
-          </javacArgs>
-        </configuration>
-        <executions>
-          <execution>
-            <id>scala-compile</id>
-            <goals>
-              <goal>compile</goal>
-            </goals>
-          </execution>
-          <execution>
-            <id>scala-test-compile</id>
-            <goals>
-              <goal>testCompile</goal>
-            </goals>
-          </execution>
-        </executions>
-
-      </plugin>
-      <plugin>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>default-compile</id>
-            <phase>none</phase>
-          </execution>
-          <execution>
-            <id>default-testCompile</id>
-            <phase>none</phase>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.scala-lang</groupId>
-      <artifactId>scala-library</artifactId>
-      <version>${scala.version}</version>
-    </dependency>
-
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>containermanager</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>commons.northbound</artifactId>
-      <version>0.4.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
-      <artifactId>yang-binding</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
-      <artifactId>yang-common</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-connector-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-common-util</artifactId>
-      <version>1.0-SNAPSHOT</version>
-    </dependency>
-
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.jeromq</groupId>
-      <artifactId>jeromq</artifactId>
-      <version>0.3.0-SNAPSHOT</version>
-    </dependency>
-
-  </dependencies>
-  <repositories>
-    <repository>
-      <id>sonatype-nexus-snapshots</id>
-      <url>https://oss.sonatype.org/content/repositories/snapshots</url>
-      <releases>
-        <enabled>false</enabled>
-      </releases>
-      <snapshots>
-        <enabled>true</enabled>
-      </snapshots>
-    </repository>
-  </repositories>
-
-</project>
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChange.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChange.java
deleted file mode 100644 (file)
index ba90f37..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (c) 2013 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.connector.remoterpc.api;
-
-import java.util.Map;
-import java.util.Set;
-
-public interface RouteChange<I, R> {
-
-  Map<I, Set<R>> getRemovals();
-  Map<I, Set<R>> getAnnouncements();
-}
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/Activator.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/Activator.java
deleted file mode 100644 (file)
index 5b927a5..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2013 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.connector.remoterpc.router.zeromq;
-
-import org.opendaylight.controller.sal.core.api.AbstractProvider;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.osgi.framework.BundleContext;
-
-public class Activator extends AbstractProvider {
-
-  ZeroMqRpcRouter router;
-
-  @Override
-  public void onSessionInitiated(ProviderSession session) {
-    router = ZeroMqRpcRouter.getInstance();
-    router.setBrokerSession(session);
-    router.start();
-  }
-
-  @Override
-  protected void stopImpl(BundleContext context) {
-    router.stop();
-  }
-
-}
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/ZeroMqRpcRouter.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/ZeroMqRpcRouter.java
deleted file mode 100644 (file)
index af94804..0000000
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * Copyright (c) 2013 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.connector.remoterpc.router.zeromq;
-
-import java.io.IOException;
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.controller.sal.connector.remoterpc.router.zeromq.Message.MessageType;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.zeromq.ZMQ;
-
-/**
- * ZeroMq based implementation of RpcRouter
- * TODO:
- *    1. Make it multi VM aware
- *    2. Make rpc request handling async and non-blocking. Note zmq socket is not thread safe
- *    3. sendRpc() should use connection pooling
- *    4. Read properties from config file using existing(?) ODL properties framework
- */
-public class ZeroMqRpcRouter implements RpcRouter<QName, QName, InstanceIdentifier, Object> {
-
-  private ExecutorService serverPool;
-  private static ExecutorService handlersPool;
-
-  private Map<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String> routingTable;
-
-  private ProviderSession brokerSession;
-
-  private ZMQ.Context context;
-  private ZMQ.Socket publisher;
-  private ZMQ.Socket subscriber;
-  private ZMQ.Socket replySocket;
-
-  private static ZeroMqRpcRouter _instance = new ZeroMqRpcRouter();
-
-  private final RpcFacade facade = new RpcFacade();
-  private final RpcListener listener = new RpcListener();
-
-  private final String localIp = getLocalIpAddress();
-
-  private String pubPort = System.getProperty("pub.port");// port on which announcements are sent
-  private String subPort = System.getProperty("sub.port");// other controller's pub port
-  private String pubIp = System.getProperty("pub.ip"); // other controller's ip
-  private String rpcPort = System.getProperty("rpc.port");// port on which RPC messages are received
-
-  private Logger _logger = LoggerFactory.getLogger(ZeroMqRpcRouter.class);
-
-  //Prevent instantiation
-  private ZeroMqRpcRouter() {
-  }
-
-  public static ZeroMqRpcRouter getInstance() {
-    return _instance;
-  }
-
-  public void start() {
-    context = ZMQ.context(2);
-    publisher = context.socket(ZMQ.PUB);
-    int ret = publisher.bind("tcp://*:" + pubPort);
-    // serverPool = Executors.newSingleThreadExecutor();
-    serverPool = Executors.newCachedThreadPool();
-    handlersPool = Executors.newCachedThreadPool();
-    routingTable = new ConcurrentHashMap<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String>();
-
-    // Start listening for announce and rpc messages
-    serverPool.execute(receive());
-
-    brokerSession.addRpcRegistrationListener(listener);
-
-    Set<QName> currentlySupported = brokerSession.getSupportedRpcs();
-    for (QName rpc : currentlySupported) {
-      listener.onRpcImplementationAdded(rpc);
-    }
-
-  }
-
-  public void stop() {
-    if (handlersPool != null)
-      handlersPool.shutdown();
-    if (serverPool != null)
-      serverPool.shutdown();
-    if (publisher != null) {
-      publisher.setLinger(0);
-      publisher.close();
-    }
-    if (replySocket != null) {
-      replySocket.setLinger(0);
-      replySocket.close();
-    }
-    if (subscriber != null) {
-      subscriber.setLinger(0);
-      subscriber.close();
-    }
-    if (context != null)
-      context.term();
-
-  }
-
-  private Runnable receive() {
-    return new Runnable() {
-      public void run() {
-        try {
-          // Bind to RPC reply socket
-          replySocket = context.socket(ZMQ.REP);
-          replySocket.bind("tcp://*:" + rpcPort);
-
-          // Bind to publishing controller
-          subscriber = context.socket(ZMQ.SUB);
-          String pubAddress = "tcp://" + pubIp + ":" + subPort;
-          subscriber.connect(pubAddress);
-          _logger.debug("{} Subscribing at[{}]", Thread.currentThread().getName(), pubAddress);
-
-          //subscribe for announcements
-          //TODO: Message type would be changed. Update this
-          subscriber.subscribe(Message.serialize(Message.MessageType.ANNOUNCE));
-
-          // Poller enables listening on multiple sockets using a single thread
-          ZMQ.Poller poller = new ZMQ.Poller(2);
-          poller.register(replySocket, ZMQ.Poller.POLLIN);
-          poller.register(subscriber, ZMQ.Poller.POLLIN);
-
-          //TODO: Add code to restart the thread after exception
-          while (!Thread.currentThread().isInterrupted()) {
-
-            poller.poll();
-
-            if (poller.pollin(0)) {
-              handleRpcCall();
-            }
-            if (poller.pollin(1)) {
-              handleAnnouncement();
-            }
-          }
-        } catch (Exception e) {
-          e.printStackTrace();
-        }
-        replySocket.setLinger(0);
-        replySocket.close();
-        subscriber.setLinger(0);
-        subscriber.close();
-      }
-    };
-  }
-
-  /**
-   * @throws IOException
-   * @throws ClassNotFoundException
-   */
-  private void handleAnnouncement() throws IOException, ClassNotFoundException {
-
-    _logger.info("Announcement received");
-    Message.MessageType topic = (MessageType) Message.deserialize(subscriber.recv());
-
-    if (subscriber.hasReceiveMore()) {
-      try {
-        Message m = (Message) Message.deserialize(subscriber.recv());
-        _logger.debug("Announcement message [{}]", m);
-
-        // TODO: check on msg type or topic. Both
-        // should be same. Need to normalize.
-        if (Message.MessageType.ANNOUNCE == m.getType())
-          updateRoutingTable(m);
-      } catch (IOException | ClassNotFoundException e) {
-        e.printStackTrace();
-      }
-    }
-
-  }
-
-  /**
-   * @throws InterruptedException
-   * @throws ExecutionException
-   */
-  private void handleRpcCall() throws InterruptedException, ExecutionException {
-    try {
-      Message request = parseMessage(replySocket);
-
-      _logger.debug("Received rpc request [{}]", request);
-
-      // Call broker to process the message then reply
-      Future<RpcResult<CompositeNode>> rpc = brokerSession.rpc(
-          (QName) request.getRoute().getType(), (CompositeNode) request.getPayload());
-
-      RpcResult<CompositeNode> result = rpc.get();
-
-      Message response = new Message.MessageBuilder()
-          .type(MessageType.RESPONSE)
-          .sender(localIp + ":" + rpcPort)
-          .route(request.getRoute())
-          //.payload(result)    TODO: enable and test
-          .build();
-
-      replySocket.send(Message.serialize(response));
-
-      _logger.debug("Sent rpc response [{}]", response);
-
-    } catch (IOException ex) {
-      //TODO: handle exception and send error codes to caller
-      ex.printStackTrace();
-    }
-  }
-
-
-  @Override
-  public Future<RpcReply<Object>> sendRpc(
-      final RpcRequest<QName, QName, InstanceIdentifier, Object> input) {
-
-    return handlersPool.submit(new Callable<RpcReply<Object>>() {
-
-      @Override
-      public RpcReply<Object> call() {
-        ZMQ.Socket requestSocket = context.socket(ZMQ.REQ);
-
-        // TODO pick the ip and port from routing table based on routing identifier
-        requestSocket.connect("tcp://" + pubIp + ":5554");
-
-        Message requestMessage = new Message.MessageBuilder()
-            .type(MessageType.REQUEST)
-            .sender(localIp + ":" + rpcPort)
-            .route(input.getRoutingInformation())
-            .payload(input.getPayload())
-            .build();
-
-        _logger.debug("Sending rpc request [{}]", requestMessage);
-
-        RpcReply<Object> reply = null;
-
-        try {
-
-          requestSocket.send(Message.serialize(requestMessage));
-          final Message response = parseMessage(requestSocket);
-
-          _logger.debug("Received response [{}]", response);
-
-          reply = new RpcReply<Object>() {
-
-            @Override
-            public Object getPayload() {
-              return response.getPayload();
-            }
-          };
-        } catch (IOException ex) {
-          // TODO: Pass exception back to the caller
-          ex.printStackTrace();
-        }
-
-        return reply;
-      }
-    });
-  }
-
-  /**
-   * TODO: Remove this implementation and use RoutingTable implementation to send announcements
-   * Publishes a notice to other controllers in the cluster
-   *
-   * @param notice
-   */
-  public void publish(final Message notice) {
-    Runnable task = new Runnable() {
-      public void run() {
-
-        try {
-
-          publisher.sendMore(Message.serialize(Message.MessageType.ANNOUNCE));
-          publisher.send(Message.serialize(notice));
-          _logger.debug("Announcement sent [{}]", notice);
-        } catch (IOException ex) {
-          _logger.error("Error in sending announcement [{}]", notice);
-          ex.printStackTrace();
-        }
-      }
-    };
-    handlersPool.execute(task);
-  }
-
-  /**
-   * Finds IPv4 address of the local VM
-   * TODO: This method is non-deterministic. There may be more than one IPv4 address. Cant say which
-   * address will be returned. Read IP from a property file or enhance the code to make it deterministic.
-   * Should we use IP or hostname?
-   *
-   * @return
-   */
-  private String getLocalIpAddress() {
-    String hostAddress = null;
-    Enumeration e = null;
-    try {
-      e = NetworkInterface.getNetworkInterfaces();
-    } catch (SocketException e1) {
-      e1.printStackTrace();
-    }
-    while (e.hasMoreElements()) {
-
-      NetworkInterface n = (NetworkInterface) e.nextElement();
-
-      Enumeration ee = n.getInetAddresses();
-      while (ee.hasMoreElements()) {
-        InetAddress i = (InetAddress) ee.nextElement();
-        if ((i instanceof Inet4Address) && (i.isSiteLocalAddress()))
-          hostAddress = i.getHostAddress();
-      }
-    }
-    return hostAddress;
-
-  }
-
-  /**
-   * TODO: Change to use external routing table implementation
-   *
-   * @param msg
-   */
-  private void updateRoutingTable(Message msg) {
-    routingTable.put(msg.getRoute(), msg.getSender());
-    RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> route = msg.getRoute();
-
-    // Currently only registers rpc implementation.
-    // TODO: do registration for instance based routing
-    QName rpcType = route.getType();
-    RpcRegistration registration = brokerSession.addRpcImplementation(rpcType, facade);
-    _logger.debug("Routing table updated");
-  }
-
-  /**
-   * @param socket
-   * @return
-   */
-  private Message parseMessage(ZMQ.Socket socket) {
-
-    Message msg = null;
-    try {
-      byte[] bytes = socket.recv();
-      _logger.debug("Received bytes:[{}]", bytes.length);
-      msg = (Message) Message.deserialize(bytes);
-    } catch (Throwable t) {
-      t.printStackTrace();
-    }
-    return msg;
-  }
-
-  private class RpcFacade implements RpcImplementation {
-
-    @Override
-    public Set<QName> getSupportedRpcs() {
-      return Collections.emptySet();
-    }
-
-    @Override
-    public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
-
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl();
-      routeId.setType(rpc);
-
-      RpcRequestImpl request = new RpcRequestImpl();
-      request.setRouteIdentifier(routeId);
-      request.setPayload(input);
-
-      final Future<RpcReply<Object>> ret = sendRpc(request);
-
-      //TODO: Review result handling
-      RpcResult<CompositeNode> result = new RpcResult<CompositeNode>() {
-        @Override
-        public boolean isSuccessful() {
-          try {
-            ret.get();
-          } catch (InterruptedException | ExecutionException e) {
-            e.printStackTrace();
-            return false;
-          }
-          return true;
-        }
-
-        @Override
-        public CompositeNode getResult() {
-          return null;
-        }
-
-        @Override
-        public Collection<RpcError> getErrors() {
-          return Collections.EMPTY_LIST;
-        }
-      };
-      return result;
-    }
-  }
-
-  /**
-   * Listener for rpc registrations
-   */
-  private class RpcListener implements RpcRegistrationListener {
-
-    @Override
-    public void onRpcImplementationAdded(QName name) {
-
-      _logger.debug("Announcing registration for [{}]", name);
-      RouteIdentifierImpl routeId = new RouteIdentifierImpl();
-      routeId.setType(name);
-
-      //TODO: Make notice immutable and change message type
-      Message notice = new Message.MessageBuilder()
-          .type(MessageType.ANNOUNCE)
-          .sender("tcp://" + localIp + ":" + rpcPort)
-          .route(routeId)
-          .build();
-
-      publish(notice);
-    }
-
-    @Override
-    public void onRpcImplementationRemoved(QName name) {
-      // TODO: send a rpc-deregistrtation notice
-
-    }
-  }
-
-  public void setBrokerSession(ProviderSession session) {
-    this.brokerSession = session;
-
-  }
-
-}
diff --git a/opendaylight/md-sal/test/pom.xml b/opendaylight/md-sal/test/pom.xml
deleted file mode 100644 (file)
index f9e500e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-<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>
-               <artifactId>sal-parent</artifactId>
-               <version>1.0-SNAPSHOT</version>
-               <groupId>org.opendaylight.controller</groupId>
-       </parent>
-       <packaging>pom</packaging>
-       <groupId>org.opendaylight.controller.tests</groupId>
-       <artifactId>sal-test-parent</artifactId>
-    <scm>
-      <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
-      <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
-      <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
-    </scm>
-
-       <modules>
-               <module>zeromq-test-consumer</module>
-        <module>zeromq-test-it</module>
-        <module>zeromq-test-provider</module>
-       </modules>
-       
-</project>
diff --git a/opendaylight/md-sal/test/zeromq-test-consumer/src/main/java/org/opendaylight/controller/sample/zeromq/consumer/ExampleConsumer.java b/opendaylight/md-sal/test/zeromq-test-consumer/src/main/java/org/opendaylight/controller/sample/zeromq/consumer/ExampleConsumer.java
deleted file mode 100644 (file)
index a56a7de..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-package org.opendaylight.controller.sample.zeromq.consumer;
-
-import java.net.URI;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import org.opendaylight.controller.sal.core.api.AbstractConsumer;
-import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.osgi.framework.BundleContext;
-
-public class ExampleConsumer extends AbstractConsumer {
-
-    private final URI namespace = URI.create("http://cisco.com/example");
-    private final QName QNAME = new QName(namespace,"heartbeat");
-    
-    ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
-    private ConsumerSession session;
-    
-    
-    @Override
-    public void onSessionInitiated(ConsumerSession session) {
-        this.session = session;
-        executor.scheduleAtFixedRate(new Runnable() {
-            
-            @Override
-            public void run() {
-                int count = 0;
-                try {
-                    Future<RpcResult<CompositeNode>> future = ExampleConsumer.this.session.rpc(QNAME, null);
-                    RpcResult<CompositeNode> result = future.get();
-                    System.out.println("Result received. Status is :" + result.isSuccessful());
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-                
-            }
-        }, 0, 10, TimeUnit.SECONDS);
-    }
-    
-    @Override
-    protected void stopImpl(BundleContext context) {
-        // TODO Auto-generated method stub
-        super.stopImpl(context);
-        executor.shutdown();
-    }
-}
diff --git a/opendaylight/md-sal/test/zeromq-test-it/pom.xml b/opendaylight/md-sal/test/zeromq-test-it/pom.xml
deleted file mode 100644 (file)
index 56945d1..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-<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>
-        <artifactId>sal-test-parent</artifactId>
-        <groupId>org.opendaylight.controller.tests</groupId>
-        <version>1.0-SNAPSHOT</version>
-    </parent>
-    <artifactId>zeromq-test-it</artifactId>
-    <scm>
-        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
-        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
-        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
-    </scm>
-
-    <properties>
-        <exam.version>3.0.0</exam.version>
-        <url.version>1.5.0</url.version>
-    </properties>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.ops4j.pax.exam</groupId>
-                <artifactId>maven-paxexam-plugin</artifactId>
-                <version>1.2.4</version>
-                <executions>
-                    <execution>
-                        <id>generate-config</id>
-                        <goals>
-                            <goal>generate-depends-file</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-        <pluginManagement>
-            <plugins>
-                <!--This plugin's configuration is used to store Eclipse m2e settings 
-                    only. It has no influence on the Maven build itself. -->
-                <plugin>
-                    <groupId>org.eclipse.m2e</groupId>
-                    <artifactId>lifecycle-mapping</artifactId>
-                    <version>1.0.0</version>
-                    <configuration>
-                        <lifecycleMappingMetadata>
-                            <pluginExecutions>
-                                <pluginExecution>
-                                    <pluginExecutionFilter>
-                                        <groupId>
-                                            org.ops4j.pax.exam
-                                        </groupId>
-                                        <artifactId>
-                                            maven-paxexam-plugin
-                                        </artifactId>
-                                        <versionRange>
-                                            [1.2.4,)
-                                        </versionRange>
-                                        <goals>
-                                            <goal>
-                                                generate-depends-file
-                                            </goal>
-                                        </goals>
-                                    </pluginExecutionFilter>
-                                    <action>
-                                        <ignore></ignore>
-                                    </action>
-                                </pluginExecution>
-                            </pluginExecutions>
-                        </lifecycleMappingMetadata>
-                    </configuration>
-                </plugin>
-            </plugins>
-        </pluginManagement>
-    </build>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
-            <artifactId>xtend-lib-osgi</artifactId>
-            <version>2.4.3</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller.tests</groupId>
-            <artifactId>zeromq-test-provider</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller.tests</groupId>
-            <artifactId>zeromq-test-consumer</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-broker-impl</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-container-native</artifactId>
-            <version>${exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-junit4</artifactId>
-            <version>${exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-link-mvn</artifactId>
-            <version>${exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>equinoxSDK381</groupId>
-            <artifactId>org.eclipse.osgi</artifactId>
-            <version>3.8.1.v20120830-144521</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>log4j-over-slf4j</artifactId>
-            <version>1.7.2</version>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-core</artifactId>
-            <version>1.0.9</version>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <version>1.0.9</version>
-        </dependency>
-      <dependency>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>sal-binding-api</artifactId>
-        <version>1.0-SNAPSHOT</version>
-      </dependency>
-      <dependency>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>sal-common-util</artifactId>
-        <version>1.0-SNAPSHOT</version>
-      </dependency>
-      <dependency>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>sal-core-api</artifactId>
-        <version>1.0-SNAPSHOT</version>
-      </dependency>
-
-
-      <dependency>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>containermanager</artifactId>
-        <version>0.5.1-SNAPSHOT</version>
-      </dependency>
-
-      <dependency>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>sal</artifactId>
-        <version>0.5.1-SNAPSHOT</version>
-      </dependency>
-      <dependency>
-        <groupId>org.opendaylight.yangtools</groupId>
-        <artifactId>yang-binding</artifactId>
-      </dependency>
-      <dependency>
-        <groupId>org.opendaylight.yangtools</groupId>
-        <artifactId>yang-common</artifactId>
-      </dependency>
-      <dependency>
-        <groupId>org.opendaylight.yangtools</groupId>
-        <artifactId>yang-data-api</artifactId>
-      </dependency>
-
-      <dependency>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>sal-common-util</artifactId>
-        <version>1.0-SNAPSHOT</version>
-      </dependency>
-    </dependencies>
-</project>
diff --git a/opendaylight/md-sal/test/zeromq-test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/ServiceConsumerController.java b/opendaylight/md-sal/test/zeromq-test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/ServiceConsumerController.java
deleted file mode 100644 (file)
index c17b143..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.opendaylight.controller.sample.zeromq.test.it;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.ops4j.pax.exam.Configuration;
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.PaxExam;
-import org.osgi.framework.BundleContext;
-
-import javax.inject.Inject;
-
-import static org.junit.Assert.assertTrue;
-import static org.ops4j.pax.exam.CoreOptions.*;
-
-@RunWith(PaxExam.class)
-public class ServiceConsumerController {
-
-    public static final String ODL = "org.opendaylight.controller";
-    public static final String YANG = "org.opendaylight.yangtools";
-    public static final String SAMPLE = "org.opendaylight.controller.samples";
-
-    @Test
-    public void properInitialized() throws Exception {
-
-        Thread.sleep(30000); // Waiting for services to get wired.
-        assertTrue(true);
-        //assertTrue(consumer.createToast(WhiteBread.class, 5));
-
-    }
-
-//    @Inject
-//    BindingAwareBroker broker;
-
-//    @Inject
-//    ToastConsumer consumer;
-
-    @Inject
-    BundleContext ctx;
-
-    @Configuration
-    public Option[] config() {
-        return options(systemProperty("osgi.console").value("2401"),
-                systemProperty("pub.port").value("5557"),
-                systemProperty("sub.port").value("5556"),
-                systemProperty("rpc.port").value("5555"),
-                systemProperty("pub.ip").value("localhost"),
-                mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(), //
-                mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
-                mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
-                mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
-               
-                //mavenBundle(ODL, "sal-binding-broker-impl").versionAsInProject().update(), //
-                mavenBundle(ODL, "sal-common").versionAsInProject(), //
-                mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
-                mavenBundle(ODL, "sal-common-impl").versionAsInProject(), //
-                mavenBundle(ODL, "sal-common-util").versionAsInProject(), //
-                mavenBundle(ODL, "sal-core-api").versionAsInProject().update(), //
-                mavenBundle(ODL, "sal-broker-impl").versionAsInProject(), //
-                mavenBundle(ODL, "sal-core-spi").versionAsInProject().update(), //
-                mavenBundle(ODL, "sal-connector-api").versionAsInProject(), //
-                mavenBundle(SAMPLE, "zeromq-test-consumer").versionAsInProject(), //
-                mavenBundle(ODL, "sal-zeromq-connector").versionAsInProject(), //
-                mavenBundle(YANG, "concepts").versionAsInProject(),
-                mavenBundle(YANG, "yang-binding").versionAsInProject(), //
-                mavenBundle(YANG, "yang-common").versionAsInProject(), //
-                mavenBundle(YANG, "yang-data-api").versionAsInProject(), //
-                mavenBundle(YANG, "yang-model-api").versionAsInProject(), //
-                mavenBundle(YANG+".thirdparty", "xtend-lib-osgi").versionAsInProject(), //
-                mavenBundle("com.google.guava", "guava").versionAsInProject(), //
-                mavenBundle("org.jeromq", "jeromq").versionAsInProject(),
-                junitBundles()
-                );
-    }
-
-}
diff --git a/opendaylight/md-sal/test/zeromq-test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/ServiceProviderController.java b/opendaylight/md-sal/test/zeromq-test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/ServiceProviderController.java
deleted file mode 100644 (file)
index 2d28b0b..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.opendaylight.controller.sample.zeromq.test.it;
-
-import static org.junit.Assert.*;
-import static org.ops4j.pax.exam.CoreOptions.junitBundles;
-import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
-import static org.ops4j.pax.exam.CoreOptions.options;
-import static org.ops4j.pax.exam.CoreOptions.systemPackages;
-import static org.ops4j.pax.exam.CoreOptions.systemProperty;
-import static org.ops4j.pax.exam.CoreOptions.maven;
-
-import java.util.Collection;
-
-import javax.inject.Inject;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.ops4j.pax.exam.Configuration;
-import org.ops4j.pax.exam.CoreOptions;
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.PaxExam;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-
-@RunWith(PaxExam.class)
-public class ServiceProviderController {
-
-    public static final String ODL = "org.opendaylight.controller";
-    public static final String YANG = "org.opendaylight.yangtools";
-    public static final String SAMPLE = "org.opendaylight.controller.samples";
-
-    @Test
-    public void properInitialized() throws Exception {
-
-        Thread.sleep(30000); // Waiting for services to get wired.
-        assertTrue(true);
-        //assertTrue(consumer.createToast(WhiteBread.class, 5));
-
-    }
-
-//    @Inject
-//    BindingAwareBroker broker;
-
-//    @Inject
-//    ToastConsumer consumer;
-
-    @Inject
-    BundleContext ctx;
-
-    @Configuration
-    public Option[] config() {
-        return options(systemProperty("osgi.console").value("2401"),
-                systemProperty("pub.port").value("5556"),
-                systemProperty("sub.port").value("5557"),
-                systemProperty("rpc.port").value("5554"),
-                systemProperty("pub.ip").value("localhost"),
-                mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(), //
-                mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
-                mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
-                mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
-               
-                //mavenBundle(ODL, "sal-binding-broker-impl").versionAsInProject().update(), //
-                mavenBundle(ODL, "sal-common").versionAsInProject(), //
-                mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
-                mavenBundle(ODL, "sal-common-impl").versionAsInProject(), //
-                mavenBundle(ODL, "sal-common-util").versionAsInProject(), //
-                mavenBundle(ODL, "sal-core-api").versionAsInProject().update(), //
-                mavenBundle(ODL, "sal-broker-impl").versionAsInProject(), //
-                mavenBundle(ODL, "sal-core-spi").versionAsInProject().update(), //
-                mavenBundle(ODL, "sal-connector-api").versionAsInProject(), //
-                mavenBundle(SAMPLE, "zeromq-test-provider").versionAsInProject(), //
-                mavenBundle(ODL, "sal-zeromq-connector").versionAsInProject(), //
-                mavenBundle(YANG, "concepts").versionAsInProject(),
-                mavenBundle(YANG, "yang-binding").versionAsInProject(), //
-                mavenBundle(YANG, "yang-common").versionAsInProject(), //
-                mavenBundle(YANG, "yang-data-api").versionAsInProject(), //
-                mavenBundle(YANG, "yang-model-api").versionAsInProject(), //
-                mavenBundle(YANG+".thirdparty", "xtend-lib-osgi").versionAsInProject(), //
-                mavenBundle("com.google.guava", "guava").versionAsInProject(), //
-                mavenBundle("org.jeromq", "jeromq").versionAsInProject(),
-                junitBundles()
-                );
-    }
-
-}
diff --git a/opendaylight/md-sal/test/zeromq-test-provider/src/main/java/org/opendaylight/controller/sample/zeromq/provider/ExampleProvider.java b/opendaylight/md-sal/test/zeromq-test-provider/src/main/java/org/opendaylight/controller/sample/zeromq/provider/ExampleProvider.java
deleted file mode 100644 (file)
index ec7d7a8..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.opendaylight.controller.sample.zeromq.provider;
-
-import java.net.URI;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-
-import org.opendaylight.controller.sal.common.util.Rpcs;
-import org.opendaylight.controller.sal.core.api.AbstractProvider;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.osgi.framework.BundleContext;
-
-public class ExampleProvider extends AbstractProvider implements RpcImplementation  {
-
-    private final URI namespace = URI.create("http://cisco.com/example");
-    private final QName QNAME = new QName(namespace,"heartbeat");
-    private RpcRegistration reg;
-    
-    
-    @Override
-    public void onSessionInitiated(ProviderSession session) {
-      //Adding heartbeat 10 times just to make sure subscriber get it
-      for (int i=0;i<10;i++){
-        System.out.println("ExampleProvider: Adding " + QNAME + " " + i);
-        reg = session.addRpcImplementation(QNAME, this);
-        try {
-          Thread.sleep(1000);
-        } catch (InterruptedException e) {
-          e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
-        }
-      }
-    }
-    
-    @Override
-    public Set<QName> getSupportedRpcs() {
-        return Collections.singleton(QNAME);
-    }
-    
-    @Override
-    public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
-        if(QNAME.equals(rpc)) {
-            RpcResult<CompositeNode> output = Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
-            return output;
-        }
-        RpcResult<CompositeNode> output = Rpcs.getRpcResult(false, null, Collections.<RpcError>emptySet());
-        return output;
-    }
-    
-    @Override
-    protected void stopImpl(BundleContext context) {
-     if(reg != null) {
-         try {
-            reg.close();
-        } catch (Exception e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-     }
-    }
-
-}
index 37c973e864958c92f25956d63b52b782c4c7c24d..2926786849f82999903565f3388e49481b4ab637 100644 (file)
@@ -1,6 +1,6 @@
 <?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">
+    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</groupId>
                 <extensions>true</extensions>
                 <configuration>
                     <instructions>
-
+                        <Export-Package>
+                            org.opendaylight.controller.sal.connector.remoterpc.api,
+                            org.opendaylight.controller.sal.connector.remoterpc.impl
+                        </Export-Package>
                         <Import-Package>
                             javax.xml.bind.annotation,
                             org.opendaylight.controller.sal.core,
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal</artifactId>
-            <version>0.5.1-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.osgi</groupId>
+                    <artifactId>org.osgi.compendium</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
index d855f1554125764c16170b84c26457bd0976fa04..888f13c8fee1750bdd402b5e104a5798ea5730b1 100644 (file)
                             org.osgi.framework,
                             org.osgi.util.tracker,
                             org.slf4j,
-                            org.w3c.dom
+                            org.w3c.dom,
+                            com.google.common.io,
+                            org.opendaylight.yangtools.yang.model.api.type
                         </Import-Package>
                         <Export-Package>
                         </Export-Package>
index 2b6f862bd7dc17ed8cb3960a81fe951721b7888e..697b811d51c90c9b7cab4f05f266292d25d2a260 100644 (file)
@@ -14,6 +14,7 @@ import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribu
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
+import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
 
 import javax.management.openmbean.ArrayType;
 import javax.management.openmbean.CompositeType;
@@ -30,7 +31,10 @@ public abstract class AttributeIfcSwitchStatement<T> {
 
         if (attributeIfc instanceof JavaAttribute) {
             try {
-                return caseJavaAttribute(attributeIfc.getOpenType());
+                if(((JavaAttribute)attributeIfc).getTypeDefinition() instanceof BinaryTypeDefinition) {
+                    return caseJavaBinaryAttribute(attributeIfc.getOpenType());
+                } else
+                    return caseJavaAttribute(attributeIfc.getOpenType());
             } catch (UnknownOpenTypeException e) {
                 throw getIllegalArgumentException(attributeIfc);
             }
@@ -48,6 +52,9 @@ public abstract class AttributeIfcSwitchStatement<T> {
         throw getIllegalArgumentException(attributeIfc);
     }
 
+    protected T caseJavaBinaryAttribute(OpenType<?> openType) {
+        return caseJavaAttribute(openType);
+    }
 
     private IllegalArgumentException getIllegalArgumentException(AttributeIfc attributeIfc) {
         return new IllegalArgumentException("Unknown attribute type " + attributeIfc.getClass() + ", " + attributeIfc
index 867d94e0b70f628a1454cde825f44d6c27233528..793911262810f826f332f84c75bb642bb1d7fe6e 100644 (file)
@@ -27,11 +27,14 @@ public abstract class AbstractAttributeReadingStrategy implements AttributeReadi
     @Override
     public AttributeConfigElement readElement(List<XmlElement> configNodes) {
         if (configNodes.size() == 0)
-            return AttributeConfigElement.createNullValue(nullableDefault);
+            return AttributeConfigElement.createNullValue(postprocessNullableDefault(nullableDefault));
 
         return readElementHook(configNodes);
     }
 
     abstract AttributeConfigElement readElementHook(List<XmlElement> configNodes);
 
+    protected Object postprocessNullableDefault(String nullableDefault) {
+        return nullableDefault;
+    }
 }
index 598935a0bc4f15ddcc61039723e313d55c0d9860..a1f46dde54ff078596b709e12e0eeeb8914e7056 100644 (file)
@@ -9,7 +9,6 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
 
 import com.google.common.base.Optional;
-import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.AttributeResolvingStrategy;
 
 import javax.management.openmbean.OpenType;
@@ -47,24 +46,14 @@ public class AttributeConfigElement {
 
     }
 
-    public static AttributeConfigElement create(AttributeIfc attributeIfc, Object value) {
-        String nullableDefault = attributeIfc.getNullableDefault();
-        return create(nullableDefault, value);
-    }
-
-    public static AttributeConfigElement create(String nullableDefault, Object value) {
+    public static AttributeConfigElement create(Object nullableDefault, Object value) {
         return new AttributeConfigElement(nullableDefault, value);
     }
 
-    public static AttributeConfigElement createNullValue(AttributeIfc attributeIfc) {
-        return new AttributeConfigElement(attributeIfc.getNullableDefault(), null);
-    }
-
-    public static AttributeConfigElement createNullValue(String nullableDefault) {
+    public static AttributeConfigElement createNullValue(Object nullableDefault) {
         return new AttributeConfigElement(nullableDefault, null);
     }
 
-
     public Object getValue() {
         return value;
     }
index e2ea404e2158f40c0d56ada00994e8fcd371da82..a2691f241cfa9a6c273c95c653c2fa9720d03cb9 100644 (file)
@@ -18,6 +18,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attrib
 
 import javax.management.openmbean.ArrayType;
 import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
 import javax.management.openmbean.SimpleType;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -41,6 +42,11 @@ public class ObjectXmlReader extends AttributeIfcSwitchStatement<AttributeReadin
         return switchAttribute(attributeIfc);
     }
 
+    @Override
+    protected AttributeReadingStrategy caseJavaBinaryAttribute(OpenType<?> openType) {
+        return new SimpleBinaryAttributeReadingStrategy(lastAttribute.getNullableDefault());
+    }
+
     @Override
     public AttributeReadingStrategy caseJavaSimpleAttribute(SimpleType<?> openType) {
         return new SimpleAttributeReadingStrategy(lastAttribute.getNullableDefault());
index be86a2ab6f58181894700e95e1f5bee413bc8a21..a8605243af3f77f587563d453ea69d51401f2aa4 100644 (file)
@@ -28,7 +28,13 @@ public class SimpleAttributeReadingStrategy extends AbstractAttributeReadingStra
         String textContent = xmlElement.getTextContent();
 
         Preconditions.checkNotNull(textContent, "This element should contain text %s", xmlElement);
-        return AttributeConfigElement.create(getNullableDefault(), postprocessParsedValue(textContent));
+        return AttributeConfigElement.create(postprocessNullableDefault(getNullableDefault()),
+                postprocessParsedValue(textContent));
+    }
+
+    @Override
+    protected Object postprocessNullableDefault(String nullableDefault) {
+        return nullableDefault;
     }
 
     protected Object postprocessParsedValue(String textContent) {
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleBinaryAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleBinaryAttributeReadingStrategy.java
new file mode 100644 (file)
index 0000000..2cac902
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013 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.netconf.confignetconfconnector.mapping.attributes.fromxml;
+
+import com.google.common.collect.Lists;
+import com.google.common.io.BaseEncoding;
+
+import java.util.List;
+
+public class SimpleBinaryAttributeReadingStrategy extends SimpleAttributeReadingStrategy {
+
+    public SimpleBinaryAttributeReadingStrategy(String nullableDefault) {
+        super(nullableDefault);
+    }
+
+    protected Object postprocessParsedValue(String textContent) {
+        BaseEncoding en = BaseEncoding.base64();
+        byte[] decode = en.decode(textContent);
+        List<String> parsed = Lists.newArrayListWithCapacity(decode.length);
+        for (byte b : decode) {
+            parsed.add(Byte.toString(b));
+        }
+        return parsed;
+    }
+
+    @Override
+    protected Object postprocessNullableDefault(String nullableDefault) {
+        return nullableDefault == null ? null : postprocessParsedValue(nullableDefault);
+    }
+}
index 9249ac9fa82b4a8cd03cfb8ce394c58b207f0dc2..22c9e015a94d4bb2a72e800927f7af1da2ca2363 100644 (file)
@@ -14,7 +14,6 @@ import java.util.HashMap;
 
 public class SimpleCompositeAttributeReadingStrategy extends SimpleAttributeReadingStrategy {
 
-
     private final String key;
 
     public SimpleCompositeAttributeReadingStrategy(String nullableDefault, String key) {
@@ -28,4 +27,8 @@ public class SimpleCompositeAttributeReadingStrategy extends SimpleAttributeRead
         return map;
     }
 
+    @Override
+    protected Object postprocessNullableDefault(String nullableDefault) {
+        return nullableDefault == null ? null : postprocessParsedValue(nullableDefault);
+    }
 }
index a85f3064cf742b3ec0782f213a5bf3cd8e173468..c477821051b08d03288d129fc29c1aaddd32eef6 100644 (file)
@@ -70,7 +70,7 @@ final class CompositeAttributeResolvingStrategy extends
                     parsedInnerValue.isPresent() ? parsedInnerValue.get() : null);
         }
 
-        CompositeDataSupport parsedValue = null;
+        CompositeDataSupport parsedValue;
         try {
             parsedValue = new CompositeDataSupport(getOpenType(), items);
         } catch (OpenDataException e) {
index ad587ea9879b41ca06f59020f41b0be0ba5fb536..a174e9a25160e8aa3d52ab66891c9d1314e58185 100644 (file)
@@ -19,6 +19,7 @@ import org.w3c.dom.Document;
 
 import javax.management.openmbean.ArrayType;
 import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
 import javax.management.openmbean.SimpleType;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -51,6 +52,11 @@ public class ObjectXmlWriter extends AttributeIfcSwitchStatement<AttributeWritin
         return switchAttribute(expectedAttr);
     }
 
+    @Override
+    protected AttributeWritingStrategy caseJavaBinaryAttribute(OpenType<?> openType) {
+        return new SimpleBinaryAttributeWritingStrategy(document, key);
+    }
+
     @Override
     protected AttributeWritingStrategy caseJavaSimpleAttribute(SimpleType<?> openType) {
         return new SimpleAttributeWritingStrategy(document, key);
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleBinaryAttributeWritingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleBinaryAttributeWritingStrategy.java
new file mode 100644 (file)
index 0000000..c159e46
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013 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.netconf.confignetconfconnector.mapping.attributes.toxml;
+
+import com.google.common.base.Preconditions;
+import com.google.common.io.BaseEncoding;
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.w3c.dom.Document;
+
+import java.util.List;
+
+public class SimpleBinaryAttributeWritingStrategy extends SimpleAttributeWritingStrategy {
+
+    /**
+     * @param document
+     * @param key
+     */
+    public SimpleBinaryAttributeWritingStrategy(Document document, String key) {
+        super(document, key);
+    }
+
+    protected Object preprocess(Object value) {
+        Util.checkType(value, List.class);
+        BaseEncoding en = BaseEncoding.base64();
+
+        List<?> list = (List<?>) value;
+        byte[] decoded = new byte[list.size()];
+        int i = 0;
+        for (Object bAsStr : list) {
+            Preconditions.checkArgument(bAsStr instanceof String, "Unexpected inner value for %s, expected string", value);
+            byte b = Byte.parseByte((String) bAsStr);
+            decoded[i++] = b;
+        }
+
+        return en.encode(decoded);
+    }
+
+}
index 35fa0428ec1cd60ed4a9e39415ce219c2a06ae9c..f8916ecac2244943b55abe0dd036e0e52204f3f3 100644 (file)
@@ -55,7 +55,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
 
 import javax.management.InstanceAlreadyExistsException;
@@ -125,6 +124,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
         edit("netconfMessages/editConfig.xml");
         checkBinaryLeafEdited(getConfigCandidate());
 
+
         // default-operation:none, should not affect binary leaf
         edit("netconfMessages/editConfig_none.xml");
         checkBinaryLeafEdited(getConfigCandidate());
@@ -132,7 +132,6 @@ public class NetconfMappingTest extends AbstractConfigTest {
         // check after edit
         commit();
         Element response = getConfigRunning();
-        System.err.println(XmlUtil.toString(response));
 
         checkBinaryLeafEdited(response);
         checkTypeConfigAttribute(response);
@@ -165,6 +164,15 @@ public class NetconfMappingTest extends AbstractConfigTest {
         verifyNoMoreInteractions(netconfOperationRouter);
     }
 
+    private void checkBigDecimal(Element response) {
+        String responseTrimmed = XmlUtil.toString(response).replaceAll("\\s", "");
+
+        assertContainsString(responseTrimmed, "<sleep-factorxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">2.58</sleep-factor>");
+        // Default
+        assertContainsString(responseTrimmed, "<sleep-factorxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">2.00</sleep-factor>");
+
+    }
+
     private void closeSession() throws NetconfDocumentedException, ParserConfigurationException, SAXException,
             IOException {
         DefaultCloseSession closeOp = new DefaultCloseSession(NETCONF_SESSION_ID);
@@ -232,14 +240,9 @@ public class NetconfMappingTest extends AbstractConfigTest {
             edit("netconfMessages/namespaces/editConfig_sameAttrDifferentNamespaces.xml");
         } catch (NetconfDocumentedException e) {
             String message = e.getMessage();
-            assertThat(message,
-                    JUnitMatchers
-                            .containsString("Element simple-long-2 present multiple times with different namespaces"));
-            assertThat(message,
-                    JUnitMatchers.containsString("urn:opendaylight:params:xml:ns:yang:controller:test:impl"));
-            assertThat(message,
-                    JUnitMatchers
-                            .containsString(XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG));
+            assertContainsString(message, "Element simple-long-2 present multiple times with different namespaces");
+            assertContainsString(message, "urn:opendaylight:params:xml:ns:yang:controller:test:impl");
+            assertContainsString(message, XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
             throw e;
         }
     }
@@ -250,9 +253,9 @@ public class NetconfMappingTest extends AbstractConfigTest {
             edit("netconfMessages/namespaces/editConfig_differentNamespaceTO.xml");
         } catch (NetconfDocumentedException e) {
             String message = e.getMessage();
-            assertThat(message, JUnitMatchers.containsString("Unrecognised elements"));
-            assertThat(message, JUnitMatchers.containsString("simple-int2"));
-            assertThat(message, JUnitMatchers.containsString("dto_d"));
+            assertContainsString(message, "Unrecognised elements");
+            assertContainsString(message, "simple-int2");
+            assertContainsString(message, "dto_d");
             throw e;
         }
     }
@@ -263,13 +266,9 @@ public class NetconfMappingTest extends AbstractConfigTest {
             edit("netconfMessages/namespaces/editConfig_sameAttrDifferentNamespacesList.xml");
         } catch (NetconfDocumentedException e) {
             String message = e.getMessage();
-            assertThat(message,
-                    JUnitMatchers.containsString("Element binaryLeaf present multiple times with different namespaces"));
-            assertThat(message,
-                    JUnitMatchers.containsString("urn:opendaylight:params:xml:ns:yang:controller:test:impl"));
-            assertThat(message,
-                    JUnitMatchers
-                            .containsString(XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG));
+            assertContainsString(message, "Element binaryLeaf present multiple times with different namespaces");
+            assertContainsString(message, "urn:opendaylight:params:xml:ns:yang:controller:test:impl");
+            assertContainsString(message, XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
             throw e;
         }
     }
@@ -306,8 +305,8 @@ public class NetconfMappingTest extends AbstractConfigTest {
             try {
                 edit(file);
             } catch (NetconfDocumentedException e) {
-                assertThat(e.getMessage(), JUnitMatchers.containsString("Unrecognised elements"));
-                assertThat(e.getMessage(), JUnitMatchers.containsString("unknownAttribute"));
+                assertContainsString(e.getMessage(), "Unrecognised elements");
+                assertContainsString(e.getMessage(), "unknownAttribute");
                 continue;
             }
             fail("Unrecognised test should throw exception " + file);
@@ -353,22 +352,37 @@ public class NetconfMappingTest extends AbstractConfigTest {
     }
 
     private void checkBinaryLeafEdited(final Element response) {
-        final NodeList children = response.getElementsByTagName("binaryLeaf");
-        assertEquals(3, children.getLength());
-        final StringBuffer buf = new StringBuffer();
-        for (int i = 0; i < 3; i++) {
-            final Element e = (Element) children.item(i);
-            buf.append(XmlElement.fromDomElement(e).getTextContent());
-        }
-        assertEquals("810", buf.toString());
+        String responseTrimmed = XmlUtil.toString(response).replaceAll("\\s", "");
+        String substring = "<binaryLeafxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">YmluYXJ5</binaryLeaf>";
+        assertContainsString(responseTrimmed, substring);
+        substring = "<binaryLeafxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">ZGVmYXVsdEJpbg==</binaryLeaf>";
+        assertContainsString(responseTrimmed, substring);
     }
 
     private void checkTypedefs(final Element response) {
-        NodeList children = response.getElementsByTagName("extended");
-        assertEquals(1, children.getLength());
+        String responseTrimmed = XmlUtil.toString(response).replaceAll("\\s", "");
+
+        String substring = "<extendedxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">10</extended>";
+        assertContainsString(responseTrimmed, substring);
+        // Default
+        assertContainsString(responseTrimmed,
+                "<extendedxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">1</extended>");
 
-        children = response.getElementsByTagName("extended-twice");
-        assertEquals(1, children.getLength());
+        assertContainsString(responseTrimmed,
+                "<extended-twicexmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">20</extended-twice>");
+        // Default
+        assertContainsString(responseTrimmed,
+                "<extended-twicexmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">2</extended-twice>");
+
+        assertContainsString(responseTrimmed,
+                "<extended-enumxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">TWO</extended-enum>");
+        // Default
+        assertContainsString(responseTrimmed,
+                "<extended-enumxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">ONE</extended-enum>");
+    }
+
+    private void assertContainsString(String string, String substring) {
+        assertThat(string, JUnitMatchers.containsString(substring));
     }
 
     private void checkEnum(final Element response) {
@@ -396,12 +410,6 @@ public class NetconfMappingTest extends AbstractConfigTest {
         assertEquals(2, testingDepsSize);
     }
 
-    private void checkBigDecimal(Element response) {
-        int size = response.getElementsByTagName("sleep-factor").getLength();
-        assertEquals(1, size);
-    }
-
-
     private void checkTypeConfigAttribute(Element response) {
 
         XmlElement modulesElement = XmlElement.fromDomElement(response).getOnlyChildElement("data")
@@ -458,17 +466,17 @@ public class NetconfMappingTest extends AbstractConfigTest {
         RuntimeRpc netconf = new RuntimeRpc(yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID);
 
         response = executeOp(netconf, "netconfMessages/rpc.xml");
-        assertThat(XmlUtil.toString(response), JUnitMatchers.containsString("testarg1".toUpperCase()));
+        assertContainsString(XmlUtil.toString(response), "testarg1".toUpperCase());
 
         response = executeOp(netconf, "netconfMessages/rpcInner.xml");
-        assertThat(XmlUtil.toString(response), JUnitMatchers.containsString("ok"));
+        assertContainsString(XmlUtil.toString(response), "ok");
 
         response = executeOp(netconf, "netconfMessages/rpcInnerInner.xml");
-        assertThat(XmlUtil.toString(response), JUnitMatchers.containsString("true"));
+        assertContainsString(XmlUtil.toString(response), "true");
 
         response = executeOp(netconf, "netconfMessages/rpcInnerInner_complex_output.xml");
-        assertThat(XmlUtil.toString(response), JUnitMatchers.containsString("1"));
-        assertThat(XmlUtil.toString(response), JUnitMatchers.containsString("2"));
+        assertContainsString(XmlUtil.toString(response), "1");
+        assertContainsString(XmlUtil.toString(response), "2");
     }
 
     private Element get() throws NetconfDocumentedException, ParserConfigurationException, SAXException, IOException {
index dc522d2e64a5601f019e0ce9be476bb2d7e7df71..94b73f4b100754e17918b9d5d75bed8542130f46 100644 (file)
                     <name>test1</name>
 
                     <sleep-factor>
-                        2.00
+                        2.58
                     </sleep-factor>
 
                     <extended>
-                            1
+                            10
                     </extended>
 
                     <extended-twice>
-                            1
+                            20
                     </extended-twice>
 
                     <extended-enum>
@@ -48,9 +48,8 @@
                     </extended-enum>
 
                     <simple-long-2>44</simple-long-2>
-                    <binaryLeaf>8</binaryLeaf>
-                    <binaryLeaf>1</binaryLeaf>
-                    <binaryLeaf>0</binaryLeaf>
+                    <binaryLeaf>YmluYXJ5</binaryLeaf>
+
                     <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
                     <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
                         <simple-int1>444</simple-int1>
index 388aa4f2ab6b528d8e701be6e9689d5513395ad2..b48730d3f71e74a86fde37131c38602d3f1169c1 100644 (file)
@@ -27,9 +27,7 @@
                     </type>
                     <name>test1</name>
                     <simple-long-2>44</simple-long-2>
-                    <binaryLeaf>8</binaryLeaf>
-                    <binaryLeaf>7</binaryLeaf>
-                    <binaryLeaf>9</binaryLeaf>
+                    <binaryLeaf>8ad1</binaryLeaf>
                     <dto_d>
                         <simple-int1>444</simple-int1>
                         <simple-int2>4444</simple-int2>
index 4d94d9e94962a529fc666eafc5c3ffac077cef5e..df2a5e845257c6b8308ad03eac43a91feb687772 100644 (file)
@@ -32,9 +32,7 @@
                     <name>test1</name>
 
                     <simple-long-2>44</simple-long-2>
-                    <binaryLeaf>8</binaryLeaf>
-                    <binaryLeaf>1</binaryLeaf>
-                    <binaryLeaf>0</binaryLeaf>
+                    <binaryLeaf>8545649856</binaryLeaf>
                     <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
                     <dto_d>
                         <simple-int1>444</simple-int1>
index 0e70e13a34417b885193310f12b803d6c007e2d2..02aca8d787863a2683db402b0c3a9a82ed6ff699 100644 (file)
@@ -32,9 +32,7 @@
                     <name>test1</name>
 
                     <simple-long-2>44</simple-long-2>
-                    <binaryLeaf>8</binaryLeaf>
-                    <binaryLeaf>1</binaryLeaf>
-                    <binaryLeaf>0</binaryLeaf>
+                    <binaryLeaf>8545649856</binaryLeaf>
                     <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
                         <simple-int1>444</simple-int1>
                         <simple-int2>4444</simple-int2>
index d03bb084b824370f00bd84986dcd5ae6b6746dff..825be6d19fff18b2d8ccb0c078e6266e4e89c3f1 100644 (file)
@@ -32,9 +32,7 @@
                     <name>test1</name>
 
                     <simple-long-2>44</simple-long-2>
-                    <binaryLeaf>8</binaryLeaf>
-                    <binaryLeaf>1</binaryLeaf>
-                    <binaryLeaf>0</binaryLeaf>
+                    <binaryLeaf>8545649856</binaryLeaf>
                     <dto_d>
                         <unknownAttribute>error</unknownAttribute>
                         <simple-int1>444</simple-int1>
index 3722973912192f79c7b70700e4172cdcb888d2cb..9ef2bed7d70dfb7654df642480cacc3df354baae 100644 (file)
@@ -32,9 +32,7 @@
                     <name>test1</name>
 
                     <simple-long-2>44</simple-long-2>
-                    <binaryLeaf>8</binaryLeaf>
-                    <binaryLeaf>1</binaryLeaf>
-                    <binaryLeaf>0</binaryLeaf>
+                    <binaryLeaf>8545649856</binaryLeaf>
                     <dto_d>
                         <simple-int1>444</simple-int1>
                         <simple-int2>4444</simple-int2>
index f26bcf718c75216078d4b7f37f16d19603ec20bf..e2fa8d5f1e4f89e0980da755c340d4585a78c379 100644 (file)
@@ -36,6 +36,7 @@ import org.opendaylight.controller.sal.flowprogrammer.Flow;
 import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService;
 import org.opendaylight.controller.sal.match.Match;
 import org.opendaylight.controller.sal.match.MatchType;
+import org.opendaylight.controller.sal.utils.EtherTypes;
 import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.HexEncode;
 import org.opendaylight.controller.sal.utils.NodeCreator;
@@ -225,6 +226,11 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService,
                     action, "Invalid node type"));
         }
 
+        Status status = validateFlow(flow);
+        if (!status.isSuccess()) {
+            return status;
+        }
+
         if (controller != null) {
             ISwitch sw = controller.getSwitch((Long) node.getID());
             if (sw != null) {
@@ -256,12 +262,52 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService,
                 "Internal plugin error"));
     }
 
+    /*
+     * Method which runs openflow 1.0 specific validation on the requested flow
+     * This validation is needed because the openflow switch will silently accept
+     * the request and install only the applicable match fields
+     */
+    private Status validateFlow(Flow flow) {
+        Match m = flow.getMatch();
+        boolean isIPEthertypeSet = m.isPresent(MatchType.DL_TYPE)
+                && (m.getField(MatchType.DL_TYPE).getValue().equals(EtherTypes.IPv4.shortValue()) || m
+                        .getField(MatchType.DL_TYPE).getValue().equals(EtherTypes.IPv6.shortValue()));
+
+        // network address check
+        if ((m.isPresent(MatchType.NW_SRC) || m.isPresent(MatchType.NW_DST)) && !isIPEthertypeSet) {
+            return new Status(StatusCode.NOTACCEPTABLE,
+                    "The match on network source or destination address cannot be accepted if the match "
+                     + "on proper ethertype is missing");
+        }
+
+        // transport protocol check
+        if (m.isPresent(MatchType.NW_PROTO) && !isIPEthertypeSet) {
+            return new Status(StatusCode.NOTACCEPTABLE,
+                    "The match on network protocol cannot be accepted if the match on proper ethertype is missing");
+        }
+
+        // transport ports check
+        if ((m.isPresent(MatchType.TP_SRC) || m.isPresent(MatchType.TP_DST))
+                && (!isIPEthertypeSet || m.isAny(MatchType.NW_PROTO))) {
+            return new Status(
+                    StatusCode.NOTACCEPTABLE,
+                    "The match on transport source or destination port cannot be accepted if the match on network protocol and match on IP ethertype are missing");
+        }
+        return new Status(StatusCode.SUCCESS);
+    }
+
     private Status modifyFlowInternal(Node node, Flow oldFlow, Flow newFlow, long rid) {
         String action = "modify";
         if (!node.getType().equals(NodeIDType.OPENFLOW)) {
             return new Status(StatusCode.NOTACCEPTABLE, errorString("send",
                     action, "Invalid node type"));
         }
+
+        Status status = validateFlow(newFlow);
+        if (!status.isSuccess()) {
+            return status;
+        }
+
         if (controller != null) {
             ISwitch sw = controller.getSwitch((Long) node.getID());
             if (sw != null) {
index f4843cf8283f36f2dc4ae957c2e46c42d363e4d6..2b26ecb749447aa3e31648c3d425f641a11a82e2 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.controller.protocol_plugin.openflow.internal;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
@@ -238,6 +239,7 @@ public class InventoryServiceShim implements IContainerListener,
     @Override
     public void switchAdded(ISwitch sw) {
         if (sw == null) {
+            logger.debug("Ignore null switch addition");
             return;
         }
         Node node = NodeCreator.createOFNode(sw.getId());
@@ -246,17 +248,24 @@ public class InventoryServiceShim implements IContainerListener,
             return;
         }
 
-        // Add all the nodeConnectors of this switch
-        Map<NodeConnector, Set<Property>> ncProps = InventoryServiceHelper
-                .OFSwitchToProps(sw);
-        for (Map.Entry<NodeConnector, Set<Property>> entry : ncProps.entrySet()) {
-            Set<Property> props = new HashSet<Property>();
-            Set<Property> prop = entry.getValue();
-            if (prop != null) {
-                props.addAll(prop);
+        // Add all the nodeConnectors of this switch if any
+        Map<NodeConnector, Set<Property>> ncProps = InventoryServiceHelper.OFSwitchToProps(sw);
+        if (!ncProps.isEmpty()) {
+            for (Map.Entry<NodeConnector, Set<Property>> entry : ncProps.entrySet()) {
+                Set<Property> props = new HashSet<Property>();
+                Set<Property> prop = entry.getValue();
+                if (prop != null) {
+                    props.addAll(prop);
+                }
+                nodeConnectorProps.put(entry.getKey(), props);
+                notifyInventoryShimListener(entry.getKey(), UpdateType.ADDED, entry.getValue());
             }
-            nodeConnectorProps.put(entry.getKey(), props);
-            notifyInventoryShimListener(entry.getKey(), UpdateType.ADDED, entry.getValue());
+        } else {
+            /*
+             * If no node connector is present, publish the node addition itself
+             * in order to let Connection Manager properly set the node locality
+             */
+            this.notifyInventoryShimListener(node, UpdateType.ADDED, Collections.<Property>emptySet());
         }
 
         // Add this node
index eb33ad67995f2621fd95024c0736e897fb6f18ee..e4c3961a140da41ff0078c893fe198677c2353b7 100644 (file)
@@ -48,6 +48,7 @@ public class NodeTableStatistics implements Serializable {
         result = prime * result + activeCount;
         result = prime * result + (int) (lookupCount ^ (lookupCount >>> 32));
         result = prime * result + (int) (matchedCount ^ (matchedCount >>> 32));
+        result = prime * result + maximumEntries;
         result = prime * result + ((name == null) ? 0 : name.hashCode());
         result = prime * result + ((nodeTable == null) ? 0 : nodeTable.hashCode());
         return result;
@@ -74,6 +75,9 @@ public class NodeTableStatistics implements Serializable {
         if (matchedCount != other.matchedCount) {
             return false;
         }
+        if (maximumEntries != other.maximumEntries) {
+            return false;
+        }
         if (name == null) {
             if (other.name != null) {
                 return false;
@@ -169,7 +173,7 @@ public class NodeTableStatistics implements Serializable {
     /**
      * @return the maximumEntries
      */
-    public long getMaximumEntries() {
+    public int getMaximumEntries() {
         return maximumEntries;
     }
 
@@ -185,6 +189,7 @@ public class NodeTableStatistics implements Serializable {
         return "NodeTableStats[tableId = " + nodeTable
                 + ", activeCount = " + activeCount
                 + ", lookupCount = " + lookupCount
-                + ", matchedCount = " + matchedCount + "]";
+                + ", matchedCount = " + matchedCount
+                + ", maximumEntries = " + maximumEntries + "]";
     }
 }
index 4950cae33a9fc37813afb963250e31a5ff71e824..217b8d46904aad44eee3ed399b2651d77826da0e 100644 (file)
@@ -461,6 +461,10 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
             if (!status.isSuccess()) {
                 return status;
             }
+        } else {
+            if (conf.getName().equals(DEFAULT_SUBNET_NAME)) {
+                return new Status(StatusCode.NOTALLOWED, "The specified subnet gateway cannot be removed");
+            }
         }
 
         // Update Database
@@ -492,6 +496,9 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
 
     @Override
     public Status removeSubnet(String name) {
+        if (name.equals(DEFAULT_SUBNET_NAME)) {
+            return new Status(StatusCode.NOTALLOWED, "The specified subnet gateway cannot be removed");
+        }
         SubnetConfig conf = subnetsConfigList.get(name);
         if (conf == null) {
             return new Status(StatusCode.SUCCESS, "Subnet not present");
index 6867ef4b9806379ad533f7292a76b929c5a0c8f4..0c14dea38a4a9ff69993d1e6a88503ceb5db0792 100644 (file)
@@ -27,6 +27,8 @@ import org.opendaylight.controller.sal.authorization.AuthResultEnum;
 import org.opendaylight.controller.sal.utils.HexEncode;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Configuration Java Object which represents a Local AAA user configuration
@@ -36,6 +38,23 @@ import org.opendaylight.controller.sal.utils.StatusCode;
 @XmlAccessorType(XmlAccessType.NONE)
 public class UserConfig implements Serializable {
     private static final long serialVersionUID = 1L;
+    private static Logger log = LoggerFactory.getLogger(UserConfig.class);
+    private static final boolean strongPasswordCheck = Boolean.getBoolean("enableStrongPasswordCheck");
+    private static final String DIGEST_ALGORITHM = "SHA-384";
+    private static final String BAD_PASSWORD = "Bad Password";
+    private static final int USERNAME_MAXLENGTH = 32;
+    protected static final String PASSWORD_REGEX = "(?=.*[^a-zA-Z0-9])(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,256}$";
+    private static final Pattern INVALID_USERNAME_CHARACTERS = Pattern.compile("([/\\s\\.\\?#%;\\\\]+)");
+    private static MessageDigest oneWayFunction;
+
+    static {
+        try {
+            UserConfig.oneWayFunction = MessageDigest.getInstance(DIGEST_ALGORITHM);
+        } catch (NoSuchAlgorithmException e) {
+            log.error(String.format("Implementation of %s digest algorithm not found: %s", DIGEST_ALGORITHM,
+                    e.getMessage()));
+        }
+    }
 
     /**
      * User Id
@@ -48,7 +67,7 @@ public class UserConfig implements Serializable {
      * example
      * System-Admin
      * Network-Admin
-     * Netowrk-Operator
+     * Network-Operator
      */
     @XmlElement
     protected List<String> roles;
@@ -62,20 +81,7 @@ public class UserConfig implements Serializable {
     @XmlElement
     private String password;
 
-    private static final boolean strongPasswordCheck = Boolean.getBoolean("enableStrongPasswordCheck");
-    private static final String BAD_PASSWORD = "Bad Password";
-    private static final int USERNAME_MAXLENGTH = 32;
-    protected static final String PASSWORD_REGEX = "(?=.*[^a-zA-Z0-9])(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,256}$";
-    private static final Pattern INVALID_USERNAME_CHARACTERS = Pattern.compile("([/\\s\\.\\?#%;\\\\]+)");
-    private static MessageDigest oneWayFunction = null;
 
-    static {
-        try {
-            UserConfig.oneWayFunction = MessageDigest.getInstance("SHA-1");
-        } catch (NoSuchAlgorithmException e) {
-            e.printStackTrace();
-        }
-    }
 
     public UserConfig() {
     }
index 8a7c3983d1cae6e7c2260c00dbdeb8d1263065f2..259ffde4b447e1d5d8c916ff96a26ee38198b3bf 100644 (file)
@@ -142,17 +142,17 @@ public class Flows implements IDaylightWeb {
         }
 
         Map<String, Object> nodes = new HashMap<String, Object>();
-        Map<Short, String> port;
+        Map<String, String> port;
 
         for (Switch node : switchManager.getNetworkDevices()) {
-            port = new HashMap<Short, String>(); // new port
+            port = new HashMap<String, String>(); // new port
             Set<NodeConnector> nodeConnectorSet = node.getNodeConnectors();
 
             if (nodeConnectorSet != null) {
                 for (NodeConnector nodeConnector : nodeConnectorSet) {
                     String nodeConnectorName = ((Name) switchManager.getNodeConnectorProp(nodeConnector,
                             Name.NamePropName)).getValue();
-                    port.put((Short) nodeConnector.getID(),
+                    port.put( nodeConnector.getID().toString(),
                             nodeConnectorName + "(" + nodeConnector.getNodeConnectorIDString() + ")");
                 }
             }
index 3c28152c25fa0a16e7263d3b69b2fa49f8264306..4c8a6b8439f2b18482a848605e1f5e234a27f8cd 100644 (file)
@@ -143,17 +143,22 @@ public class DaylightWebAdmin {
         return gson.toJson(result);
     }
 
-    @RequestMapping("/users")
+    @RequestMapping(value = "/users", method = RequestMethod.GET)
     @ResponseBody
-    public List<UserConfig> getUsers() {
+    public List<UserBean> getUsers() {
         IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
         if (userManager == null) {
             return null;
         }
 
-        List<UserConfig> userConfList = userManager.getLocalUserList();
+        List<UserBean> result = new ArrayList<UserBean>();
+        List<UserConfig> configs = userManager.getLocalUserList();
+        for (UserConfig config : configs) {
+            UserBean bean = new UserBean(config);
+            result.add(bean);
+        }
 
-        return userConfList;
+        return result;
     }
 
     /*
diff --git a/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/UserBean.java b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/UserBean.java
new file mode 100644 (file)
index 0000000..4d30ed3
--- /dev/null
@@ -0,0 +1,27 @@
+package org.opendaylight.controller.web;
+
+import java.util.List;
+
+import org.opendaylight.controller.usermanager.UserConfig;
+
+public class UserBean {
+    private String user;
+    private List<String> roles;
+
+    public UserBean(String user, List<String> roles) {
+        this.user = user;
+        this.roles = roles;
+    }
+
+    public UserBean(UserConfig config) {
+        this(config.getUser(), config.getRoles());
+    }
+
+    public String getUser() {
+        return user;
+    }
+
+    public List<String> getRoles() {
+        return roles;
+    }
+}
\ No newline at end of file