From: Ed Warnicke Date: Tue, 10 Dec 2013 20:01:51 +0000 (+0000) Subject: Merge "Fixed deserialization of IdentityRefs in Restconf URI." X-Git-Tag: jenkins-controller-bulk-release-prepare-only-2-1~213 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=43b37a609662f705d2dd701cb8b7c479144d2ef1;hp=fa6fb41931d79ecb8088904219e8ffd92e6e2b09 Merge "Fixed deserialization of IdentityRefs in Restconf URI." --- diff --git a/opendaylight/config/logback-config/src/main/yang/config-logging.yang b/opendaylight/config/logback-config/src/main/yang/config-logging.yang index 7f4ea39dd4..3b28b57469 100644 --- a/opendaylight/config/logback-config/src/main/yang/config-logging.yang +++ b/opendaylight/config/logback-config/src/main/yang/config-logging.yang @@ -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; diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/TemplateFactory.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/TemplateFactory.java index 6da68018f2..115bb85b61 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/TemplateFactory.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/TemplateFactory.java @@ -129,7 +129,7 @@ public class TemplateFactory { for (JavaAttribute ja : rpc.getParameters()) { Field field = new Field(Collections. 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 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 attributes, String packageName) { for (Entry 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(); diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/Field.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/Field.java index fe9e885b6f..0857ec6f8d 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/Field.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/Field.java @@ -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. newArrayList(), type, name, null); } + public Field(String type, String name, String definition) { + this(Lists. newArrayList(), type, name, definition); + } + public Field(List modifiers, String type, String name) { this(modifiers, type, name, null); } diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java b/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java index 2f1437404a..1945cac1c2 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java @@ -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"); diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ModuleMXBeanEntryTemplatesTest.java b/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ModuleMXBeanEntryTemplatesTest.java index 3c47931896..48d5b30eb2 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ModuleMXBeanEntryTemplatesTest.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ModuleMXBeanEntryTemplatesTest.java @@ -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; } diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntry.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntry.java index a7110b874c..4eba739b46 100644 --- a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntry.java +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntry.java @@ -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 getProvidedServices() { return providedServices; @@ -360,7 +362,6 @@ public class ModuleMXBeanEntry extends AbstractEntry { e.getConflictingName(), when.getQName(), when.getQName()); } - checkUniqueRuntimeBeansGeneratedClasses( uniqueGeneratedClassesNames, when, runtimeBeans); Set runtimeBeanEntryValues = Sets @@ -415,6 +416,11 @@ public class ModuleMXBeanEntry extends AbstractEntry { . emptyList()); } } + // check attributes name uniqueness + for (Entry 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 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 uniqueGeneratedClassNames, QName parentQName, Map yangToAttributes) { @@ -566,7 +591,8 @@ public class ModuleMXBeanEntry extends AbstractEntry { private static AttributeIfc getAttributeValue(DataSchemaNode attrNode, Module currentModule, Map 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 dependencyAttributeOptional = extractDependency(containerSchemaNode, - attrNode, currentModule, qNamesToSIEs, schemaContext); + Optional 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 dependencyAttributeOptional = extractDependency(listSchemaNode, - attrNode, currentModule, qNamesToSIEs, schemaContext); + Optional 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 extractDependency(DataNodeContainer dataNodeContainer, - DataSchemaNode attrNode, - Module currentModule, - Map qNamesToSIEs, - SchemaContext schemaContext) { + private static Optional extractDependency( + DataNodeContainer dataNodeContainer, DataSchemaNode attrNode, + Module currentModule, + Map 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); } diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/TypeProviderWrapper.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/TypeProviderWrapper.java index a2238d1a13..764ecd3886 100644 --- a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/TypeProviderWrapper.java +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/TypeProviderWrapper.java @@ -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 { diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/JavaAttribute.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/JavaAttribute.java index 325ca9ee06..3e20e4a55a 100644 --- a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/JavaAttribute.java +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/JavaAttribute.java @@ -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; diff --git a/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryNameConflictTest.java b/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryNameConflictTest.java index deef08a292..9032a2c930 100644 --- a/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryNameConflictTest.java +++ b/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryNameConflictTest.java @@ -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 index 0000000000..58c3af262c --- /dev/null +++ b/opendaylight/config/yang-jmx-generator/src/test/resources/duplicates/config-test-duplicate-attribute-in-runtime-and-mxbean.yang @@ -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 diff --git a/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang b/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang index bd83a4cc70..9ad7a44915 100644 --- a/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang +++ b/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang @@ -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 { diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index adc0c0973f..4c0b81f7d7 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -441,6 +441,23 @@ org.opendaylight.controller.thirdparty ganymed + + org.opendaylight.controller + sal-remoterpc-connector + 1.0-SNAPSHOT + + + org.opendaylight.controller + + zeromq-routingtable.implementation + + 0.4.1-SNAPSHOT + + + org.zeromq + jeromq + 0.3.1 + diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/00-netty.conf b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/00-netty.conf index e83fdcc5c8..c2f9bc311d 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/00-netty.conf +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/00-netty.conf @@ -20,25 +20,25 @@ netty:netty-threadgroup global-boss-group - /config/modules/module[name='netty-threadgroup-fixed']/instance[name='global-boss-group'] + /modules/module[type='netty-threadgroup-fixed'][name='global-boss-group'] global-worker-group - /config/modules/module[name='netty-threadgroup-fixed']/instance[name='global-worker-group'] + /modules/module[type='netty-threadgroup-fixed'][name='global-worker-group'] netty:netty-event-executor global-event-executor - /config/modules/module[name='netty-global-event-executor']/instance[name='global-event-executor'] + /modules/module[type='netty-global-event-executor'][name='global-event-executor'] netty:netty-timer global-timer - /config/modules/module[name='netty-hashed-wheel-timer']/instance[name='global-timer'] + /modules/module[type='netty-hashed-wheel-timer'][name='global-timer'] //CAPABILITIES START diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.conf b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.conf index 430a278a60..fa33215ea6 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.conf +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.conf @@ -58,60 +58,60 @@ dom:schema-service ref_yang-schema-service - /config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service'] + /modules/module[type='schema-service-singleton'][name='yang-schema-service'] binding:binding-notification-service ref_binding-notification-broker - /config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker'] + /modules/module[type='binding-notification-broker'][name='binding-notification-broker'] dom:dom-data-store ref_hash-map-data-store - /config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store'] + /modules/module[type='hash-map-data-store'][name='hash-map-data-store'] - ref_cluster-data-store - /config/modules/module[name='dom-clustered-store-impl']/instance[name='cluster-data-store'] - + ref_cluster-data-store + /modules/module[type='dom-clustered-store-impl'][name='cluster-data-store'] + binding:binding-broker-osgi-registry ref_binding-broker-impl - /config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl'] + /modules/module[type='binding-broker-impl'][name='binding-broker-impl'] binding:binding-rpc-registry - ref_binding-rpc-broker - /config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl'] + binding-rpc-broker + /modules/module[type='binding-broker-impl'][name='binding-broker-impl'] binding-impl:binding-dom-mapping-service ref_runtime-mapping-singleton - /config/modules/module[name='runtime-generated-mapping']/instance[name='runtime-mapping-singleton'] + /modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton'] dom:dom-broker-osgi-registry ref_dom-broker - /config/modules/module[name='dom-broker-impl']/instance[name='dom-broker'] + /modules/module[type='dom-broker-impl'][name='dom-broker'] binding:binding-data-broker ref_binding-data-broker - /config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker'] + /modules/module[type='binding-data-broker'][name='binding-data-broker'] //CAPABILITIES START diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend index 1e33481e70..6cf728cde9 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend @@ -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 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.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(); } diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java index b5ed3fe4c2..a8349be1b4 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java @@ -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; diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestFromSalConversionsUtils.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestFromSalConversionsUtils.java index cb70174103..b062b0016d 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestFromSalConversionsUtils.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestFromSalConversionsUtils.java @@ -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 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()); } } } diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestToSalConversionsUtils.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestToSalConversionsUtils.java index 97e1660443..793f3cc395 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestToSalConversionsUtils.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestToSalConversionsUtils.java @@ -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 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 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 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 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 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) { diff --git a/opendaylight/md-sal/forwardingrules-manager/pom.xml b/opendaylight/md-sal/forwardingrules-manager/pom.xml index 597483ef65..e2948fd54e 100644 --- a/opendaylight/md-sal/forwardingrules-manager/pom.xml +++ b/opendaylight/md-sal/forwardingrules-manager/pom.xml @@ -23,7 +23,7 @@ maven-bundle-plugin - org.opendaylight.controller.forwardingrulesmanager.consumer.impl.FRMConsumerImpl + org.opendaylight.controller.frm.FRMActivator diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/FRMUtil.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/FRMUtil.java index 24bfc4fdf4..ab2e19e9d4 100644 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/FRMUtil.java +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/FRMUtil.java @@ -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 = ((WriteActions) curInstruction).getAction(); + List action = ((WriteActionsCase) curInstruction).getWriteActions().getAction(); validateActions(action); } - else if (curInstruction instanceof ApplyActions) { - List action = ((ApplyActions) curInstruction).getAction(); + else if (curInstruction instanceof ApplyActionsCase) { + List action = ((ApplyActionsCase) curInstruction).getApplyActions().getAction(); validateActions(action); } - else if (curInstruction instanceof ClearActions) { - List action = ((ClearActions) curInstruction).getAction(); + else if (curInstruction instanceof ClearActionsCase) { + List 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 index 0000000000..9f45a11d2d --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractTransaction.xtend @@ -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, DataObject> { + + @Property + val DataModification, DataObject> modification; + + new(DataModification, DataObject> modification) { + _modification = modification; + } + + def void validate() throws IllegalStateException + + override finish() throws IllegalStateException { + validate() + callRpcs(); + return Rpcs.getRpcResult(true, null, Collections.emptySet()); + } + + override getModification() { + return _modification; + } + + override rollback() throws IllegalStateException { + rollbackRpcs(); + return Rpcs.getRpcResult(true, null, Collections.emptySet()); + } + + def private callRpcs() { + val Set, 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, DataObject>> updatedEntries = new HashSet, DataObject>>(); + updatedEntries.addAll(_modification.getUpdatedConfigurationData().entrySet()); + updatedEntries.removeAll(createdEntries); + + val Set> removeEntriesInstanceIdentifiers = _modification.getRemovedConfigurationData(); + for (Entry, DataObject> entry : createdEntries) { + add(entry.key,entry.value); + } + for (Entry, 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, 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, DataObject>> updatedEntries = new HashSet, DataObject>>(); + updatedEntries.addAll(_modification.getUpdatedConfigurationData().entrySet()); + updatedEntries.removeAll(createdEntries); + + val Set> removeEntriesInstanceIdentifiers = _modification.getRemovedConfigurationData(); + for (Entry, DataObject> entry : createdEntries) { + remove(entry.key,entry.value); // because we are rolling back, remove what we would have added. + } + for (Entry, 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 index 0000000000..8ec9d79bfc --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FRMActivator.xtend @@ -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 index 0000000000..03095faaf1 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowCommitHandler.xtend @@ -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, DataObject> { + + @Property + val SalFlowService salFlowService; + + new(SalFlowService manager) { + _salFlowService = manager; + } + + override requestCommit(DataModification, 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 index 0000000000..e664c7bd3b --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.xtend @@ -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,DataObject>> commitHandlerRegistration; + + static val LOG = LoggerFactory.getLogger(FlowProvider); + + def void start() { + commitHandler = new FlowCommitHandler(salFlowService) + val InstanceIdentifier 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 index 0000000000..5203d3c1a8 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransaction.xtend @@ -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, 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 index 0000000000..f6ffdb81c7 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransactionValidator.java @@ -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 index 0000000000..2c5f42b0ac --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupCommitHandler.xtend @@ -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, DataObject> { + + @Property + val SalGroupService groupService; + + new(SalGroupService groupService) { + _groupService = groupService; + } + + override requestCommit(DataModification, 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 index 0000000000..a75a668b65 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.xtend @@ -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,DataObject>> commitHandlerRegistration; + + static val LOG = LoggerFactory.getLogger(GroupProvider); + + def void start() { + commitHandler = new GroupCommitHandler(salGroupService) + val InstanceIdentifier 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 index 0000000000..54382ea056 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransaction.xtend @@ -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, 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 index 0000000000..a264c332c9 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransactionValidator.java @@ -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 index 0000000000..dd8d4c7b40 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterCommitHandler.xtend @@ -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, DataObject> { + + @Property + val SalMeterService salMeterService; + + new(SalMeterService manager) { + _salMeterService = manager; + } + + override requestCommit(DataModification, 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 index 0000000000..75d29d54b7 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.xtend @@ -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,DataObject>> commitHandlerRegistration; + + static val LOG = LoggerFactory.getLogger(MeterProvider); + + def void start() { + commitHandler = new FlowCommitHandler(salMeterService) + val InstanceIdentifier 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 index 0000000000..3ed1f40735 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransaction.xtend @@ -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, 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 index 0000000000..d8afd2a60f --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransactionValidator.java @@ -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 index 3850dd551f..0000000000 --- a/opendaylight/md-sal/model/model-flow-base/src/main/yang/action-types.yang +++ /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 diff --git a/opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang b/opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang index f03e28b110..8c874e2fe8 100644 --- a/opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang +++ b/opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang @@ -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 diff --git a/opendaylight/md-sal/model/model-flow-base/src/main/yang/match-types.yang b/opendaylight/md-sal/model/model-flow-base/src/main/yang/match-types.yang index 5ba92aba9d..7dcd254ad7 100644 --- a/opendaylight/md-sal/model/model-flow-base/src/main/yang/match-types.yang +++ b/opendaylight/md-sal/model/model-flow-base/src/main/yang/match-types.yang @@ -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 index 0000000000..81303d6867 --- /dev/null +++ b/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-action-types.yang @@ -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 diff --git a/opendaylight/md-sal/model/model-flow-base/src/main/yang/flow-types.yang b/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-flow-types.yang 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 29ea8ddf18..e83306db50 100644 --- a/opendaylight/md-sal/model/model-flow-base/src/main/yang/flow-types.yang +++ b/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-flow-types.yang @@ -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; diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang index 005f7c330d..d717e87f76 100644 --- a/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang +++ b/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang @@ -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 index 0000000000..aaaedc1dc5 --- /dev/null +++ b/opendaylight/md-sal/model/model-inventory/src/main/yang/opendaylight-inventory-config.yang @@ -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 diff --git a/opendaylight/md-sal/pom.xml b/opendaylight/md-sal/pom.xml index 0e78598c11..b34621d02d 100644 --- a/opendaylight/md-sal/pom.xml +++ b/opendaylight/md-sal/pom.xml @@ -12,7 +12,7 @@ - + sal-common sal-common-api sal-common-impl @@ -42,45 +42,47 @@ sal-connector-api sal-rest-connector sal-netconf-connector - + + zeromq-routingtable/implementation + sal-remoterpc-connector/implementation clustered-data-store/implementation inventory-manager statistics-manager forwardingrules-manager - + compatibility - zeromq-routingtable/implementation - sal-zeromq-connector - integrationtests - - false - + integrationtests + + false + sal-binding-it - zeromq-routingtable/integrationtest clustered-data-store/integrationtest - test + + + - IDE - - - m2e.version - - - - - target-ide - + IDE + + + m2e.version + + + + + target-ide + @@ -103,9 +105,13 @@ 14.0.1 5.0.0 4.8.1 + 1.5.1 + 1.9.5 2.4.3 2.5 0.5.3.201107060350 + 0.5.1-SNAPSHOT + jacoco reuseReports @@ -119,28 +125,28 @@ - opendaylight-mirror - opendaylight-mirror - ${nexusproxy}/groups/public/ - - false - - - true - never - + opendaylight-mirror + opendaylight-mirror + ${nexusproxy}/groups/public/ + + false + + + true + never + - opendaylight-snapshot - opendaylight-snapshot - ${nexusproxy}/repositories/opendaylight.snapshot/ - - true - - - false - + opendaylight-snapshot + opendaylight-snapshot + ${nexusproxy}/repositories/opendaylight.snapshot/ + + true + + + false + @@ -148,28 +154,28 @@ - opendaylight-mirror - opendaylight-mirror - ${nexusproxy}/groups/public/ - - false - - - true - never - + opendaylight-mirror + opendaylight-mirror + ${nexusproxy}/groups/public/ + + false + + + true + never + - opendaylight-snapshot - opendaylight-snapshot - ${nexusproxy}/repositories/opendaylight.snapshot/ - - true - - - false - + opendaylight-snapshot + opendaylight-snapshot + ${nexusproxy}/repositories/opendaylight.snapshot/ + + true + + + false + @@ -216,6 +222,11 @@ yang-data-api ${yang.version} + + org.opendaylight.yangtools + yang-data-impl + ${yang.version} + org.opendaylight.yangtools yang-model-api @@ -232,6 +243,17 @@ sal-connector-api ${project.version} + + org.opendaylight.controller + sal + ${sal.version} + + + org.osgi + org.osgi.compendium + + + @@ -249,7 +271,11 @@ org.eclipse.xtend.lib ${xtend.version} - + + org.osgi + org.osgi.core + ${osgi.core.version} + junit @@ -260,7 +286,25 @@ org.mockito mockito-all - 1.9.5 + ${mockito.version} + test + + + org.powermock + powermock-module-junit4 + ${powermock.version} + test + + + org.powermock + powermock-api-mockito + ${powermock.version} + test + + + org.powermock + powermock-core + ${powermock.version} test @@ -278,15 +322,9 @@ maven-bundle-plugin ${bundle.plugin.version} true - + ${project.groupId}.${project.artifactId} @@ -328,7 +366,8 @@ jacoco-maven-plugin ${jacoco.version} - + org.eclipse.m2e lifecycle-mapping @@ -346,7 +385,7 @@ - + @@ -360,7 +399,7 @@ - + @@ -373,7 +412,7 @@ - + diff --git a/opendaylight/md-sal/sal-binding-broker/pom.xml b/opendaylight/md-sal/sal-binding-broker/pom.xml index ac84aab977..f9f72094f8 100644 --- a/opendaylight/md-sal/sal-binding-broker/pom.xml +++ b/opendaylight/md-sal/sal-binding-broker/pom.xml @@ -245,5 +245,25 @@ ${slf4j.version} test + + org.opendaylight.yangtools.model + ietf-inet-types + 2010.09.24.2-SNAPSHOT + + + org.opendaylight.controller.model + model-flow-base + 1.0-SNAPSHOT + + + org.opendaylight.controller.model + model-flow-service + 1.0-SNAPSHOT + + + org.opendaylight.controller.model + model-flow-statistics + 1.0-SNAPSHOT + 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 index 0000000000..bff77bec18 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AugmentationVerifier.java @@ -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> { + + private T object; + + public AugmentationVerifier(T objectToVerify) { + this.object = objectToVerify; + } + + public AugmentationVerifier assertHasAugmentation(Class> augmentation) { + assertHasAugmentation(object, augmentation); + return (AugmentationVerifier) this; + } + + public static > void assertHasAugmentation(T object, + Class> augmentation) { + Assert.assertNotNull(object); + Assert.assertNotNull("Augmentation " + augmentation.getSimpleName() + " is not present.", object.getAugmentation(augmentation)); + } + + public static > AugmentationVerifier from(T obj) { + return new AugmentationVerifier(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 index 0000000000..7d149192ac --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/BindingTestUtilities.java @@ -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 index 0000000000..6d1a699145 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/MultipleAugmentationPuts.java @@ -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 NODE_KEY_BI = Collections. singletonMap(NODE_ID_QNAME, + NODE_ID); + + private static final InstanceIdentifier NODES_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) // + .toInstance(); + + private static final InstanceIdentifier 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, 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 = nodeWithUpdatedList.getAugmentation(NodeMeterStatistics.class).getMeterStatistics().getMeterStats(); + assertNotNull(meterStats); + assertFalse(meterStats.isEmpty()); + assertBindingIndependentVersion(NODE_INSTANCE_ID_BI); + testNodeRemove(); + } + + private > Node createTestNode(Class 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 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 result = transaction.commit().get(); + assertEquals(TransactionStatus.COMMITED, result.getResult()); + + Node node = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA); + assertNull(node); + } + + private AugmentationVerifier 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(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 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, DataObject> change) { + receivedChangeEvent = change; + } + +} diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java index 5a98767ff8..56fbb9a525 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java @@ -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 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 instructionList = Collections.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()); diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java index 7111501b53..ea36f81b0b 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java @@ -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, 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, DataObject> modificationCapture; private static final Map NODE_KEY_BI = Collections. 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 FLOW_KEY_BI = // - ImmutableMap. of(FLOW_ID_QNAME, FLOW_ID, FLOW_NODE_QNAME, NODE_INSTANCE_ID_BI); + ImmutableMap. of(FLOW_ID_QNAME, FLOW_ID.getValue()); + + private static final Map TABLE_KEY_BI = // + ImmutableMap. 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_PATH_BA = // - InstanceIdentifier.builder(Flows.class) // - .toInstance(); - - + private static final TableKey TABLE_KEY_BA = new TableKey((short) 0); + + private static final InstanceIdentifier 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_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 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, DataObject> flowTestCommitHandler = new DataCommitHandler, DataObject>() { - - + @Override public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction, DataObject> requestCommit( DataModification, DataObject> modification) { modificationCapture = modification; return CommitHandlersTransactions.allwaysSuccessfulTransaction(modification); } - - + }; - Registration, DataObject>> registration = baDataService.registerCommitHandler(FLOWS_PATH_BA, flowTestCommitHandler); + Registration, 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 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 actionList = new ArrayList(); + 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 instructions = new ArrayList(); + instructions.add(ib.build()); + isb.setInstruction(instructions); - List instructionList = Collections.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; } diff --git a/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/AbstractTest.java b/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/AbstractTest.java index 338561ab48..9b814291b9 100644 --- a/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/AbstractTest.java +++ b/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/AbstractTest.java @@ -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()); } } diff --git a/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/Rpcs.java b/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/Rpcs.java index e46b566522..54e1a065f4 100644 --- a/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/Rpcs.java +++ b/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/Rpcs.java @@ -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 implements RpcResult { + private static class RpcResultTO implements RpcResult, Serializable { private final Collection errors; private final T result; diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractConsumer.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractConsumer.java index 1fb73bc9a9..99a38ca43a 100644 --- a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractConsumer.java +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractConsumer.java @@ -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 { + + + + + private BundleContext context; + private ServiceTracker tracker; + private Broker broker; - Broker broker; - ServiceReference 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 reference) { + if(broker == null) { + broker = context.getService(reference); + broker.registerConsumer(this, context); + return broker; + } + + return null; + } + + @Override + public void modifiedService(ServiceReference reference, Broker service) { + // NOOP + } + + @Override + public void removedService(ServiceReference reference, Broker service) { + stopImpl(context); + } } diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractProvider.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractProvider.java index 621ef92132..1cb1a2bc85 100644 --- a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractProvider.java +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/AbstractProvider.java @@ -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 { - private ServiceReference brokerRef; private Broker broker; - + private BundleContext context; + private ServiceTracker tracker; @Override public Collection 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 reference) { + if(broker == null) { + broker = context.getService(reference); + broker.registerProvider(this, context); + return broker; + } + + return null; + } + + @Override + public void modifiedService(ServiceReference reference, Broker service) { + // NOOP + } + + @Override + public void removedService(ServiceReference reference, Broker service) { + stopImpl(context); + } + } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend index 482cfa959f..dc116ca979 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend @@ -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(); 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 index 0000000000..b8e0938a5f --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/pom.xml @@ -0,0 +1,199 @@ + + + 4.0.0 + + org.opendaylight.controller + sal-parent + ../.. + 1.0-SNAPSHOT + + + sal-remoterpc-connector + bundle + + + 0.3.1 + 1.9.8 + 1.0.1 + + + + + + ${project.groupId} + sal-core-api + ${project.version} + + + ${project.groupId} + sal-connector-api + ${project.version} + + + ${project.groupId} + sal-common-util + ${project.version} + + + org.opendaylight.controller + zeromq-routingtable.implementation + + 0.4.1-SNAPSHOT + + + + + org.opendaylight.controller + sal + + + + + org.opendaylight.yangtools + yang-common + + + org.opendaylight.yangtools + yang-data-api + + + org.opendaylight.yangtools + yang-data-impl + + + org.opendaylight.yangtools + yang-common + + + + + org.osgi + org.osgi.core + + + org.zeromq + jeromq + ${zeromq.version} + + + com.google.guava + guava + + + org.slf4j + slf4j-api + + + org.codehaus.jackson + jackson-core-asl + ${jackson.version} + + + org.codehaus.jackson + jackson-mapper-asl + ${jackson.version} + + + stax + stax-api + ${stax.version} + + + + + junit + junit + + + org.mockito + mockito-all + + + org.powermock + powermock-module-junit4 + + + org.powermock + powermock-api-mockito + + + org.powermock + powermock-core + + + + + + + + + org.apache.felix + maven-bundle-plugin + ${bundle.plugin.version} + true + + + + *, + !org.codehaus.enunciate.jaxrs + + + org.opendaylight.controller.config.yang.md.sal.remote.rpc, + org.opendaylight.controller.sal.connector.remoterpc, + org.opendaylight.controller.sal.connector.remoterpc.* + + ${project.groupId}.${project.artifactId} + + + + + + + org.opendaylight.yangtools + yang-maven-plugin + 0.5.9-SNAPSHOT + + + + generate-sources + + + + + + org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + + ${project.build.directory}/generated-sources/config + + + urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang + + + + + org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl + target/site/models + + + true + + + + + + org.opendaylight.controller + yang-jmx-generator-plugin + 0.2.3-SNAPSHOT + + + org.opendaylight.yangtools + maven-sal-api-gen-plugin + 0.6.0-SNAPSHOT + jar + + + + + + 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 index 0000000000..606f282bd7 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/remote/rpc/ZeroMQServerModule.java @@ -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 index 0000000000..3cc3ac0f68 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/config/yang/md/sal/remote/rpc/ZeroMQServerModuleFactory.java @@ -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 index 0000000000..ef3162359c --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Client.java @@ -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 requestQueue = new LinkedBlockingQueue(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 getRequestQueue() { + return requestQueue; + } + + @Override + public Set 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 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 errors = new ArrayList(); + + 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 = routingTableProvider.getRoutingTable(); + checkNotNull(routingTable.isPresent(), "Routing table is null"); + + Set 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 errors) { + if (e == null) + return; + if (errors == null) + errors = new ArrayList(); + + 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 index 0000000000..f0bf12cbc0 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Context.java @@ -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 index 0000000000..6bd123b7e4 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcClient.java @@ -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 index 0000000000..3c2e3b0872 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProvider.java @@ -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 invokeRpc(QName rpc, CompositeNode input) { + return client.invokeRpc(rpc, input); + } + + @Override + public Set 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 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 index 0000000000..932600fcb1 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcServer.java @@ -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 index 0000000000..cfdf98638d --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RoutingTableProvider.java @@ -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 tracker; + + + public RoutingTableProvider(BundleContext ctx) { + @SuppressWarnings("rawtypes") + ServiceTracker rawTracker = new ServiceTracker<>(ctx, RoutingTable.class, null); + tracker = rawTracker; + tracker.open(); + } + + public Optional> getRoutingTable() { + @SuppressWarnings("unchecked") + RoutingTable 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 index 0000000000..7e8590ab9b --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RpcSocket.java @@ -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: + *
  • Retry logic - Tries 3 times before giving up + *
  • Request times out after {@link TIMEOUT} property + *
  • 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 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(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 index 0000000000..f53d5adc1c --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/Sender.java @@ -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 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 index 0000000000..83b93858cf --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ServerImpl.java @@ -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 { + + private Logger _logger = LoggerFactory.getLogger(ServerImpl.class); + + private ExecutorService serverPool; + + // private RoutingTable routingTable; + private RoutingTableProvider routingTable; + private Set 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(); + + // Start listening rpc requests + serverPool.execute(receive()); + + brokerSession.addRpcRegistrationListener(listener); + // routingTable.registerRouteChangeListener(routeChangeListener); + + Set 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> rpc = null; + RpcResult 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 index 0000000000..588a299626 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/SocketManager.java @@ -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 managedSockets = new ConcurrentHashMap(); + + 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://:' 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 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 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 index 0000000000..67b3a830e3 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/SocketPair.java @@ -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 index 0000000000..073601a1c0 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/CompositeNodeImpl.java @@ -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> children; + + @Override + public List> getChildren() { + return children; + } + + @Override + public List getCompositesByName(QName children) { + throw new UnsupportedOperationException(); + } + + @Override + public List getCompositesByName(String children) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List> getSimpleNodesByName(QName children) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List> 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> setValue(List> 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> get(Object key) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List> put(QName key, List> value) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List> remove(Object key) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void putAll(Map>> 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 keySet() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public Collection>> values() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public Set>>> 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> 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. + } +} diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/Message.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/Message.java similarity index 88% rename from opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/Message.java rename to opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/Message.java index c2c037aee6..95fe99c81c 100644 --- a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/Message.java +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/Message.java @@ -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 index 0000000000..8d2198c365 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/MessageWrapper.java @@ -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; + } +} diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/RouteIdentifierImpl.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/RouteIdentifierImpl.java similarity index 54% rename from opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/RouteIdentifierImpl.java rename to opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/RouteIdentifierImpl.java index ca404f2ca9..6c5e5fbf11 100644 --- a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/RouteIdentifierImpl.java +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/RouteIdentifierImpl.java @@ -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,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 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 index 0000000000..63b68089d3 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/scala/org/opendaylight/controller/sal/connector/remoterpc/Client.scala @@ -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 index 0000000000..d20efe50c1 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/yang/odl-sal-dom-rpc-remote-cfg.yang @@ -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 index 0000000000..2e77537756 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientTest.java @@ -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 index 0000000000..550d9ef125 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/RouteIdentifierImplTest.java @@ -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 index 0000000000..e23a3ca5ef --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/RpcSocketTest.java @@ -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 index 0000000000..36a4acddca --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/SerilizationTest.java @@ -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 index 0000000000..130b30d5f5 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/SocketManagerTest.java @@ -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.absent(), manager.getManagedSocketFor(nonManagedSocket) ); + Assert.assertSame(Optional.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 index 0000000000..5ac991b120 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/resources/FourSimpleChildren.xml @@ -0,0 +1,6 @@ + + eth0 + ethernetCsmacd + false + some interface + diff --git a/opendaylight/md-sal/test/zeromq-test-consumer/pom.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/pom.xml 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 7c6bc21b46..fa7b73be0e 100644 --- a/opendaylight/md-sal/test/zeromq-test-consumer/pom.xml +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/pom.xml @@ -2,11 +2,11 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - sal-test-parent + sal-remoterpc-connector-test-parent org.opendaylight.controller.tests 1.0-SNAPSHOT - zeromq-test-consumer + sal-remoterpc-connector-test-consumer bundle scm:git:ssh://git.opendaylight.org:29418/controller.git @@ -23,11 +23,6 @@ org.opendaylight.controller.sample.zeromq.consumer.ExampleConsumer - - org.opendaylight.controller.sal.core.api, - org.opendaylight.yangtools.yang.common;version="[0.5,1)", - org.opendaylight.yangtools.yang.data.api, - @@ -75,6 +70,11 @@ org.opendaylight.yangtools yang-data-api + + org.opendaylight.yangtools + yang-data-impl + 0.5.9-SNAPSHOT + org.opendaylight.controller 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 index 0000000000..87078ea712 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/java/org/opendaylight/controller/sample/zeromq/consumer/ExampleConsumer.java @@ -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 thisReg; + private Logger _logger = LoggerFactory.getLogger(ExampleConsumer.class); + + @Override + public void onSessionInitiated(ConsumerSession session) { + this.session = session; + } + + public RpcResult invokeRpc(QName qname, CompositeNode input) { + _logger.info("Invoking RPC:[{}] with Input:[{}]", qname.getLocalName(), input); + RpcResult result = null; + Future> 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()); + } + @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 index 0000000000..5ac991b120 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/FourSimpleChildren.xml @@ -0,0 +1,6 @@ + + eth0 + ethernetCsmacd + false + some interface + 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 index 0000000000..3979d02ccf --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/InvalidCompositeChild.xml @@ -0,0 +1,14 @@ + + + eth1 + ethernet + false + some interface + + + error + ethernet + true + some interface + + 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 index 0000000000..6082d72a71 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/InvalidSimpleChild.xml @@ -0,0 +1,3 @@ + + error + 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 index 0000000000..f431b0453d --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/OneSimpleChild.xml @@ -0,0 +1,3 @@ + + eth0 + 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 index 0000000000..bca7682ee7 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/OneSimpleOneCompositeChild.xml @@ -0,0 +1,9 @@ + + eth0 + + eth1 + ethernetCsmacd + false + some interface + + 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 index 0000000000..c49407e4c0 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/TwoCompositeChildren.xml @@ -0,0 +1,14 @@ + + + eth1 + ethernet + false + some interface + + + eth2 + ethernet + true + some interface + + 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 index 0000000000..5f4729c99d --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/src/main/resources/TwoSimpleChildren.xml @@ -0,0 +1,4 @@ + + eth0 + ethernetCsmacd + \ 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 index 0000000000..5bfbcba5f8 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/pom.xml @@ -0,0 +1,26 @@ + + 4.0.0 + + org.opendaylight.controller + sal-parent + 1.0-SNAPSHOT + ../.. + + pom + org.opendaylight.controller.tests + sal-remoterpc-connector-test-parent + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + + + + consumer-service + provider-service + test-it + test-nb + + + diff --git a/opendaylight/md-sal/test/zeromq-test-provider/pom.xml b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/provider-service/pom.xml 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 10e15aa917..a13a5aeba0 100644 --- a/opendaylight/md-sal/test/zeromq-test-provider/pom.xml +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/provider-service/pom.xml @@ -2,11 +2,11 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - sal-test-parent + sal-remoterpc-connector-test-parent org.opendaylight.controller.tests 1.0-SNAPSHOT - zeromq-test-provider + sal-remoterpc-connector-test-provider bundle scm:git:ssh://git.opendaylight.org:29418/controller.git @@ -70,7 +70,10 @@ org.opendaylight.yangtools yang-data-api - + + org.opendaylight.yangtools + yang-data-impl + org.opendaylight.controller sal-common-util @@ -78,7 +81,7 @@ org.opendaylight.controller - sal-zeromq-connector + sal-remoterpc-connector 1.0-SNAPSHOT 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 index 0000000000..6c294dddcc --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/provider-service/src/main/java/org/opendaylight/controller/sample/zeromq/provider/ExampleProvider.java @@ -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 getSupportedRpcs() { + Set supportedRpcs = new HashSet(); + supportedRpcs.add(QNAME); + return supportedRpcs; + } + + @Override + public RpcResult invokeRpc(final QName rpc, CompositeNode input) { + boolean success = false; + CompositeNode output = null; + Collection 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> list = new ArrayList>(input.getChildren()); + SimpleNodeTOImpl simpleNode = new SimpleNodeTOImpl(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()); + } + + @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 index 0000000000..4305a283e2 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/pom.xml @@ -0,0 +1,536 @@ + + 4.0.0 + + sal-remoterpc-connector-test-parent + org.opendaylight.controller.tests + 1.0-SNAPSHOT + + sal-remoterpc-connector-test-it + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + + + + 3.0.0 + 1.5.0 + 0.2.3-SNAPSHOT + 0.2.3-SNAPSHOT + + + + + + commons-codec + commons-codec + 1.7 + + + + + + + + + org.ops4j.pax.exam + maven-paxexam-plugin + 1.2.4 + + + generate-config + + generate-depends-file + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + + org.ops4j.pax.exam + + + maven-paxexam-plugin + + + [1.2.4,) + + + + generate-depends-file + + + + + + + + + + + + + + + + + + org.opendaylight.yangtools.thirdparty + xtend-lib-osgi + 2.4.3 + + + org.opendaylight.controller.tests + sal-remoterpc-connector-test-provider + 1.0-SNAPSHOT + + + org.opendaylight.controller.tests + sal-remoterpc-connector-test-consumer + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-broker-impl + 1.0-SNAPSHOT + + + org.ops4j.pax.exam + pax-exam-container-native + ${exam.version} + test + + + org.ops4j.pax.exam + pax-exam-junit4 + ${exam.version} + test + + + org.ops4j.pax.exam + pax-exam-link-mvn + ${exam.version} + test + + + org.ops4j.pax.url + pax-url-aether + 1.5.2 + test + + + equinoxSDK381 + org.eclipse.osgi + 3.8.1.v20120830-144521 + test + + + org.slf4j + log4j-over-slf4j + 1.7.2 + + + ch.qos.logback + logback-core + 1.0.9 + + + ch.qos.logback + logback-classic + 1.0.9 + + + org.opendaylight.controller + sal-binding-api + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-common-util + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-core-api + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-remoterpc-connector + 1.0-SNAPSHOT + + + + org.opendaylight.controller + containermanager + 0.5.1-SNAPSHOT + + + org.osgi + org.osgi.compendium + + + commons-io + commons-io + + + + + + org.opendaylight.yangtools + yang-binding + + + org.opendaylight.yangtools + yang-common + + + org.opendaylight.yangtools + yang-data-api + + + + org.opendaylight.yangtools + yang-parser-impl + 0.5.9-SNAPSHOT + + + org.opendaylight.controller + sal-common-util + 1.0-SNAPSHOT + + + org.opendaylight.yangtools.thirdparty + antlr4-runtime-osgi-nohead + 4.0 + + + + + org.opendaylight.controller + zeromq-routingtable.implementation + 0.4.1-SNAPSHOT + + + org.opendaylight.controller + clustering.services + 0.4.1-SNAPSHOT + + + org.opendaylight.controller + sal + 0.5.1-SNAPSHOT + + + org.osgi + org.osgi.compendium + + + + + org.opendaylight.controller + sal.implementation + 0.4.0-SNAPSHOT + + + commons-io + commons-io + + + + + org.opendaylight.controller + containermanager + 0.5.0-SNAPSHOT + + + org.osgi + org.osgi.compendium + + + commons-io + commons-io + + + + + org.opendaylight.controller + containermanager.it.implementation + 0.5.0-SNAPSHOT + + + commons-io + commons-io + + + + + org.opendaylight.controller + clustering.stub + 0.4.0-SNAPSHOT + + + commons-io + commons-io + + + + + + org.apache.felix + org.apache.felix.dependencymanager.shell + 3.0.1 + + + org.osgi + org.osgi.compendium + + + + + eclipselink + javax.resource + 1.5.0.v200906010428 + + + com.google.guava + guava + + + org.opendaylight.controller + sal + 0.5.1-SNAPSHOT + + + org.opendaylight.controller + ietf-netconf-monitoring + ${netconf.version} + + + org.opendaylight.yangtools + yang-binding + + + org.opendaylight.yangtools.model + yang-ext + 2013.09.07.1 + + + org.opendaylight.yangtools.model + opendaylight-l2-types + 2013.08.27.1 + + + org.opendaylight.controller + sal-binding-it + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-binding-config + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-binding-broker-impl + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-broker-impl + 1.0-SNAPSHOT + + + + org.opendaylight.controller.model + model-inventory + 1.0-SNAPSHOT + + + org.opendaylight.yangtools + yang-common + + + org.opendaylight.controller + sal-connector-api + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-common-util + 1.0-SNAPSHOT + + + + org.opendaylight.controller + clustering.services + 0.4.1-SNAPSHOT + + + + equinoxSDK381 + org.eclipse.osgi + 3.8.1.v20120830-144521 + + + + org.codehaus.jackson + jackson-mapper-asl + 1.9.2 + + + org.codehaus.jackson + jackson-core-asl + 1.9.2 + + + org.zeromq + jeromq + 0.3.1 + + + org.opendaylight.yangtools.thirdparty + xtend-lib-osgi + 2.4.3 + test + + + org.opendaylight.controller + sal-binding-broker-impl + 1.0-SNAPSHOT + provided + + + org.ops4j.pax.exam + pax-exam-container-native + ${exam.version} + test + + + org.ops4j.pax.exam + pax-exam-junit4 + ${exam.version} + test + + + org.opendaylight.controller + config-netconf-connector + ${netconf.version} + test + + + org.opendaylight.controller + yang-store-impl + ${config.version} + + + org.opendaylight.controller + logback-config + ${config.version} + + + org.opendaylight.controller + config-persister-impl + ${config.version} + + + org.opendaylight.controller + config-persister-file-adapter + ${config.version} + + + org.opendaylight.controller + netconf-impl + ${netconf.version} + + + org.opendaylight.controller + netconf-client + ${netconf.version} + + + org.ops4j.pax.exam + pax-exam + ${exam.version} + + compile + + + org.ops4j.pax.exam + pax-exam-link-mvn + ${exam.version} + test + + + equinoxSDK381 + org.eclipse.osgi + 3.8.1.v20120830-144521 + test + + + org.slf4j + log4j-over-slf4j + 1.7.2 + + + ch.qos.logback + logback-core + 1.0.9 + + + ch.qos.logback + logback-classic + 1.0.9 + + + org.mockito + mockito-all + test + + + org.opendaylight.controller.model + model-flow-service + 1.0-SNAPSHOT + provided + + + org.opendaylight.controller + config-manager + 0.2.3-SNAPSHOT + + + commons-io + commons-io + + + + + org.opendaylight.controller.model + model-flow-management + 1.0-SNAPSHOT + provided + + + org.opendaylight.yangtools.thirdparty + antlr4-runtime-osgi-nohead + 4.0 + + + 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 index 0000000000..62c094d7a6 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/RouterTest.java @@ -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 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 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 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 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 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 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 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 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 + + + prefix:schema-service-singleton + yang-schema-service + + + prefix:hash-map-data-store + hash-map-data-store + + + prefix:dom-broker-impl + dom-broker + + dom:dom-data-store + ref_hash-map-data-store + + + + prefix:binding-broker-impl + binding-broker-impl + + binding:binding-notification-service + ref_binding-notification-broker + + + binding:binding-data-broker + ref_binding-data-broker + + + + prefix:runtime-generated-mapping + runtime-mapping-singleton + + + prefix:binding-notification-broker + binding-notification-broker + + + prefix:binding-data-broker + binding-data-broker + + dom:dom-broker-osgi-registry + ref_dom-broker + + + binding:binding-dom-mapping-service + ref_runtime-mapping-singleton + + + + prefix:remote-zeromq-rpc-server + remoter + 5666 + + prefix:dom-broker-osgi-registry + ref_dom-broker + + + + + + dom:schema-service + + ref_yang-schema-service + /config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service'] + + + + binding:binding-notification-service + + ref_binding-notification-broker + /config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker'] + + + + dom:dom-data-store + + ref_hash-map-data-store + /config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store'] + + + + binding:binding-broker-osgi-registry + + ref_binding-broker-impl + /config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl'] + + + + binding-impl:binding-dom-mapping-service + + ref_runtime-mapping-singleton + /config/modules/module[name='runtime-generated-mapping']/instance[name='runtime-mapping-singleton'] + + + + dom:dom-broker-osgi-registry + + ref_dom-broker + /config/modules/module[name='dom-broker-impl']/instance[name='dom-broker'] + + + + binding:binding-data-broker + + ref_binding-data-broker + /config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker'] + + + + + + +//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 index 0000000000..1d17796373 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/src/test/resources/logback.xml @@ -0,0 +1,16 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + 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 index 0000000000..dd7e36cfb4 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/pom.xml @@ -0,0 +1,109 @@ + + + 4.0.0 + + sal-remoterpc-connector-test-parent + org.opendaylight.controller.tests + 1.0-SNAPSHOT + + + sal-remoterpc-connector-test-nb + bundle + + + + + org.apache.felix + maven-bundle-plugin + ${bundle.plugin.version} + true + + + + + + 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 + + + /controller/nb/v2/zmqnb + ,${classes;ANNOTATION;javax.ws.rs.Path} + + ${project.basedir}/src/main/resources/META-INF + + + + + + + org.opendaylight.controller + containermanager + 0.5.1-SNAPSHOT + + + org.opendaylight.controller + commons.northbound + 0.4.1-SNAPSHOT + + + org.opendaylight.controller + sal + 0.5.1-SNAPSHOT + + + org.opendaylight.controller.tests + sal-remoterpc-connector-test-provider + 1.0-SNAPSHOT + + + org.opendaylight.controller.tests + sal-remoterpc-connector-test-consumer + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-remoterpc-connector + 1.0-SNAPSHOT + + + org.osgi + org.osgi.core + 5.0.0 + + + junit + junit + + + org.opendaylight.controller + zeromq-routingtable.implementation + 0.4.1-SNAPSHOT + + + com.google.guava + guava + + + + 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 index 0000000000..6c9ec4e788 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/src/main/java/org/opendaylight/controller/tests/zmqrouter/rest/Router.java @@ -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 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 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 result = consumer.invokeRpc(QNAME, consumer.getInvalidCompositeNodeCompositeChild()); //TODO: Change this + RpcResult 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 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 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 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 index 0000000000..5bd21398fb --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/src/main/resources/WEB-INF/web.xml @@ -0,0 +1,58 @@ + + + + JAXRSZmq + com.sun.jersey.spi.container.servlet.ServletContainer + + javax.ws.rs.Application + org.opendaylight.controller.northbound.commons.NorthboundApplication + + 1 + + + + JAXRSZmq + /* + + + + + + + NB api + /* + POST + GET + PUT + PATCH + DELETE + HEAD + + + System-Admin + Network-Admin + Network-Operator + Container-User + + + + + System-Admin + + + Network-Admin + + + Network-Operator + + + Container-User + + + + BASIC + opendaylight + + diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java index 7022db2bc9..04114fa0ed 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java @@ -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> 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> 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 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; - + } } } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java index 103c9ed3cd..d58b7e9dab 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java @@ -27,7 +27,7 @@ public class InvokeRpcMethodTest { @Override public RpcResult answer(InvocationOnMock invocation) throws Throwable { CompositeNode compNode = (CompositeNode) invocation.getArguments()[1]; - return new DummyRpcResult.Builder().result(compNode).build(); + return new DummyRpcResult.Builder().result(compNode).isSuccessful(true).build(); } } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java index 5b0eea3212..ec7dba67b9 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java @@ -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 index 7859908768..0000000000 --- a/opendaylight/md-sal/sal-zeromq-connector/pom.xml +++ /dev/null @@ -1,149 +0,0 @@ - - - 4.0.0 - - org.opendaylight.controller - sal-parent - 1.0-SNAPSHOT - - - sal-zeromq-connector - bundle - - - 2.10.3 - - - - - - org.apache.felix - maven-bundle-plugin - true - - - - 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)" - - org.opendaylight.controller.sal.connector.remoterpc.router.zeromq.Activator - - - - - - net.alchim31.maven - scala-maven-plugin - 3.1.6 - - incremental - - -target:jvm-1.7 - - - -source1.7 - -target1.7 - - - - - scala-compile - - compile - - - - scala-test-compile - - testCompile - - - - - - - maven-compiler-plugin - - - default-compile - none - - - default-testCompile - none - - - - - - - - - org.scala-lang - scala-library - ${scala.version} - - - - org.opendaylight.controller - containermanager - 0.5.1-SNAPSHOT - - - org.opendaylight.controller - commons.northbound - 0.4.1-SNAPSHOT - - - org.opendaylight.controller - sal - 0.5.1-SNAPSHOT - - - org.opendaylight.yangtools - yang-binding - - - org.opendaylight.yangtools - yang-common - - - org.opendaylight.controller - sal-connector-api - - - org.opendaylight.controller - sal-common-util - 1.0-SNAPSHOT - - - - junit - junit - - - org.jeromq - jeromq - 0.3.0-SNAPSHOT - - - - - - sonatype-nexus-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - - - 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 index ba90f3705f..0000000000 --- a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChange.java +++ /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 { - - Map> getRemovals(); - Map> 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 index 5b927a56b1..0000000000 --- a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/Activator.java +++ /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 index af94804322..0000000000 --- a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/router/zeromq/ZeroMqRpcRouter.java +++ /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 { - - private ExecutorService serverPool; - private static ExecutorService handlersPool; - - private Map, 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, String>(); - - // Start listening for announce and rpc messages - serverPool.execute(receive()); - - brokerSession.addRpcRegistrationListener(listener); - - Set 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> rpc = brokerSession.rpc( - (QName) request.getRoute().getType(), (CompositeNode) request.getPayload()); - - RpcResult 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> sendRpc( - final RpcRequest input) { - - return handlersPool.submit(new Callable>() { - - @Override - public RpcReply 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 reply = null; - - try { - - requestSocket.send(Message.serialize(requestMessage)); - final Message response = parseMessage(requestSocket); - - _logger.debug("Received response [{}]", response); - - reply = new RpcReply() { - - @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 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 getSupportedRpcs() { - return Collections.emptySet(); - } - - @Override - public RpcResult invokeRpc(QName rpc, CompositeNode input) { - - RouteIdentifierImpl routeId = new RouteIdentifierImpl(); - routeId.setType(rpc); - - RpcRequestImpl request = new RpcRequestImpl(); - request.setRouteIdentifier(routeId); - request.setPayload(input); - - final Future> ret = sendRpc(request); - - //TODO: Review result handling - RpcResult result = new RpcResult() { - @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 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 index f9e500ea2b..0000000000 --- a/opendaylight/md-sal/test/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - 4.0.0 - - sal-parent - 1.0-SNAPSHOT - org.opendaylight.controller - - pom - org.opendaylight.controller.tests - sal-test-parent - - scm:git:ssh://git.opendaylight.org:29418/controller.git - scm:git:ssh://git.opendaylight.org:29418/controller.git - https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL - - - - zeromq-test-consumer - zeromq-test-it - zeromq-test-provider - - - 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 index a56a7dedff..0000000000 --- a/opendaylight/md-sal/test/zeromq-test-consumer/src/main/java/org/opendaylight/controller/sample/zeromq/consumer/ExampleConsumer.java +++ /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> future = ExampleConsumer.this.session.rpc(QNAME, null); - RpcResult 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 index 56945d1d34..0000000000 --- a/opendaylight/md-sal/test/zeromq-test-it/pom.xml +++ /dev/null @@ -1,184 +0,0 @@ - - 4.0.0 - - sal-test-parent - org.opendaylight.controller.tests - 1.0-SNAPSHOT - - zeromq-test-it - - scm:git:ssh://git.opendaylight.org:29418/controller.git - scm:git:ssh://git.opendaylight.org:29418/controller.git - https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL - - - - 3.0.0 - 1.5.0 - - - - - - org.ops4j.pax.exam - maven-paxexam-plugin - 1.2.4 - - - generate-config - - generate-depends-file - - - - - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - - org.ops4j.pax.exam - - - maven-paxexam-plugin - - - [1.2.4,) - - - - generate-depends-file - - - - - - - - - - - - - - - - - - org.opendaylight.yangtools.thirdparty - xtend-lib-osgi - 2.4.3 - - - org.opendaylight.controller.tests - zeromq-test-provider - 1.0-SNAPSHOT - - - org.opendaylight.controller.tests - zeromq-test-consumer - 1.0-SNAPSHOT - - - org.opendaylight.controller - sal-broker-impl - 1.0-SNAPSHOT - - - org.ops4j.pax.exam - pax-exam-container-native - ${exam.version} - test - - - org.ops4j.pax.exam - pax-exam-junit4 - ${exam.version} - test - - - org.ops4j.pax.exam - pax-exam-link-mvn - ${exam.version} - test - - - equinoxSDK381 - org.eclipse.osgi - 3.8.1.v20120830-144521 - test - - - org.slf4j - log4j-over-slf4j - 1.7.2 - - - ch.qos.logback - logback-core - 1.0.9 - - - ch.qos.logback - logback-classic - 1.0.9 - - - org.opendaylight.controller - sal-binding-api - 1.0-SNAPSHOT - - - org.opendaylight.controller - sal-common-util - 1.0-SNAPSHOT - - - org.opendaylight.controller - sal-core-api - 1.0-SNAPSHOT - - - - - org.opendaylight.controller - containermanager - 0.5.1-SNAPSHOT - - - - org.opendaylight.controller - sal - 0.5.1-SNAPSHOT - - - org.opendaylight.yangtools - yang-binding - - - org.opendaylight.yangtools - yang-common - - - org.opendaylight.yangtools - yang-data-api - - - - org.opendaylight.controller - sal-common-util - 1.0-SNAPSHOT - - - 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 index c17b143d70..0000000000 --- a/opendaylight/md-sal/test/zeromq-test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/ServiceConsumerController.java +++ /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 index 2d28b0b5b5..0000000000 --- a/opendaylight/md-sal/test/zeromq-test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/ServiceProviderController.java +++ /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 index ec7d7a8285..0000000000 --- a/opendaylight/md-sal/test/zeromq-test-provider/src/main/java/org/opendaylight/controller/sample/zeromq/provider/ExampleProvider.java +++ /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 getSupportedRpcs() { - return Collections.singleton(QNAME); - } - - @Override - public RpcResult invokeRpc(QName rpc, CompositeNode input) { - if(QNAME.equals(rpc)) { - RpcResult output = Rpcs.getRpcResult(true, null, Collections.emptySet()); - return output; - } - RpcResult output = Rpcs.getRpcResult(false, null, Collections.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(); - } - } - } - -} diff --git a/opendaylight/md-sal/zeromq-routingtable/implementation/pom.xml b/opendaylight/md-sal/zeromq-routingtable/implementation/pom.xml index 37c973e864..2926786849 100644 --- a/opendaylight/md-sal/zeromq-routingtable/implementation/pom.xml +++ b/opendaylight/md-sal/zeromq-routingtable/implementation/pom.xml @@ -1,6 +1,6 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.opendaylight.controller @@ -28,7 +28,10 @@ true - + + org.opendaylight.controller.sal.connector.remoterpc.api, + org.opendaylight.controller.sal.connector.remoterpc.impl + javax.xml.bind.annotation, org.opendaylight.controller.sal.core, @@ -67,7 +70,12 @@ org.opendaylight.controller sal - 0.5.1-SNAPSHOT + + + org.osgi + org.osgi.compendium + + org.opendaylight.controller diff --git a/opendaylight/netconf/config-netconf-connector/pom.xml b/opendaylight/netconf/config-netconf-connector/pom.xml index d855f15541..888f13c8fe 100644 --- a/opendaylight/netconf/config-netconf-connector/pom.xml +++ b/opendaylight/netconf/config-netconf-connector/pom.xml @@ -136,7 +136,9 @@ 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 diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java index 2b6f862bd7..697b811d51 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java @@ -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 { 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 { 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 diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AbstractAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AbstractAttributeReadingStrategy.java index 867d94e0b7..7939112628 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AbstractAttributeReadingStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AbstractAttributeReadingStrategy.java @@ -27,11 +27,14 @@ public abstract class AbstractAttributeReadingStrategy implements AttributeReadi @Override public AttributeConfigElement readElement(List configNodes) { if (configNodes.size() == 0) - return AttributeConfigElement.createNullValue(nullableDefault); + return AttributeConfigElement.createNullValue(postprocessNullableDefault(nullableDefault)); return readElementHook(configNodes); } abstract AttributeConfigElement readElementHook(List configNodes); + protected Object postprocessNullableDefault(String nullableDefault) { + return nullableDefault; + } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeConfigElement.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeConfigElement.java index 598935a0bc..a1f46dde54 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeConfigElement.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeConfigElement.java @@ -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; } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java index e2ea404e21..a2691f241c 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java @@ -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 openType) { + return new SimpleBinaryAttributeReadingStrategy(lastAttribute.getNullableDefault()); + } + @Override public AttributeReadingStrategy caseJavaSimpleAttribute(SimpleType openType) { return new SimpleAttributeReadingStrategy(lastAttribute.getNullableDefault()); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleAttributeReadingStrategy.java index be86a2ab6f..a8605243af 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleAttributeReadingStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleAttributeReadingStrategy.java @@ -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 index 0000000000..2cac9029c6 --- /dev/null +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleBinaryAttributeReadingStrategy.java @@ -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 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); + } +} diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleCompositeAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleCompositeAttributeReadingStrategy.java index 9249ac9fa8..22c9e015a9 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleCompositeAttributeReadingStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleCompositeAttributeReadingStrategy.java @@ -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); + } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/CompositeAttributeResolvingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/CompositeAttributeResolvingStrategy.java index a85f3064cf..c477821051 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/CompositeAttributeResolvingStrategy.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/CompositeAttributeResolvingStrategy.java @@ -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) { diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java index ad587ea987..a174e9a251 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java @@ -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 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 index 0000000000..c159e46987 --- /dev/null +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleBinaryAttributeWritingStrategy.java @@ -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); + } + +} diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java index 35fa0428ec..f8916ecac2 100644 --- a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java +++ b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java @@ -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, "2.58"); + // Default + assertContainsString(responseTrimmed, "2.00"); + + } + 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 = "YmluYXJ5"; + assertContainsString(responseTrimmed, substring); + substring = "ZGVmYXVsdEJpbg=="; + 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 = "10"; + assertContainsString(responseTrimmed, substring); + // Default + assertContainsString(responseTrimmed, + "1"); - children = response.getElementsByTagName("extended-twice"); - assertEquals(1, children.getLength()); + assertContainsString(responseTrimmed, + "20"); + // Default + assertContainsString(responseTrimmed, + "2"); + + assertContainsString(responseTrimmed, + "TWO"); + // Default + assertContainsString(responseTrimmed, + "ONE"); + } + + 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 { diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml index dc522d2e64..94b73f4b10 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml @@ -32,15 +32,15 @@ test1 - 2.00 + 2.58 - 1 + 10 - 1 + 20 @@ -48,9 +48,8 @@ 44 - 8 - 1 - 0 + YmluYXJ5 + configAttributeType 444 diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml index 388aa4f2ab..b48730d3f7 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml @@ -27,9 +27,7 @@ test1 44 - 8 - 7 - 9 + 8ad1 444 4444 diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_differentNamespaceTO.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_differentNamespaceTO.xml index 4d94d9e949..df2a5e8452 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_differentNamespaceTO.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_differentNamespaceTO.xml @@ -32,9 +32,7 @@ test1 44 - 8 - 1 - 0 + 8545649856 configAttributeType 444 diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_typeNameConfigAttributeMatching.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_typeNameConfigAttributeMatching.xml index 0e70e13a34..02aca8d787 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_typeNameConfigAttributeMatching.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/namespaces/editConfig_typeNameConfigAttributeMatching.xml @@ -32,9 +32,7 @@ test1 44 - 8 - 1 - 0 + 8545649856 444 4444 diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised7.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised7.xml index d03bb084b8..825be6d19f 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised7.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised7.xml @@ -32,9 +32,7 @@ test1 44 - 8 - 1 - 0 + 8545649856 error 444 diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised8.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised8.xml index 3722973912..9ef2bed7d7 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised8.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/unrecognised/editConfig_unrecognised8.xml @@ -32,9 +32,7 @@ test1 44 - 8 - 1 - 0 + 8545649856 444 4444 diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java index f26bcf718c..e2fa8d5f1e 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java @@ -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) { diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java index f4843cf828..2b26ecb749 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java @@ -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> ncProps = InventoryServiceHelper - .OFSwitchToProps(sw); - for (Map.Entry> entry : ncProps.entrySet()) { - Set props = new HashSet(); - Set prop = entry.getValue(); - if (prop != null) { - props.addAll(prop); + // Add all the nodeConnectors of this switch if any + Map> ncProps = InventoryServiceHelper.OFSwitchToProps(sw); + if (!ncProps.isEmpty()) { + for (Map.Entry> entry : ncProps.entrySet()) { + Set props = new HashSet(); + Set 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.emptySet()); } // Add this node diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeTableStatistics.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeTableStatistics.java index eb33ad6799..e4c3961a14 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeTableStatistics.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeTableStatistics.java @@ -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 + "]"; } } diff --git a/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java b/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java index 4950cae33a..217b8d4690 100644 --- a/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java +++ b/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java @@ -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"); diff --git a/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/UserConfig.java b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/UserConfig.java index 6867ef4b98..0c14dea38a 100644 --- a/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/UserConfig.java +++ b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/UserConfig.java @@ -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 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() { } diff --git a/opendaylight/web/flows/src/main/java/org/opendaylight/controller/flows/web/Flows.java b/opendaylight/web/flows/src/main/java/org/opendaylight/controller/flows/web/Flows.java index 8a7c3983d1..259ffde4b4 100644 --- a/opendaylight/web/flows/src/main/java/org/opendaylight/controller/flows/web/Flows.java +++ b/opendaylight/web/flows/src/main/java/org/opendaylight/controller/flows/web/Flows.java @@ -142,17 +142,17 @@ public class Flows implements IDaylightWeb { } Map nodes = new HashMap(); - Map port; + Map port; for (Switch node : switchManager.getNetworkDevices()) { - port = new HashMap(); // new port + port = new HashMap(); // new port Set 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() + ")"); } } diff --git a/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java index 3c28152c25..4c8a6b8439 100644 --- a/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java +++ b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java @@ -143,17 +143,22 @@ public class DaylightWebAdmin { return gson.toJson(result); } - @RequestMapping("/users") + @RequestMapping(value = "/users", method = RequestMethod.GET) @ResponseBody - public List getUsers() { + public List getUsers() { IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this); if (userManager == null) { return null; } - List userConfList = userManager.getLocalUserList(); + List result = new ArrayList(); + List 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 index 0000000000..4d30ed34e9 --- /dev/null +++ b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/UserBean.java @@ -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 roles; + + public UserBean(String user, List roles) { + this.user = user; + this.roles = roles; + } + + public UserBean(UserConfig config) { + this(config.getUser(), config.getRoles()); + } + + public String getUser() { + return user; + } + + public List getRoles() { + return roles; + } +} \ No newline at end of file