From: Ed Warnicke Date: Fri, 14 Jun 2013 18:53:08 +0000 (+0000) Subject: Merge "Parents pom distribution" X-Git-Tag: releasepom-0.1.0~354 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=ff1b4a79cca00743a00c3b0b1100bd0ab2b2fb31;hp=5cb959c28b66deaab914e168a8f0bf65612f70b5 Merge "Parents pom distribution" --- diff --git a/.gitignore b/.gitignore index b92845c8d7..d1b82619fd 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ target .project .settings MANIFEST.MF +opendaylight/northbound/integrationtest/logs/* diff --git a/opendaylight/arphandler/src/test/java/org/opendaylight/controller/arphandler/internal/ArphandlerTest.java b/opendaylight/arphandler/src/test/java/org/opendaylight/controller/arphandler/internal/ArphandlerTest.java index 5a6641c685..19c8b4d35b 100644 --- a/opendaylight/arphandler/src/test/java/org/opendaylight/controller/arphandler/internal/ArphandlerTest.java +++ b/opendaylight/arphandler/src/test/java/org/opendaylight/controller/arphandler/internal/ArphandlerTest.java @@ -16,14 +16,14 @@ import org.junit.Assert; import org.junit.Test; public class ArphandlerTest extends TestCase { - - @Test - public void testArphandlerCreation() { - - ArpHandler ah = null; - ah = new ArpHandler(); - Assert.assertTrue(ah != null); - - } + + @Test + public void testArphandlerCreation() { + + ArpHandler ah = null; + ah = new ArpHandler(); + Assert.assertTrue(ah != null); + + } } diff --git a/opendaylight/clustering/integrationtest/pom.xml b/opendaylight/clustering/integrationtest/pom.xml index 460b09e9da..52c568203b 100644 --- a/opendaylight/clustering/integrationtest/pom.xml +++ b/opendaylight/clustering/integrationtest/pom.xml @@ -32,7 +32,7 @@ sal.implementation 0.4.0-SNAPSHOT - + org.opendaylight.controller clustering.services-implementation 0.4.0-SNAPSHOT diff --git a/opendaylight/clustering/integrationtest/src/test/resources/logback.xml b/opendaylight/clustering/integrationtest/src/test/resources/logback.xml index 2d63ce5744..6d9dfda9a3 100644 --- a/opendaylight/clustering/integrationtest/src/test/resources/logback.xml +++ b/opendaylight/clustering/integrationtest/src/test/resources/logback.xml @@ -1,5 +1,4 @@ - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n diff --git a/opendaylight/clustering/services_implementation/src/main/resources/config/infinispan-config.xml b/opendaylight/clustering/services_implementation/src/main/resources/config/infinispan-config.xml index 03a9b4d93e..2aa3fdb849 100644 --- a/opendaylight/clustering/services_implementation/src/main/resources/config/infinispan-config.xml +++ b/opendaylight/clustering/services_implementation/src/main/resources/config/infinispan-config.xml @@ -19,7 +19,7 @@ - + diff --git a/opendaylight/clustering/test/src/test/java/org/opendaylight/controller/clustering/test/internal/TestClusteringTest.java b/opendaylight/clustering/test/src/test/java/org/opendaylight/controller/clustering/test/internal/TestClusteringTest.java index fa00c7f455..1142909f85 100644 --- a/opendaylight/clustering/test/src/test/java/org/opendaylight/controller/clustering/test/internal/TestClusteringTest.java +++ b/opendaylight/clustering/test/src/test/java/org/opendaylight/controller/clustering/test/internal/TestClusteringTest.java @@ -17,51 +17,51 @@ import junit.framework.TestCase; public class TestClusteringTest extends TestCase { - @Test - public void testComplexClass() { - ComplexClass cc = new ComplexClass("cplxc1"); - Assert.assertTrue(cc.whoAmI().equals("ComplexClass_cplxc1")); - cc.IAm("cplxc2"); - Assert.assertTrue(cc.whoAmI().equals("ComplexClass_cplxc2")); - } - - @Test - public void testComplexClass1() { - ComplexClass1 cc1 = new ComplexClass1("cplxc1a"); - Assert.assertTrue(cc1.whoAmI().equals("ComplexClass1_cplxc1a")); - cc1.IAm("cplxc1b"); - Assert.assertTrue(cc1.whoAmI().equals("ComplexClass1_cplxc1b")); - } - - - @Test - public void testComplexContainer() { - ComplexContainer cplxcontnr1 = new ComplexContainer("cct1", 5); - Assert.assertTrue(cplxcontnr1.getIdentity().equals("[ComplexClass_cct1]-[ComplexClass1_cct1]")); - Assert.assertTrue(cplxcontnr1.getState() == 5); - - cplxcontnr1.setIdentity("cct2"); - Assert.assertTrue(cplxcontnr1.getIdentity().equals("[ComplexClass_cct2]-[ComplexClass1_cct2]")); - - Assert.assertTrue(cplxcontnr1.toString().equals( - "{ID:[ComplexClass_cct2]-[ComplexClass1_cct2],STATE:5}")); - } - - @Test - public void testStringContainer() { - StringContainer strcontainer1 = new StringContainer(); - Assert.assertTrue(strcontainer1.getMystring() == null); - Assert.assertTrue(strcontainer1.hashCode() == 0); - - StringContainer strcontainer2 = new StringContainer("foo"); - Assert.assertTrue(strcontainer2.getMystring() != null); - Assert.assertTrue(strcontainer2.hashCode() != 0); - - strcontainer1.setMystring("foo"); - Assert.assertTrue(strcontainer2.equals(strcontainer1)); - - Assert.assertTrue(strcontainer2.toString().equals("{foo}")); - } - + @Test + public void testComplexClass() { + ComplexClass cc = new ComplexClass("cplxc1"); + Assert.assertTrue(cc.whoAmI().equals("ComplexClass_cplxc1")); + cc.IAm("cplxc2"); + Assert.assertTrue(cc.whoAmI().equals("ComplexClass_cplxc2")); + } + + @Test + public void testComplexClass1() { + ComplexClass1 cc1 = new ComplexClass1("cplxc1a"); + Assert.assertTrue(cc1.whoAmI().equals("ComplexClass1_cplxc1a")); + cc1.IAm("cplxc1b"); + Assert.assertTrue(cc1.whoAmI().equals("ComplexClass1_cplxc1b")); + } + + + @Test + public void testComplexContainer() { + ComplexContainer cplxcontnr1 = new ComplexContainer("cct1", 5); + Assert.assertTrue(cplxcontnr1.getIdentity().equals("[ComplexClass_cct1]-[ComplexClass1_cct1]")); + Assert.assertTrue(cplxcontnr1.getState() == 5); + + cplxcontnr1.setIdentity("cct2"); + Assert.assertTrue(cplxcontnr1.getIdentity().equals("[ComplexClass_cct2]-[ComplexClass1_cct2]")); + + Assert.assertTrue(cplxcontnr1.toString().equals( + "{ID:[ComplexClass_cct2]-[ComplexClass1_cct2],STATE:5}")); + } + + @Test + public void testStringContainer() { + StringContainer strcontainer1 = new StringContainer(); + Assert.assertTrue(strcontainer1.getMystring() == null); + Assert.assertTrue(strcontainer1.hashCode() == 0); + + StringContainer strcontainer2 = new StringContainer("foo"); + Assert.assertTrue(strcontainer2.getMystring() != null); + Assert.assertTrue(strcontainer2.hashCode() != 0); + + strcontainer1.setMystring("foo"); + Assert.assertTrue(strcontainer2.equals(strcontainer1)); + + Assert.assertTrue(strcontainer2.toString().equals("{foo}")); + } + } diff --git a/opendaylight/commons/concepts/pom.xml b/opendaylight/commons/concepts/pom.xml index 802b00e5cc..9f3107d1a8 100644 --- a/opendaylight/commons/concepts/pom.xml +++ b/opendaylight/commons/concepts/pom.xml @@ -28,6 +28,15 @@ ${project.basedir}/META-INF + + org.apache.maven.plugins + maven-checkstyle-plugin + ${checkstyle.version} + + true + ${project.parent.parent.basedir}/space_and_tabs_checks.xml + + diff --git a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/Acceptor.java b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/Acceptor.java index 9d34dfb8a7..9e9774e266 100644 --- a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/Acceptor.java +++ b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/Acceptor.java @@ -12,7 +12,7 @@ package org.opendaylight.controller.concepts.transform; public interface Acceptor { /** - * + * * @param input * @return true if input is accepted. */ diff --git a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/AggregateTransformer.java b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/AggregateTransformer.java index 23bcb563d3..061a57fc15 100644 --- a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/AggregateTransformer.java +++ b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/AggregateTransformer.java @@ -10,7 +10,7 @@ package org.opendaylight.controller.concepts.transform; import java.util.Collection; /** - * + * * @author Tony Tkacik * * @param diff --git a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/CompositeClassBasedTransformer.java b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/CompositeClassBasedTransformer.java index fa6408d3d1..dae949912b 100644 --- a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/CompositeClassBasedTransformer.java +++ b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/CompositeClassBasedTransformer.java @@ -17,26 +17,26 @@ import java.util.concurrent.ConcurrentHashMap; /** * Transformer which aggregates multiple implementations of * {@link InputClassBasedTransformer}. - * + * * The transformation process is driven by {@link Class} of input. The selection * of used {@link InputClassBasedTransformer} is done by using the {@link Class} * of input as a key to select the transformer. - * + * * This approach provides quick resolution of transformer, but does not support * registering a super type of input to provide transformation support for all * subclasses, one must register a new instance of transformer for each valid * input class. - * + * * If you need more flexible selection of transformation consider using * {@link CompositeConditionalTransformer} which is slower but most flexible or * {@link RuleBasedTransformer} which provides declarative approach for * transformation. - * + * * See {@link #transform(Object)} for more information about tranformation * process. - * + * * @author Tony Tkacik - * + * * @param * Input super-type * @param

@@ -50,18 +50,18 @@ public abstract class CompositeClassBasedTransformer implements /** * Transforms an input into instance of Product class. - * + * * The final registered transformer is the one which match following * condition: - * + * * input.getClass() == transformer.getInputClass() - * + * * This means that transformers are not resolved by class hierarchy, only * selected based on final class of the input. If you need more flexible * selection of transformation consider using * {@link CompositeConditionalTransformer} which is slower but more * flexible. - * + * */ @Override public P transform(I input) { @@ -76,11 +76,11 @@ public abstract class CompositeClassBasedTransformer implements /** * Registers a new transformer. - * + * * The transformer is registered for class returned by * {@link InputClassBasedTransformer#getInputClass()}. Only one transformer * can be registered for particular input class. - * + * */ public void addTransformer( InputClassBasedTransformer transformer) @@ -95,9 +95,9 @@ public abstract class CompositeClassBasedTransformer implements /** * Removes an registered transformer. - * + * * Note: Removal is currently unsupported. - * + * * @param transformer * Tranformer to be removed. * @throws IllegalArgumentException @@ -108,7 +108,7 @@ public abstract class CompositeClassBasedTransformer implements throws IllegalArgumentException { throw new UnsupportedOperationException("Not implemented yet"); } - + @Override public Collection

transformAll(Collection inputs) { Collection

ret = new ArrayList

(); diff --git a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/InputClassBasedTransformer.java b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/InputClassBasedTransformer.java index 3e6b39abf5..1ad849bddc 100644 --- a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/InputClassBasedTransformer.java +++ b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/InputClassBasedTransformer.java @@ -10,15 +10,15 @@ package org.opendaylight.controller.concepts.transform; /** * Input class based transformer - * + * * {@link Transformer} which accepts / transforms only specific classes of * input, and is useful if the selection of transformer should be based on the * class of the input and there is one-to-one mapping between input class and * transformer. - * - * + * + * * @author Tony Tkacik - * + * * @param * Common supertype of input * @param @@ -31,7 +31,7 @@ public interface InputClassBasedTransformer extends /** * Returns an {@link Class} of input which is acceptable for transformation. - * + * * @return {@link Class} of input which is acceptable for transformation. */ Class getInputClass(); diff --git a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/RuleBasedTransformer.java b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/RuleBasedTransformer.java index 9f717eaa5b..820b94a7ac 100644 --- a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/RuleBasedTransformer.java +++ b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/RuleBasedTransformer.java @@ -12,15 +12,15 @@ import java.util.Set; /** * Transformer with set of acceptance rules - * + * * The transformer provides a set of {@link Acceptor}s, which could be used to * verify if the input will produce result using the transformer. - * + * * The transormer is able to produce result if ANY of associated * {@link Acceptor}s accepted result. - * + * * @author Tony Tkacik - * + * * @param * Input class for transformation * @param

@@ -31,10 +31,10 @@ public interface RuleBasedTransformer extends Transformer { /** * Set of {@link Acceptor}, which could be used to verify if the input is * usable by transformer. - * + * * The transformer is able to produce result if ANY of associated * {@link Acceptor}s accepted result. - * + * * @return Set of input acceptance rules associated to this transformer. */ Set> getRules(); diff --git a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/SimpleConditionalTransformer.java b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/SimpleConditionalTransformer.java index 81e43c39d1..4d0aa03e15 100644 --- a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/SimpleConditionalTransformer.java +++ b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/SimpleConditionalTransformer.java @@ -10,15 +10,15 @@ package org.opendaylight.controller.concepts.transform; /** * Simple condition-based transformer - * + * * The transformer provides {@link #isAcceptable(Object)} method, * which could be used to query transformer if the input will produce * result. - * + * * This interface is simplified version of {@link RuleBasedTransformer} - does not * provide decoupling of Acceptance rule from transformer, and should be used only * for simple use-cases. - * + * * @author Tony Tkacik * * @param Input class for transformation @@ -28,9 +28,9 @@ public interface SimpleConditionalTransformer extends Transformer, Ac /** - * Checks if the input is acceptable + * Checks if the input is acceptable * for processing by the transformer. - * + * * @return true it the input is acceptable for processing by transformer. */ @Override diff --git a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/Transformer.java b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/Transformer.java index f80ccfffd8..18184e122a 100644 --- a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/Transformer.java +++ b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/transform/Transformer.java @@ -10,7 +10,7 @@ package org.opendaylight.controller.concepts.transform; /** * Factory which produces product based on input object - * + * * @author Tony Tkacik * * @param Input @@ -19,7 +19,7 @@ package org.opendaylight.controller.concepts.transform; public interface Transformer { /** * Transforms input into instance of product. - * + * * @param input Input which drives transformation * @return Instance of product which was created from supplied input. */ diff --git a/opendaylight/commons/integrationtest/pom.xml b/opendaylight/commons/integrationtest/pom.xml index a438ad8393..89dbb77ecd 100644 --- a/opendaylight/commons/integrationtest/pom.xml +++ b/opendaylight/commons/integrationtest/pom.xml @@ -49,12 +49,13 @@ 0.8.0.v201110170705 - + org.ops4j.pax.exam maven-paxexam-plugin + 1.2.4 generate-config @@ -64,6 +65,35 @@ + + org.apache.maven.plugins + maven-checkstyle-plugin + ${checkstyle.version} + + true + ${project.parent.parent.basedir}/space_and_tabs_checks.xml + + + + org.codehaus.mojo + properties-maven-plugin + ${propertymavenplugin.version} + + + + set-system-properties + + + + + logback.configurationFile + ${project.parent.parent.basedir}/logback.xml + + + + + + diff --git a/opendaylight/commons/opendaylight/logback.xml b/opendaylight/commons/opendaylight/logback.xml index 043ceef329..05e607573e 100644 --- a/opendaylight/commons/opendaylight/logback.xml +++ b/opendaylight/commons/opendaylight/logback.xml @@ -1,11 +1,11 @@ - + %date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n - + diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index 9814b5f91c..142c9d5d6c 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -9,10 +9,16 @@ commons.opendaylight 1.4.0-SNAPSHOT pom + + org.opendaylight.controller + commons.parent + 1.0.0-SNAPSHOT + ../parent + + 1.0-alpha-2 https://sonar.opendaylight.org/ - http://nexus.opendaylight.org/content dav:http://nexus.opendaylight.org/content/sites/site 3.2 2.6 @@ -32,6 +38,7 @@ 1.17 3.6.0.RELEASE 2.2.0.RELEASE + 2.10 @@ -218,7 +225,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 2.10 + ${checkstyle.version} org.apache.maven.plugins @@ -251,7 +258,7 @@ org.codehaus.mojo properties-maven-plugin - 1.0-alpha-2 + ${propertymavenplugin.version} @@ -261,7 +268,7 @@ logback.configurationFile - ${project.parent.relativePath}/logback.xml + ${project.parent.basedir}/logback.xml @@ -276,7 +283,28 @@ 1.6 1.6 1.6 - ${project.parent.relativePath}/sun_coding_style.xml + ${project.parent.basedir}/sun_coding_style.xml + + + + org.apache.maven.plugins + maven-checkstyle-plugin + ${checkstyle.version} + + + process-sources + + check + + + + + true + ${project.parent.basedir}/space_and_tabs_checks.xml + true + true + ${project.basedir} + **\/*.java,**\/*.xml,**\/*.ini,**\/*.sh,**\/*.bat @@ -345,17 +373,30 @@ - - org.ops4j.pax.exam - maven-paxexam-plugin - [1.2.4,) - - generate-depends-file - - - - - + + org.ops4j.pax.exam + maven-paxexam-plugin + [1.2.4,) + + generate-depends-file + + + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + [2.0,) + + check + + + + + diff --git a/opendaylight/commons/opendaylight/space_and_tabs_checks.xml b/opendaylight/commons/opendaylight/space_and_tabs_checks.xml new file mode 100644 index 0000000000..49a5802444 --- /dev/null +++ b/opendaylight/commons/opendaylight/space_and_tabs_checks.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/opendaylight/commons/parent/README b/opendaylight/commons/parent/README new file mode 100644 index 0000000000..4560dd4b79 --- /dev/null +++ b/opendaylight/commons/parent/README @@ -0,0 +1,10 @@ +This contains a dummy parent project. The use case of this is for +example the maven-checkstyle plugin call in commons/opendaylight in +there the plugin references the spaces_tabs_checks.xml from the +parent, it works well for all the childs of commons/opendaylight +artifact but when trying to deploy that one itself it breaks because +the plugin section will still refer to the parent when there is no +parent. +This fake parents allow to still set a parent for the +commons/opendaylight even if pretty much empty or limited to the bare +minimum and yet allow the commons/opendaylight to reference a parent. diff --git a/opendaylight/commons/parent/logback.xml b/opendaylight/commons/parent/logback.xml new file mode 100644 index 0000000000..05e607573e --- /dev/null +++ b/opendaylight/commons/parent/logback.xml @@ -0,0 +1,12 @@ + + + + + %date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n + + + + + + + diff --git a/opendaylight/commons/parent/pom.xml b/opendaylight/commons/parent/pom.xml new file mode 100644 index 0000000000..a3fb6b4549 --- /dev/null +++ b/opendaylight/commons/parent/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + 3.0 + + org.opendaylight.controller + commons.parent + 1.0.0-SNAPSHOT + pom + + + http://nexus.opendaylight.org/content + + + + + opendaylight-release + ${nexusproxy}/repositories/opendaylight.release/ + + + + opendaylight-snapshot + ${nexusproxy}/repositories/opendaylight.snapshot/ + + + + website + ${sitedeploy} + + + diff --git a/opendaylight/commons/parent/space_and_tabs_checks.xml b/opendaylight/commons/parent/space_and_tabs_checks.xml new file mode 100644 index 0000000000..49a5802444 --- /dev/null +++ b/opendaylight/commons/parent/space_and_tabs_checks.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/opendaylight/commons/parent/sun_coding_style.xml b/opendaylight/commons/parent/sun_coding_style.xml new file mode 100644 index 0000000000..f4516b913d --- /dev/null +++ b/opendaylight/commons/parent/sun_coding_style.xml @@ -0,0 +1,291 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerImpl.java b/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerImpl.java index 3d0c5659d6..9fb0c23b36 100644 --- a/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerImpl.java +++ b/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerImpl.java @@ -51,9 +51,9 @@ public class ConfigurationContainerImpl implements } public int getConfigurationAwareListSize() { - return this.configurationAwareList.size(); + return this.configurationAwareList.size(); } - + public void removeConfigurationContainerAware( IConfigurationContainerAware configurationAware) { this.configurationAwareList.remove(configurationAware); @@ -88,16 +88,16 @@ public class ConfigurationContainerImpl implements Status status = configurationAware.saveConfiguration(); if (!status.isSuccess()) { - success = false; - logger.info("Failed to save config for {}", - configurationAware.getClass().getSimpleName()); + success = false; + logger.info("Failed to save config for {}", + configurationAware.getClass().getSimpleName()); } } if (success) { return new Status(StatusCode.SUCCESS, null); } else { return new Status(StatusCode.INTERNALERROR, - "Failed to Save All Configurations"); + "Failed to Save All Configurations"); } } diff --git a/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationImpl.java b/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationImpl.java index ee15b4a9c2..20821f1028 100644 --- a/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationImpl.java +++ b/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationImpl.java @@ -41,11 +41,11 @@ public class ConfigurationImpl implements IConfigurationService { private Set configurationAwareList = (Set) Collections .synchronizedSet(new HashSet()); - + public int getConfigurationAwareListSize() { - return this.configurationAwareList.size(); + return this.configurationAwareList.size(); } - + public void addConfigurationAware(IConfigurationAware configurationAware) { if (!this.configurationAwareList.contains(configurationAware)) { this.configurationAwareList.add(configurationAware); @@ -81,18 +81,18 @@ public class ConfigurationImpl implements IConfigurationService { public Status saveConfigurations() { boolean success = true; for (IConfigurationAware configurationAware : configurationAwareList) { - Status status = configurationAware.saveConfiguration(); + Status status = configurationAware.saveConfiguration(); if (!status.isSuccess()) { - success = false; - logger.info("Failed to save config for {}", - configurationAware.getClass().getName()); + success = false; + logger.info("Failed to save config for {}", + configurationAware.getClass().getName()); } } if (success) { return new Status(StatusCode.SUCCESS, null); } else { return new Status(StatusCode.INTERNALERROR, - "Failed to Save All Configurations"); + "Failed to Save All Configurations"); } } diff --git a/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationAwareTest.java b/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationAwareTest.java index e93b467b9a..c9dd5e2f39 100644 --- a/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationAwareTest.java +++ b/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationAwareTest.java @@ -22,11 +22,11 @@ import org.opendaylight.controller.sal.utils.Status; public class ConfigurationAwareTest implements IConfigurationAware { - - @Override - public Status saveConfiguration() { - return null; - } + + @Override + public Status saveConfiguration() { + return null; + } } diff --git a/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerAwareTest.java b/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerAwareTest.java index 52f3776e6d..c5d6bdc5d6 100644 --- a/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerAwareTest.java +++ b/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerAwareTest.java @@ -23,13 +23,13 @@ import org.opendaylight.controller.sal.utils.Status; public class ConfigurationContainerAwareTest implements IConfigurationContainerAware { - - - - @Override - public Status saveConfiguration() { - return null; - } - - + + + + @Override + public Status saveConfiguration() { + return null; + } + + } diff --git a/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerImplTest.java b/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerImplTest.java index 1d704a1937..a82a9f23d8 100644 --- a/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerImplTest.java +++ b/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerImplTest.java @@ -14,52 +14,51 @@ import org.opendaylight.controller.configuration.IConfigurationContainerAware; -public class ConfigurationContainerImplTest { - - - @Test - public void testAddRemoveSaveConfiguration() { - - ConfigurationContainerImpl configurationContainerImpl = new ConfigurationContainerImpl(); - IConfigurationContainerAware testConfigurationContainerAware = new ConfigurationContainerAwareTest(); - - configurationContainerImpl.addConfigurationContainerAware(testConfigurationContainerAware); - configurationContainerImpl.addConfigurationContainerAware(testConfigurationContainerAware); - - Assert.assertEquals(1, configurationContainerImpl.getConfigurationAwareListSize()); - - IConfigurationContainerAware testConfigurationAware1 = new ConfigurationContainerAwareTest(); - configurationContainerImpl.addConfigurationContainerAware(testConfigurationAware1); - - Assert.assertEquals(2, configurationContainerImpl.getConfigurationAwareListSize()); - - IConfigurationContainerAware testConfigurationAware2 = new ConfigurationContainerAwareTest(); - configurationContainerImpl.addConfigurationContainerAware(testConfigurationAware2); - - Assert.assertEquals(3, configurationContainerImpl.getConfigurationAwareListSize()); - - IConfigurationContainerAware testConfigurationAware3 = new ConfigurationContainerAwareTest(); - configurationContainerImpl.addConfigurationContainerAware(testConfigurationAware3); - - Assert.assertEquals(4, configurationContainerImpl.getConfigurationAwareListSize()); - - configurationContainerImpl.removeConfigurationContainerAware(testConfigurationContainerAware); - Assert.assertEquals(3, configurationContainerImpl.getConfigurationAwareListSize()); - - configurationContainerImpl.removeConfigurationContainerAware(testConfigurationContainerAware); - Assert.assertEquals(3, configurationContainerImpl.getConfigurationAwareListSize()); - - configurationContainerImpl.removeConfigurationContainerAware(testConfigurationAware3); - Assert.assertEquals(2, configurationContainerImpl.getConfigurationAwareListSize()); - - configurationContainerImpl.removeConfigurationContainerAware(testConfigurationAware2); - Assert.assertEquals(1, configurationContainerImpl.getConfigurationAwareListSize()); - - configurationContainerImpl.removeConfigurationContainerAware(testConfigurationAware1); - Assert.assertEquals(0, configurationContainerImpl.getConfigurationAwareListSize()); - - - } - -} +public class ConfigurationContainerImplTest { + + + @Test + public void testAddRemoveSaveConfiguration() { + + ConfigurationContainerImpl configurationContainerImpl = new ConfigurationContainerImpl(); + IConfigurationContainerAware testConfigurationContainerAware = new ConfigurationContainerAwareTest(); + + configurationContainerImpl.addConfigurationContainerAware(testConfigurationContainerAware); + configurationContainerImpl.addConfigurationContainerAware(testConfigurationContainerAware); + + Assert.assertEquals(1, configurationContainerImpl.getConfigurationAwareListSize()); + + IConfigurationContainerAware testConfigurationAware1 = new ConfigurationContainerAwareTest(); + configurationContainerImpl.addConfigurationContainerAware(testConfigurationAware1); + + Assert.assertEquals(2, configurationContainerImpl.getConfigurationAwareListSize()); + + IConfigurationContainerAware testConfigurationAware2 = new ConfigurationContainerAwareTest(); + configurationContainerImpl.addConfigurationContainerAware(testConfigurationAware2); + + Assert.assertEquals(3, configurationContainerImpl.getConfigurationAwareListSize()); + IConfigurationContainerAware testConfigurationAware3 = new ConfigurationContainerAwareTest(); + configurationContainerImpl.addConfigurationContainerAware(testConfigurationAware3); + + Assert.assertEquals(4, configurationContainerImpl.getConfigurationAwareListSize()); + + configurationContainerImpl.removeConfigurationContainerAware(testConfigurationContainerAware); + Assert.assertEquals(3, configurationContainerImpl.getConfigurationAwareListSize()); + + configurationContainerImpl.removeConfigurationContainerAware(testConfigurationContainerAware); + Assert.assertEquals(3, configurationContainerImpl.getConfigurationAwareListSize()); + + configurationContainerImpl.removeConfigurationContainerAware(testConfigurationAware3); + Assert.assertEquals(2, configurationContainerImpl.getConfigurationAwareListSize()); + + configurationContainerImpl.removeConfigurationContainerAware(testConfigurationAware2); + Assert.assertEquals(1, configurationContainerImpl.getConfigurationAwareListSize()); + + configurationContainerImpl.removeConfigurationContainerAware(testConfigurationAware1); + Assert.assertEquals(0, configurationContainerImpl.getConfigurationAwareListSize()); + + + } + +} diff --git a/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationImplTest.java b/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationImplTest.java index 71d768d907..816c6ce2bd 100644 --- a/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationImplTest.java +++ b/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationImplTest.java @@ -12,52 +12,51 @@ package org.opendaylight.controller.configuration.internal; import org.junit.*; import org.opendaylight.controller.configuration.IConfigurationAware; -public class ConfigurationImplTest { - - - @Test - public void testAddRemoveSaveConfiguration() { - - ConfigurationImpl configurationImpl = new ConfigurationImpl(); - IConfigurationAware testConfigurationAware = new ConfigurationAwareTest(); - - configurationImpl.addConfigurationAware(testConfigurationAware); - configurationImpl.addConfigurationAware(testConfigurationAware); - - Assert.assertEquals(1, configurationImpl.getConfigurationAwareListSize()); - - ConfigurationAwareTest testConfigurationAware1 = new ConfigurationAwareTest(); - configurationImpl.addConfigurationAware(testConfigurationAware1); - - Assert.assertEquals(2, configurationImpl.getConfigurationAwareListSize()); - - ConfigurationAwareTest testConfigurationAware2 = new ConfigurationAwareTest(); - configurationImpl.addConfigurationAware(testConfigurationAware2); - - Assert.assertEquals(3, configurationImpl.getConfigurationAwareListSize()); - - ConfigurationAwareTest testConfigurationAware3 = new ConfigurationAwareTest(); - configurationImpl.addConfigurationAware(testConfigurationAware3); - - Assert.assertEquals(4, configurationImpl.getConfigurationAwareListSize()); - - - configurationImpl.removeConfigurationAware(testConfigurationAware); - Assert.assertEquals(3, configurationImpl.getConfigurationAwareListSize()); - - configurationImpl.removeConfigurationAware(testConfigurationAware); - Assert.assertEquals(3, configurationImpl.getConfigurationAwareListSize()); - - configurationImpl.removeConfigurationAware(testConfigurationAware3); - Assert.assertEquals(2, configurationImpl.getConfigurationAwareListSize()); - - configurationImpl.removeConfigurationAware(testConfigurationAware1); - Assert.assertEquals(1, configurationImpl.getConfigurationAwareListSize()); - - configurationImpl.removeConfigurationAware(testConfigurationAware2); - Assert.assertEquals(0, configurationImpl.getConfigurationAwareListSize()); - - } - -} +public class ConfigurationImplTest { + + + @Test + public void testAddRemoveSaveConfiguration() { + + ConfigurationImpl configurationImpl = new ConfigurationImpl(); + IConfigurationAware testConfigurationAware = new ConfigurationAwareTest(); + + configurationImpl.addConfigurationAware(testConfigurationAware); + configurationImpl.addConfigurationAware(testConfigurationAware); + + Assert.assertEquals(1, configurationImpl.getConfigurationAwareListSize()); + + ConfigurationAwareTest testConfigurationAware1 = new ConfigurationAwareTest(); + configurationImpl.addConfigurationAware(testConfigurationAware1); + + Assert.assertEquals(2, configurationImpl.getConfigurationAwareListSize()); + + ConfigurationAwareTest testConfigurationAware2 = new ConfigurationAwareTest(); + configurationImpl.addConfigurationAware(testConfigurationAware2); + + Assert.assertEquals(3, configurationImpl.getConfigurationAwareListSize()); + ConfigurationAwareTest testConfigurationAware3 = new ConfigurationAwareTest(); + configurationImpl.addConfigurationAware(testConfigurationAware3); + + Assert.assertEquals(4, configurationImpl.getConfigurationAwareListSize()); + + + configurationImpl.removeConfigurationAware(testConfigurationAware); + Assert.assertEquals(3, configurationImpl.getConfigurationAwareListSize()); + + configurationImpl.removeConfigurationAware(testConfigurationAware); + Assert.assertEquals(3, configurationImpl.getConfigurationAwareListSize()); + + configurationImpl.removeConfigurationAware(testConfigurationAware3); + Assert.assertEquals(2, configurationImpl.getConfigurationAwareListSize()); + + configurationImpl.removeConfigurationAware(testConfigurationAware1); + Assert.assertEquals(1, configurationImpl.getConfigurationAwareListSize()); + + configurationImpl.removeConfigurationAware(testConfigurationAware2); + Assert.assertEquals(0, configurationImpl.getConfigurationAwareListSize()); + + } + +} diff --git a/opendaylight/configuration/integrationtest/.gitignore b/opendaylight/configuration/integrationtest/.gitignore new file mode 100644 index 0000000000..f92f36385a --- /dev/null +++ b/opendaylight/configuration/integrationtest/.gitignore @@ -0,0 +1 @@ +configuration diff --git a/opendaylight/configuration/integrationtest/pom.xml b/opendaylight/configuration/integrationtest/pom.xml new file mode 100644 index 0000000000..037b43515a --- /dev/null +++ b/opendaylight/configuration/integrationtest/pom.xml @@ -0,0 +1,91 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.integrationtest + 0.5.0-SNAPSHOT + ../../commons/integrationtest + + configuration.integrationtest + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + protocol_plugins.stub + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + sal + 0.5.0-SNAPSHOT + + + org.opendaylight.controller + sal.implementation + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + forwardingrulesmanager + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + clustering.services + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + clustering.services-implementation + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + clustering.stub + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + containermanager + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + containermanager.implementation + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + switchmanager + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + switchmanager.implementation + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + configuration + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + configuration.implementation + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + hosttracker + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + topologymanager + 0.4.0-SNAPSHOT + + + diff --git a/opendaylight/configuration/integrationtest/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationIT.java b/opendaylight/configuration/integrationtest/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationIT.java new file mode 100644 index 0000000000..8e1f34e612 --- /dev/null +++ b/opendaylight/configuration/integrationtest/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationIT.java @@ -0,0 +1,212 @@ +package org.opendaylight.controller.configuration.internal; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +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 java.io.File; + +import javax.inject.Inject; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.configuration.IConfigurationService; +import org.opendaylight.controller.sal.utils.GlobalConstants; +import org.opendaylight.controller.sal.utils.Status; +import org.opendaylight.controller.sal.utils.StatusCode; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.Configuration; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.util.PathUtils; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@RunWith(PaxExam.class) +public class ConfigurationIT { + private Logger logger = LoggerFactory + .getLogger(ConfigurationIT.class); + // get the OSGI bundle context + @Inject + private BundleContext bc; + private IClusterServices clusterService = null; + private IConfigurationService configService = null; + + // Configure the OSGi container + @Configuration + public Option[] config() { + return options( + systemProperty("logback.configurationFile").value( + "file:" + PathUtils.getBaseDir() + + "/src/test/resources/logback.xml"), + // To start OSGi console for inspection remotely + systemProperty("osgi.console").value("2401"), + // Set the systemPackages (used by clustering) + systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"), + // List framework bundles + mavenBundle("equinoxSDK381", "org.eclipse.equinox.console", + "1.0.0.v20120522-1841"), + mavenBundle("equinoxSDK381", "org.eclipse.equinox.util", + "1.0.400.v20120522-2049"), + mavenBundle("equinoxSDK381", "org.eclipse.osgi.services", + "3.3.100.v20120522-1822"), + mavenBundle("equinoxSDK381", "org.eclipse.equinox.ds", + "1.4.0.v20120522-1841"), + mavenBundle("equinoxSDK381", "org.apache.felix.gogo.command", + "0.8.0.v201108120515"), + mavenBundle("equinoxSDK381", "org.apache.felix.gogo.runtime", + "0.8.0.v201108120515"), + mavenBundle("equinoxSDK381", "org.apache.felix.gogo.shell", + "0.8.0.v201110170705"), + // List logger bundles + mavenBundle("org.slf4j", "slf4j-api", "1.7.2"), + mavenBundle("org.slf4j", "log4j-over-slf4j", "1.7.2"), + mavenBundle("ch.qos.logback", "logback-core", "1.0.9"), + mavenBundle("ch.qos.logback", "logback-classic", "1.0.9"), + mavenBundle("org.apache.commons", "commons-lang3", "3.1"), + mavenBundle("org.jboss.spec.javax.transaction", + "jboss-transaction-api_1.1_spec", "1.0.1.Final"), + mavenBundle("org.apache.felix", + "org.apache.felix.dependencymanager", "3.1.0"), + // List all the bundles on which the test case depends + mavenBundle("org.opendaylight.controller", "sal", + "0.5.0-SNAPSHOT"), // SAL connects the protocols + // plug-ins to other stuff + mavenBundle("org.opendaylight.controller", + "sal.implementation", "0.4.0-SNAPSHOT"), + mavenBundle("org.opendaylight.controller", + "protocol_plugins.stub", "0.4.0-SNAPSHOT"), + // needed bundles by switchmanager + mavenBundle("org.opendaylight.controller", "containermanager", + "0.4.0-SNAPSHOT"), + mavenBundle("org.opendaylight.controller", + "containermanager.implementation", "0.4.0-SNAPSHOT"), + mavenBundle("org.opendaylight.controller", "switchmanager", + "0.4.0-SNAPSHOT"), + mavenBundle("org.opendaylight.controller", + "switchmanager.implementation", "0.4.0-SNAPSHOT"), + // needed bundles by configuration + mavenBundle("org.opendaylight.controller", + "clustering.services", "0.4.0-SNAPSHOT"), // what are + // the + // clustering + // services + // for + mavenBundle("org.opendaylight.controller", "clustering.stub", + "0.4.0-SNAPSHOT"), + mavenBundle("org.opendaylight.controller", + "clustering.services-implementation", "0.4.0-SNAPSHOT"), + mavenBundle("org.opendaylight.controller", "configuration", + "0.4.0-SNAPSHOT"), + mavenBundle("org.opendaylight.controller", + "configuration.implementation", "0.4.0-SNAPSHOT"), + junitBundles()); + } + + private String stateToString(int state) { + switch (state) { + case Bundle.ACTIVE: + return "ACTIVE"; + case Bundle.INSTALLED: + return "INSTALLED"; + case Bundle.RESOLVED: + return "RESOLVED"; + case Bundle.UNINSTALLED: + return "UNINSTALLED"; + default: + return "Not CONVERTED"; + } + } + + @Before + public void areWeReadyForClustering() { + assertNotNull(bc); + boolean debugit = false; + Bundle b[] = bc.getBundles(); + for (int i = 0; i < b.length; i++) { + int state = b[i].getState(); + if (state != Bundle.ACTIVE && state != Bundle.RESOLVED) { + logger.debug("Bundle:" + b[i].getSymbolicName() + " state:" + + stateToString(state)); + debugit = true; + } + } + if (debugit) { + logger.debug("Do some debugging because some bundle is unresolved"); + } + + // Assert if true, if false we are good to go! + assertFalse(debugit); + ServiceReference r = bc.getServiceReference(IClusterServices.class + .getName()); + if (r != null) { + this.clusterService = (IClusterServices) bc.getService(r); + } + // If StatisticsManager is null, cannot run tests. + assertNotNull(this.clusterService); + + } + + @Before + public void areWeReadyForConfiguration() { + assertNotNull(bc); + boolean debugit = false; + Bundle b[] = bc.getBundles(); + for (int i = 0; i < b.length; i++) { + int state = b[i].getState(); + if (state != Bundle.ACTIVE && state != Bundle.RESOLVED) { + logger.debug("Bundle:" + b[i].getSymbolicName() + " state:" + + stateToString(state)); + debugit = true; + } + } + if (debugit) { + logger.debug("Do some debugging because some bundle is unresolved"); + } + + // Assert if true, if false we are good to go! + assertFalse(debugit); + ServiceReference r = bc.getServiceReference(IConfigurationService.class + .getName()); + if (r != null) { + this.configService = (IConfigurationService) bc.getService(r); + } + // If StatisticsManager is null, cannot run tests. + assertNotNull(this.configService); + + } + + @Test + public void saveConfiguration() { + File f = new File(GlobalConstants.STARTUPHOME.toString()); + boolean success = f.exists(); + if (!success) { + success = f.mkdirs(); + } + if(success){ + Status status = new Status(StatusCode.SUCCESS, null); + if (this.configService != null) { + status = this.configService.saveConfigurations(); + } + if (status.getCode().equals(StatusCode.SUCCESS)) { + Assert.assertTrue("Successfully saved config for " + + configService.getClass().getSimpleName(), status + .getCode().equals(StatusCode.SUCCESS)); + } else { + Assert.assertFalse("Failed to save config for " + + configService.getClass().getSimpleName(), status + .getCode().equals(StatusCode.INTERNALERROR)); + } + } + } + +} diff --git a/opendaylight/configuration/integrationtest/src/test/resources/logback.xml b/opendaylight/configuration/integrationtest/src/test/resources/logback.xml new file mode 100644 index 0000000000..2d63ce5744 --- /dev/null +++ b/opendaylight/configuration/integrationtest/src/test/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + diff --git a/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/IContainerManager.java b/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/IContainerManager.java index f057959ee8..b956d76a2e 100644 --- a/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/IContainerManager.java +++ b/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/IContainerManager.java @@ -23,14 +23,14 @@ public interface IContainerManager { /** * Returns a list of Containers that currently exist. * - * @return array of String Container names + * @return array of String Container names */ public boolean hasNonDefaultContainer(); /** * Returns a list of Containers that currently exist. * - * @return array of String Container names + * @return array of String Container names */ public List getContainerNames(); @@ -39,7 +39,7 @@ public interface IContainerManager { * TODO : REMOVE THIS FUNCTION and make Save as a service rather than the * current hack of calling individual save routines. * - * @return status code + * @return status code */ public Status saveContainerConfig(); } diff --git a/opendaylight/containermanager/implementation/pom.xml b/opendaylight/containermanager/implementation/pom.xml index 42ff3387f7..a324fca0d9 100644 --- a/opendaylight/containermanager/implementation/pom.xml +++ b/opendaylight/containermanager/implementation/pom.xml @@ -59,10 +59,10 @@ containermanager 0.4.0-SNAPSHOT - + org.opendaylight.controller sal 0.5.0-SNAPSHOT - + diff --git a/opendaylight/containermanager/implementation/src/test/java/org/opendaylight/controller/containermanager/internal/ContainerImplTest.java b/opendaylight/containermanager/implementation/src/test/java/org/opendaylight/controller/containermanager/internal/ContainerImplTest.java index 4bdd6797d6..2d6439954a 100644 --- a/opendaylight/containermanager/implementation/src/test/java/org/opendaylight/controller/containermanager/internal/ContainerImplTest.java +++ b/opendaylight/containermanager/implementation/src/test/java/org/opendaylight/controller/containermanager/internal/ContainerImplTest.java @@ -20,41 +20,41 @@ import org.opendaylight.controller.sal.utils.NodeCreator; public class ContainerImplTest { - @Test - public void test() { - - ContainerImpl container1 = new ContainerImpl(); - - //Create Component for init - ComponentImpl component1 = new ComponentImpl(null, null, null); - component1.setInterface("serviceTestName", null); - - //container1 does not have name yet - container1.init(component1); - assertNull(container1.getName()); - - //Sets container1 name to TestName - Hashtable properties = new Hashtable(); - properties.put("dummyKey", "dummyValue"); - properties.put("containerName", "TestName"); - component1.setInterface("serviceTestName", properties); - - container1.init(component1); - assertEquals("TestName", container1.getName()); - - //getContainerFlows always returns null for now - assertNull(container1.getContainerFlows()); - - //getTag always returns 0 for now - Node n = NodeCreator.createOFNode(1L); - assertEquals(0, container1.getTag(n)); - - //getNodeConnectors always returns null for now - assertNull(container1.getNodeConnectors()); - - //getNodes always returns null for now - assertNull(container1.getNodes()); - - } + @Test + public void test() { + + ContainerImpl container1 = new ContainerImpl(); + + //Create Component for init + ComponentImpl component1 = new ComponentImpl(null, null, null); + component1.setInterface("serviceTestName", null); + + //container1 does not have name yet + container1.init(component1); + assertNull(container1.getName()); + + //Sets container1 name to TestName + Hashtable properties = new Hashtable(); + properties.put("dummyKey", "dummyValue"); + properties.put("containerName", "TestName"); + component1.setInterface("serviceTestName", properties); + + container1.init(component1); + assertEquals("TestName", container1.getName()); + + //getContainerFlows always returns null for now + assertNull(container1.getContainerFlows()); + + //getTag always returns 0 for now + Node n = NodeCreator.createOFNode(1L); + assertEquals(0, container1.getTag(n)); + + //getNodeConnectors always returns null for now + assertNull(container1.getNodeConnectors()); + + //getNodes always returns null for now + assertNull(container1.getNodes()); + + } } diff --git a/opendaylight/containermanager/implementation/src/test/java/org/opendaylight/controller/containermanager/internal/ContainerManagerTest.java b/opendaylight/containermanager/implementation/src/test/java/org/opendaylight/controller/containermanager/internal/ContainerManagerTest.java index b5e7a11097..c7e35a069c 100644 --- a/opendaylight/containermanager/implementation/src/test/java/org/opendaylight/controller/containermanager/internal/ContainerManagerTest.java +++ b/opendaylight/containermanager/implementation/src/test/java/org/opendaylight/controller/containermanager/internal/ContainerManagerTest.java @@ -18,21 +18,21 @@ import org.opendaylight.controller.sal.utils.GlobalConstants; public class ContainerManagerTest { - @Test - public void test() { - ContainerManager cm = new ContainerManager(); - - cm.init(); - - ArrayList names = (ArrayList) cm.getContainerNames(); - assertEquals(1, names.size()); - assertEquals(GlobalConstants.DEFAULT.toString(), names.get(0)); - - assertFalse(cm.hasNonDefaultContainer()); - assertNull(cm.saveContainerConfig()); - - cm.destroy(); - - } + @Test + public void test() { + ContainerManager cm = new ContainerManager(); + + cm.init(); + + ArrayList names = (ArrayList) cm.getContainerNames(); + assertEquals(1, names.size()); + assertEquals(GlobalConstants.DEFAULT.toString(), names.get(0)); + + assertFalse(cm.hasNonDefaultContainer()); + assertNull(cm.saveContainerConfig()); + + cm.destroy(); + + } } diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index b30241daa8..50b34faac8 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -38,6 +38,7 @@ ../../clustering/test ../../configuration/api ../../configuration/implementation + ../../configuration/integrationtest ../../routing/dijkstra_implementation ../../arphandler ../../forwardingrulesmanager/api @@ -46,6 +47,8 @@ ../../hosttracker/api ../../hosttracker/implementation ../../hosttracker/integrationtest + ../../hosttracker_new/api + ../../hosttracker_new/implementation ../../containermanager/api ../../containermanager/implementation ../../switchmanager/api @@ -55,7 +58,8 @@ ../../statisticsmanager/implementation ../../statisticsmanager/integrationtest ../../topologymanager - ../../usermanager + ../../usermanager/api + ../../usermanager/implementation ../../security @@ -99,7 +103,7 @@ ../../samples/northbound/loadbalancer ../../commons/concepts ../../commons/integrationtest - + diff --git a/opendaylight/distribution/opendaylight/src/assemble/bin.xml b/opendaylight/distribution/opendaylight/src/assemble/bin.xml index 8c00d7f0fc..67a4735813 100644 --- a/opendaylight/distribution/opendaylight/src/assemble/bin.xml +++ b/opendaylight/distribution/opendaylight/src/assemble/bin.xml @@ -1,6 +1,6 @@ - + osgipackage dir @@ -12,9 +12,11 @@ org.opendaylight.controller.thirdparty:org.openflow.openflowj org.opendaylight.controller:clustering.stub - org.opendaylight.controller:logging.bridge - org.opendaylight.controller:protocol_plugins.stub - org.opendaylight.controller:*.integrationtest + org.opendaylight.controller:logging.bridge + org.opendaylight.controller:protocol_plugins.stub + org.opendaylight.controller:*.integrationtest + org.opendaylight.controller:hosttracker_new + org.opendaylight.controller:hosttracker_new.implementation opendaylight/plugins @@ -25,19 +27,19 @@ false - - - org.opendaylight.controller:logging.bridge - - - opendaylight/lib - - ${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension} - - false - false - - + + + org.opendaylight.controller:logging.bridge + + + opendaylight/lib + + ${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension} + + false + false + + @@ -52,15 +54,15 @@ virgomirror:org.eclipse.jdt.core.compiler.batch org.apache.felix:org.apache.felix.fileinstall geminiweb:org.eclipse.virgo.kernel.equinox.extensions - org.slf4j:slf4j-api - ch.qos.logback:logback-core - ch.qos.logback:logback-classic - com.sun.jersey:jersey-core - com.sun.jersey:jersey-json - com.sun.jersey:jersey-server + org.slf4j:slf4j-api + ch.qos.logback:logback-core + ch.qos.logback:logback-classic + com.sun.jersey:jersey-core + com.sun.jersey:jersey-json + com.sun.jersey:jersey-server - ${artifact.groupId}.${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension} + ${artifact.groupId}.${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension} false runtime @@ -78,16 +80,16 @@ virgomirror:org.eclipse.jdt.core.compiler.batch org.apache.felix:org.apache.felix.fileinstall geminiweb:org.eclipse.virgo.kernel.equinox.extensions - org.slf4j:slf4j-api - ch.qos.logback:logback-core - ch.qos.logback:logback-classic - com.sun.jersey:jersey-core - com.sun.jersey:jersey-json - com.sun.jersey:jersey-server + org.slf4j:slf4j-api + ch.qos.logback:logback-core + ch.qos.logback:logback-classic + com.sun.jersey:jersey-core + com.sun.jersey:jersey-json + com.sun.jersey:jersey-server false - ${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension} + ${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension} false runtime diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini index a8d7beb49b..460145ee87 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini @@ -1,13 +1,13 @@ osgi.bundles=\ - reference\:file\:../lib/org.apache.felix.fileinstall-3.1.6.jar@1:start,\ - reference\:file\:../lib/org.eclipse.jdt.core.compiler.batch-3.8.0.I20120518-2145.jar@1:start,\ - reference\:file\:../lib/org.eclipse.equinox.ds-1.4.0.v20120522-1841.jar@2:start,\ - reference\:file\:../lib/org.eclipse.equinox.util-1.0.400.v20120522-2049.jar@2:start,\ - reference\:file\:../lib/org.eclipse.osgi.services-3.3.100.v20120522-1822@2:start,\ - reference\:file\:../lib/org.eclipse.equinox.console-1.0.0.v20120522-1841.jar@start,\ - reference\:file\:../lib/slf4j-api-1.7.2.jar@1:start,\ - reference\:file\:../lib/logback-classic-1.0.9.jar@1:start,\ - reference\:file\:../lib/logback-core-1.0.9.jar@1:start,\ + reference\:file\:../lib/org.apache.felix.fileinstall-3.1.6.jar@1:start,\ + reference\:file\:../lib/org.eclipse.jdt.core.compiler.batch-3.8.0.I20120518-2145.jar@1:start,\ + reference\:file\:../lib/org.eclipse.equinox.ds-1.4.0.v20120522-1841.jar@2:start,\ + reference\:file\:../lib/org.eclipse.equinox.util-1.0.400.v20120522-2049.jar@2:start,\ + reference\:file\:../lib/org.eclipse.osgi.services-3.3.100.v20120522-1822@2:start,\ + reference\:file\:../lib/org.eclipse.equinox.console-1.0.0.v20120522-1841.jar@start,\ + reference\:file\:../lib/slf4j-api-1.7.2.jar@1:start,\ + reference\:file\:../lib/logback-classic-1.0.9.jar@1:start,\ + reference\:file\:../lib/logback-core-1.0.9.jar@1:start,\ reference\:file\:../lib/logging.bridge-0.4.0-SNAPSHOT@1:start,\ reference\:file\:../lib/jersey-core-1.17.jar@2:start,\ reference\:file\:../lib/jersey-json-1.17.jar@2:start,\ @@ -19,7 +19,7 @@ osgi.bundles.defaultStartLevel=4 org.osgi.framework.system.packages.extra=sun.reflect,sun.reflect.misc,sun.misc # This is not Eclipse App eclipse.ignoreApp=true -# Don't shutdown equinox if the eclipse App has ended, +# Don't shutdown equinox if the eclipse App has ended, # which is our case because we are not running any eclipse application osgi.noShutdown=true # Clean any cached data on restart of the framework @@ -33,7 +33,7 @@ felix.fileinstall.dir=./plugins felix.fileinstall.noInitialDelay=true # Auto start the bundles at level 4 felix.fileinstall.start.level=4 -# Avoid to auto-install following bundles, that means those need +# Avoid to auto-install following bundles, that means those need # to be started manually or in other way like osgi.bundles felix.fileinstall.filter=^(?!org.apache.felix.fileinstall).* @@ -69,7 +69,7 @@ org.eclipse.gemini.web.tomcat.config.path=configuration/tomcat-server.xml # TLS configuration # To enable TLS, set secureChannelEnabled=true and specify the location of controller Java KeyStore and TrustStore files. -# The Java KeyStore contains controller's private key and certificate. The Java TrustStore contains the trusted certificate +# The Java KeyStore contains controller's private key and certificate. The Java TrustStore contains the trusted certificate # entries, including switches' Certification Authority (CA) certificates. For example, # secureChannelEnabled=true # controllerKeyStore=./configuration/ctlKeyStore diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml index a99d17d37c..de70a52a31 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml @@ -54,5 +54,5 @@ - + diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/tomcat-server.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/tomcat-server.xml index 4be075451e..56d469b599 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/tomcat-server.xml +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/tomcat-server.xml @@ -30,13 +30,13 @@ connectionTimeout="20000" redirectPort="8443" /> - - - ../../northbound/commons - + diff --git a/opendaylight/distribution/sdk/src/assemble/bin.xml b/opendaylight/distribution/sdk/src/assemble/bin.xml index bb3c6734f6..b2f45c38c9 100644 --- a/opendaylight/distribution/sdk/src/assemble/bin.xml +++ b/opendaylight/distribution/sdk/src/assemble/bin.xml @@ -1,4 +1,4 @@ - package diff --git a/opendaylight/forwarding/staticrouting/pom.xml b/opendaylight/forwarding/staticrouting/pom.xml index 80eea57b8f..ea22c4f1ca 100644 --- a/opendaylight/forwarding/staticrouting/pom.xml +++ b/opendaylight/forwarding/staticrouting/pom.xml @@ -70,7 +70,7 @@ org.opendaylight.controller configuration 0.4.0-SNAPSHOT - + junit junit diff --git a/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/IForwardingStaticRouting.java b/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/IForwardingStaticRouting.java index 5fabb2629d..0166d279f6 100644 --- a/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/IForwardingStaticRouting.java +++ b/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/IForwardingStaticRouting.java @@ -12,14 +12,14 @@ package org.opendaylight.controller.forwarding.staticrouting; import java.net.InetAddress; import java.util.concurrent.ConcurrentMap; /** - * + * * This interface provides APIs to configure and manage static routes. * */ import org.opendaylight.controller.sal.utils.Status; /** - * + * * This Interface provides APIs to manage and query the static routes * */ diff --git a/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteConfig.java b/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteConfig.java index 262c0170db..ceacebffb0 100644 --- a/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteConfig.java +++ b/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteConfig.java @@ -151,18 +151,18 @@ public class StaticRouteConfig implements Serializable { public Status isValid() { if ((name == null) || (name.trim().length() < 1)) { return new Status(StatusCode.BADREQUEST, - "Invalid Static Route name"); + "Invalid Static Route name"); } if (!isValidStaticRouteEntry()) { return new Status(StatusCode.BADREQUEST, - "Invalid Static Route entry. Please use the " + - "IPAddress/mask format. Default gateway " + - "(0.0.0.0/0) is NOT supported."); + "Invalid Static Route entry. Please use the " + + "IPAddress/mask format. Default gateway " + + "(0.0.0.0/0) is NOT supported."); } if (!isValidNextHop()) { return new Status(StatusCode.BADREQUEST, - "Invalid NextHop IP Address configuration. " + - "Please use the X.X.X.X format."); + "Invalid NextHop IP Address configuration. " + + "Please use the X.X.X.X format."); } return new Status(StatusCode.SUCCESS, null); diff --git a/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementation.java b/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementation.java index 1ac923c15e..8819be3988 100644 --- a/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementation.java +++ b/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementation.java @@ -131,7 +131,7 @@ public class StaticRoutingImplementation implements IfNewHostNotify, } } - + private Status saveConfig() { // Publish the save config event to the cluster nodes configSaveEvent.put(new Date().getTime(), SAVE); @@ -154,7 +154,7 @@ public class StaticRoutingImplementation implements IfNewHostNotify, } @SuppressWarnings("deprecation") - private void allocateCaches() { + private void allocateCaches() { if (this.clusterContainerService == null) { log .info("un-initialized clusterContainerService, can't create cache"); @@ -207,7 +207,7 @@ public class StaticRoutingImplementation implements IfNewHostNotify, } @SuppressWarnings("deprecation") - private void destroyCaches() { + private void destroyCaches() { if (this.clusterContainerService == null) { log .info("un-initialized clusterContainerService, can't destroy cache"); @@ -390,16 +390,16 @@ public class StaticRoutingImplementation implements IfNewHostNotify, return status; } if (staticRouteConfigs.get(config.getName()) != null) { - return new Status(StatusCode.CONFLICT, - "A valid Static Route configuration with this name " + - "already exists. Please use a different name"); + return new Status(StatusCode.CONFLICT, + "A valid Static Route configuration with this name " + + "already exists. Please use a different name"); } for (StaticRouteConfig s : staticRouteConfigs.values()) { if (s.equals(config)) { - return new Status(StatusCode.CONFLICT, - "This conflicts with an existing Static Route " + - "Configuration. Please check the configuration " + - "and try again"); + return new Status(StatusCode.CONFLICT, + "This conflicts with an existing Static Route " + + "Configuration. Please check the configuration " + + "and try again"); } } @@ -407,7 +407,7 @@ public class StaticRoutingImplementation implements IfNewHostNotify, StaticRoute sRoute = new StaticRoute(config); staticRoutes.put(config.getName(), sRoute); checkAndUpdateListeners(sRoute, true); - return status; + return status; } public Status removeStaticRoute(String name) { @@ -417,8 +417,8 @@ public class StaticRoutingImplementation implements IfNewHostNotify, checkAndUpdateListeners(sRoute, false); return new Status(StatusCode.SUCCESS, null); } - return new Status(StatusCode.NOTFOUND, - "Static Route with name " + name + " is not found"); + return new Status(StatusCode.NOTFOUND, + "Static Route with name " + name + " is not found"); } void setClusterContainerService(IClusterContainerServices s) { diff --git a/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteConfigTest.java b/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteConfigTest.java index 84ec54b807..7cd085f896 100644 --- a/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteConfigTest.java +++ b/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteConfigTest.java @@ -18,94 +18,93 @@ import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.sal.utils.StatusCode; public class StaticRouteConfigTest { - - @Test - public void testStaticRouteSetGet() { - StaticRouteConfig staticRouteConfig1 = new StaticRouteConfig(); - staticRouteConfig1.setName("route"); - staticRouteConfig1.setStaticRoute("10.1.1.2/32"); - staticRouteConfig1.setNextHop("200.2.2.2"); - staticRouteConfig1.setNextHopType(NextHopType.IPADDRESS.toString()); - StaticRouteConfig staticRouteConfig2 = new StaticRouteConfig("route", "10.1.1.2/32", "200.2.2.2"); - - Assert.assertEquals(staticRouteConfig2.getName(), staticRouteConfig1.getName()); - Assert.assertEquals(staticRouteConfig2.getStaticRoute(), staticRouteConfig1.getStaticRoute()); - Assert.assertEquals(staticRouteConfig2.getNextHop(), staticRouteConfig1.getNextHop()); - Assert.assertEquals("nexthop-ip", staticRouteConfig1.getNextHopType()); - } - - @Test - public void testStaticRouteisValid() { + + @Test + public void testStaticRouteSetGet() { + StaticRouteConfig staticRouteConfig1 = new StaticRouteConfig(); + staticRouteConfig1.setName("route"); + staticRouteConfig1.setStaticRoute("10.1.1.2/32"); + staticRouteConfig1.setNextHop("200.2.2.2"); + staticRouteConfig1.setNextHopType(NextHopType.IPADDRESS.toString()); + StaticRouteConfig staticRouteConfig2 = new StaticRouteConfig("route", "10.1.1.2/32", "200.2.2.2"); + + Assert.assertEquals(staticRouteConfig2.getName(), staticRouteConfig1.getName()); + Assert.assertEquals(staticRouteConfig2.getStaticRoute(), staticRouteConfig1.getStaticRoute()); + Assert.assertEquals(staticRouteConfig2.getNextHop(), staticRouteConfig1.getNextHop()); + Assert.assertEquals("nexthop-ip", staticRouteConfig1.getNextHopType()); + } + + @Test + public void testStaticRouteisValid() { StaticRouteConfig staticRouteConfig1 = new StaticRouteConfig("route1", "10.1.1.254/24", "100.1.1.1"); - Status receivedResponse1 = staticRouteConfig1.isValid(); - Status expectedResponse1 = new Status(StatusCode.SUCCESS, null); - Assert.assertEquals(expectedResponse1.toString(), receivedResponse1.toString()); - + Status receivedResponse1 = staticRouteConfig1.isValid(); + Status expectedResponse1 = new Status(StatusCode.SUCCESS, null); + Assert.assertEquals(expectedResponse1.toString(), receivedResponse1.toString()); + StaticRouteConfig staticRouteConfig2 = new StaticRouteConfig("", "", "100.1.1.1"); - Status receivedResponse2 = staticRouteConfig2.isValid(); - Status expectedResponse2 = new Status(StatusCode.BADREQUEST, - "Invalid Static Route name"); - Assert.assertEquals(expectedResponse2.toString(), receivedResponse2.toString()); + Status receivedResponse2 = staticRouteConfig2.isValid(); + Status expectedResponse2 = new Status(StatusCode.BADREQUEST, + "Invalid Static Route name"); + Assert.assertEquals(expectedResponse2.toString(), receivedResponse2.toString()); StaticRouteConfig staticRouteConfig3 = new StaticRouteConfig("route1", "10.1.1.254", "100.1.1.1"); - Status receivedResponse3 = staticRouteConfig3.isValid(); - Status expectedResponse3 = new Status(StatusCode.BADREQUEST, - "Invalid Static Route entry. Please use the " + - "IPAddress/mask format. Default gateway " + - "(0.0.0.0/0) is NOT supported."); - Assert.assertEquals(expectedResponse3.toString(), receivedResponse3.toString()); + Status receivedResponse3 = staticRouteConfig3.isValid(); + Status expectedResponse3 = new Status(StatusCode.BADREQUEST, + "Invalid Static Route entry. Please use the " + + "IPAddress/mask format. Default gateway " + + "(0.0.0.0/0) is NOT supported."); + Assert.assertEquals(expectedResponse3.toString(), receivedResponse3.toString()); StaticRouteConfig staticRouteConfig4 = new StaticRouteConfig("route1", "289.1.1.254/24", "100.1.1.1"); - Status receivedResponse4 = staticRouteConfig4.isValid(); - Status expectedResponse4 = new Status(StatusCode.BADREQUEST, - "Invalid Static Route entry. Please use the " + - "IPAddress/mask format. Default gateway " + - "(0.0.0.0/0) is NOT supported."); - Assert.assertEquals(expectedResponse4.toString(), receivedResponse4.toString()); - + Status receivedResponse4 = staticRouteConfig4.isValid(); + Status expectedResponse4 = new Status(StatusCode.BADREQUEST, + "Invalid Static Route entry. Please use the " + + "IPAddress/mask format. Default gateway " + + "(0.0.0.0/0) is NOT supported."); + Assert.assertEquals(expectedResponse4.toString(), receivedResponse4.toString()); + StaticRouteConfig staticRouteConfig5 = new StaticRouteConfig("route1", "10.1.1.254/24", "100.1.1"); - Status receivedResponse5 = staticRouteConfig5.isValid(); - Status expectedResponse5 = new Status(StatusCode.BADREQUEST, - "Invalid NextHop IP Address configuration. " + - "Please use the X.X.X.X format."); - Assert.assertEquals(expectedResponse5.toString(), receivedResponse5.toString()); - } - - @Test - public void testGetStaticRouteIP() { + Status receivedResponse5 = staticRouteConfig5.isValid(); + Status expectedResponse5 = new Status(StatusCode.BADREQUEST, + "Invalid NextHop IP Address configuration. " + + "Please use the X.X.X.X format."); + Assert.assertEquals(expectedResponse5.toString(), receivedResponse5.toString()); + } + + @Test + public void testGetStaticRouteIP() { StaticRouteConfig staticRouteConfig1 = new StaticRouteConfig("route1", "10.1.1.0/24", "100.1.1.1"); InetAddress ip1 = staticRouteConfig1.getStaticRouteIP(); - Assert.assertEquals("10.1.1.0", ip1.getHostAddress()); - + Assert.assertEquals("10.1.1.0", ip1.getHostAddress()); + StaticRouteConfig staticRouteConfig2 = new StaticRouteConfig("route1", "10.1.1.0/80", "100.1.1.1"); InetAddress ip2 = staticRouteConfig2.getStaticRouteIP(); - Assert.assertEquals(null, ip2); + Assert.assertEquals(null, ip2); + + } - } - - @Test - public void testGetStaticRouteMask() { + @Test + public void testGetStaticRouteMask() { StaticRouteConfig staticRouteConfig1 = new StaticRouteConfig("route1", "10.1.1.0/24", "100.1.1.1"); - Short receivedMaskLen1 = staticRouteConfig1.getStaticRouteMask(); - Short expectedMaskLen1 = 24; - Assert.assertEquals(expectedMaskLen1, receivedMaskLen1); - - StaticRouteConfig staticRouteConfig2 = new StaticRouteConfig("route1", "10.1.1.0/40", "100.1.1.1"); - Short receivedMaskLen2 = staticRouteConfig2.getStaticRouteMask(); - Short expectedMaskLen2 = 0; - Assert.assertEquals(expectedMaskLen2, receivedMaskLen2); - } - - @Test - public void testGetNextHopIP() { + Short receivedMaskLen1 = staticRouteConfig1.getStaticRouteMask(); + Short expectedMaskLen1 = 24; + Assert.assertEquals(expectedMaskLen1, receivedMaskLen1); + + StaticRouteConfig staticRouteConfig2 = new StaticRouteConfig("route1", "10.1.1.0/40", "100.1.1.1"); + Short receivedMaskLen2 = staticRouteConfig2.getStaticRouteMask(); + Short expectedMaskLen2 = 0; + Assert.assertEquals(expectedMaskLen2, receivedMaskLen2); + } + + @Test + public void testGetNextHopIP() { StaticRouteConfig staticRouteConfig1 = new StaticRouteConfig("route1", "10.1.1.254/24", "100.1.1.1"); InetAddress ip1 = staticRouteConfig1.getNextHopIP(); - Assert.assertEquals("100.1.1.1", ip1.getHostAddress()); + Assert.assertEquals("100.1.1.1", ip1.getHostAddress()); - StaticRouteConfig staticRouteConfig2 = new StaticRouteConfig("route1", "10.1.1.254/24", "100.1.1"); + StaticRouteConfig staticRouteConfig2 = new StaticRouteConfig("route1", "10.1.1.254/24", "100.1.1"); InetAddress ip2 = staticRouteConfig2.getNextHopIP(); - Assert.assertEquals(null, ip2); - } - -} + Assert.assertEquals(null, ip2); + } +} diff --git a/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteTest.java b/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteTest.java index f05b10c9cf..4a497a058c 100644 --- a/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteTest.java +++ b/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteTest.java @@ -23,35 +23,35 @@ import org.opendaylight.controller.sal.utils.NodeConnectorCreator; import org.opendaylight.controller.sal.utils.NodeCreator; public class StaticRouteTest { - - @Test - public void testStaticRouteGetSet() { - StaticRoute staticRoute = new StaticRoute(); - InetAddress networkAddress = null; - InetAddress mask = null; - InetAddress nextHopAddress = null; - try { - networkAddress = InetAddress.getByName("10.1.1.0"); - mask = InetAddress.getByName("255.255.255.0"); - nextHopAddress = InetAddress.getByName("200.0.0.1"); - - } catch (UnknownHostException e) { - Assert.assertTrue(false); - } - staticRoute.setNetworkAddress(networkAddress); - Assert.assertEquals(networkAddress.getHostAddress(), staticRoute.getNetworkAddress().getHostAddress()); - staticRoute.setMask(mask); - Assert.assertEquals(mask.getHostAddress(), staticRoute.getMask().getHostAddress()); - staticRoute.setType(NextHopType.IPADDRESS); - Assert.assertEquals("nexthop-ip", staticRoute.getType().toString()); - staticRoute.setNextHopAddress(nextHopAddress); - Assert.assertEquals(nextHopAddress.getHostAddress(), staticRoute.getNextHopAddress().getHostAddress()); - Node node = NodeCreator.createOFNode(((long)10)); - staticRoute.setNode(node); - Assert.assertEquals(node, staticRoute.getNode()); - NodeConnector nc0 = NodeConnectorCreator.createOFNodeConnector((short)20, node); - staticRoute.setPort(nc0); - Assert.assertEquals(nc0, staticRoute.getPort()); + + @Test + public void testStaticRouteGetSet() { + StaticRoute staticRoute = new StaticRoute(); + InetAddress networkAddress = null; + InetAddress mask = null; + InetAddress nextHopAddress = null; + try { + networkAddress = InetAddress.getByName("10.1.1.0"); + mask = InetAddress.getByName("255.255.255.0"); + nextHopAddress = InetAddress.getByName("200.0.0.1"); + + } catch (UnknownHostException e) { + Assert.assertTrue(false); + } + staticRoute.setNetworkAddress(networkAddress); + Assert.assertEquals(networkAddress.getHostAddress(), staticRoute.getNetworkAddress().getHostAddress()); + staticRoute.setMask(mask); + Assert.assertEquals(mask.getHostAddress(), staticRoute.getMask().getHostAddress()); + staticRoute.setType(NextHopType.IPADDRESS); + Assert.assertEquals("nexthop-ip", staticRoute.getType().toString()); + staticRoute.setNextHopAddress(nextHopAddress); + Assert.assertEquals(nextHopAddress.getHostAddress(), staticRoute.getNextHopAddress().getHostAddress()); + Node node = NodeCreator.createOFNode(((long)10)); + staticRoute.setNode(node); + Assert.assertEquals(node, staticRoute.getNode()); + NodeConnector nc0 = NodeConnectorCreator.createOFNodeConnector((short)20, node); + staticRoute.setPort(nc0); + Assert.assertEquals(nc0, staticRoute.getPort()); InetAddress ip1 = null; HostNodeConnector h1 = null; try { @@ -66,10 +66,10 @@ public class StaticRouteTest { } staticRoute.setHost(h1); Assert.assertEquals(h1, staticRoute.getHost()); - } - - @Test - public void testStaticRouteComparison() { + } + + @Test + public void testStaticRouteComparison() { StaticRouteConfig staticRouteConfig1 = new StaticRouteConfig("route1", "10.1.1.0/24", "100.1.1.1"); StaticRouteConfig staticRouteConfig2 = new StaticRouteConfig("route2", "10.1.1.0/24", "100.2.1.1"); StaticRouteConfig staticRouteConfig3 = new StaticRouteConfig("route3", "10.2.1.0/24", "100.3.1.1"); @@ -82,28 +82,28 @@ public class StaticRouteTest { Assert.assertTrue(staticRoute1.equals(staticRoute2)); Assert.assertFalse(staticRoute1.equals(staticRoute3)); Assert.assertFalse(staticRoute1.equals(staticRoute4)); - + Assert.assertTrue(staticRoute1.compareTo(staticRoute2) == 0 ? true : false); Assert.assertFalse(staticRoute1.compareTo(staticRoute3) == 0 ? true : false); Assert.assertTrue(staticRoute1.compareTo(staticRoute4) == 0 ? true : false); - - } - - @Test - public void testLongestPrefixMatch() { + + } + + @Test + public void testLongestPrefixMatch() { StaticRouteConfig staticRouteConfig1 = new StaticRouteConfig("route1", "10.1.1.254/24", "100.1.1.1"); StaticRoute staticRoute1 = new StaticRoute(staticRouteConfig1); - InetAddress ip1 = null; - InetAddress ip2 = null; - try { - ip1 = InetAddress.getByName("10.1.0.2"); - ip2 = InetAddress.getByName("10.1.1.2"); - } catch (UnknownHostException e) { - Assert.assertTrue(false); - } + InetAddress ip1 = null; + InetAddress ip2 = null; + try { + ip1 = InetAddress.getByName("10.1.0.2"); + ip2 = InetAddress.getByName("10.1.1.2"); + } catch (UnknownHostException e) { + Assert.assertTrue(false); + } InetAddress rxdIp1 = staticRoute1.longestPrefixMatch(ip1); InetAddress rxdIp2 = staticRoute1.longestPrefixMatch(ip2); - Assert.assertEquals(null, rxdIp1); - Assert.assertEquals("10.1.1.0", rxdIp2.getHostAddress()); - } + Assert.assertEquals(null, rxdIp1); + Assert.assertEquals("10.1.1.0", rxdIp2.getHostAddress()); + } } diff --git a/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementationTest.java b/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementationTest.java index 4df0590b1d..4c9d4ab1f3 100644 --- a/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementationTest.java +++ b/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementationTest.java @@ -13,16 +13,12 @@ import org.junit.Assert; import org.junit.Test; public class StaticRoutingImplementationTest { - - @Test - public void isIPv4AddressValidTest() { - StaticRoutingImplementation staticRouteImpl = new StaticRoutingImplementation(); - Assert.assertTrue(staticRouteImpl.isIPv4AddressValid("192.168.100.0/24")); - Assert.assertFalse(staticRouteImpl.isIPv4AddressValid("192.168.100.0/36")); - Assert.assertFalse(staticRouteImpl.isIPv4AddressValid("192.168.300.0/32")); - } -} - - - + @Test + public void isIPv4AddressValidTest() { + StaticRoutingImplementation staticRouteImpl = new StaticRoutingImplementation(); + Assert.assertTrue(staticRouteImpl.isIPv4AddressValid("192.168.100.0/24")); + Assert.assertFalse(staticRouteImpl.isIPv4AddressValid("192.168.100.0/36")); + Assert.assertFalse(staticRouteImpl.isIPv4AddressValid("192.168.300.0/32")); + } +} diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntry.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntry.java index 6aa5b07e2a..8a055329e1 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntry.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntry.java @@ -51,7 +51,7 @@ public class FlowEntry implements Cloneable, Serializable { /** * Return the actual Flow contained in this entry - * + * * @return the flow */ public Flow getFlow() { @@ -147,12 +147,12 @@ public class FlowEntry implements Cloneable, Serializable { /** * Merges the current Flow with the passed Container Flow - * + * * Note: Container Flow merging is not an injective function. Be m1 and m2 * two different matches, and be f() the flow merge function, such that y1 = * f(m1) and y2 = f(m2) are the two merged matches, we may have: y1 = y2 - * - * + * + * * @param containerFlow * @return this merged FlowEntry */ diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntryInstall.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntryInstall.java index 18255bc021..311d2f96ac 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntryInstall.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntryInstall.java @@ -17,10 +17,10 @@ import org.opendaylight.controller.sal.core.Node; * install, the container flow with which that entry had to be merged and the * resultant merged flow entry, which is the one that was eventually installed * on the network node - * + * * Note: If the container flow is null, the install entry will be a clone of the * original entry - * + * */ public class FlowEntryInstall { private FlowEntry original; @@ -115,7 +115,7 @@ public class FlowEntryInstall { public void setRequestId(long rid) { this.requestId = rid; } - + public long getRequestId() { return requestId; } diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManager.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManager.java index 087c0bc878..b3d0c8acdf 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManager.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManager.java @@ -18,7 +18,7 @@ import org.opendaylight.controller.sal.utils.Status; /** * Interface that describes methods for installing or removing forwarding rules * and to access to the flows database. - * + * */ public interface IForwardingRulesManager { @@ -27,7 +27,7 @@ public interface IForwardingRulesManager { * SDN protocol plugin to install the flow on the network node. Based on the * result of this operation FRM will update its database accordingly and * will return the proper {@code Status} code. - * + * * @param flow * the flow entry to install * @return the {@code Status} object indicating the result of this action. @@ -39,7 +39,7 @@ public interface IForwardingRulesManager { * protocol plugin to uninstall the flow from the network node. Based on the * result of this operation FRM will update its database accordingly and * will return the proper {@code Status} code. - * + * * @param flow * the flow entry to uninstall * @return the {@code Status} object indicating the result of this action @@ -53,7 +53,7 @@ public interface IForwardingRulesManager { * modify message depending on the SDN protocol specifications If the * current flow is equal to the new one it will be a no op and success code * is returned. - * + * * @param current * the current flow entry to modify * @param newone @@ -72,8 +72,8 @@ public interface IForwardingRulesManager { * it, it will request plugin to add the new flow. If the passed entry is * not valid an error code is returned. If the existing flow is equal to the * passed one it will be a no op and success code is returned. - * - * + * + * * @param newone * the new flow entry to install * @return the {@code Status} object indicating the result of this action @@ -86,7 +86,7 @@ public interface IForwardingRulesManager { * SDN protocol plugin to install the flow on the network node. As immediate * result of this asynchronous call, FRM will update its flow database as if * the flow was successfully installed. - * + * * @param flow * the flow entry to install * @return the status of this request containing the request id associated @@ -100,7 +100,7 @@ public interface IForwardingRulesManager { * SDN protocol plugin to uninstall the flow from the network node. As * immediate result of this asynchronous call, FRM will update its flow * database as if the flow was successfully installed. - * + * * @param flow * the flow entry to uninstall * @return the status of this request containing the unique id associated to @@ -115,7 +115,7 @@ public interface IForwardingRulesManager { * this message to the network node. It could be a delete + add or a single * modify message depending on the SDN protocol specifications. If the * current flow is equal to the new one it will be a no op. - * + * * @param current * the current flow entry to modify * @param newone @@ -136,7 +136,7 @@ public interface IForwardingRulesManager { * it, it will request plugin to add the new flow. If the passed entry is * not valid a zero request id is returned. If the existing flow is equal to * the passed one it will be a no op. - * + * * @param newone * the new flow entry to install * @return the unique id associated to this request. In case of not @@ -154,7 +154,7 @@ public interface IForwardingRulesManager { * blocked until the solicitation response is received from the network node * or receive timeout. Otherwise, it is a non-blocking call and does not * guarantee the node will respond in any given time. - * + * * @param node * The network node to solicit a response * @param blocking @@ -166,7 +166,7 @@ public interface IForwardingRulesManager { /** * Check whether the passed flow entry conflicts with the Container flows - * + * * @param flow * the flow entry to test * @return true if conflicts, false otherwise @@ -176,7 +176,7 @@ public interface IForwardingRulesManager { /** * Returns the list of Flow entries across network nodes which are part of * the same flow group, policy - * + * * @param group * the group name * @return the list of flow entries belonging to the specified group @@ -186,7 +186,7 @@ public interface IForwardingRulesManager { /** * Add a list of output port to the flow with the specified name on the * specified network node - * + * * @param node * the network node * @param flowName @@ -200,7 +200,7 @@ public interface IForwardingRulesManager { /** * Remove a list of output port from the flow with the specified name on the * specified network node - * + * * @param node * the network node * @param flowName @@ -214,7 +214,7 @@ public interface IForwardingRulesManager { /** * Replace the current output port in the specified flow with the specified * one - * + * * @param node * the network node * @param groupName @@ -229,7 +229,7 @@ public interface IForwardingRulesManager { /** * Returns the output port configured on the specified flow - * + * * @param node * the network node * @param flowName @@ -242,14 +242,14 @@ public interface IForwardingRulesManager { * Returns all the troubleshooting information that applications have set * along with the policy they have configured through forwarding rules * manger. - * + * * @return the collection of troubleshooting objects */ public Map getTSPolicyData(); /** * Set the troubleshooting information for the policy - * + * * @param policyname * the flow group name * @param o @@ -262,7 +262,7 @@ public interface IForwardingRulesManager { /** * Returns the troubleshooting information that was set for the specified * policy - * + * * @param groupName * the flows group name * @return the troubleshooting info object @@ -272,7 +272,7 @@ public interface IForwardingRulesManager { /** * Returns the specifications of all the flows configured for all the * switches on the current container - * + * * @return the list of flow configurations present in the database */ public List getStaticFlows(); @@ -280,7 +280,7 @@ public interface IForwardingRulesManager { /** * Returns the specifications of all the flows configured for the given * switch on the current container - * + * * @param node * the network node identifier * @return the list of {@code FlowConfig} objects @@ -290,7 +290,7 @@ public interface IForwardingRulesManager { /** * Returns the specification of the flow configured for the given network * node on the current container - * + * * @param name * the flow name * @param n @@ -302,7 +302,7 @@ public interface IForwardingRulesManager { /** * Returns the list of names of flows configured for the given Network node * on the current container - * + * * @param node * the network node identifier * @return the list of flow names @@ -311,14 +311,14 @@ public interface IForwardingRulesManager { /** * Returns the list of Node(s) for which a static flow has been configured - * + * * @return the list of network nodes */ public List getListNodeWithConfiguredFlows(); /** * Save the flow configured so far to file - * + * * @return the {@code Status} object indicating the result of this action. */ public Status saveConfig(); @@ -326,7 +326,7 @@ public interface IForwardingRulesManager { /** * Add a flow specified by the {@code FlowConfig} object on the current * container - * + * * @param config * the {@code FlowConfig} object representing the static flow * @param restore @@ -339,7 +339,7 @@ public interface IForwardingRulesManager { /** * Remove a flow specified by the {@code FlowConfig} object on the current * container - * + * * @param config * the {@code FlowConfig} object representing the static flow * @return the {@code Status} object indicating the result of this action @@ -350,7 +350,7 @@ public interface IForwardingRulesManager { * Replace the flow identified by the {@code FlowConfig.name} name for the * {@code FlowConfig.node} network node with the new flow specified by * {@code FlowConfig} object - * + * * @param config * the {@code FlowConfig} object * @returnthe {@code Status} object indicating the result of this action @@ -359,7 +359,7 @@ public interface IForwardingRulesManager { /** * Remove the flow specified by name on the passed network node - * + * * @param name * for the static flow * @param node @@ -372,7 +372,7 @@ public interface IForwardingRulesManager { * Toggle the installation status of the specified configured flow If the * flow configuration status is active, this call will change the flow * status to inactive and vice-versa - * + * * @param configObject * the {@code FlowConfig} object * @return the {@code Status} object indicating the result of this action @@ -383,7 +383,7 @@ public interface IForwardingRulesManager { * Toggle the installation status of the specified configured flow If the * flow configuration status is active, this call will change the flow * status to inactive and vice-versa - * + * * @param name * for the static flow * @param node diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManagerAware.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManagerAware.java index 43d1b29a75..952b3cdff7 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManagerAware.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManagerAware.java @@ -11,14 +11,14 @@ package org.opendaylight.controller.forwardingrulesmanager; /** * The interface which describes the methods forwarding rules manager will call * for notifying the listeners of policy installation updates. - * + * */ public interface IForwardingRulesManagerAware { /** * Inform the listeners that a troubleshooting information was added or * removed for the specified policy. - * + * * @param policyName * the policy affected * @param add @@ -31,7 +31,7 @@ public interface IForwardingRulesManagerAware { * Inform listeners that the network node has notified us about a failure in * executing the controller generated asynchronous request identified by the * passed unique id. - * + * * @param requestId * the unique id associated with the request which failed to be * executed on the network node diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroup.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroup.java index 5acd3e2ebc..95e9b00d14 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroup.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroup.java @@ -14,11 +14,11 @@ import java.util.Set; /** * PortGroup is a simple data-structure to represent any arbitrary group of * ports on a Switch (that is represented using its switch-ID). - * + * * PortGroup is used by PortGroupProvider application to signal a set of ports * that represent a configured PortGroupConfig. - * - * + * + * */ public class PortGroup { private long matrixSwitchId; @@ -26,7 +26,7 @@ public class PortGroup { /** * PortGroup Constructor using Switch and Ports. - * + * * @param matrixSwitchId * Switch Id that represents an openflow Switch * @param ports @@ -40,7 +40,7 @@ public class PortGroup { /** * PortGroup Constructor using Switch. - * + * * @param matrixSwitchId * Switch-Id that represents an openflow Switch */ @@ -51,7 +51,7 @@ public class PortGroup { /** * Returns the switchId representing the Switch that makes this PortGroup. - * + * * @return long switchId */ public long getMatrixSwitchId() { @@ -60,7 +60,7 @@ public class PortGroup { /** * Assigns a Switch to this PortGroup - * + * * @param matrixSwitchId * Switch-Id that represents an openflow Switch */ @@ -70,7 +70,7 @@ public class PortGroup { /** * Returns the Set of Ports that makes this PortGroup. - * + * * @return Set of short values representing openflow port-ids. */ public Set getPorts() { @@ -79,7 +79,7 @@ public class PortGroup { /** * Assigns a set of openflow ports to this PortGroup - * + * * @param ports * Set of short values representing openflow port-ids. */ @@ -89,7 +89,7 @@ public class PortGroup { /** * Adds a port to this PortGroup - * + * * @param port * Short value of a openflow port. */ diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupChangeListener.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupChangeListener.java index 7c8ade5b89..77ff64014b 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupChangeListener.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupChangeListener.java @@ -15,14 +15,14 @@ import org.opendaylight.controller.sal.core.Node; /** * PortGroupChangeListener listens to the PortGroup updates provided by the * PortGroupProvider. - * - * + * + * */ public interface PortGroupChangeListener { /** * This method is invoked by PortGroupProvider whenever it detects a change * in PortGroup membership for a given PortGroupConfig. - * + * * @param config * Port Group Configuration * @param portGroupData diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupConfig.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupConfig.java index 164f26484e..b45f4898bf 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupConfig.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupConfig.java @@ -16,12 +16,12 @@ import java.util.List; /** * PortGroupConfig class represents the User's Configuration with a Opaque * Regular Expression String that is parsed and handled by PortGroupProvider. - * + * * Typically, the opaque matchString will be a Regular Expression String * supported by a particular PortGroupProvider based on Customer requirements. - * - * - * + * + * + * */ public class PortGroupConfig implements Serializable { private static final long serialVersionUID = 1L; @@ -41,7 +41,7 @@ public class PortGroupConfig implements Serializable { /** * Constructor to create a Port Group Configuration using a Group Name and * an Opaque String that is managed by PortGroupProvider. - * + * * @param name * Group Name representing a Port Group configuration * @param matchString @@ -55,7 +55,7 @@ public class PortGroupConfig implements Serializable { /** * Returns the user configured PortGroup Configuration name. - * + * * @return Configuration Name */ public String getName() { @@ -64,7 +64,7 @@ public class PortGroupConfig implements Serializable { /** * Assigns a name to the configuration - * + * * @param name * configuration name */ @@ -74,7 +74,7 @@ public class PortGroupConfig implements Serializable { /** * Returns the Opaque string - * + * * @return */ public String getMatchString() { @@ -83,7 +83,7 @@ public class PortGroupConfig implements Serializable { /** * Assigns an opaque String to the Configuration. - * + * * @param matchString * Opaque string handled by PortGroupProvider */ @@ -94,7 +94,7 @@ public class PortGroupConfig implements Serializable { /** * Returns the names of all the configurable fields in PortGroupConfig. This * method is typically used by NorthBound apis. - * + * * @return List of Field names that can be configured. */ public static List getFieldsNames() { @@ -113,7 +113,7 @@ public class PortGroupConfig implements Serializable { * Returns the names of all the configurable fields in PortGroupConfig in * human readable format for UI purposes. This method is typically used by * Web/UI apis. - * + * * @return List of Human readable Strings that corresponds to the * configurable field names. */ diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupProvider.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupProvider.java index 37cbcd17e6..5a9281aea8 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupProvider.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupProvider.java @@ -17,15 +17,15 @@ import org.opendaylight.controller.sal.core.Node; * application to implement in order to provide Port Grouping Service. Custom * Application that implements this interface will have to handle the opaque * match criteria passed to it via PortGroupConfig. - * - * - * + * + * + * */ public interface PortGroupProvider { /** * This method is invoked by the Controller towards the Provider when a new * port group is configured. - * + * * @param config * New PortGroupConfig object created by user Configuration. * @return true if successful. false otherwise. @@ -35,7 +35,7 @@ public interface PortGroupProvider { /** * This method is invoked by the Controller towards the Provider when an * existing port group is deleted. - * + * * @param config * Existing Port Group Configuration deleted by the user. * @return true if successful. false otherwise. @@ -47,7 +47,7 @@ public interface PortGroupProvider { * Configuration. Its the PortGroupProvider Application's responsibility to * manage the Switches & the Set of its Ports that correspond to each of the * Configuration and return it to the Controller when requested. - * + * * @param config * User Configuration * @see PortGroupConfig @@ -61,7 +61,7 @@ public interface PortGroupProvider { * PortGroupProvider Application's responsibility to manage the Switches & * the Set of its Ports that correspond to each of the Configuration and * return it to the Controller when requested. - * + * * @param config * User Configuration * @param matrixSwitchId @@ -76,7 +76,7 @@ public interface PortGroupProvider { /** * Registers a Listener for Port Group membership changes based on Custom * application algorithm. - * + * * @param listener * A Controller module that listens to events from the Custom * Port Grouping Application. @@ -89,7 +89,7 @@ public interface PortGroupProvider { * implement Custom Algorithm for Port Grouping. This method exposes the * custom algorithm to the user so that the user can configure the * matchString regular expression in PortGroupConfig appropriately. - * + * * @return Usage string. */ public String getApplicationDrivenMatchCriteriaUsage(); @@ -97,7 +97,7 @@ public interface PortGroupProvider { /** * Returns the name of the Custom Application that implements * PortGroupProvider interface. - * + * * @return Provider Name */ public String getProviderName(); @@ -105,7 +105,7 @@ public interface PortGroupProvider { /** * Controller uses this method to check with the Provider supports the * matchCriteria String configured by the User. - * + * * @param matchCriteria * @return true if the Provider supports the matchCriteria String. false * otherwise. diff --git a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/Activator.java b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/Activator.java index d0a370276f..969287719d 100644 --- a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/Activator.java +++ b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/Activator.java @@ -40,7 +40,7 @@ public class Activator extends ComponentActivatorAbstractBase { /** * Function called when the activator starts just after some initializations * are done by the ComponentActivatorAbstractBase. - * + * */ public void init() { @@ -49,7 +49,7 @@ public class Activator extends ComponentActivatorAbstractBase { /** * Function called when the activator stops just before the cleanup done by * ComponentActivatorAbstractBase - * + * */ public void destroy() { @@ -58,8 +58,8 @@ public class Activator extends ComponentActivatorAbstractBase { /** * Function that is used to communicate to dependency manager the list of * known implementations for services inside a container - * - * + * + * * @return An array containing all the CLASS objects that will be * instantiated in order to get an fully working implementation * Object @@ -72,7 +72,7 @@ public class Activator extends ComponentActivatorAbstractBase { /** * Function that is called when configuration of the dependencies is * required. - * + * * @param c * dependency manager Component object, used for configuring the * dependencies exported and imported diff --git a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerImpl.java b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerImpl.java index 5fbe12bd1c..db1186e6b7 100644 --- a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerImpl.java +++ b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerImpl.java @@ -135,7 +135,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * Adds a flow entry onto the network node It runs various validity checks * and derive the final container flows merged entries that will be * attempted to be installed - * + * * @param flowEntry * the original flow entry application requested to add * @param async @@ -144,7 +144,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * will contain the unique id assigned to this request */ private Status addEntry(FlowEntry flowEntry, boolean async) { - + // Sanity Check if (flowEntry == null || flowEntry.getNode() == null) { String msg = "Invalid FlowEntry"; @@ -209,7 +209,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * complication for now and assume we will always deal with * one flow only per request */ - succeded = ret; + succeded = ret; } else { error = ret; log.warn("Failed to install the entry: {}. The failure is: {}", @@ -228,7 +228,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * flow entry is congruent with all the N container flows, then the output * install entry list will contain N entries. If the output list is empty, * it means the passed flow entry conflicts with all the container flows. - * + * * @param cFlowList * The list of container flows * @return the list of container flow merged entries good to be installed on @@ -260,7 +260,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, /** * Modify a flow entry with a new one It runs various validity check and * derive the final container flows merged flow entries to work with - * + * * @param currentFlowEntry * @param newFlowEntry * @param async @@ -335,13 +335,13 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * This is only possible when the new entry and current entry have * different match. In this scenario the modification would ultimately * be handled as a remove and add operations in the protocol plugin. - * + * * Also, if any of the new flow entries would clash with an existing * one, we cannot proceed with the modify operation, because it would * fail for some entries and leave stale entries on the network node. * Modify path can be taken only if it can be performed completely, for * all entries. - * + * * So, for the above two cases, to simplify, let's decouple the modify * in: 1) remove current entries 2) install new entries */ @@ -384,7 +384,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * (and might be wrong) that the same container flows that were * satisfied by the current entries are the same that are satisfied * by the new entries. Let's take the risk for now. - * + * * Note: modification has to be complete. If any entry modification * fails, we need to stop, restore the already modified entries, and * declare failure. @@ -440,7 +440,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * This is the function that modifies the final container flows merged * entries on the network node and update the database. It expects that all * the validity checks are passed - * + * * @param currentEntries * @param newEntries * @param async @@ -451,7 +451,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, private Status modifyEntryInternal(FlowEntryInstall currentEntries, FlowEntryInstall newEntries, boolean async) { // Modify the flow on the network node - Status status = (async)? + Status status = (async)? programmer.modifyFlowAsync(currentEntries.getNode(), currentEntries.getInstall().getFlow(), newEntries.getInstall() .getFlow()) : @@ -481,7 +481,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, /** * Remove a flow entry. If the entry is not present in the software view * (entry or node not present), it return successfully - * + * * @param flowEntry * the flow entry to remove * @param async @@ -554,7 +554,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * This is the function that removes the final container flows merged entry * from the network node and update the database. It expects that all the * validity checks are passed - * + * * @param entry * the flow entry to remove * @param async @@ -572,7 +572,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, .getInstall().getFlow()) : programmer.removeFlow(entry.getNode(), entry .getInstall().getFlow()); - + if (!status.isSuccess()) { log.warn( @@ -593,7 +593,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * on the network node and updates the database. It expects that all the * validity and conflict checks are passed. That means it does not check * whether this flow would conflict or overwrite an existing one. - * + * * @param entry * the flow entry to install * @param async @@ -631,7 +631,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * means that if the function returns true, the passed flow entry is * congruent with at least one container flow, hence it is good to be * installed on this container. - * + * * @param flowEntry * @return true if flow conflicts with all the container flows, false * otherwise @@ -837,7 +837,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } return status; } - + @Override public Status modifyFlowEntry(FlowEntry currentFlowEntry, FlowEntry newFlowEntry) { @@ -908,13 +908,13 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } } - + /** * Try to find in the database if a Flow with the same Match and priority of * the passed one already exists for the specified network node. Flow, * priority and network node are all specified in the FlowEntry If found, * the respective FlowEntryInstall Object is returned - * + * * @param flowEntry * the FlowEntry to be tested against the ones installed * @param looseCheck @@ -1409,9 +1409,9 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * multiple entry configuration (PortGroup) and hardware installation is * NOT done directly on this event. 3. The User prefers to retain the * configuration in Controller and skip hardware installation. - * + * * Hence it is safe to update the StaticFlow DB at this point. - * + * * Note : For the case of PortGrouping, it is essential to have this DB * populated before the PortGroupListeners can query for the DB * triggered using portGroupChanged event... @@ -1924,7 +1924,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, /** * Remove from the databases all the flows installed on the node - * + * * @param node */ private synchronized void cleanDatabaseForNode(Node node) { @@ -2210,7 +2210,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, /** * Function called by the dependency manager when all the required * dependencies are satisfied - * + * */ void init() { frmAware = Collections @@ -2245,7 +2245,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * Function called by the dependency manager when at least one dependency * become unsatisfied or when the component is shutting down because for * example bundle is being stopped. - * + * */ void destroy() { destroyCaches(); @@ -2254,7 +2254,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, /** * Function called by dependency manager after "init ()" is called and after * the services provided by the class are registered in the service registry - * + * */ void start() { /* @@ -2270,7 +2270,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * Function called by the dependency manager before the services exported by * the component are unregistered, this will be followed by a "destroy ()" * calls - * + * */ void stop() { } @@ -2541,8 +2541,8 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, /* * If this was for a flow install, remove the corresponding entry * from the software view. If it was a Looking for the rid going through the - * software database. - * TODO: A more efficient rid <-> FlowEntryInstall mapping will + * software database. + * TODO: A more efficient rid <-> FlowEntryInstall mapping will * have to be added in future */ Set entries = nodeFlows.get(node); @@ -2559,7 +2559,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, this.updateLocalDatabase(target, false); } } - + // Notify listeners if (frmAware != null) { synchronized (frmAware) { @@ -2573,19 +2573,19 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } } } - + @Override public Status solicitStatusResponse(Node node, boolean blocking) { Status rv = new Status(StatusCode.INTERNALERROR); - + if (this.programmer != null) { if (blocking) { rv = programmer.syncSendBarrierMessage(node); } else { - rv = programmer.asyncSendBarrierMessage(node); + rv = programmer.asyncSendBarrierMessage(node); } } - + return rv; } } diff --git a/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/IfHostListener.java b/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/IfHostListener.java index cb15fb09fd..51d68d87b4 100644 --- a/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/IfHostListener.java +++ b/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/IfHostListener.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -12,21 +11,21 @@ package org.opendaylight.controller.hosttracker; import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; /** - * This interface defines the method to notify detected Host on the - * network. The information includes Host's IP address, MAC address, - * switch ID, port, and VLAN. + * This interface defines the method to notify detected Host on the network. The + * information includes Host's IP address, MAC address, switch ID, port, and + * VLAN. * */ public interface IfHostListener { /** - * Learns new Hosts. Called by ArpHandler and implemented in - * HostTracker.java. If a Host is learned for the first time then - * adds it to the local database and informs other applications - * of coming up a new Host. For the hosts which it has already - * learned, it refreshes them. + * Learns new Hosts. Called by ArpHandler and implemented in + * HostTracker.java. If a Host is learned for the first time then adds it to + * the local database and informs other applications of coming up a new + * Host. For the hosts which it has already learned, it refreshes them. * - * @param host Host info encapsulated in HostNodeConnector class + * @param host + * Host info encapsulated in HostNodeConnector class */ public void hostListener(HostNodeConnector host); } diff --git a/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/IfIptoHost.java b/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/IfIptoHost.java index 554da42f4a..995ee57515 100644 --- a/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/IfIptoHost.java +++ b/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/IfIptoHost.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -13,29 +12,31 @@ import java.net.InetAddress; import java.util.List; import java.util.Set; import java.util.concurrent.Future; -import org.opendaylight.controller.sal.core.NodeConnector; + import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; +import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.utils.Status; /** - * This interface defines the methods to retrieve information about - * learned Hosts. Also provides methods to statically add/remove - * Hosts from the local database. + * This interface defines the methods to retrieve information about learned + * Hosts. Also provides methods to statically add/remove Hosts from the local + * database. * */ public interface IfIptoHost { /** - * Applications call this interface methods to determine IP address to MAC binding and its - * connectivity to an OpenFlow switch in term of Node, Port, and VLAN. These - * bindings are learned dynamically as well as can be added statically through - * Northbound APIs. If a binding is unknown, then an ARP request is initiated - * immediately to discover the host. + * Applications call this interface methods to determine IP address to MAC + * binding and its connectivity to an OpenFlow switch in term of Node, Port, + * and VLAN. These bindings are learned dynamically as well as can be added + * statically through Northbound APIs. If a binding is unknown, then an ARP + * request is initiated immediately to discover the host. * - * @param networkAddress IP Address of the Host encapsulated in class InetAddress - * @return {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector} - * Class that contains the Host info such as its MAC address, - * Switch ID, port, VLAN. If Host is not found, returns NULL + * @param networkAddress + * IP Address of the Host encapsulated in class InetAddress + * @return {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector} + * Class that contains the Host info such as its MAC address, Switch + * ID, port, VLAN. If Host is not found, returns NULL */ public HostNodeConnector hostFind(InetAddress networkAddress); @@ -43,10 +44,11 @@ public interface IfIptoHost { * Checks the local Host Database to see if a Host has been learned for a * given IP address. * - * @param networkAddress IP Address of the Host encapsulated in class InetAddress - * @return {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector} - * Class that contains the Host info such as its MAC address, - * Switch ID, port, VLAN. If Host is not found, returns NULL + * @param networkAddress + * IP Address of the Host encapsulated in class InetAddress + * @return {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector} + * Class that contains the Host info such as its MAC address, Switch + * ID, port, VLAN. If Host is not found, returns NULL * */ public HostNodeConnector hostQuery(InetAddress networkAddress); @@ -55,73 +57,82 @@ public interface IfIptoHost { * Initiates an immediate discovery of the Host for a given IP address. This * provides for the calling applications to block on the host discovery. * - * @param networkAddress IP address encapsulated in InetAddress class - * @return Future {@link org.opendaylight.controller.hosttracker.HostTrackerCallable} + * @param networkAddress + * IP address encapsulated in InetAddress class + * @return Future + * {@link org.opendaylight.controller.hosttracker.HostTrackerCallable} */ public Future discoverHost(InetAddress networkAddress); /** - * Returns the Network Hierarchy for a given Host. This API is typically used by - * applications like Hadoop for Rack Awareness functionality. + * Returns the Network Hierarchy for a given Host. This API is typically + * used by applications like Hadoop for Rack Awareness functionality. * - * @param IP address of the Host encapsulated in InetAddress class - * @return List of String ArrayList containing the Hierarchies. + * @param IP + * address of the Host encapsulated in InetAddress class + * @return List of String ArrayList containing the Hierarchies. */ public List> getHostNetworkHierarchy(InetAddress hostAddress); /** - * Returns all the the Hosts either learned dynamically or added statically via - * Northbound APIs. + * Returns all the the Hosts either learned dynamically or added statically + * via Northbound APIs. * - * @return Set of {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector}. - * Class that contains the Host info such as its MAC address, - * Switch ID, port, VLAN. + * @return Set of + * {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector} + * . Class that contains the Host info such as its MAC address, + * Switch ID, port, VLAN. */ public Set getAllHosts(); /** - * Returns all the "Active Hosts" learned "Statically" via Northbound APIs. These Hosts - * are categorized as "Active" because the Switch and Port they are connected to, are in - * up state. + * Returns all the "Active Hosts" learned "Statically" via Northbound APIs. + * These Hosts are categorized as "Active" because the Switch and Port they + * are connected to, are in up state. * - * @return Set of {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector}. - * Class that contains the Host info such as MAC address, - * Switch ID, port, VLAN. If Host is not found, returns NULL + * @return Set of + * {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector} + * . Class that contains the Host info such as MAC address, Switch + * ID, port, VLAN. If Host is not found, returns NULL */ public Set getActiveStaticHosts(); /** - * Returns all the "Inactive Hosts" learned "Statically" via Northbound APIs. These Hosts - * are categorized as "Inactive" because either the Switch or the Port they are connected - * to, is in down state. + * Returns all the "Inactive Hosts" learned "Statically" via Northbound + * APIs. These Hosts are categorized as "Inactive" because either the Switch + * or the Port they are connected to, is in down state. * - * @return Set of HostNodeConnector {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector}. - * HostNodeConnector is Class that - * contains the Host info such as its MAC address, OpenFlowNode - * ID, port, VLAN. + * @return Set of HostNodeConnector + * {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector} + * . HostNodeConnector is Class that contains the Host info such as + * its MAC address, OpenFlowNode ID, port, VLAN. */ public Set getInactiveStaticHosts(); /** - * Hosts can be learned dynamically or added statically. This method allows the addition - * of a Host to the local database statically. + * Hosts can be learned dynamically or added statically. This method allows + * the addition of a Host to the local database statically. * - * @param networkAddress IP Address of the Host - * @param dataLayerAddress MAC Address of the Host - * @param nc NodeConnector to which the host is attached - * @param vlan VLAN the host belongs to - * @return The status object as described in {@code Status} - * indicating the result of this action. + * @param networkAddress + * IP Address of the Host + * @param dataLayerAddress + * MAC Address of the Host + * @param nc + * NodeConnector to which the host is attached + * @param vlan + * VLAN the host belongs to + * @return The status object as described in {@code Status} indicating the + * result of this action. */ public Status addStaticHost(String networkAddress, String dataLayerAddress, - NodeConnector nc, String vlan); + NodeConnector nc, String vlan); /** * Allows the deletion of statically learned Host * * @param networkAddress - * @return The status object as described in {@code Status} - * indicating the result of this action. + * @return The status object as described in {@code Status} indicating the + * result of this action. */ public Status removeStaticHost(String networkAddress); } diff --git a/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/IfNewHostNotify.java b/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/IfNewHostNotify.java index 88db0811d7..ef900e475e 100644 --- a/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/IfNewHostNotify.java +++ b/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/IfNewHostNotify.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -12,25 +11,27 @@ package org.opendaylight.controller.hosttracker; import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; /** - * This Interface defines the methods for client applications of - * Host Tracker to get notifications when a new host is learned or - * existing host is removed from the network. + * This Interface defines the methods for client applications of Host Tracker to + * get notifications when a new host is learned or existing host is removed from + * the network. * */ public interface IfNewHostNotify { /** * Notifies the HostTracker Clients that a new Host has been learned * - * @param host Host Info encapsulated in HostNodeConnector class + * @param host + * Host Info encapsulated in HostNodeConnector class */ public void notifyHTClient(HostNodeConnector host); /** - * Notifies the HostTracker Clients that a Host which was learned in - * the past has been removed either due to switch/port down event or - * due to ARP Aging + * Notifies the HostTracker Clients that a Host which was learned in the + * past has been removed either due to switch/port down event or due to ARP + * Aging * - * @param host Host Info encapsulated in HostNodeConnector class + * @param host + * Host Info encapsulated in HostNodeConnector class */ public void notifyHTClientHostRemoved(HostNodeConnector host); } diff --git a/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnector.java b/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnector.java index 243da05869..8345b5adbc 100644 --- a/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnector.java +++ b/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnector.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -19,14 +18,13 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; -import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.opendaylight.controller.sal.core.ConstructionException; import org.opendaylight.controller.sal.core.Host; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.packet.address.EthernetAddress; -@XmlRootElement(name="host") +@XmlRootElement(name = "host") @XmlAccessorType(XmlAccessType.NONE) public class HostNodeConnector extends Host { private static final long serialVersionUID = 1L; @@ -173,13 +171,10 @@ public class HostNodeConnector extends Host { return !Arrays.equals(emptyArray, macaddr); } - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ @Override public String toString() { - return "HostNodeConnector[" + ReflectionToStringBuilder.toString(this) - + "]"; + return "HostNodeConnector [nodeConnector=" + nodeConnector + ", vlan=" + + vlan + ", staticHost=" + staticHost + "]"; } public boolean isV4Host() { diff --git a/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/hostAware/IHostFinder.java b/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/hostAware/IHostFinder.java index 5ea7fb0e49..abe75180cf 100644 --- a/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/hostAware/IHostFinder.java +++ b/opendaylight/hosttracker/api/src/main/java/org/opendaylight/controller/hosttracker/hostAware/IHostFinder.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -10,32 +9,32 @@ package org.opendaylight.controller.hosttracker.hostAware; import java.net.InetAddress; -import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; - /** - * This Interface defines the methods to trigger the discovery of - * a Host and to probe if a learned Host is still in the network. + * This Interface defines the methods to trigger the discovery of a Host and to + * probe if a learned Host is still in the network. * * * */ public interface IHostFinder { /** - * This method initiates the discovery of a host based on its IP address. This is triggered - * by query of an application to the HostTracker. The requested IP address - * doesn't exist in the local database at this point. + * This method initiates the discovery of a host based on its IP address. + * This is triggered by query of an application to the HostTracker. The + * requested IP address doesn't exist in the local database at this point. * - * @param networkAddress IP Address encapsulated in InetAddress class + * @param networkAddress + * IP Address encapsulated in InetAddress class * */ public void find(InetAddress networkAddress); /** - * This method is called by HostTracker to see if a learned Host is still in the network. - * Used mostly for ARP Aging. + * This method is called by HostTracker to see if a learned Host is still in + * the network. Used mostly for ARP Aging. * - * @param host The Host that needs to be probed + * @param host + * The Host that needs to be probed */ public void probe(HostNodeConnector host); } diff --git a/opendaylight/hosttracker/api/src/test/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnectorTest.java b/opendaylight/hosttracker/api/src/test/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnectorTest.java index c29e5b1645..bdccc99c9c 100644 --- a/opendaylight/hosttracker/api/src/test/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnectorTest.java +++ b/opendaylight/hosttracker/api/src/test/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnectorTest.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -26,64 +25,73 @@ import org.opendaylight.controller.sal.utils.NodeConnectorCreator; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.utils.NodeCreator; - public class HostNodeConnectorTest extends TestCase { - @Test - public void testHostNodeConnector() throws UnknownHostException { - HostNodeConnector hostnodeconnector_1, hostnodeconnector_2, hostnodeconnector_3; - InetAddress hostIP_1 = InetAddress.getByName("192.168.0.8"); - InetAddress hostIP_2 = InetAddress.getByName("2001:420:281:1004:e123:e688:d655:a1b0"); - InetAddress hostIP_3 = InetAddress.getByName("192.168.0.28"); - byte[] hostMAC_2 = new byte[]{(byte)0x11,(byte)0x22,(byte)0x33,(byte)0x22,(byte)0x22,(byte)0x22}; - byte[] hostMAC_3 = new byte[]{(byte)0x11,(byte)0x22,(byte)0x33,(byte)0x33,(byte)0x33,(byte)0x33}; - - Node node = NodeCreator.createOFNode(1L); - NodeConnector nc1 = NodeConnectorCreator.createOFNodeConnector((short) 2, node); - NodeConnector nc2 = NodeConnectorCreator.createOFNodeConnector((short) 1, node); - - try { - hostnodeconnector_1 = new HostNodeConnector(hostIP_1); - Assert.assertTrue(hostnodeconnector_1.equalsByIP(hostIP_1)); - Assert.assertTrue(hostnodeconnector_1.isV4Host()); - Assert.assertTrue(hostnodeconnector_1.equalsByIP(hostIP_1)); - } catch (ConstructionException e) { - Assert.assertTrue(false); - } - - try { - hostnodeconnector_2 = new HostNodeConnector( - hostMAC_2, hostIP_2, nc1, (short)2); - Assert.assertTrue(hostnodeconnector_2.isV6Host()); - Assert.assertTrue(hostnodeconnector_2.getnodeConnector().equals(nc1)); - Assert.assertTrue(hostnodeconnector_2.getnodeconnectorNode().equals(node)); - Assert.assertTrue(node.equals(hostnodeconnector_2.getnodeconnectorNode())); - } catch (ConstructionException e) { - Assert.assertTrue(false); - } - - try { - hostnodeconnector_3 = new HostNodeConnector( - new EthernetAddress(hostMAC_3), hostIP_3, nc2, (short)3); - byte[] hostMAC_3_rb = hostnodeconnector_3.getDataLayerAddressBytes(); - HostNodeConnector hostnodeconnector_3rb = new HostNodeConnector( - new EthernetAddress(hostMAC_3_rb), hostIP_3, nc2, (short)3); - Assert.assertTrue(hostnodeconnector_3.equals(hostnodeconnector_3rb)); - - Assert.assertTrue(hostnodeconnector_3.getVlan() == (short)3); - - hostnodeconnector_3.setStaticHost(true); - Assert.assertTrue(hostnodeconnector_3.isStaticHost()); - - Assert.assertTrue(hostnodeconnector_3.isRewriteEnabled()); - - hostnodeconnector_3.initArpSendCountDown().setArpSendCountDown((short) 10); - Assert.assertTrue(hostnodeconnector_3.getArpSendCountDown() == (short)10); - - } catch (ConstructionException e) { - Assert.assertTrue(false); - } - - } + @Test + public void testHostNodeConnector() throws UnknownHostException { + HostNodeConnector hostnodeconnector_1, hostnodeconnector_2, hostnodeconnector_3; + InetAddress hostIP_1 = InetAddress.getByName("192.168.0.8"); + InetAddress hostIP_2 = InetAddress + .getByName("2001:420:281:1004:e123:e688:d655:a1b0"); + InetAddress hostIP_3 = InetAddress.getByName("192.168.0.28"); + byte[] hostMAC_2 = new byte[] { (byte) 0x11, (byte) 0x22, (byte) 0x33, + (byte) 0x22, (byte) 0x22, (byte) 0x22 }; + byte[] hostMAC_3 = new byte[] { (byte) 0x11, (byte) 0x22, (byte) 0x33, + (byte) 0x33, (byte) 0x33, (byte) 0x33 }; + + Node node = NodeCreator.createOFNode(1L); + NodeConnector nc1 = NodeConnectorCreator.createOFNodeConnector( + (short) 2, node); + NodeConnector nc2 = NodeConnectorCreator.createOFNodeConnector( + (short) 1, node); + + try { + hostnodeconnector_1 = new HostNodeConnector(hostIP_1); + Assert.assertTrue(hostnodeconnector_1.equalsByIP(hostIP_1)); + Assert.assertTrue(hostnodeconnector_1.isV4Host()); + Assert.assertTrue(hostnodeconnector_1.equalsByIP(hostIP_1)); + } catch (ConstructionException e) { + Assert.assertTrue(false); + } + + try { + hostnodeconnector_2 = new HostNodeConnector(hostMAC_2, hostIP_2, + nc1, (short) 2); + Assert.assertTrue(hostnodeconnector_2.isV6Host()); + Assert.assertTrue(hostnodeconnector_2.getnodeConnector() + .equals(nc1)); + Assert.assertTrue(hostnodeconnector_2.getnodeconnectorNode() + .equals(node)); + Assert.assertTrue(node.equals(hostnodeconnector_2 + .getnodeconnectorNode())); + } catch (ConstructionException e) { + Assert.assertTrue(false); + } + + try { + hostnodeconnector_3 = new HostNodeConnector(new EthernetAddress( + hostMAC_3), hostIP_3, nc2, (short) 3); + byte[] hostMAC_3_rb = hostnodeconnector_3 + .getDataLayerAddressBytes(); + HostNodeConnector hostnodeconnector_3rb = new HostNodeConnector( + new EthernetAddress(hostMAC_3_rb), hostIP_3, nc2, (short) 3); + Assert.assertTrue(hostnodeconnector_3.equals(hostnodeconnector_3rb)); + + Assert.assertTrue(hostnodeconnector_3.getVlan() == (short) 3); + + hostnodeconnector_3.setStaticHost(true); + Assert.assertTrue(hostnodeconnector_3.isStaticHost()); + + Assert.assertTrue(hostnodeconnector_3.isRewriteEnabled()); + + hostnodeconnector_3.initArpSendCountDown().setArpSendCountDown( + (short) 10); + Assert.assertTrue(hostnodeconnector_3.getArpSendCountDown() == (short) 10); + + } catch (ConstructionException e) { + Assert.assertTrue(false); + } + + } } diff --git a/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/Activator.java b/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/Activator.java index ef88fa2e16..65cb8225c8 100644 --- a/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/Activator.java +++ b/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/Activator.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -10,51 +9,48 @@ package org.opendaylight.controller.hosttracker.internal; import org.apache.felix.dm.Component; -import org.opendaylight.controller.hosttracker.internal.HostTracker; +import org.opendaylight.controller.clustering.services.IClusterContainerServices; import org.opendaylight.controller.hosttracker.IfHostListener; import org.opendaylight.controller.hosttracker.IfIptoHost; import org.opendaylight.controller.hosttracker.IfNewHostNotify; import org.opendaylight.controller.hosttracker.hostAware.IHostFinder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.opendaylight.controller.clustering.services.IClusterContainerServices; import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase; import org.opendaylight.controller.switchmanager.IInventoryListener; import org.opendaylight.controller.switchmanager.ISwitchManager; import org.opendaylight.controller.switchmanager.ISwitchManagerAware; import org.opendaylight.controller.topologymanager.ITopologyManager; import org.opendaylight.controller.topologymanager.ITopologyManagerAware; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Activator extends ComponentActivatorAbstractBase { protected static final Logger logger = LoggerFactory .getLogger(Activator.class); /** - * Function called when the activator starts just after some - * initializations are done by the - * ComponentActivatorAbstractBase. + * Function called when the activator starts just after some initializations + * are done by the ComponentActivatorAbstractBase. * */ public void init() { } /** - * Function called when the activator stops just before the - * cleanup done by ComponentActivatorAbstractBase + * Function called when the activator stops just before the cleanup done by + * ComponentActivatorAbstractBase * */ public void destroy() { } /** - * Function that is used to communicate to dependency manager the - * list of known implementations for services inside a container + * Function that is used to communicate to dependency manager the list of + * known implementations for services inside a container * * * @return An array containing all the CLASS objects that will be - * instantiated in order to get an fully working implementation - * Object + * instantiated in order to get an fully working implementation + * Object */ public Object[] getImplementations() { Object[] res = { HostTracker.class }; @@ -62,57 +58,64 @@ public class Activator extends ComponentActivatorAbstractBase { } /** - * Function that is called when configuration of the dependencies - * is required. + * Function that is called when configuration of the dependencies is + * required. * - * @param c dependency manager Component object, used for - * configuring the dependencies exported and imported - * @param imp Implementation class that is being configured, - * needed as long as the same routine can configure multiple - * implementations - * @param containerName The containerName being configured, this allow - * also optional per-container different behavior if needed, usually - * should not be the case though. + * @param c + * dependency manager Component object, used for configuring the + * dependencies exported and imported + * @param imp + * Implementation class that is being configured, needed as long + * as the same routine can configure multiple implementations + * @param containerName + * The containerName being configured, this allow also optional + * per-container different behavior if needed, usually should not + * be the case though. */ public void configureInstance(Component c, Object imp, String containerName) { if (imp.equals(HostTracker.class)) { // export the service - c.setInterface(new String[] { ISwitchManagerAware.class.getName(), - IInventoryListener.class.getName(), - IfIptoHost.class.getName(), IfHostListener.class.getName(), - ITopologyManagerAware.class.getName() }, null); + c.setInterface( + new String[] { ISwitchManagerAware.class.getName(), + IInventoryListener.class.getName(), + IfIptoHost.class.getName(), + IfHostListener.class.getName(), + ITopologyManagerAware.class.getName() }, null); - c.add(createContainerServiceDependency(containerName).setService( - ISwitchManager.class).setCallbacks("setSwitchManager", - "unsetSwitchManager").setRequired(false)); - c.add(createContainerServiceDependency(containerName).setService( - IClusterContainerServices.class).setCallbacks( - "setClusterContainerService", - "unsetClusterContainerService").setRequired(true)); - c.add(createContainerServiceDependency(containerName).setService( - IHostFinder.class).setCallbacks("setArpHandler", - "unsetArpHandler").setRequired(false)); - c.add(createContainerServiceDependency(containerName).setService( - ITopologyManager.class).setCallbacks("setTopologyManager", - "unsetTopologyManager").setRequired(false)); - c.add(createContainerServiceDependency(containerName).setService( - IfNewHostNotify.class).setCallbacks("setnewHostNotify", - "unsetnewHostNotify").setRequired(false)); + c.add(createContainerServiceDependency(containerName) + .setService(ISwitchManager.class) + .setCallbacks("setSwitchManager", "unsetSwitchManager") + .setRequired(false)); + c.add(createContainerServiceDependency(containerName) + .setService(IClusterContainerServices.class) + .setCallbacks("setClusterContainerService", + "unsetClusterContainerService").setRequired(true)); + c.add(createContainerServiceDependency(containerName) + .setService(IHostFinder.class) + .setCallbacks("setArpHandler", "unsetArpHandler") + .setRequired(false)); + c.add(createContainerServiceDependency(containerName) + .setService(ITopologyManager.class) + .setCallbacks("setTopologyManager", "unsetTopologyManager") + .setRequired(false)); + c.add(createContainerServiceDependency(containerName) + .setService(IfNewHostNotify.class) + .setCallbacks("setnewHostNotify", "unsetnewHostNotify") + .setRequired(false)); } } /** - * Method which tells how many Global implementations are - * supported by the bundle. This way we can tune the number of - * components created. This components will be created ONLY at the - * time of bundle startup and will be destroyed only at time of - * bundle destruction, this is the major difference with the - * implementation retrieved via getImplementations where all of - * them are assumed to be in a container ! + * Method which tells how many Global implementations are supported by the + * bundle. This way we can tune the number of components created. This + * components will be created ONLY at the time of bundle startup and will be + * destroyed only at time of bundle destruction, this is the major + * difference with the implementation retrieved via getImplementations where + * all of them are assumed to be in a container ! * * - * @return The list of implementations the bundle will support, - * in Global version + * @return The list of implementations the bundle will support, in Global + * version */ protected Object[] getGlobalImplementations() { return null; @@ -121,10 +124,13 @@ public class Activator extends ComponentActivatorAbstractBase { /** * Configure the dependency for a given instance Global * - * @param c Component assigned for this instance, this will be - * what will be used for configuration - * @param imp implementation to be configured - * @param containerName container on which the configuration happens + * @param c + * Component assigned for this instance, this will be what will + * be used for configuration + * @param imp + * implementation to be configured + * @param containerName + * container on which the configuration happens */ protected void configureGlobalInstance(Component c, Object imp) { if (imp.equals(HostTracker.class)) { diff --git a/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTracker.java b/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTracker.java index f8534e9810..707a776138 100644 --- a/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTracker.java +++ b/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTracker.java @@ -33,11 +33,11 @@ import org.opendaylight.controller.clustering.services.CacheConfigException; import org.opendaylight.controller.clustering.services.CacheExistException; import org.opendaylight.controller.clustering.services.IClusterContainerServices; import org.opendaylight.controller.clustering.services.IClusterServices; -import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; -import org.opendaylight.controller.hosttracker.hostAware.IHostFinder; import org.opendaylight.controller.hosttracker.IfHostListener; import org.opendaylight.controller.hosttracker.IfIptoHost; import org.opendaylight.controller.hosttracker.IfNewHostNotify; +import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; +import org.opendaylight.controller.hosttracker.hostAware.IHostFinder; import org.opendaylight.controller.sal.core.ConstructionException; import org.opendaylight.controller.sal.core.Edge; import org.opendaylight.controller.sal.core.Host; @@ -433,7 +433,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, */ removePendingARPFromList(i); logger.debug("Host Removed from ARPPending List, IP: {}", - networkAddr); + networkAddr); return; } } @@ -991,13 +991,14 @@ public class HostTracker implements IfIptoHost, IfHostListener, * there */ if (logger.isTraceEnabled()) { - logger.trace( - "ARP Probing ({}) for {}({})", - new Object[] { - arp_cntdown, - host.getNetworkAddress().getHostAddress(), - HexEncode.bytesToHexString(host - .getDataLayerAddressBytes()) }); + logger.trace( + "ARP Probing ({}) for {}({})", + new Object[] { + arp_cntdown, + host.getNetworkAddress() + .getHostAddress(), + HexEncode.bytesToHexString(host + .getDataLayerAddressBytes()) }); } host.setArpSendCountDown(arp_cntdown); hostFinder.probe(host); @@ -1260,7 +1261,9 @@ public class HostTracker implements IfIptoHost, IfHostListener, for (Entry entry : hostsDB.entrySet()) { HostNodeConnector host = entry.getValue(); if (host.getnodeConnector().equals(nodeConnector)) { - logger.debug(" NodeConnector: {} is down, remove from Hosts_DB", nodeConnector); + logger.debug( + " NodeConnector: {} is down, remove from Hosts_DB", + nodeConnector); removeKnownHost(entry.getKey()); notifyHostLearnedOrRemoved(host, false); } diff --git a/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTrackerCallable.java b/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTrackerCallable.java index 0af523aaa9..06311a5206 100644 --- a/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTrackerCallable.java +++ b/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTrackerCallable.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -15,8 +14,8 @@ package org.opendaylight.controller.hosttracker.internal; /** * This Class provides methods to discover Host through a blocking call - * mechanism. Applications can make use of these methods if they don't - * find a host in HostTracker's database and want to discover the host + * mechanism. Applications can make use of these methods if they don't + * find a host in HostTracker's database and want to discover the host * in the same thread without being called by a callback function. */ import java.net.InetAddress; diff --git a/opendaylight/hosttracker/implementation/src/test/java/org/opendaylight/controller/hosttracker/internal/HostTrackerTest.java b/opendaylight/hosttracker/implementation/src/test/java/org/opendaylight/controller/hosttracker/internal/HostTrackerTest.java index 9bd28c8e45..25de544f52 100644 --- a/opendaylight/hosttracker/implementation/src/test/java/org/opendaylight/controller/hosttracker/internal/HostTrackerTest.java +++ b/opendaylight/hosttracker/implementation/src/test/java/org/opendaylight/controller/hosttracker/internal/HostTrackerTest.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -9,51 +8,48 @@ package org.opendaylight.controller.hosttracker.internal; - import java.net.InetAddress; import java.net.UnknownHostException; import java.util.concurrent.Future; +import junit.framework.TestCase; + import org.junit.Assert; import org.junit.Test; - -import junit.framework.TestCase; import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; public class HostTrackerTest extends TestCase { - @Test - public void testHostTrackerCallable() throws UnknownHostException { - - HostTracker hostTracker = null; - hostTracker = new HostTracker(); - Assert.assertFalse(hostTracker== null); - - InetAddress hostIP = InetAddress.getByName("192.168.0.8"); - - HostTrackerCallable htCallable = new HostTrackerCallable (hostTracker, hostIP); - Assert.assertTrue(htCallable.trackedHost.equals(hostIP)); - Assert.assertTrue(htCallable.hostTracker.equals(hostTracker)); - - long count = htCallable.latch.getCount(); - htCallable.wakeup(); - Assert.assertTrue(htCallable.latch.getCount() == --count ); - } - - - - @Test - public void testHostTracker() throws UnknownHostException { - HostTracker hostTracker = null; - hostTracker = new HostTracker(); - Assert.assertFalse(hostTracker== null); - - InetAddress hostIP_1 = InetAddress.getByName("192.168.0.8"); - InetAddress hostIP_2 = InetAddress.getByName("192.168.0.18"); - Future dschost = hostTracker.discoverHost(hostIP_1); - dschost = hostTracker.discoverHost(hostIP_2); - hostTracker.nonClusterObjectCreate(); - } - + @Test + public void testHostTrackerCallable() throws UnknownHostException { + + HostTracker hostTracker = null; + hostTracker = new HostTracker(); + Assert.assertFalse(hostTracker == null); + + InetAddress hostIP = InetAddress.getByName("192.168.0.8"); + + HostTrackerCallable htCallable = new HostTrackerCallable(hostTracker, + hostIP); + Assert.assertTrue(htCallable.trackedHost.equals(hostIP)); + Assert.assertTrue(htCallable.hostTracker.equals(hostTracker)); + + long count = htCallable.latch.getCount(); + htCallable.wakeup(); + Assert.assertTrue(htCallable.latch.getCount() == --count); + } + + @Test + public void testHostTracker() throws UnknownHostException { + HostTracker hostTracker = null; + hostTracker = new HostTracker(); + Assert.assertFalse(hostTracker == null); + + InetAddress hostIP_1 = InetAddress.getByName("192.168.0.8"); + InetAddress hostIP_2 = InetAddress.getByName("192.168.0.18"); + Future dschost = hostTracker.discoverHost(hostIP_1); + dschost = hostTracker.discoverHost(hostIP_2); + hostTracker.nonClusterObjectCreate(); + } } diff --git a/opendaylight/hosttracker/integrationtest/src/test/java/org/opendaylight/controller/hosttracker/internal/HostTrackerIT.java b/opendaylight/hosttracker/integrationtest/src/test/java/org/opendaylight/controller/hosttracker/internal/HostTrackerIT.java index 1cf320b4df..04219502f6 100644 --- a/opendaylight/hosttracker/integrationtest/src/test/java/org/opendaylight/controller/hosttracker/internal/HostTrackerIT.java +++ b/opendaylight/hosttracker/integrationtest/src/test/java/org/opendaylight/controller/hosttracker/internal/HostTrackerIT.java @@ -59,8 +59,7 @@ import org.ops4j.pax.exam.spi.reactors.PerClass; @RunWith(PaxExam.class) public class HostTrackerIT { - private Logger log = LoggerFactory - .getLogger(HostTrackerIT.class); + private Logger log = LoggerFactory.getLogger(HostTrackerIT.class); // get the OSGI bundle context @Inject private BundleContext bc; diff --git a/opendaylight/hosttracker_new/api/pom.xml b/opendaylight/hosttracker_new/api/pom.xml new file mode 100644 index 0000000000..6a98c71e6a --- /dev/null +++ b/opendaylight/hosttracker_new/api/pom.xml @@ -0,0 +1,72 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../commons/opendaylight + + hosttracker_new + 0.4.0-SNAPSHOT + bundle + + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + + org.opendaylight.controller.hosttracker, + org.opendaylight.controller.hosttracker.hostAware + + + org.opendaylight.controller.sal.core, + org.opendaylight.controller.sal.utils, + org.opendaylight.controller.topologymanager, + org.opendaylight.controller.sal.packet.address, + org.opendaylight.controller.switchmanager, + org.opendaylight.controller.clustering.services, + javax.xml.bind.annotation, + javax.xml.bind, + org.apache.felix.dm, + org.apache.commons.lang3.builder, + org.osgi.service.component, + org.slf4j, + org.eclipse.osgi.framework.console, + org.osgi.framework + + + ${project.basedir}/META-INF + + + + + + + org.opendaylight.controller + topologymanager + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + switchmanager + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + clustering.services + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + sal + 0.5.0-SNAPSHOT + + + diff --git a/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/Entity.java b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/Entity.java new file mode 100644 index 0000000000..7c98e9505b --- /dev/null +++ b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/Entity.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2011,2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker; + +import java.util.Date; + +import org.opendaylight.controller.sal.core.NodeConnector; + +/** + * An entity on the network is a visible trace of a device that corresponds to a + * packet received from a particular interface on the edge of a network, with a + * particular VLAN tag, and a particular MAC address, along with any other + * packet characteristics we might want to consider as helpful for + * disambiguating devices. + * + * Entities are the most basic element of devices; devices consist of one or + * more entities. Entities are immutable once created, except for the last seen + * timestamp. + * + * @author readams + * + */ +public class Entity implements Comparable { + /** + * Timeout for computing {@link Entity#activeSince}. + * + * @see {@link Entity#activeSince} + */ + protected static int ACTIVITY_TIMEOUT = 30000; + + /** + * The MAC address associated with this entity + */ + protected long macAddress; + + /** + * The IP address associated with this entity, or null if no IP learned from + * the network observation associated with this entity + */ + protected Integer ipv4Address; + + /** + * The VLAN tag on this entity, or null if untagged + */ + protected Short vlan; + + /** + * The attachment point for this entity + */ + NodeConnector port; + + /** + * The last time we observed this entity on the network + */ + protected Date lastSeenTimestamp; + + /** + * The time between {@link Entity#activeSince} and + * {@link Entity#lastSeenTimestamp} is a period of activity for this entity + * where it was observed repeatedly. If, when the entity is observed, the is + * longer ago than the activity timeout, {@link Entity#lastSeenTimestamp} + * and {@link Entity#activeSince} will be set to the current time. + */ + protected Date activeSince; + + private int hashCode = 0; + + // ************ + // Constructors + // ************ + + /** + * Create a new entity + * + * @param macAddress + * @param vlan + * @param ipv4Address + * @param switchDPID + * @param switchPort + * @param lastSeenTimestamp + */ + public Entity(long macAddress, Short vlan, Integer ipv4Address, + NodeConnector port, Date lastSeenTimestamp) { + this.macAddress = macAddress; + this.ipv4Address = ipv4Address; + this.vlan = vlan; + this.port = port; + this.lastSeenTimestamp = lastSeenTimestamp; + this.activeSince = lastSeenTimestamp; + } + + // *************** + // Getters/Setters + // *************** + + // @JsonSerialize(using=MACSerializer.class) + public long getMacAddress() { + return macAddress; + } + + // @JsonSerialize(using=IPv4Serializer.class) + public Integer getIpv4Address() { + return ipv4Address; + } + + public Short getVlan() { + return vlan; + } + + public NodeConnector getPort() { + return port; + } + + // @JsonIgnore + public boolean hasSwitchPort() { + return port != null; + } + + public Date getLastSeenTimestamp() { + return lastSeenTimestamp; + } + + /** + * Set the last seen timestamp and also update {@link Entity#activeSince} if + * appropriate + * + * @param lastSeenTimestamp + * the new last seen timestamp + * @see {@link Entity#activeSince} + */ + public void setLastSeenTimestamp(Date lastSeenTimestamp) { + if (activeSince == null + || (activeSince.getTime() + ACTIVITY_TIMEOUT) < lastSeenTimestamp + .getTime()) + this.activeSince = lastSeenTimestamp; + this.lastSeenTimestamp = lastSeenTimestamp; + } + + public Date getActiveSince() { + return activeSince; + } + + public void setActiveSince(Date activeSince) { + this.activeSince = activeSince; + } + + @Override + public int hashCode() { + if (hashCode != 0) + return hashCode; + final int prime = 31; + hashCode = 1; + hashCode = prime * hashCode + + ((ipv4Address == null) ? 0 : ipv4Address.hashCode()); + hashCode = prime * hashCode + (int) (macAddress ^ (macAddress >>> 32)); + hashCode = prime * hashCode + ((port == null) ? 0 : port.hashCode()); + hashCode = prime * hashCode + ((vlan == null) ? 0 : vlan.hashCode()); + return hashCode; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Entity other = (Entity) obj; + if (ipv4Address == null) { + if (other.ipv4Address != null) + return false; + } else if (!ipv4Address.equals(other.ipv4Address)) + return false; + if (macAddress != other.macAddress) + return false; + if (port == null) { + if (other.port != null) + return false; + } else if (!port.equals(other.port)) + return false; + if (vlan == null) { + if (other.vlan != null) + return false; + } else if (!vlan.equals(other.vlan)) + return false; + return true; + } + + @Override + public String toString() { + return "Entity [macAddress=" + macAddress + ", ipv4Address=" + + ipv4Address + ", vlan=" + vlan + ", port=" + port + "]"; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public int compareTo(Entity o) { + int r; + if (port == null) + r = o.port == null ? 0 : -1; + else if (o.port == null) + r = 1; + else { + // XXX - the node id is only defined as an object rather + // than something useful. We're just going to have to + // blindly cast to Comparable and hope it works. + Comparable switchId = (Comparable) port.getNode().getID(); + Comparable oswitchId = (Comparable) o.port.getNode().getID(); + r = switchId.compareTo(oswitchId); + if (r != 0) + return r; + + Comparable portId = (Comparable) port.getID(); + Comparable oportId = (Comparable) o.port.getID(); + r = portId.compareTo(oportId); + } + return r; + } + +} diff --git a/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IDevice.java b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IDevice.java new file mode 100644 index 0000000000..b2ba643a0c --- /dev/null +++ b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IDevice.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2011,2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker; + +import java.util.Date; + +import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; + +/** + * Represents an independent device on the network. A device consists of a set + * of entities, and all the information known about a given device comes only + * from merging all associated entities for that device. + * + * @author readams + */ +public interface IDevice { + /** + * Get the primary key for this device. + * + * @return the primary key + */ + public Long getDeviceKey(); + + /** + * Get the MAC address of the device as a Long value. + * + * @return the MAC address for the device + */ + public long getMACAddress(); + + /** + * Get the MAC address of the device as a String value. + * + * @return the MAC address for the device + */ + public String getMACAddressString(); + + /** + * Get all unique VLAN IDs for the device. If the device has untagged + * entities, then the value -1 will be returned. + * + * @return an array containing all unique VLAN IDs for the device. + */ + public Short[] getVlanId(); + + /** + * Get all unique IPv4 addresses associated with the device. + * + * @return an array containing the unique IPv4 addresses for the device. + */ + public Integer[] getIPv4Addresses(); + + /** + * Get all unique attachment points associated with the device. This will + * not include any blocked attachment points. + * + * @return an array containing all unique attachment points for the device + */ + public SwitchPort[] getAttachmentPoints(); + + /** + * Get all old attachment points associated with the device. this is used in + * host movement scenario. + * + * @return an array containing all unique old attachment points for the + * device + */ + public SwitchPort[] getOldAP(); + + /** + * Get all unique attachment points associated with the device. + * + * @param includeError + * whether to include blocked attachment points. Blocked + * attachment points should not be used for forwarding, but could + * be useful to show to a user + * @return an array containing all unique attachment points for the device + */ + public SwitchPort[] getAttachmentPoints(boolean includeError); + + /** + * Returns all unique VLAN IDs for the device that were observed on the + * given switch port + * + * @param swp + * the switch port to query + * @return an array containing the unique VLAN IDs + */ + public Short[] getSwitchPortVlanIds(SwitchPort swp); + + /** + * Get the most recent timestamp for this device + * + * @return the last seen timestamp + */ + public Date getLastSeen(); + + /** + * Get the entity class for the device. + * + * @return the entity class + * @see IEntityClassifierService + */ + public IEntityClass getEntityClass(); + + public HostNodeConnector toHostNodeConnector(); + +} diff --git a/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IDeviceListener.java b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IDeviceListener.java new file mode 100644 index 0000000000..586191531b --- /dev/null +++ b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IDeviceListener.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2011 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker; + +import org.opendaylight.controller.sal.utils.IListener; + +/** + * Implementors of this interface can receive updates from DeviceManager about + * the state of devices under its control. + * + * @author David Erickson (daviderickson@cs.stanford.edu) + */ +public interface IDeviceListener extends IListener { + /** + * Called when a new Device is found + * + * @param device + * the device that changed + */ + public void deviceAdded(IDevice device); + + /** + * Called when a Device is removed, this typically occurs when the port the + * Device is attached to goes down, or the switch it is attached to is + * removed. + * + * @param device + * the device that changed + */ + public void deviceRemoved(IDevice device); + + /** + * Called when a Device has moved to a new location on the network. Note + * that either the switch or the port or both has changed. + * + * @param device + * the device that changed + */ + public void deviceMoved(IDevice device); + + /** + * Called when a network address has been added or remove from a device + * + * @param device + * the device that changed + */ + public void deviceIPV4AddrChanged(IDevice device); + + /** + * Called when a VLAN tag for the device has been added or removed + * + * @param device + * the device that changed + */ + public void deviceVlanChanged(IDevice device); +} diff --git a/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IDeviceService.java b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IDeviceService.java new file mode 100755 index 0000000000..9199f5a54e --- /dev/null +++ b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IDeviceService.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2011,2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker; + +import java.util.Collection; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.Set; + +import org.opendaylight.controller.sal.core.NodeConnector; +import org.osgi.service.device.Device; + +/** + * Device manager allows interacting with devices on the network. Note that + * under normal circumstances, {@link Device} objects should be retrieved from + * the {@link FloodlightContext} rather than from {@link IDeviceManager}. + */ +public interface IDeviceService { + + /** + * Fields used in devices for indexes and querying + * + * @see IDeviceService#addIndex + */ + enum DeviceField { + MAC, IPV4, VLAN, SWITCHPORT + } + + /** + * The source device for the current packet-in, if applicable. + */ + // public static final String CONTEXT_SRC_DEVICE = + // "net.floodlightcontroller.devicemanager.srcDevice"; + + /** + * The destination device for the current packet-in, if applicable. + */ + // public static final String CONTEXT_DST_DEVICE = + // / "net.floodlightcontroller.devicemanager.dstDevice"; + + /** + * The original destination device for the current packet-in + */ + // public static final String CONTEXT_ORIG_DST_DEVICE = + // "net.floodlightcontroller.devicemanager.origDstDevice"; + + /** + * A FloodlightContextStore object that can be used to interact with the + * FloodlightContext information created by BVS manager. + */ + // public static final FloodlightContextStore fcStore = + // new FloodlightContextStore(); + + /** + * Get the device with the given device key. + * + * @param deviceKey + * the key to search for + * @return the device associated with the key, or null if no such device + * @see IDevice#getDeviceKey() + */ + public IDevice getDevice(Long deviceKey); + + /** + * Search for a device exactly matching the provided device fields. This is + * the same lookup process that is used for packet_in processing and device + * learning. Thus, findDevice() can be used to match flow entries from + * switches to devices. Only the key fields as defined by the + * {@link IEntityClassifierService} will be important in this search. All + * key fields MUST be supplied. + * + * {@link queryDevices()} might be more appropriate! + * + * @param macAddress + * The MAC address + * @param vlan + * the VLAN. Null means no VLAN and is valid even if VLAN is a + * key field. + * @param ipv4Address + * the ipv4 address + * @param port + * the node connector + * @return an {@link IDevice} or null if no device is found. + * @see IDeviceManager#setEntityClassifier(IEntityClassifierService) + * @throws IllegalArgumentException + * if not all key fields of the current + * {@link IEntityClassifierService} are specified. + */ + public IDevice findDevice(long macAddress, Short vlan, Integer ipv4Address, + NodeConnector port) throws IllegalArgumentException; + + /** + * Get a destination device using entity fields that corresponds with the + * given source device. The source device is important since there could be + * ambiguity in the destination device without the attachment point + * information. Search for a device in a given entity class. This is the + * same as the lookup process for destination devices. + * + * Only the key fields as defined by the reference entity class will be + * important in this search. All key fields MUST be supplied. + * + * @param entityClass + * The entity class in which to perform the lookup. + * @param macAddress + * The MAC address for the destination + * @param vlan + * the VLAN if available + * @param ipv4Address + * The IP address if available. + * @return an {@link IDevice} or null if no device is found. + * @see IDeviceService#findDevice(long, Short, Integer, Long, Integer) + * @throws IllegalArgumentException + * if not all key fields of the source's {@link IEntityClass} + * are specified. + */ + public IDevice findClassDevice(IEntityClass entityClass, long macAddress, + Short vlan, Integer ipv4Address) throws IllegalArgumentException; + + /** + * Get an unmodifiable collection view over all devices currently known. + * + * @return the collection of all devices + */ + public Collection getAllDevices(); + + /** + * Create an index over a set of fields. This allows efficient lookup of + * devices when querying using the indexed set of specified fields. The + * index must be registered before any device learning takes place, or it + * may be incomplete. It's OK if this is called multiple times with the same + * fields; only one index will be created for each unique set of fields. + * + * @param perClass + * set to true if the index should be maintained for each entity + * class separately. + * @param keyFields + * the set of fields on which to index + */ + public void addIndex(boolean perClass, EnumSet keyFields); + + /** + * Find devices that match the provided query. Any fields that are null will + * not be included in the query. If there is an index for the query, then it + * will be performed efficiently using the index. Otherwise, there will be a + * full scan of the device list. + * + * @param macAddress + * The MAC address + * @param vlan + * the VLAN + * @param ipv4Address + * the ipv4 address + * @param port + * the switch port + * @return an iterator over a set of devices matching the query + * @see IDeviceService#queryClassDevices(IEntityClass, Long, Short, Integer, + * Long, Integer) + */ + public Iterator queryDevices(Long macAddress, + Short vlan, Integer ipv4Address, NodeConnector port); + + /** + * Find devices that match the provided query. Only the index for the + * specified class will be searched. Any fields that are null will not be + * included in the query. If there is an index for the query, then it will + * be performed efficiently using the index. Otherwise, there will be a full + * scan of the device list. + * + * @param entityClass + * The entity class in which to perform the query + * @param macAddress + * The MAC address + * @param vlan + * the VLAN + * @param ipv4Address + * the ipv4 address + * @param port + * the switch port + * @return an iterator over a set of devices matching the query + * @see IDeviceService#queryClassDevices(Long, Short, Integer, Long, + * Integer) + */ + public Iterator queryClassDevices( + IEntityClass entityClass, Long macAddress, Short vlan, + Integer ipv4Address, NodeConnector port); + + /** + * Adds a listener to listen for IDeviceManagerServices notifications + * + * @param listener + * The listener that wants the notifications + * @param type + * The type of the listener + */ + public void addListener(IDeviceListener listener); + + /** + * Specify points in the network where attachment points are not to be + * learned. + * + * @param sw + * @param port + */ + public void addSuppressAPs(NodeConnector port); + + public void removeSuppressAPs(NodeConnector port); + + public Set getSuppressAPs(); + +} diff --git a/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IEntityClass.java b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IEntityClass.java new file mode 100644 index 0000000000..7c1c100d57 --- /dev/null +++ b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IEntityClass.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011,2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker; + +import java.util.EnumSet; + +import org.opendaylight.controller.hosttracker.IDeviceService.DeviceField; +import org.osgi.service.device.Device; + +/** + * Entities within an entity class are grouped into {@link Device} objects based + * on the {@link IEntityClass}, and the key fields specified by the entity + * class. A set of entities are considered to be the same device if and only if + * they belong to the same entity class and they match on all key fields for + * that entity class. A field is effectively wildcarded by not including it in + * the list of key fields returned by {@link IEntityClassifierService} and/or + * {@link IEntityClass}. + * + * Note that if you're not using static objects, you'll need to override + * {@link Object#equals(Object)} and {@link Object#hashCode()}. + * + * @author readams + * + */ +public interface IEntityClass { + /** + * Return the set of key fields for this entity class. Entities belonging to + * this class that differ in fields not included in this collection will be + * considered the same device. The key fields for an entity class must not + * change unless associated with a flush of that entity class. + * + * @return a set containing the fields that should not be wildcarded. May be + * null to indicate that all fields are key fields. + */ + EnumSet getKeyFields(); + + /** + * Returns a user-friendly, unique name for this EntityClass + * + * @return the name of the entity class + */ + String getName(); +} diff --git a/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IEntityClassListener.java b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IEntityClassListener.java new file mode 100644 index 0000000000..be5f2585a6 --- /dev/null +++ b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IEntityClassListener.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker; + +import java.util.Set; + +/** + * Implementors of this interface can receive updates from the Entity Classifier + * about the changes to entity Classes. + * + * @author Ananth Suryanarayana (Ananth.Suryanarayana@bigswitch.com) + */ +public interface IEntityClassListener { + + /** + * Process entity classes change event. + * + * @param entityClassNames + * Set of entity classes changed + */ + public void entityClassChanged(Set entityClassNames); +} diff --git a/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IEntityClassifierService.java b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IEntityClassifierService.java new file mode 100644 index 0000000000..f6071e1072 --- /dev/null +++ b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IEntityClassifierService.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2011,2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker; + +import java.util.Collection; +import java.util.EnumSet; + +import org.opendaylight.controller.hosttracker.IDeviceService.DeviceField; + +/** + * A component that wishes to participate in entity classification needs to + * implement the IEntityClassifier interface, and register with the Device + * Manager as an entity classifier. An entity is classified by the classifier + * into an {@link IEntityClass} + * + * @author readams + */ +public interface IEntityClassifierService { + /** + * Classify the given entity into an IEntityClass. It is important that the + * key fields returned by {@link IEntityClassifierService#getKeyFields()} be + * sufficient for classifying entities. That is, if two entities are + * identical except for a field that is not a key field, they must be + * assigned the same class. Furthermore, entity classification must be + * transitive: For all entities x, y, z, if x and y belong to a class c, and + * y and z belong class c, then x and z must belong to class c. + * + * @param entity + * the entity to classify + * @return the IEntityClass resulting from the classification. + * @see IEntityClassifierService#getKeyFields() + */ + IEntityClass classifyEntity(Entity entity); + + /** + * Return the most general list of fields that should be used as key fields. + * If devices differ in any fields not listed here, they can never be + * considered a different device by any {@link IEntityClass} returned by + * {@link IEntityClassifierService#classifyEntity}. The key fields for an + * entity classifier must not change unless associated with a flush of all + * entity state. The list of key fields must be the union of all key fields + * that could be returned by {@link IEntityClass#getKeyFields()}. + * + * @return a set containing the fields that should not be wildcarded. May be + * null to indicate that all fields are key fields. + * @see {@link IEntityClass#getKeyFields()} + * @see {@link IEntityClassifierService#classifyEntity} + */ + EnumSet getKeyFields(); + + /** + * Reclassify the given entity into a class. When reclassifying entities, it + * can be helpful to take into account the current classification either as + * an optimization or to allow flushing any cached state tied to the key for + * that device. The entity will be assigned to a new device with a new + * object if the entity class returned is different from the entity class + * for curDevice. + * + *

+ * Note that you must take steps to ensure you always return classes in some + * consistent ordering. + * + * @param curDevice + * the device currently associated with the entity + * @param entity + * the entity to reclassify + * @return the IEntityClass resulting from the classification + */ + IEntityClass reclassifyEntity(IDevice curDevice, Entity entity); + + /** + * Once reclassification is complete for a device, this method will be + * called. If any entities within the device changed their classification, + * it will split into one or more new devices for each of the entities. If + * two devices are merged because of a reclassification, then this will be + * called on each of the devices, with the same device in the newDevices + * collection. + * + * @param oldDevice + * the original device object + * @param newDevices + * all the new devices derived from the entities of the old + * device. If null, the old device was unchanged. + */ + void deviceUpdate(IDevice oldDevice, + Collection newDevices); + + /** + * Adds a listener to listen for IEntityClassifierServices notifications + * + * @param listener + * The listener that wants the notifications + */ + public void addListener(IEntityClassListener listener); +} diff --git a/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IfHostListener.java b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IfHostListener.java new file mode 100644 index 0000000000..51d68d87b4 --- /dev/null +++ b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IfHostListener.java @@ -0,0 +1,31 @@ +/* + * 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.hosttracker; + +import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; + +/** + * This interface defines the method to notify detected Host on the network. The + * information includes Host's IP address, MAC address, switch ID, port, and + * VLAN. + * + */ + +public interface IfHostListener { + /** + * Learns new Hosts. Called by ArpHandler and implemented in + * HostTracker.java. If a Host is learned for the first time then adds it to + * the local database and informs other applications of coming up a new + * Host. For the hosts which it has already learned, it refreshes them. + * + * @param host + * Host info encapsulated in HostNodeConnector class + */ + public void hostListener(HostNodeConnector host); +} diff --git a/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IfIptoHost.java b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IfIptoHost.java new file mode 100644 index 0000000000..995ee57515 --- /dev/null +++ b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IfIptoHost.java @@ -0,0 +1,138 @@ +/* + * 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.hosttracker; + +import java.net.InetAddress; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Future; + +import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.utils.Status; + +/** + * This interface defines the methods to retrieve information about learned + * Hosts. Also provides methods to statically add/remove Hosts from the local + * database. + * + */ + +public interface IfIptoHost { + /** + * Applications call this interface methods to determine IP address to MAC + * binding and its connectivity to an OpenFlow switch in term of Node, Port, + * and VLAN. These bindings are learned dynamically as well as can be added + * statically through Northbound APIs. If a binding is unknown, then an ARP + * request is initiated immediately to discover the host. + * + * @param networkAddress + * IP Address of the Host encapsulated in class InetAddress + * @return {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector} + * Class that contains the Host info such as its MAC address, Switch + * ID, port, VLAN. If Host is not found, returns NULL + */ + public HostNodeConnector hostFind(InetAddress networkAddress); + + /** + * Checks the local Host Database to see if a Host has been learned for a + * given IP address. + * + * @param networkAddress + * IP Address of the Host encapsulated in class InetAddress + * @return {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector} + * Class that contains the Host info such as its MAC address, Switch + * ID, port, VLAN. If Host is not found, returns NULL + * + */ + public HostNodeConnector hostQuery(InetAddress networkAddress); + + /** + * Initiates an immediate discovery of the Host for a given IP address. This + * provides for the calling applications to block on the host discovery. + * + * @param networkAddress + * IP address encapsulated in InetAddress class + * @return Future + * {@link org.opendaylight.controller.hosttracker.HostTrackerCallable} + */ + public Future discoverHost(InetAddress networkAddress); + + /** + * Returns the Network Hierarchy for a given Host. This API is typically + * used by applications like Hadoop for Rack Awareness functionality. + * + * @param IP + * address of the Host encapsulated in InetAddress class + * @return List of String ArrayList containing the Hierarchies. + */ + public List> getHostNetworkHierarchy(InetAddress hostAddress); + + /** + * Returns all the the Hosts either learned dynamically or added statically + * via Northbound APIs. + * + * @return Set of + * {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector} + * . Class that contains the Host info such as its MAC address, + * Switch ID, port, VLAN. + */ + public Set getAllHosts(); + + /** + * Returns all the "Active Hosts" learned "Statically" via Northbound APIs. + * These Hosts are categorized as "Active" because the Switch and Port they + * are connected to, are in up state. + * + * @return Set of + * {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector} + * . Class that contains the Host info such as MAC address, Switch + * ID, port, VLAN. If Host is not found, returns NULL + */ + public Set getActiveStaticHosts(); + + /** + * Returns all the "Inactive Hosts" learned "Statically" via Northbound + * APIs. These Hosts are categorized as "Inactive" because either the Switch + * or the Port they are connected to, is in down state. + * + * @return Set of HostNodeConnector + * {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector} + * . HostNodeConnector is Class that contains the Host info such as + * its MAC address, OpenFlowNode ID, port, VLAN. + */ + public Set getInactiveStaticHosts(); + + /** + * Hosts can be learned dynamically or added statically. This method allows + * the addition of a Host to the local database statically. + * + * @param networkAddress + * IP Address of the Host + * @param dataLayerAddress + * MAC Address of the Host + * @param nc + * NodeConnector to which the host is attached + * @param vlan + * VLAN the host belongs to + * @return The status object as described in {@code Status} indicating the + * result of this action. + */ + public Status addStaticHost(String networkAddress, String dataLayerAddress, + NodeConnector nc, String vlan); + + /** + * Allows the deletion of statically learned Host + * + * @param networkAddress + * @return The status object as described in {@code Status} indicating the + * result of this action. + */ + public Status removeStaticHost(String networkAddress); +} diff --git a/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IfNewHostNotify.java b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IfNewHostNotify.java new file mode 100644 index 0000000000..ef900e475e --- /dev/null +++ b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/IfNewHostNotify.java @@ -0,0 +1,37 @@ +/* + * 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.hosttracker; + +import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; + +/** + * This Interface defines the methods for client applications of Host Tracker to + * get notifications when a new host is learned or existing host is removed from + * the network. + * + */ +public interface IfNewHostNotify { + /** + * Notifies the HostTracker Clients that a new Host has been learned + * + * @param host + * Host Info encapsulated in HostNodeConnector class + */ + public void notifyHTClient(HostNodeConnector host); + + /** + * Notifies the HostTracker Clients that a Host which was learned in the + * past has been removed either due to switch/port down event or due to ARP + * Aging + * + * @param host + * Host Info encapsulated in HostNodeConnector class + */ + public void notifyHTClientHostRemoved(HostNodeConnector host); +} diff --git a/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/SwitchPort.java b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/SwitchPort.java new file mode 100644 index 0000000000..e60f8b4b0e --- /dev/null +++ b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/SwitchPort.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker; + +import org.opendaylight.controller.sal.core.NodeConnector; + +/** + * A simple switch DPID/port pair This class is immutable + * + * @author readams + * + */ +public class SwitchPort { + public enum ErrorStatus { + DUPLICATE_DEVICE("duplicate-device"); + + private String value; + + ErrorStatus(String v) { + value = v; + } + + @Override + public String toString() { + return value; + } + + public static ErrorStatus fromString(String str) { + for (ErrorStatus m : ErrorStatus.values()) { + if (m.value.equals(str)) { + return m; + } + } + return null; + } + } + + private final NodeConnector port; + private final ErrorStatus errorStatus; + + /** + * Simple constructor + * + * @param switchDPID + * the dpid + * @param port + * the port + * @param errorStatus + * any error status for the switch port + */ + public SwitchPort(NodeConnector port, ErrorStatus errorStatus) { + super(); + this.port = port; + this.errorStatus = errorStatus; + } + + /** + * Simple constructor + * + * @param switchDPID + * the dpid + * @param port + * the port + */ + public SwitchPort(NodeConnector port) { + super(); + this.port = port; + this.errorStatus = null; + } + + // *************** + // Getters/Setters + // *************** + + public NodeConnector getPort() { + return port; + } + + public ErrorStatus getErrorStatus() { + return errorStatus; + } + + // ****** + // Object + // ****** + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((errorStatus == null) ? 0 : errorStatus.hashCode()); + result = prime * result + ((port == null) ? 0 : port.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SwitchPort other = (SwitchPort) obj; + if (errorStatus != other.errorStatus) + return false; + if (port == null) { + if (other.port != null) + return false; + } else if (!port.equals(other.port)) + return false; + return true; + } + + @Override + public String toString() { + return "SwitchPort [port=" + port + ", errorStatus=" + errorStatus + + "]"; + } +} \ No newline at end of file diff --git a/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnector.java b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnector.java new file mode 100644 index 0000000000..fe396ba92b --- /dev/null +++ b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnector.java @@ -0,0 +1,215 @@ +/* + * 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.hosttracker.hostAware; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.util.Arrays; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.core.Host; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.packet.address.EthernetAddress; + +@XmlRootElement(name = "host") +@XmlAccessorType(XmlAccessType.NONE) +public class HostNodeConnector extends Host { + private static final long serialVersionUID = 1L; + @XmlElement + private NodeConnector nodeConnector; + @XmlElement + private short vlan; + @XmlElement + private boolean staticHost; + private transient short arpSendCountDown; + + /** + * Private constructor used for JAXB mapping + */ + @SuppressWarnings("unused") + private HostNodeConnector() { + } + + public HostNodeConnector(InetAddress ip) throws ConstructionException { + this(ip, null); + } + + public HostNodeConnector(InetAddress ip, NodeConnector nc) + throws ConstructionException { + this(new EthernetAddress(new byte[] { (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }), ip, nc, + (short) 0); + } + + public HostNodeConnector(byte[] mac, InetAddress ip, NodeConnector nc, + short vlan) throws ConstructionException { + this(new EthernetAddress(mac.clone()), ip, nc, vlan); + } + + public HostNodeConnector(EthernetAddress eaddr, InetAddress naddr, + NodeConnector nc, short vlan) throws ConstructionException { + super(eaddr, naddr); + this.nodeConnector = nc; + this.vlan = vlan; + } + + /** + * @return the NodeConnector + */ + public NodeConnector getnodeConnector() { + return this.nodeConnector; + } + + /** + * @return the Node + */ + public Node getnodeconnectorNode() { + return this.nodeConnector.getNode(); + } + + /** + * @return the NodeId + */ + public Long getnodeconnectornodeId() { + return (Long) this.nodeConnector.getNode().getID(); + } + + /** + * @return the port + */ + public Short getnodeconnectorportId() { + return (Short) this.nodeConnector.getID(); + } + + /** + * @return the DataLayerAddress + */ + public byte[] getDataLayerAddressBytes() { + byte[] macaddr = null; + if (getDataLayerAddress() instanceof EthernetAddress) { + EthernetAddress e = (EthernetAddress) getDataLayerAddress(); + macaddr = e.getValue(); + } + return macaddr; + } + + /** + * @return the vlan + */ + public short getVlan() { + return this.vlan; + } + + public boolean isStaticHost() { + return this.staticHost; + } + + public HostNodeConnector setStaticHost(boolean statically_learned) { + this.staticHost = statically_learned; + return this; + } + + public HostNodeConnector initArpSendCountDown() { + this.arpSendCountDown = 24; + return this; + } + + public short getArpSendCountDown() { + return (this.arpSendCountDown); + } + + public HostNodeConnector setArpSendCountDown(short cntdown) { + this.arpSendCountDown = cntdown; + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + ((nodeConnector == null) ? 0 : nodeConnector.hashCode()); + result = prime * result + (staticHost ? 1231 : 1237); + result = prime * result + vlan; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + HostNodeConnector other = (HostNodeConnector) obj; + if (nodeConnector == null) { + if (other.nodeConnector != null) + return false; + } else if (!nodeConnector.equals(other.nodeConnector)) + return false; + if (staticHost != other.staticHost) + return false; + if (vlan != other.vlan) + return false; + return true; + } + + public boolean equalsByIP(InetAddress networkAddress) { + return (this.getNetworkAddress().equals(networkAddress)); + } + + public boolean isRewriteEnabled() { + byte[] emptyArray = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00 }; + byte[] macaddr = null; + if (getDataLayerAddress() instanceof EthernetAddress) { + EthernetAddress e = (EthernetAddress) getDataLayerAddress(); + macaddr = e.getValue(); + } + if (macaddr == null) + return false; + return !Arrays.equals(emptyArray, macaddr); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "HostNodeConnector[" + ReflectionToStringBuilder.toString(this) + + "]"; + } + + public boolean isV4Host() { + return (getNetworkAddress() instanceof Inet4Address); + } + + public boolean isV6Host() { + return (getNetworkAddress() instanceof Inet6Address); + } + + public String toJson() { + return "{\"host\":\"" + super.toString() + "\", " + "\"vlan\":\"" + + String.valueOf(vlan) + "\",\"NodeConnector\":\"" + + nodeConnector.toString() + "\"," + "\"static\":\"" + + String.valueOf(isStaticHost()) + "\"}"; + } + +} diff --git a/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/hostAware/IHostFinder.java b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/hostAware/IHostFinder.java new file mode 100644 index 0000000000..abe75180cf --- /dev/null +++ b/opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/hostAware/IHostFinder.java @@ -0,0 +1,40 @@ +/* + * 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.hosttracker.hostAware; + +import java.net.InetAddress; + +/** + * This Interface defines the methods to trigger the discovery of a Host and to + * probe if a learned Host is still in the network. + * + * + * + */ +public interface IHostFinder { + /** + * This method initiates the discovery of a host based on its IP address. + * This is triggered by query of an application to the HostTracker. The + * requested IP address doesn't exist in the local database at this point. + * + * @param networkAddress + * IP Address encapsulated in InetAddress class + * + */ + public void find(InetAddress networkAddress); + + /** + * This method is called by HostTracker to see if a learned Host is still in + * the network. Used mostly for ARP Aging. + * + * @param host + * The Host that needs to be probed + */ + public void probe(HostNodeConnector host); +} diff --git a/opendaylight/hosttracker_new/api/src/test/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnectorTest.java b/opendaylight/hosttracker_new/api/src/test/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnectorTest.java new file mode 100644 index 0000000000..0c3ca2f6da --- /dev/null +++ b/opendaylight/hosttracker_new/api/src/test/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnectorTest.java @@ -0,0 +1,100 @@ +/* + * 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.hosttracker.hostAware; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +import org.junit.Assert; +import org.junit.Test; + +import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.core.Node; + +import junit.framework.TestCase; + +import org.opendaylight.controller.sal.packet.address.EthernetAddress; + +import org.opendaylight.controller.sal.utils.NodeConnectorCreator; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.utils.NodeCreator; + +public class HostNodeConnectorTest extends TestCase { + + @Test + public void testHostNodeConnector() throws UnknownHostException { + HostNodeConnector hostnodeconnector_1, hostnodeconnector_2, hostnodeconnector_3; + InetAddress hostIP_1 = InetAddress.getByName("192.168.0.8"); + InetAddress hostIP_2 = InetAddress + .getByName("2001:420:281:1004:e123:e688:d655:a1b0"); + InetAddress hostIP_3 = InetAddress.getByName("192.168.0.28"); + byte[] hostMAC_2 = new byte[] { (byte) 0x11, (byte) 0x22, (byte) 0x33, + (byte) 0x22, (byte) 0x22, (byte) 0x22 }; + byte[] hostMAC_3 = new byte[] { (byte) 0x11, (byte) 0x22, (byte) 0x33, + (byte) 0x33, (byte) 0x33, (byte) 0x33 }; + + Node node = NodeCreator.createOFNode(1L); + NodeConnector nc1 = NodeConnectorCreator.createOFNodeConnector( + (short) 2, node); + NodeConnector nc2 = NodeConnectorCreator.createOFNodeConnector( + (short) 1, node); + + try { + hostnodeconnector_1 = new HostNodeConnector(hostIP_1); + Assert.assertTrue(hostnodeconnector_1.equalsByIP(hostIP_1)); + Assert.assertTrue(hostnodeconnector_1.isV4Host()); + Assert.assertTrue(hostnodeconnector_1.equalsByIP(hostIP_1)); + } catch (ConstructionException e) { + Assert.assertTrue(false); + } + + try { + hostnodeconnector_2 = new HostNodeConnector(hostMAC_2, hostIP_2, + nc1, (short) 2); + Assert.assertTrue(hostnodeconnector_2.isV6Host()); + Assert.assertTrue(hostnodeconnector_2.getnodeConnector() + .equals(nc1)); + Assert.assertTrue(hostnodeconnector_2.getnodeconnectorNode() + .equals(node)); + Assert.assertTrue(node.getID().equals( + hostnodeconnector_2.getnodeconnectornodeId())); + Assert.assertTrue(hostnodeconnector_2.getnodeconnectorportId() + .equals((short) 2)); + } catch (ConstructionException e) { + Assert.assertTrue(false); + } + + try { + hostnodeconnector_3 = new HostNodeConnector(new EthernetAddress( + hostMAC_3), hostIP_3, nc2, (short) 3); + byte[] hostMAC_3_rb = hostnodeconnector_3 + .getDataLayerAddressBytes(); + HostNodeConnector hostnodeconnector_3rb = new HostNodeConnector( + new EthernetAddress(hostMAC_3_rb), hostIP_3, nc2, (short) 3); + Assert.assertTrue(hostnodeconnector_3.equals(hostnodeconnector_3rb)); + + Assert.assertTrue(hostnodeconnector_3.getVlan() == (short) 3); + + hostnodeconnector_3.setStaticHost(true); + Assert.assertTrue(hostnodeconnector_3.isStaticHost()); + + Assert.assertTrue(hostnodeconnector_3.isRewriteEnabled()); + + hostnodeconnector_3.initArpSendCountDown().setArpSendCountDown( + (short) 10); + Assert.assertTrue(hostnodeconnector_3.getArpSendCountDown() == (short) 10); + + } catch (ConstructionException e) { + Assert.assertTrue(false); + } + + } + +} diff --git a/opendaylight/hosttracker_new/implementation/pom.xml b/opendaylight/hosttracker_new/implementation/pom.xml new file mode 100644 index 0000000000..804f5e3638 --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/pom.xml @@ -0,0 +1,125 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../commons/opendaylight + + hosttracker_new.implementation + 0.4.0-SNAPSHOT + bundle + + + + jacoco + reuseReports + target/jacoco.exec + target/jacoco-it.exec + java + + + + + + + org.jacoco + jacoco-maven-plugin + 0.5.3.201107060350 + + + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + + + + org.opendaylight.controller.sal.core, + org.opendaylight.controller.sal.utils, + org.opendaylight.controller.sal.topology, + org.opendaylight.controller.sal.packet, + org.opendaylight.controller.hosttracker, + org.opendaylight.controller.topologymanager, + org.opendaylight.controller.sal.packet.address, + org.opendaylight.controller.switchmanager, + org.opendaylight.controller.clustering.services, + org.opendaylight.controller.hosttracker.hostAware, + javax.xml.bind.annotation, + javax.xml.bind, + org.apache.felix.dm, + org.apache.commons.lang3.builder, + org.osgi.service.component, + org.slf4j, + org.eclipse.osgi.framework.console, + org.osgi.framework + + + org.opendaylight.controller.hosttracker.internal.Activator + + + + + ${project.basedir}/META-INF + + + + org.jacoco + jacoco-maven-plugin + + org.opendaylight.controller.* + + + + pre-test + + prepare-agent + + + + post-test + test + + report + + + + + + + + + org.opendaylight.controller + topologymanager + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + switchmanager + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + clustering.services + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + sal + 0.5.0-SNAPSHOT + + + org.opendaylight.controller + hosttracker_new + 0.4.0-SNAPSHOT + + + diff --git a/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/Activator.java b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/Activator.java new file mode 100644 index 0000000000..2cf1c1d6fe --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/Activator.java @@ -0,0 +1,143 @@ +/* + * 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.hosttracker.internal; + +import java.util.Dictionary; +import java.util.Hashtable; + +import org.apache.felix.dm.Component; +import org.opendaylight.controller.hosttracker.IDeviceService; +import org.opendaylight.controller.hosttracker.IfIptoHost; +import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase; +import org.opendaylight.controller.sal.packet.IDataPacketService; +import org.opendaylight.controller.sal.packet.IListenDataPacket; +import org.opendaylight.controller.switchmanager.ISwitchManager; +import org.opendaylight.controller.topologymanager.ITopologyManager; +import org.opendaylight.controller.topologymanager.ITopologyManagerAware; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Activator extends ComponentActivatorAbstractBase { + protected static final Logger logger = LoggerFactory + .getLogger(Activator.class); + + @Override + protected void init() { + + } + + @Override + protected void destroy() { + + } + + /** + * Function that is used to communicate to dependency manager the list of + * known implementations for services inside a container + * + * + * @return An array containing all the CLASS objects that will be + * instantiated in order to get an fully working implementation + * Object + */ + @Override + public Object[] getImplementations() { + Object[] res = { DeviceManagerImpl.class }; + return res; + } + + /** + * Function that is called when configuration of the dependencies is + * required. + * + * @param c + * dependency manager Component object, used for configuring the + * dependencies exported and imported + * @param imp + * Implementation class that is being configured, needed as long + * as the same routine can configure multiple implementations + * @param containerName + * The containerName being configured, this allow also optional + * per-container different behavior if needed, usually should not + * be the case though. + */ + @Override + public void configureInstance(Component c, Object imp, String containerName) { + if (imp.equals(DeviceManagerImpl.class)) { + // export the service + // XXX - TODO merge with existing APIs + Dictionary props = new Hashtable(); + props.put("salListenerName", "devicemanager"); + + c.setInterface( + new String[] { IDeviceService.class.getName(), + IfIptoHost.class.getName(), + IListenDataPacket.class.getName(), + ITopologyManagerAware.class.getName() }, props); + + c.add(createContainerServiceDependency(containerName) + .setService(ISwitchManager.class) + .setCallbacks("setSwitchManager", "unsetSwitchManager") + .setRequired(false)); + + c.add(createContainerServiceDependency(containerName) + .setService(IDataPacketService.class) + .setCallbacks("setDataPacketService", + "unsetDataPacketService").setRequired(true)); + + // c.add(createContainerServiceDependency(containerName).setService( + // IClusterContainerServices.class).setCallbacks( + // "setClusterContainerService", + // "unsetClusterContainerService").setRequired(true)); + c.add(createContainerServiceDependency(containerName) + .setService(ITopologyManager.class) + .setCallbacks("setTopologyManager", "unsetTopologyManager") + .setRequired(false)); + + c.add(createContainerServiceDependency(containerName) + .setService(IDataPacketService.class) + .setCallbacks("setDataPacketService", + "unsetDataPacketService").setRequired(true)); + } + } + + /** + * Method which tells how many Global implementations are supported by the + * bundle. This way we can tune the number of components created. This + * components will be created ONLY at the time of bundle startup and will be + * destroyed only at time of bundle destruction, this is the major + * difference with the implementation retrieved via getImplementations where + * all of them are assumed to be in a container ! + * + * + * @return The list of implementations the bundle will support, in Global + * version + */ + @Override + protected Object[] getGlobalImplementations() { + return null; + } + + /** + * Configure the dependency for a given instance Global + * + * @param c + * Component assigned for this instance, this will be what will + * be used for configuration + * @param imp + * implementation to be configured + * @param containerName + * container on which the configuration happens + */ + @Override + protected void configureGlobalInstance(Component c, Object imp) { + + } + +} diff --git a/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/AttachmentPoint.java b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/AttachmentPoint.java new file mode 100644 index 0000000000..ba2c64aff0 --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/AttachmentPoint.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2011,2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/** + * @author Srini + */ + +package org.opendaylight.controller.hosttracker.internal; + +import org.opendaylight.controller.sal.core.NodeConnector; + +public class AttachmentPoint { + NodeConnector port; + long activeSince; + long lastSeen; + + // Timeout for moving attachment points from OF/broadcast + // domain to another. + public static final long INACTIVITY_INTERVAL = 30000; // 30 seconds + public static final long EXTERNAL_TO_EXTERNAL_TIMEOUT = 5000; // 5 seconds + public static final long OPENFLOW_TO_EXTERNAL_TIMEOUT = 30000; // 30 seconds + public static final long CONSISTENT_TIMEOUT = 30000; // 30 seconds + + public AttachmentPoint(NodeConnector port, long activeSince, long lastSeen) { + this.port = port; + this.activeSince = activeSince; + this.lastSeen = lastSeen; + } + + public AttachmentPoint(NodeConnector port, long lastSeen) { + this.port = port; + this.lastSeen = lastSeen; + this.activeSince = lastSeen; + } + + public AttachmentPoint(AttachmentPoint ap) { + this.port = ap.port; + this.activeSince = ap.activeSince; + this.lastSeen = ap.lastSeen; + } + + public NodeConnector getPort() { + return port; + } + + public void setPort(NodeConnector port) { + this.port = port; + } + + public long getActiveSince() { + return activeSince; + } + + public void setActiveSince(long activeSince) { + this.activeSince = activeSince; + } + + public long getLastSeen() { + return lastSeen; + } + + public void setLastSeen(long lastSeen) { + if (this.lastSeen + INACTIVITY_INTERVAL < lastSeen) + this.activeSince = lastSeen; + if (this.lastSeen < lastSeen) + this.lastSeen = lastSeen; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((port == null) ? 0 : port.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AttachmentPoint other = (AttachmentPoint) obj; + if (port == null) { + if (other.port != null) + return false; + } else if (!port.equals(other.port)) + return false; + return true; + } + + @Override + public String toString() { + return "AttachmentPoint [port=" + port + ", activeSince=" + activeSince + + ", lastSeen=" + lastSeen + "]"; + } +} diff --git a/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DefaultEntityClassifier.java b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DefaultEntityClassifier.java new file mode 100644 index 0000000000..39c322fdef --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DefaultEntityClassifier.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2011,2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker.internal; + +import java.util.Collection; +import java.util.EnumSet; + +import org.opendaylight.controller.hosttracker.Entity; +import org.opendaylight.controller.hosttracker.IDevice; +import org.opendaylight.controller.hosttracker.IDeviceService; +import org.opendaylight.controller.hosttracker.IDeviceService.DeviceField; +import org.opendaylight.controller.hosttracker.IEntityClass; +import org.opendaylight.controller.hosttracker.IEntityClassListener; +import org.opendaylight.controller.hosttracker.IEntityClassifierService; + +/** + * This is a default entity classifier that simply classifies all entities into + * a fixed entity class, with key fields of MAC and VLAN. + * + * @author readams + */ +public class DefaultEntityClassifier implements IEntityClassifierService { + /** + * A default fixed entity class + */ + protected static class DefaultEntityClass implements IEntityClass { + String name; + + public DefaultEntityClass(String name) { + this.name = name; + } + + @Override + public EnumSet getKeyFields() { + return keyFields; + } + + @Override + public String getName() { + return name; + } + } + + protected static EnumSet keyFields; + static { + keyFields = EnumSet.of(DeviceField.MAC, DeviceField.VLAN); + } + protected static DefaultEntityClass entityClass = new DefaultEntityClass( + "DefaultEntityClass"); + + @Override + public IEntityClass classifyEntity(Entity entity) { + return entityClass; + } + + @Override + public IEntityClass reclassifyEntity(IDevice curDevice, Entity entity) { + return entityClass; + } + + @Override + public void deviceUpdate(IDevice oldDevice, + Collection newDevices) { + // no-op + } + + @Override + public EnumSet getKeyFields() { + return keyFields; + } + + @Override + public void addListener(IEntityClassListener listener) { + // no-op + + } +} diff --git a/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/Device.java b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/Device.java new file mode 100755 index 0000000000..50e77ec643 --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/Device.java @@ -0,0 +1,829 @@ +/* + * Copyright (c) 2011,2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker.internal; + +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeSet; + +import org.opendaylight.controller.hosttracker.Entity; +import org.opendaylight.controller.hosttracker.IDevice; +import org.opendaylight.controller.hosttracker.IDeviceService.DeviceField; +import org.opendaylight.controller.hosttracker.IEntityClass; +import org.opendaylight.controller.hosttracker.SwitchPort; +import org.opendaylight.controller.hosttracker.SwitchPort.ErrorStatus; +import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.utils.HexEncode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Concrete implementation of {@link IDevice} + * + * @author readams + */ +public class Device implements IDevice { + protected static Logger log = LoggerFactory.getLogger(Device.class); + public static final short VLAN_UNTAGGED = (short) 0xffff; + + private final Long deviceKey; + protected final DeviceManagerImpl deviceManager; + + protected final Entity[] entities; + private final IEntityClass entityClass; + + protected final String macAddressString; + // the vlan Ids from the entities of this device + protected final Short[] vlanIds; + protected volatile String dhcpClientName; + + /** + * These are the old attachment points for the device that were valid no + * more than INACTIVITY_TIME ago. + */ + protected volatile List oldAPs; + /** + * The current attachment points for the device. + */ + protected volatile List attachmentPoints; + + // ************ + // Constructors + // ************ + + /** + * Create a device from an entities + * + * @param deviceManager + * the device manager for this device + * @param deviceKey + * the unique identifier for this device object + * @param entity + * the initial entity for the device + * @param entityClass + * the entity classes associated with the entity + */ + public Device(DeviceManagerImpl deviceManager, Long deviceKey, + Entity entity, IEntityClass entityClass) { + this.deviceManager = deviceManager; + this.deviceKey = deviceKey; + this.entities = new Entity[] { entity }; + this.macAddressString = HexEncode.longToHexString(entity + .getMacAddress()); + this.entityClass = entityClass; + Arrays.sort(this.entities); + + this.dhcpClientName = null; + this.oldAPs = null; + this.attachmentPoints = null; + + if (entity.getPort() != null) { + NodeConnector port = entity.getPort(); + + if (deviceManager.isValidAttachmentPoint(port)) { + AttachmentPoint ap; + ap = new AttachmentPoint(port, entity.getLastSeenTimestamp() + .getTime()); + + this.attachmentPoints = new ArrayList(); + this.attachmentPoints.add(ap); + } + } + vlanIds = computeVlandIds(); + } + + /** + * Create a device from a set of entities + * + * @param deviceManager + * the device manager for this device + * @param deviceKey + * the unique identifier for this device object + * @param entities + * the initial entities for the device + * @param entityClass + * the entity class associated with the entities + */ + public Device(DeviceManagerImpl deviceManager, Long deviceKey, + String dhcpClientName, Collection oldAPs, + Collection attachmentPoints, + Collection entities, IEntityClass entityClass) { + this.deviceManager = deviceManager; + this.deviceKey = deviceKey; + this.dhcpClientName = dhcpClientName; + this.entities = entities.toArray(new Entity[entities.size()]); + this.oldAPs = null; + this.attachmentPoints = null; + if (oldAPs != null) { + this.oldAPs = new ArrayList(oldAPs); + } + if (attachmentPoints != null) { + this.attachmentPoints = new ArrayList( + attachmentPoints); + } + this.macAddressString = HexEncode.longToHexString(this.entities[0] + .getMacAddress()); + this.entityClass = entityClass; + Arrays.sort(this.entities); + vlanIds = computeVlandIds(); + } + + /** + * Construct a new device consisting of the entities from the old device + * plus an additional entity. The caller needs to ensure that the additional + * entity is not already present in the array + * + * @param device + * the old device object + * @param newEntity + * the entity to add. newEntity must be have the same entity + * class as device + * @param if positive indicates the index in the entities array were the new + * entity should be inserted. If negative we will compute the correct + * insertion point + */ + public Device(Device device, Entity newEntity, int insertionpoint) { + this.deviceManager = device.deviceManager; + this.deviceKey = device.deviceKey; + this.dhcpClientName = device.dhcpClientName; + + this.entities = new Entity[device.entities.length + 1]; + if (insertionpoint < 0) { + insertionpoint = -(Arrays.binarySearch(device.entities, newEntity) + 1); + } + if (insertionpoint > 0) { + // insertion point is not the beginning: + // copy up to insertion point + System.arraycopy(device.entities, 0, this.entities, 0, + insertionpoint); + } + if (insertionpoint < device.entities.length) { + // insertion point is not the end + // copy from insertion point + System.arraycopy(device.entities, insertionpoint, this.entities, + insertionpoint + 1, device.entities.length - insertionpoint); + } + this.entities[insertionpoint] = newEntity; + /* + * this.entities = Arrays.copyOf(device.entities, + * device.entities.length + 1); this.entities[this.entities.length - 1] + * = newEntity; Arrays.sort(this.entities); + */ + this.oldAPs = null; + if (device.oldAPs != null) { + this.oldAPs = new ArrayList(device.oldAPs); + } + this.attachmentPoints = null; + if (device.attachmentPoints != null) { + this.attachmentPoints = new ArrayList( + device.attachmentPoints); + } + + this.macAddressString = HexEncode.longToHexString(this.entities[0] + .getMacAddress()); + + this.entityClass = device.entityClass; + vlanIds = computeVlandIds(); + } + + private Short[] computeVlandIds() { + if (entities.length == 1) { + if (entities[0].getVlan() != null) { + return new Short[] { entities[0].getVlan() }; + } else { + return new Short[] { Short.valueOf((short) -1) }; + } + } + + TreeSet vals = new TreeSet(); + for (Entity e : entities) { + if (e.getVlan() == null) + vals.add((short) -1); + else + vals.add(e.getVlan()); + } + return vals.toArray(new Short[vals.size()]); + } + + /** + * Given a list of attachment points (apList), the procedure would return a + * map of attachment points for each L2 domain. L2 domain id is the key. + * + * @param apList + * @return + */ + private Map getAPMap(List apList) { + + if (apList == null) + return null; + // ITopologyService topology = deviceManager.topology; + + // Get the old attachment points and sort them. + List oldAP = new ArrayList(); + if (apList != null) + oldAP.addAll(apList); + + // Remove invalid attachment points before sorting. + List tempAP = new ArrayList(); + for (AttachmentPoint ap : oldAP) { + if (deviceManager.isValidAttachmentPoint(ap.getPort())) { + tempAP.add(ap); + } + } + oldAP = tempAP; + + Collections.sort(oldAP, deviceManager.apComparator); + + // Map of attachment point by L2 domain Id. + Map apMap = new HashMap(); + + for (int i = 0; i < oldAP.size(); ++i) { + AttachmentPoint ap = oldAP.get(i); + // if this is not a valid attachment point, continue + if (!deviceManager.isValidAttachmentPoint(ap.getPort())) + continue; + + // long id = topology.getL2DomainId(ap.getSw()); + // XXX - Missing functionality + long id = 0; + + apMap.put(id, ap); + } + + if (apMap.isEmpty()) + return null; + return apMap; + } + + /** + * Remove all attachment points that are older than INACTIVITY_INTERVAL from + * the list. + * + * @param apList + * @return + */ + private boolean removeExpiredAttachmentPoints(List apList) { + + List expiredAPs = new ArrayList(); + + if (apList == null) + return false; + + for (AttachmentPoint ap : apList) { + if (ap.getLastSeen() + AttachmentPoint.INACTIVITY_INTERVAL < System + .currentTimeMillis()) + expiredAPs.add(ap); + } + if (expiredAPs.size() > 0) { + apList.removeAll(expiredAPs); + return true; + } else + return false; + } + + /** + * Get a list of duplicate attachment points, given a list of old attachment + * points and one attachment point per L2 domain. Given a true attachment + * point in the L2 domain, say trueAP, another attachment point in the same + * L2 domain, say ap, is duplicate if: 1. ap is inconsistent with trueAP, + * and 2. active time of ap is after that of trueAP; and 3. last seen time + * of ap is within the last INACTIVITY_INTERVAL + * + * @param oldAPList + * @param apMap + * @return + */ + List getDuplicateAttachmentPoints( + List oldAPList, Map apMap) { + // ITopologyService topology = deviceManager.topology; + List dupAPs = new ArrayList(); + long timeThreshold = System.currentTimeMillis() + - AttachmentPoint.INACTIVITY_INTERVAL; + + if (oldAPList == null || apMap == null) + return dupAPs; + + for (AttachmentPoint ap : oldAPList) { + // XXX - Missing functionality + // long id = topology.getL2DomainId(ap.getSw()); + long id = 0; + AttachmentPoint trueAP = apMap.get(id); + + if (trueAP == null) + continue; + // XXX - Missing functionality + // boolean c = (topology.isConsistent(trueAP.getSw(), + // trueAP.getPort(), + // ap.getSw(), ap.getPort())); + boolean c = true; + boolean active = (ap.getActiveSince() > trueAP.getActiveSince()); + boolean last = ap.getLastSeen() > timeThreshold; + if (!c && active && last) { + dupAPs.add(ap); + } + } + + return dupAPs; + } + + /** + * Update the known attachment points. This method is called whenever + * topology changes. The method returns true if there's any change to the + * list of attachment points -- which indicates a possible device move. + * + * @return + */ + protected boolean updateAttachmentPoint() { + boolean moved = false; + this.oldAPs = attachmentPoints; + if (attachmentPoints == null || attachmentPoints.isEmpty()) + return false; + + List apList = new ArrayList(); + if (attachmentPoints != null) + apList.addAll(attachmentPoints); + Map newMap = getAPMap(apList); + if (newMap == null || newMap.size() != apList.size()) { + moved = true; + } + + // Prepare the new attachment point list. + if (moved) { + log.info("updateAttachmentPoint: ap {} newmap {} ", + attachmentPoints, newMap); + List newAPList = new ArrayList(); + if (newMap != null) + newAPList.addAll(newMap.values()); + this.attachmentPoints = newAPList; + } + + // Set the oldAPs to null. + return moved; + } + + /** + * Update the list of attachment points given that a new packet-in was seen + * from (sw, port) at time (lastSeen). The return value is true if there was + * any change to the list of attachment points for the device -- which + * indicates a device move. + * + * @param sw + * @param port + * @param lastSeen + * @return + */ + protected boolean updateAttachmentPoint(NodeConnector port, long lastSeen) { + // ITopologyService topology = deviceManager.topology; + List oldAPList; + List apList; + boolean oldAPFlag = false; + + if (!deviceManager.isValidAttachmentPoint(port)) + return false; + AttachmentPoint newAP = new AttachmentPoint(port, lastSeen); + // Copy the oldAP and ap list. + apList = new ArrayList(); + if (attachmentPoints != null) + apList.addAll(attachmentPoints); + oldAPList = new ArrayList(); + if (oldAPs != null) + oldAPList.addAll(oldAPs); + + // if the sw, port is in old AP, remove it from there + // and update the lastSeen in that object. + if (oldAPList.contains(newAP)) { + int index = oldAPList.indexOf(newAP); + newAP = oldAPList.remove(index); + newAP.setLastSeen(lastSeen); + this.oldAPs = oldAPList; + oldAPFlag = true; + } + + // newAP now contains the new attachment point. + + // Get the APMap is null or empty. + Map apMap = getAPMap(apList); + if (apMap == null || apMap.isEmpty()) { + apList.add(newAP); + attachmentPoints = apList; + // there are no old attachment points - since the device exists, + // this + // may be because the host really moved (so the old AP port went + // down); + // or it may be because the switch restarted (so old APs were + // nullified). + // For now we will treat both cases as host moved. + return true; + } + + // XXX - Missing functionality + // long id = topology.getL2DomainId(sw); + long id = 0; + AttachmentPoint oldAP = apMap.get(id); + + if (oldAP == null) // No attachment on this L2 domain. + { + apList = new ArrayList(); + apList.addAll(apMap.values()); + apList.add(newAP); + this.attachmentPoints = apList; + return true; // new AP found on an L2 island. + } + + // There is already a known attachment point on the same L2 island. + // we need to compare oldAP and newAP. + if (oldAP.equals(newAP)) { + // nothing to do here. just the last seen has to be changed. + if (newAP.lastSeen > oldAP.lastSeen) { + oldAP.setLastSeen(newAP.lastSeen); + } + this.attachmentPoints = new ArrayList( + apMap.values()); + return false; // nothing to do here. + } + + int x = deviceManager.apComparator.compare(oldAP, newAP); + if (x < 0) { + // newAP replaces oldAP. + apMap.put(id, newAP); + this.attachmentPoints = new ArrayList( + apMap.values()); + + oldAPList = new ArrayList(); + if (oldAPs != null) + oldAPList.addAll(oldAPs); + oldAPList.add(oldAP); + this.oldAPs = oldAPList; + // XXX - Missing functionality + // if (!topology.isInSameBroadcastDomain(oldAP.getSw(), + // oldAP.getPort(), + // newAP.getSw(), newAP.getPort())) + // return true; // attachment point changed. + return true; + } else if (oldAPFlag) { + // retain oldAP as is. Put the newAP in oldAPs for flagging + // possible duplicates. + oldAPList = new ArrayList(); + if (oldAPs != null) + oldAPList.addAll(oldAPs); + // Add to oldAPList only if it was picked up from the oldAPList + oldAPList.add(newAP); + this.oldAPs = oldAPList; + // XXX - Missing functionality + // if (!topology.isInSameBroadcastDomain(oldAP.getSw(), + // oldAP.getPort(), + // newAP.getSw(), newAP.getPort())) + // return true; // attachment point changed. + return true; + } + return false; + } + + /** + * Delete (sw,port) from the list of list of attachment points and oldAPs. + * + * @param sw + * @param port + * @return + */ + public boolean deleteAttachmentPoint(NodeConnector port) { + AttachmentPoint ap = new AttachmentPoint(port, 0); + + if (this.oldAPs != null) { + ArrayList apList = new ArrayList(); + apList.addAll(this.oldAPs); + int index = apList.indexOf(ap); + if (index > 0) { + apList.remove(index); + this.oldAPs = apList; + } + } + + if (this.attachmentPoints != null) { + ArrayList apList = new ArrayList(); + apList.addAll(this.attachmentPoints); + int index = apList.indexOf(ap); + if (index > 0) { + apList.remove(index); + this.attachmentPoints = apList; + return true; + } + } + return false; + } + + // ******* + // IDevice + // ******* + + @Override + public SwitchPort[] getOldAP() { + List sp = new ArrayList(); + SwitchPort[] returnSwitchPorts = new SwitchPort[] {}; + if (oldAPs == null) + return returnSwitchPorts; + if (oldAPs.isEmpty()) + return returnSwitchPorts; + + // copy ap list. + List oldAPList; + oldAPList = new ArrayList(); + + if (oldAPs != null) + oldAPList.addAll(oldAPs); + removeExpiredAttachmentPoints(oldAPList); + + if (oldAPList != null) { + for (AttachmentPoint ap : oldAPList) { + SwitchPort swport = new SwitchPort(ap.getPort()); + sp.add(swport); + } + } + return sp.toArray(new SwitchPort[sp.size()]); + } + + @Override + public SwitchPort[] getAttachmentPoints() { + return getAttachmentPoints(false); + } + + @Override + public SwitchPort[] getAttachmentPoints(boolean includeError) { + List sp = new ArrayList(); + SwitchPort[] returnSwitchPorts = new SwitchPort[] {}; + if (attachmentPoints == null) + return returnSwitchPorts; + if (attachmentPoints.isEmpty()) + return returnSwitchPorts; + + // copy ap list. + List apList = attachmentPoints; + + if (apList != null) { + for (AttachmentPoint ap : apList) { + SwitchPort swport = new SwitchPort(ap.getPort()); + sp.add(swport); + } + } + + if (!includeError) + return sp.toArray(new SwitchPort[sp.size()]); + + List oldAPList; + oldAPList = new ArrayList(); + + if (oldAPs != null) + oldAPList.addAll(oldAPs); + + if (removeExpiredAttachmentPoints(oldAPList)) + this.oldAPs = oldAPList; + + List dupList; + // get AP map. + Map apMap = getAPMap(apList); + dupList = this.getDuplicateAttachmentPoints(oldAPList, apMap); + if (dupList != null) { + for (AttachmentPoint ap : dupList) { + SwitchPort swport = new SwitchPort(ap.getPort(), + ErrorStatus.DUPLICATE_DEVICE); + sp.add(swport); + } + } + return sp.toArray(new SwitchPort[sp.size()]); + } + + @Override + public Long getDeviceKey() { + return deviceKey; + } + + @Override + public long getMACAddress() { + // we assume only one MAC per device for now. + return entities[0].getMacAddress(); + } + + @Override + public String getMACAddressString() { + return macAddressString; + } + + @Override + public Short[] getVlanId() { + return Arrays.copyOf(vlanIds, vlanIds.length); + } + + static final EnumSet ipv4Fields = EnumSet.of(DeviceField.IPV4); + + @Override + public Integer[] getIPv4Addresses() { + // XXX - TODO we can cache this result. Let's find out if this + // is really a performance bottleneck first though. + + TreeSet vals = new TreeSet(); + for (Entity e : entities) { + if (e.getIpv4Address() == null) + continue; + + // We have an IP address only if among the devices within the class + // we have the most recent entity with that IP. + boolean validIP = true; + Iterator devices = deviceManager.queryClassByEntity( + entityClass, ipv4Fields, e); + while (devices.hasNext()) { + Device d = devices.next(); + if (deviceKey.equals(d.getDeviceKey())) + continue; + for (Entity se : d.entities) { + if (se.getIpv4Address() != null + && se.getIpv4Address().equals(e.getIpv4Address()) + && se.getLastSeenTimestamp() != null + && 0 < se.getLastSeenTimestamp().compareTo( + e.getLastSeenTimestamp())) { + validIP = false; + break; + } + } + if (!validIP) + break; + } + + if (validIP) + vals.add(e.getIpv4Address()); + } + + return vals.toArray(new Integer[vals.size()]); + } + + @Override + public Short[] getSwitchPortVlanIds(SwitchPort swp) { + TreeSet vals = new TreeSet(); + for (Entity e : entities) { + if (e.getPort().equals(swp.getPort())) { + if (e.getVlan() == null) + vals.add(VLAN_UNTAGGED); + else + vals.add(e.getVlan()); + } + } + return vals.toArray(new Short[vals.size()]); + } + + @Override + public Date getLastSeen() { + Date d = null; + for (int i = 0; i < entities.length; i++) { + if (d == null + || entities[i].getLastSeenTimestamp().compareTo(d) > 0) + d = entities[i].getLastSeenTimestamp(); + } + return d; + } + + // *************** + // Getters/Setters + // *************** + + @Override + public IEntityClass getEntityClass() { + return entityClass; + } + + public Entity[] getEntities() { + return entities; + } + + public String getDHCPClientName() { + return dhcpClientName; + } + + // *************** + // Utility Methods + // *************** + + /** + * Check whether the device contains the specified entity + * + * @param entity + * the entity to search for + * @return the index of the entity, or <0 if not found + */ + protected int entityIndex(Entity entity) { + return Arrays.binarySearch(entities, entity); + } + + // ****** + // Object + // ****** + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Arrays.hashCode(entities); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Device other = (Device) obj; + if (!deviceKey.equals(other.deviceKey)) + return false; + if (!Arrays.equals(entities, other.entities)) + return false; + return true; + } + + public HostNodeConnector toHostNodeConnector() { + Integer[] ipv4s = this.getIPv4Addresses(); + try { + InetAddress ip = InetAddress.getByName(ipv4s[ipv4s.length - 1] + .toString()); + byte[] macAddr = macLongToByte(this.getMACAddress()); + HostNodeConnector nc = new HostNodeConnector(macAddr, ip, null, + (short) 0); + return nc; + } catch (Exception e) { + return null; + } + } + + private byte[] macLongToByte(long mac) { + byte[] macAddr = new byte[6]; + for (int i = 0; i < 6; i++) { + macAddr[5 - i] = (byte) (mac >> (8 * i)); + } + return macAddr; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Device [deviceKey="); + builder.append(deviceKey); + builder.append(", entityClass="); + builder.append(entityClass.getName()); + builder.append(", MAC="); + builder.append(macAddressString); + builder.append(", IPs=["); + boolean isFirst = true; + for (Integer ip : getIPv4Addresses()) { + if (!isFirst) + builder.append(", "); + isFirst = false; + // builder.append(IPv4.fromIPv4Address(ip)); + builder.append(ip); + } + builder.append("], APs="); + builder.append(Arrays.toString(getAttachmentPoints(true))); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceIndex.java b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceIndex.java new file mode 100644 index 0000000000..5f068063e7 --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceIndex.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker.internal; + +import java.util.Collection; +import java.util.EnumSet; +import java.util.Iterator; + +import org.opendaylight.controller.hosttracker.Entity; +import org.opendaylight.controller.hosttracker.IDeviceService.DeviceField; + +/** + * An index that maps key fields of an entity to device keys + */ +public abstract class DeviceIndex { + /** + * The key fields for this index + */ + protected EnumSet keyFields; + + /** + * Construct a new device index using the provided key fields + * + * @param keyFields + * the key fields to use + */ + public DeviceIndex(EnumSet keyFields) { + super(); + this.keyFields = keyFields; + } + + /** + * Find all device keys in the index that match the given entity on all the + * key fields for this index + * + * @param e + * the entity to search for + * @return an iterator over device keys + */ + public abstract Iterator queryByEntity(Entity entity); + + /** + * Get all device keys in the index. If certain devices exist multiple + * times, then these devices may be returned multiple times + * + * @return an iterator over device keys + */ + public abstract Iterator getAll(); + + /** + * Attempt to update an index with the entities in the provided + * {@link Device}. If the update fails because of a concurrent update, will + * return false. + * + * @param device + * the device to update + * @param deviceKey + * the device key for the device + * @return true if the update succeeded, false otherwise. + */ + public abstract boolean updateIndex(Device device, Long deviceKey); + + /** + * Add a mapping from the given entity to the given device key. This update + * will not fail because of a concurrent update + * + * @param device + * the device to update + * @param deviceKey + * the device key for the device + */ + public abstract void updateIndex(Entity entity, Long deviceKey); + + /** + * Remove the entry for the given entity + * + * @param entity + * the entity to remove + */ + public abstract void removeEntity(Entity entity); + + /** + * Remove the given device key from the index for the given entity + * + * @param entity + * the entity to search for + * @param deviceKey + * the key to remove + */ + public abstract void removeEntity(Entity entity, Long deviceKey); + + /** + * Remove the give device from the index only if this the collection of + * others does not contain an entity that is identical on all the key fields + * for this index. + * + * @param entity + * the entity to search for + * @param deviceKey + * the key to remove + * @param others + * the others against which to check + */ + public void removeEntityIfNeeded(Entity entity, Long deviceKey, + Collection others) { + IndexedEntity ie = new IndexedEntity(keyFields, entity); + for (Entity o : others) { + IndexedEntity oio = new IndexedEntity(keyFields, o); + if (oio.equals(ie)) + return; + } + + Iterator keyiter = this.queryByEntity(entity); + while (keyiter.hasNext()) { + Long key = keyiter.next(); + if (key.equals(deviceKey)) { + removeEntity(entity, deviceKey); + break; + } + } + } + +} diff --git a/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceIndexInterator.java b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceIndexInterator.java new file mode 100644 index 0000000000..469bd61066 --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceIndexInterator.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker.internal; + +import java.util.Iterator; + +/** + * An iterator for handling device index queries + */ +public class DeviceIndexInterator implements Iterator { + private DeviceManagerImpl deviceManager; + private Iterator subIterator; + + /** + * Construct a new device index iterator referring to a device manager + * instance and an iterator over device keys + * + * @param deviceManager + * the device manager + * @param subIterator + * an iterator over device keys + */ + public DeviceIndexInterator(DeviceManagerImpl deviceManager, + Iterator subIterator) { + super(); + this.deviceManager = deviceManager; + this.subIterator = subIterator; + } + + @Override + public boolean hasNext() { + return subIterator.hasNext(); + } + + @Override + public Device next() { + Long next = subIterator.next(); + return deviceManager.deviceMap.get(next); + } + + @Override + public void remove() { + subIterator.remove(); + } + +} diff --git a/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceIterator.java b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceIterator.java new file mode 100644 index 0000000000..68f175c52e --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceIterator.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker.internal; + +import java.util.Arrays; +import java.util.Iterator; + +import org.opendaylight.controller.hosttracker.IEntityClass; +import org.opendaylight.controller.hosttracker.SwitchPort; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.utils.FilterIterator; + +/** + * An iterator for handling device queries + */ +public class DeviceIterator extends FilterIterator { + private IEntityClass[] entityClasses; + + private Long macAddress; + private Short vlan; + private Integer ipv4Address; + private NodeConnector port; + + /** + * Construct a new device iterator over the key fields + * + * @param subIterator + * an iterator over the full data structure to scan + * @param entityClasses + * the entity classes to search for + * @param macAddress + * The MAC address + * @param vlan + * the VLAN + * @param ipv4Address + * the ipv4 address + * @param switchDPID + * the switch DPID + * @param switchPort + * the switch port + */ + public DeviceIterator(Iterator subIterator, + IEntityClass[] entityClasses, Long macAddress, Short vlan, + Integer ipv4Address, NodeConnector port) { + super(subIterator); + this.entityClasses = entityClasses; + this.subIterator = subIterator; + this.macAddress = macAddress; + this.vlan = vlan; + this.ipv4Address = ipv4Address; + this.port = port; + } + + @Override + protected boolean matches(Device value) { + boolean match; + if (entityClasses != null) { + IEntityClass clazz = value.getEntityClass(); + if (clazz == null) + return false; + + match = false; + for (IEntityClass entityClass : entityClasses) { + if (clazz.equals(entityClass)) { + match = true; + break; + } + } + if (!match) + return false; + } + if (macAddress != null) { + if (macAddress.longValue() != value.getMACAddress()) + return false; + } + if (vlan != null) { + Short[] vlans = value.getVlanId(); + if (Arrays.binarySearch(vlans, vlan) < 0) + return false; + } + if (ipv4Address != null) { + Integer[] ipv4Addresses = value.getIPv4Addresses(); + if (Arrays.binarySearch(ipv4Addresses, ipv4Address) < 0) + return false; + } + if (port != null) { + SwitchPort[] sps = value.getAttachmentPoints(); + if (sps == null) + return false; + + match = false; + for (SwitchPort sp : sps) { + if (sp.getPort().equals(sp.getPort())) { + match = true; + break; + } + } + if (!match) + return false; + } + return true; + } +} diff --git a/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceManagerImpl.java b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceManagerImpl.java new file mode 100755 index 0000000000..bda1372311 --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceManagerImpl.java @@ -0,0 +1,2371 @@ +/* + * Copyright (c) 2011,2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker.internal; + +import static org.opendaylight.controller.hosttracker.internal.DeviceManagerImpl.DeviceUpdate.Change.ADD; +import static org.opendaylight.controller.hosttracker.internal.DeviceManagerImpl.DeviceUpdate.Change.CHANGE; +import static org.opendaylight.controller.hosttracker.internal.DeviceManagerImpl.DeviceUpdate.Change.DELETE; + +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.opendaylight.controller.hosttracker.Entity; +import org.opendaylight.controller.hosttracker.IDevice; +import org.opendaylight.controller.hosttracker.IDeviceListener; +import org.opendaylight.controller.hosttracker.IDeviceService; +import org.opendaylight.controller.hosttracker.IEntityClass; +import org.opendaylight.controller.hosttracker.IEntityClassListener; +import org.opendaylight.controller.hosttracker.IEntityClassifierService; +import org.opendaylight.controller.hosttracker.IfIptoHost; +import org.opendaylight.controller.hosttracker.SwitchPort; +import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; +import org.opendaylight.controller.sal.core.Edge; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType; +import org.opendaylight.controller.sal.packet.ARP; +import org.opendaylight.controller.sal.packet.Ethernet; +import org.opendaylight.controller.sal.packet.IDataPacketService; +import org.opendaylight.controller.sal.packet.IListenDataPacket; +import org.opendaylight.controller.sal.packet.Packet; +import org.opendaylight.controller.sal.packet.PacketResult; +import org.opendaylight.controller.sal.packet.RawPacket; +import org.opendaylight.controller.sal.topology.TopoEdgeUpdate; +import org.opendaylight.controller.sal.utils.ListenerDispatcher; +import org.opendaylight.controller.sal.utils.MultiIterator; +import org.opendaylight.controller.sal.utils.SingletonTask; +import org.opendaylight.controller.sal.utils.Status; +import org.opendaylight.controller.switchmanager.ISwitchManager; +import org.opendaylight.controller.topologymanager.ITopologyManager; +import org.opendaylight.controller.topologymanager.ITopologyManagerAware; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * DeviceManager creates Devices based upon MAC addresses seen in the network. + * It tracks any network addresses mapped to the Device, and its location within + * the network. + * + * @author readams + */ +public class DeviceManagerImpl implements IDeviceService, IEntityClassListener, + IListenDataPacket, ITopologyManagerAware, IfIptoHost { + protected static Logger logger = LoggerFactory + .getLogger(DeviceManagerImpl.class); + + public static final String MODULE_NAME = "devicemanager"; + + // protected ITopologyService topology; + // protected IStorageSourceService storageSource; + // protected IRestApiService restApi; + // protected IThreadPoolService threadPool; + // protected IFlowReconcileService flowReconcileMgr; + // protected IFlowReconcileEngineService flowReconcileEngine; + // protected IDebugCounterService debugCounters; + // private ISyncService syncService; + // private IStoreClient storeClient; + // private DeviceSyncManager deviceSyncManager; + + private ITopologyManager topology; + private ISwitchManager switchManager = null; + private IDataPacketService dataPacketService = null; + + public static final String CNT_INCOMING = MODULE_NAME + "-incoming"; + public static final String CNT_RECONCILE_REQUEST = MODULE_NAME + + "-reconcileRequest"; + public static final String CNT_RECONCILE_NO_SOURCE = MODULE_NAME + + "-reconcileNoSourceDevice"; + public static final String CNT_RECONCILE_NO_DEST = MODULE_NAME + + "-reconcileNoDestDevice"; + public static final String CNT_BROADCAST_SOURCE = MODULE_NAME + + "-broadcastSource"; + public static final String CNT_NO_SOURCE = MODULE_NAME + "-noSourceDevice"; + public static final String CNT_NO_DEST = MODULE_NAME + "-noDestDevice"; + public static final String CNT_DHCP_CLIENT_NAME_SNOOPED = MODULE_NAME + + "-dhcpClientNameSnooped"; + public static final String CNT_DEVICE_ON_INTERAL_PORT_NOT_LEARNED = MODULE_NAME + + "-deviceOnInternalPortNotLearned"; + public static final String CNT_PACKET_NOT_ALLOWED = MODULE_NAME + + "-packetNotAllowed"; + public static final String CNT_NEW_DEVICE = MODULE_NAME + "-newDevice"; + public static final String CNT_PACKET_ON_INTERNAL_PORT_FOR_KNOWN_DEVICE = MODULE_NAME + + "-packetOnInternalPortForKnownDevice"; + public static final String CNT_NEW_ENTITY = MODULE_NAME + "-newEntity"; + public static final String CNT_DEVICE_CHANGED = MODULE_NAME + + "-deviceChanged"; + public static final String CNT_DEVICE_MOVED = MODULE_NAME + "-deviceMoved"; + public static final String CNT_CLEANUP_ENTITIES_RUNS = MODULE_NAME + + "-cleanupEntitiesRuns"; + public static final String CNT_ENTITY_REMOVED_TIMEOUT = MODULE_NAME + + "-entityRemovedTimeout"; + public static final String CNT_DEVICE_DELETED = MODULE_NAME + + "-deviceDeleted"; + public static final String CNT_DEVICE_RECLASSIFY_DELETE = MODULE_NAME + + "-deviceReclassifyDelete"; + public static final String CNT_DEVICE_STORED = MODULE_NAME + + "-deviceStored"; + public static final String CNT_DEVICE_STORE_THROTTLED = MODULE_NAME + + "-deviceStoreThrottled"; + public static final String CNT_DEVICE_REMOVED_FROM_STORE = MODULE_NAME + + "-deviceRemovedFromStore"; + public static final String CNT_SYNC_EXCEPTION = MODULE_NAME + + "-syncException"; + public static final String CNT_DEVICES_FROM_STORE = MODULE_NAME + + "-devicesFromStore"; + public static final String CNT_CONSOLIDATE_STORE_RUNS = MODULE_NAME + + "-consolidateStoreRuns"; + public static final String CNT_CONSOLIDATE_STORE_DEVICES_REMOVED = MODULE_NAME + + "-consolidateStoreDevicesRemoved"; + + static final String DEVICE_SYNC_STORE_NAME = DeviceManagerImpl.class + .getCanonicalName() + ".stateStore"; + + /** + * Time interval between writes of entries for the same device to the sync + * store. + */ + // static final int DEFAULT_SYNC_STORE_WRITE_INTERVAL_MS = + // 5*60*1000; // 5 min + // private int syncStoreWriteIntervalMs = + // DEFAULT_SYNC_STORE_WRITE_INTERVAL_MS; + + /** + * Time after SLAVE->MASTER until we run the consolidate store code. + */ + // static final int DEFAULT_INITIAL_SYNC_STORE_CONSOLIDATE_MS = + // 15*1000; // 15 sec + // private int initialSyncStoreConsolidateMs = + // DEFAULT_INITIAL_SYNC_STORE_CONSOLIDATE_MS; + + /** + * Time interval between consolidate store runs. + */ + // static final int DEFAULT_SYNC_STORE_CONSOLIDATE_INTERVAL_MS = + // 75*60*1000; // 75 min + // private final int syncStoreConsolidateIntervalMs = + // DEFAULT_SYNC_STORE_CONSOLIDATE_INTERVAL_MS; + + /** + * Time in milliseconds before entities will expire + */ + protected static final int ENTITY_TIMEOUT = 60 * 60 * 1000; + + /** + * Time in seconds between cleaning up old entities/devices + */ + protected static final int ENTITY_CLEANUP_INTERVAL = 60 * 60; + + /** + * This is the master device map that maps device IDs to {@link Device} + * objects. + */ + protected ConcurrentHashMap deviceMap; + + /** + * Counter used to generate device keys + */ + protected long deviceKeyCounter = 0; + + /** + * Lock for incrementing the device key counter + */ + protected Object deviceKeyLock = new Object(); + + /** + * This is the primary entity index that contains all entities + */ + protected DeviceUniqueIndex primaryIndex; + + /** + * This stores secondary indices over the fields in the devices + */ + protected Map, DeviceIndex> secondaryIndexMap; + + /** + * This map contains state for each of the {@ref IEntityClass} that exist + */ + protected ConcurrentHashMap classStateMap; + + /** + * This is the list of indices we want on a per-class basis + */ + protected Set> perClassIndices; + + /** + * The entity classifier currently in use + */ + protected IEntityClassifierService entityClassifier; + + /** + * Used to cache state about specific entity classes + */ + protected class ClassState { + + /** + * The class index + */ + protected DeviceUniqueIndex classIndex; + + /** + * This stores secondary indices over the fields in the device for the + * class + */ + protected Map, DeviceIndex> secondaryIndexMap; + + /** + * Allocate a new {@link ClassState} object for the class + * + * @param clazz + * the class to use for the state + */ + public ClassState(IEntityClass clazz) { + EnumSet keyFields = clazz.getKeyFields(); + EnumSet primaryKeyFields = entityClassifier + .getKeyFields(); + boolean keyFieldsMatchPrimary = primaryKeyFields.equals(keyFields); + + if (!keyFieldsMatchPrimary) + classIndex = new DeviceUniqueIndex(keyFields); + + secondaryIndexMap = new HashMap, DeviceIndex>(); + for (EnumSet fields : perClassIndices) { + secondaryIndexMap.put(fields, new DeviceMultiIndex(fields)); + } + } + } + + /** + * Device manager event listeners reclassifyDeviceListeners are notified + * first before reconcileDeviceListeners. This is to make sure devices are + * correctly reclassified before reconciliation. + */ + protected ListenerDispatcher deviceListeners; + + /** + * A device update event to be dispatched + */ + protected static class DeviceUpdate { + public enum Change { + ADD, DELETE, CHANGE; + } + + /** + * The affected device + */ + protected Device device; + + /** + * The change that was made + */ + protected Change change; + + /** + * If not added, then this is the list of fields changed + */ + protected EnumSet fieldsChanged; + + public DeviceUpdate(Device device, Change change, + EnumSet fieldsChanged) { + super(); + this.device = device; + this.change = change; + this.fieldsChanged = fieldsChanged; + } + + @Override + public String toString() { + String devIdStr = device.getEntityClass().getName() + "::" + + device.getMACAddressString(); + return "DeviceUpdate [device=" + devIdStr + ", change=" + change + + ", fieldsChanged=" + fieldsChanged + "]"; + } + + } + + /** + * AttachmentPointComparator + * + * Compares two attachment points and returns the latest one. It is assumed + * that the two attachment points are in the same L2 domain. + * + * @author srini + */ + protected class AttachmentPointComparator implements + Comparator { + public AttachmentPointComparator() { + super(); + } + + @Override + public int compare(AttachmentPoint oldAP, AttachmentPoint newAP) { + // First compare based on L2 domain ID; + + // XXX - missing functionality -- need topology + // long oldDomain = topology.getL2DomainId(oldSw); + // boolean oldBD = topology.isBroadcastDomainPort(oldSw, oldPort); + long oldDomain = 0; + boolean oldBD = false; + + // XXX - missing functionality -- need topology + // long newDomain = topology.getL2DomainId(newSw); + // boolean newBD = topology.isBroadcastDomainPort(newSw, newPort); + long newDomain = 0; + boolean newBD = false; + + if (oldDomain < newDomain) + return -1; + else if (oldDomain > newDomain) + return 1; + + // Give preference to OFPP_LOCAL always + if (!oldAP.getPort().getType().equals(NodeConnectorIDType.SWSTACK) + && newAP.getPort().getType() + .equals(NodeConnectorIDType.SWSTACK)) { + return -1; + } else if (oldAP.getPort().getType() + .equals(NodeConnectorIDType.SWSTACK) + && !newAP.getPort().getType() + .equals(NodeConnectorIDType.SWSTACK)) { + return 1; + } + + // We expect that the last seen of the new AP is higher than + // old AP, if it is not, just reverse and send the negative + // of the result. + if (oldAP.getActiveSince() > newAP.getActiveSince()) + return -compare(newAP, oldAP); + + long activeOffset = 0; + // XXX - missing functionality -- need topology + // if (!topology.isConsistent(oldSw, oldPort, newSw, newPort)) { + if (!newBD && oldBD) { + return -1; + } + if (newBD && oldBD) { + activeOffset = AttachmentPoint.EXTERNAL_TO_EXTERNAL_TIMEOUT; + } else if (newBD && !oldBD) { + activeOffset = AttachmentPoint.OPENFLOW_TO_EXTERNAL_TIMEOUT; + } + + // } else { + // // The attachment point is consistent. + // activeOffset = AttachmentPoint.CONSISTENT_TIMEOUT; + // } + + if ((newAP.getActiveSince() > oldAP.getLastSeen() + activeOffset) + || (newAP.getLastSeen() > oldAP.getLastSeen() + + AttachmentPoint.INACTIVITY_INTERVAL)) { + return -1; + } + return 1; + } + } + + /** + * Comparator for sorting by cluster ID + */ + public AttachmentPointComparator apComparator; + + /** + * Switch ports where attachment points shouldn't be learned + */ + private Set suppressAPs; + + /** + * Periodic task to clean up expired entities + */ + public SingletonTask entityCleanupTask; + + // ******************** + // Dependency injection + // ******************** + + void setDataPacketService(IDataPacketService s) { + this.dataPacketService = s; + } + + void unsetDataPacketService(IDataPacketService s) { + if (this.dataPacketService == s) { + this.dataPacketService = null; + } + } + + public void setTopologyManager(ITopologyManager s) { + this.topology = s; + } + + public void unsetTopologyManager(ITopologyManager s) { + if (this.topology == s) { + logger.debug("Topology Manager Service removed!"); + this.topology = null; + } + } + + private volatile boolean stopped = true; + private ScheduledExecutorService ses; + + public void stop() { + stopped = true; + if (ses != null) + ses.shutdownNow(); + } + + public void start() { + this.perClassIndices = new HashSet>(); + + // XXX - TODO need to make it possible to register a non-default + // classifier + entityClassifier = new DefaultEntityClassifier(); + this.deviceListeners = new ListenerDispatcher(); + this.suppressAPs = Collections + .newSetFromMap(new ConcurrentHashMap()); + primaryIndex = new DeviceUniqueIndex(entityClassifier.getKeyFields()); + secondaryIndexMap = new HashMap, DeviceIndex>(); + + deviceMap = new ConcurrentHashMap(); + classStateMap = new ConcurrentHashMap(); + apComparator = new AttachmentPointComparator(); + + addIndex(true, EnumSet.of(DeviceField.IPV4)); + + // floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this); + // floodlightProvider.addHAListener(this.haListenerDelegate); + // if (topology != null) + // topology.addListener(this); + // flowReconcileMgr.addFlowReconcileListener(this); + // entityClassifier.addListener(this); + + stopped = false; + // XXX - Should use a common threadpool but this doesn't currently exist + ses = Executors.newScheduledThreadPool(1); + Runnable ecr = new Runnable() { + @Override + public void run() { + cleanupEntities(); + if (!stopped) + entityCleanupTask.reschedule(ENTITY_CLEANUP_INTERVAL, + TimeUnit.SECONDS); + } + }; + entityCleanupTask = new SingletonTask(ses, ecr); + entityCleanupTask.reschedule(ENTITY_CLEANUP_INTERVAL, TimeUnit.SECONDS); + + /* + * XXX Missing functionality if (restApi != null) { + * restApi.addRestletRoutable(new DeviceRoutable()); } else { + * logger.debug("Could not instantiate REST API"); } + */ + + registerDeviceManagerDebugCounters(); + + /* + * XXX Missing functionality try { + * this.syncService.registerStore(DEVICE_SYNC_STORE_NAME, Scope.LOCAL); + * this.storeClient = this.syncService + * .getStoreClient(DEVICE_SYNC_STORE_NAME, String.class, + * DeviceSyncRepresentation.class); } catch (SyncException e) { throw + * new FloodlightModuleException("Error while setting up sync service", + * e); } + * + * Runnable consolidateStoreRunner = new Runnable() { + * + * @Override public void run() { deviceSyncManager.consolidateStore(); + * storeConsolidateTask.reschedule(syncStoreConsolidateIntervalMs, + * TimeUnit.MILLISECONDS); debugCounters.flushCounters(); } }; + * storeConsolidateTask = new SingletonTask(ses, + * consolidateStoreRunner); if (isMaster) + * storeConsolidateTask.reschedule(syncStoreConsolidateIntervalMs, + * TimeUnit.MILLISECONDS); + */ + } + + /** + * Periodic task to consolidate entries in the store. I.e., delete entries + * in the store that are not known to DeviceManager + */ + // XXX - Missing functionality + // private SingletonTask storeConsolidateTask; + + // ********************* + // IDeviceManagerService + // ********************* + + void setSwitchManager(ISwitchManager s) { + logger.debug("SwitchManager set"); + this.switchManager = s; + } + + void unsetSwitchManager(ISwitchManager s) { + if (this.switchManager == s) { + logger.debug("SwitchManager removed!"); + this.switchManager = null; + } + } + + @Override + public IDevice getDevice(Long deviceKey) { + return deviceMap.get(deviceKey); + } + + @Override + public IDevice findDevice(long macAddress, Short vlan, Integer ipv4Address, + NodeConnector port) throws IllegalArgumentException { + if (vlan != null && vlan.shortValue() <= 0) + vlan = null; + if (ipv4Address != null && ipv4Address == 0) + ipv4Address = null; + Entity e = new Entity(macAddress, vlan, ipv4Address, port, null); + if (!allKeyFieldsPresent(e, entityClassifier.getKeyFields())) { + throw new IllegalArgumentException("Not all key fields specified." + + " Required fields: " + entityClassifier.getKeyFields()); + } + return findDeviceByEntity(e); + } + + @Override + public IDevice findClassDevice(IEntityClass entityClass, long macAddress, + Short vlan, Integer ipv4Address) throws IllegalArgumentException { + if (vlan != null && vlan.shortValue() <= 0) + vlan = null; + if (ipv4Address != null && ipv4Address == 0) + ipv4Address = null; + Entity e = new Entity(macAddress, vlan, ipv4Address, null, null); + if (entityClass == null + || !allKeyFieldsPresent(e, entityClass.getKeyFields())) { + throw new IllegalArgumentException("Not all key fields and/or " + + " no source device specified. Required fields: " + + entityClassifier.getKeyFields()); + } + return findDestByEntity(entityClass, e); + } + + @Override + public Collection getAllDevices() { + return Collections.unmodifiableCollection(deviceMap.values()); + } + + @Override + public void addIndex(boolean perClass, EnumSet keyFields) { + if (perClass) { + perClassIndices.add(keyFields); + } else { + secondaryIndexMap.put(keyFields, new DeviceMultiIndex(keyFields)); + } + } + + @Override + public Iterator queryDevices(Long macAddress, + Short vlan, Integer ipv4Address, NodeConnector port) { + DeviceIndex index = null; + if (secondaryIndexMap.size() > 0) { + EnumSet keys = getEntityKeys(macAddress, vlan, + ipv4Address, port); + index = secondaryIndexMap.get(keys); + } + + Iterator deviceIterator = null; + if (index == null) { + // Do a full table scan + deviceIterator = deviceMap.values().iterator(); + } else { + // index lookup + Entity entity = new Entity((macAddress == null ? 0 : macAddress), + vlan, ipv4Address, port, null); + deviceIterator = new DeviceIndexInterator(this, + index.queryByEntity(entity)); + } + + DeviceIterator di = new DeviceIterator(deviceIterator, null, + macAddress, vlan, ipv4Address, port); + return di; + } + + @Override + public Iterator queryClassDevices( + IEntityClass entityClass, Long macAddress, Short vlan, + Integer ipv4Address, NodeConnector port) { + ArrayList> iterators = new ArrayList>(); + ClassState classState = getClassState(entityClass); + + DeviceIndex index = null; + if (classState.secondaryIndexMap.size() > 0) { + EnumSet keys = getEntityKeys(macAddress, vlan, + ipv4Address, port); + index = classState.secondaryIndexMap.get(keys); + } + + Iterator iter; + if (index == null) { + index = classState.classIndex; + if (index == null) { + // scan all devices + return new DeviceIterator(deviceMap.values().iterator(), + new IEntityClass[] { entityClass }, macAddress, vlan, + ipv4Address, port); + } else { + // scan the entire class + iter = new DeviceIndexInterator(this, index.getAll()); + } + } else { + // index lookup + Entity entity = new Entity((macAddress == null ? 0 : macAddress), + vlan, ipv4Address, port, null); + iter = new DeviceIndexInterator(this, index.queryByEntity(entity)); + } + iterators.add(iter); + + return new MultiIterator(iterators.iterator()); + } + + protected Iterator getDeviceIteratorForQuery(Long macAddress, + Short vlan, Integer ipv4Address, NodeConnector port) { + DeviceIndex index = null; + if (secondaryIndexMap.size() > 0) { + EnumSet keys = getEntityKeys(macAddress, vlan, + ipv4Address, port); + index = secondaryIndexMap.get(keys); + } + + Iterator deviceIterator = null; + if (index == null) { + // Do a full table scan + deviceIterator = deviceMap.values().iterator(); + } else { + // index lookup + Entity entity = new Entity((macAddress == null ? 0 : macAddress), + vlan, ipv4Address, port, null); + deviceIterator = new DeviceIndexInterator(this, + index.queryByEntity(entity)); + } + + DeviceIterator di = new DeviceIterator(deviceIterator, null, + macAddress, vlan, ipv4Address, port); + return di; + } + + @Override + public void addListener(IDeviceListener listener) { + deviceListeners.addListener("device", listener); + logListeners(); + } + + @Override + public void addSuppressAPs(NodeConnector port) { + suppressAPs.add(new SwitchPort(port)); + } + + @Override + public void removeSuppressAPs(NodeConnector port) { + suppressAPs.remove(new SwitchPort(port)); + } + + @Override + public Set getSuppressAPs() { + return Collections.unmodifiableSet(suppressAPs); + } + + private void logListeners() { + List listeners = deviceListeners.getOrderedListeners(); + if (listeners != null) { + StringBuffer sb = new StringBuffer(); + sb.append("DeviceListeners: "); + for (IDeviceListener l : listeners) { + sb.append(l.getName()); + sb.append(","); + } + logger.debug(sb.toString()); + } + } + + // *************** + // IFlowReconcileListener + // *************** + /* + * XXX - Missing functionality + * + * @Override public Command reconcileFlows(ArrayList + * ofmRcList) { ListIterator iter = + * ofmRcList.listIterator(); while (iter.hasNext()) { OFMatchReconcile ofm = + * iter.next(); + * + * // Remove the STOPPed flow. if (Command.STOP == reconcileFlow(ofm)) { + * iter.remove(); } } + * + * if (ofmRcList.size() > 0) { return Command.CONTINUE; } else { return + * Command.STOP; } } + * + * protected Command reconcileFlow(OFMatchReconcile ofm) { + * debugCounters.updateCounter(CNT_RECONCILE_REQUEST); // Extract source + * entity information Entity srcEntity = + * getEntityFromFlowMod(ofm.ofmWithSwDpid, true); if (srcEntity == null) { + * debugCounters.updateCounter(CNT_RECONCILE_NO_SOURCE); return + * Command.STOP; } + * + * // Find the device by source entity Device srcDevice = + * findDeviceByEntity(srcEntity); if (srcDevice == null) { + * debugCounters.updateCounter(CNT_RECONCILE_NO_SOURCE); return + * Command.STOP; } // Store the source device in the context + * fcStore.put(ofm.cntx, CONTEXT_SRC_DEVICE, srcDevice); + * + * // Find the device matching the destination from the entity // classes of + * the source. Entity dstEntity = getEntityFromFlowMod(ofm.ofmWithSwDpid, + * false); Device dstDevice = null; if (dstEntity != null) { dstDevice = + * findDestByEntity(srcDevice.getEntityClass(), dstEntity); if (dstDevice != + * null) fcStore.put(ofm.cntx, CONTEXT_DST_DEVICE, dstDevice); else + * debugCounters.updateCounter(CNT_RECONCILE_NO_DEST); } else { + * debugCounters.updateCounter(CNT_RECONCILE_NO_DEST); } if + * (logger.isTraceEnabled()) { + * logger.trace("Reconciling flow: match={}, srcEntity={}, srcDev={}, " + + * "dstEntity={}, dstDev={}", new Object[] {ofm.ofmWithSwDpid.getOfMatch(), + * srcEntity, srcDevice, dstEntity, dstDevice } ); } return + * Command.CONTINUE; } + */ + + // ***************** + // IListenDataPacket + // ***************** + + @Override + public PacketResult receiveDataPacket(RawPacket inPkt) { + // XXX - Can this really pass in null? Why would you ever want that? + if (inPkt == null) { + return PacketResult.IGNORED; + } + try { + throw new Exception("Sample"); + } catch (Exception e) { + logger.error("Sample stack trace", e); + } + + Packet formattedPak = this.dataPacketService.decodeDataPacket(inPkt); + Ethernet eth; + if (formattedPak instanceof Ethernet) { + eth = (Ethernet) formattedPak; + } else { + return PacketResult.IGNORED; + } + + // Extract source entity information + NodeConnector inPort = inPkt.getIncomingNodeConnector(); + Entity srcEntity = getSourceEntityFromPacket(eth, inPort); + if (srcEntity == null) { + // debugCounters.updateCounter(CNT_BROADCAST_SOURCE); + return PacketResult.CONSUME; + } + + // Learn from ARP packet for special VRRP settings. + // In VRRP settings, the source MAC address and sender MAC + // addresses can be different. In such cases, we need to learn + // the IP to MAC mapping of the VRRP IP address. The source + // entity will not have that information. Hence, a separate call + // to learn devices in such cases. + learnDeviceFromArpResponseData(eth, inPort); + + // Learn/lookup device information + Device srcDevice = learnDeviceByEntity(srcEntity); + if (srcDevice == null) { + // debugCounters.updateCounter(CNT_NO_SOURCE); + return PacketResult.CONSUME; + } + logger.trace("Saw packet from device {}", srcDevice); + + // // Store the source device in the context + // fcStore.put(cntx, CONTEXT_SRC_DEVICE, srcDevice); + // + // // Find the device matching the destination from the entity + // // classes of the source. + // Entity dstEntity = getDestEntityFromPacket(eth); + // Device dstDevice = null; + // if (dstEntity != null) { + // dstDevice = + // findDestByEntity(srcDevice.getEntityClass(), dstEntity); + // if (dstDevice != null) + // fcStore.put(cntx, CONTEXT_DST_DEVICE, dstDevice); + // //else + // //debugCounters.updateCounter(CNT_NO_DEST); + // } else { + // //debugCounters.updateCounter(CNT_NO_DEST); + // } + // + // if (logger.isTraceEnabled()) { + // logger.trace("Received PI: {} on switch {}, port {} *** eth={}" + + // " *** srcDev={} *** dstDev={} *** ", + // new Object[] { pi, sw.getStringId(), pi.getInPort(), eth, + // srcDevice, dstDevice }); + // } + // + // snoopDHCPClientName(eth, srcDevice); + + return PacketResult.KEEP_PROCESSING; + } + + // **************** + // Internal methods + // **************** + + /** + * Snoop and record client-provided host name from DHCP requests + * + * @param eth + * @param srcDevice + */ + // private void snoopDHCPClientName(Ethernet eth, Device srcDevice) { + // if (! (eth.getPayload() instanceof IPv4) ) + // return; + // IPv4 ipv4 = (IPv4) eth.getPayload(); + // if (! (ipv4.getPayload() instanceof UDP) ) + // return; + // UDP udp = (UDP) ipv4.getPayload(); + // if (!(udp.getPayload() instanceof DHCP)) + // return; + // DHCP dhcp = (DHCP) udp.getPayload(); + // byte opcode = dhcp.getOpCode(); + // if (opcode == DHCP.OPCODE_REQUEST) { + // DHCPOption dhcpOption = dhcp.getOption( + // DHCPOptionCode.OptionCode_Hostname); + // if (dhcpOption != null) { + // debugCounters.updateCounter(CNT_DHCP_CLIENT_NAME_SNOOPED); + // srcDevice.dhcpClientName = new String(dhcpOption.getData()); + // } + // } + // } + + /** + * Check whether the given attachment point is valid given the current + * topology + * + * @param switchDPID + * the DPID + * @param switchPort + * the port + * @return true if it's a valid attachment point + */ + public boolean isValidAttachmentPoint(NodeConnector port) { + // XXX - missing functionality -- need topology module + // if (topology.isAttachmentPointPort(port) == false) + // return false; + if (topology.isInternal(port)) + return false; + if (!switchManager.isNodeConnectorEnabled(port)) + return false; + if (suppressAPs.contains(new SwitchPort(port))) + return false; + + return true; + } + + /** + * Get sender IP address from packet if the packet is either an ARP packet. + * + * @param eth + * @param dlAddr + * @return + */ + private int getSrcNwAddr(Ethernet eth, long dlAddr) { + if (eth.getPayload() instanceof ARP) { + ARP arp = (ARP) eth.getPayload(); + if ((arp.getProtocolType() == ARP.PROTO_TYPE_IP) + && (toLong(arp.getSenderHardwareAddress()) == dlAddr)) { + return toIPv4Address(arp.getSenderProtocolAddress()); + } + } + return 0; + } + + /** + * Parse an entity from an {@link Ethernet} packet. + * + * @param eth + * the packet to parse + * @param sw + * the switch on which the packet arrived + * @param pi + * the original packetin + * @return the entity from the packet + */ + protected Entity getSourceEntityFromPacket(Ethernet eth, NodeConnector port) { + byte[] dlAddrArr = eth.getSourceMACAddress(); + long dlAddr = toLong(dlAddrArr); + + // Ignore broadcast/multicast source + if ((dlAddrArr[0] & 0x1) != 0) + return null; + + // XXX missing functionality + // short vlan = 0; + int nwSrc = getSrcNwAddr(eth, dlAddr); + return new Entity(dlAddr, null, ((nwSrc != 0) ? nwSrc : null), port, + new Date()); + } + + /** + * Learn device from ARP data in scenarios where the Ethernet source MAC is + * different from the sender hardware address in ARP data. + */ + protected void learnDeviceFromArpResponseData(Ethernet eth, + NodeConnector port) { + + if (!(eth.getPayload() instanceof ARP)) + return; + ARP arp = (ARP) eth.getPayload(); + + byte[] dlAddrArr = eth.getSourceMACAddress(); + long dlAddr = toLong(dlAddrArr); + + byte[] senderHardwareAddr = arp.getSenderHardwareAddress(); + long senderAddr = toLong(senderHardwareAddr); + + if (dlAddr == senderAddr) + return; + + // Ignore broadcast/multicast source + if ((senderHardwareAddr[0] & 0x1) != 0) + return; + + // short vlan = eth.getVlanID(); + int nwSrc = toIPv4Address(arp.getSenderProtocolAddress()); + + Entity e = new Entity(senderAddr, null, ((nwSrc != 0) ? nwSrc : null), + port, new Date()); + + learnDeviceByEntity(e); + } + + /** + * Get a (partial) entity for the destination from the packet. + * + * @param eth + * @return + */ + // protected Entity getDestEntityFromPacket(Ethernet eth) { + // byte[] dlAddrArr = eth.getDestinationMACAddress(); + // long dlAddr = Ethernet.toLong(dlAddrArr); + // short vlan = eth.getVlanID(); + // int nwDst = 0; + // + // // Ignore broadcast/multicast destination + // if ((dlAddrArr[0] & 0x1) != 0) + // return null; + // + // if (eth.getPayload() instanceof IPv4) { + // IPv4 ipv4 = (IPv4) eth.getPayload(); + // nwDst = ipv4.getDestinationAddress(); + // } + // + // return new Entity(dlAddr, + // ((vlan >= 0) ? vlan : null), + // ((nwDst != 0) ? nwDst : null), + // null, + // null, + // null); + // } + + /** + * Parse an entity from an OFMatchWithSwDpid. + * + * @param ofmWithSwDpid + * @return the entity from the packet + */ + // private Entity getEntityFromFlowMod(OFMatchWithSwDpid ofmWithSwDpid, + // boolean isSource) { + // byte[] dlAddrArr = ofmWithSwDpid.getOfMatch().getDataLayerSource(); + // int nwSrc = ofmWithSwDpid.getOfMatch().getNetworkSource(); + // if (!isSource) { + // dlAddrArr = ofmWithSwDpid.getOfMatch().getDataLayerDestination(); + // nwSrc = ofmWithSwDpid.getOfMatch().getNetworkDestination(); + // } + // + // long dlAddr = Ethernet.toLong(dlAddrArr); + // + // // Ignore broadcast/multicast source + // if ((dlAddrArr[0] & 0x1) != 0) + // return null; + // + // Long swDpid = null; + // Short inPort = null; + // + // if (isSource) { + // swDpid = ofmWithSwDpid.getSwitchDataPathId(); + // inPort = ofmWithSwDpid.getOfMatch().getInputPort(); + // } + // + // /**for the new flow cache design, the flow mods retrived are not always + // from the source, learn AP should be disabled --meiyang*/ + // boolean learnap = false; + // /** + // * if (swDpid == null || + // inPort == null || + // !isValidAttachmentPoint(swDpid, inPort)) { + // // If this is an internal port or we otherwise don't want + // // to learn on these ports. In the future, we should + // // handle this case by labeling flows with something that + // // will give us the entity class. For now, we'll do our + // // best assuming attachment point information isn't used + // // as a key field. + // learnap = false; + // } + // */ + // + // short vlan = ofmWithSwDpid.getOfMatch().getDataLayerVirtualLan(); + // return new Entity(dlAddr, + // ((vlan >= 0) ? vlan : null), + // ((nwSrc != 0) ? nwSrc : null), + // (learnap ? swDpid : null), + // (learnap ? (int)inPort : null), + // new Date()); + // } + + /** + * Look up a {@link Device} based on the provided {@link Entity}. We first + * check the primary index. If we do not find an entry there we classify the + * device into its IEntityClass and query the classIndex. This implies that + * all key field of the current IEntityClassifier must be present in the + * entity for the lookup to succeed! + * + * @param entity + * the entity to search for + * @return The {@link Device} object if found + */ + protected Device findDeviceByEntity(Entity entity) { + // Look up the fully-qualified entity to see if it already + // exists in the primary entity index. + Long deviceKey = primaryIndex.findByEntity(entity); + IEntityClass entityClass = null; + + if (deviceKey == null) { + // If the entity does not exist in the primary entity index, + // use the entity classifier for find the classes for the + // entity. Look up the entity in the returned class' + // class entity index. + entityClass = entityClassifier.classifyEntity(entity); + if (entityClass == null) { + return null; + } + ClassState classState = getClassState(entityClass); + + if (classState.classIndex != null) { + deviceKey = classState.classIndex.findByEntity(entity); + } + } + if (deviceKey == null) + return null; + return deviceMap.get(deviceKey); + } + + /** + * Get a destination device using entity fields that corresponds with the + * given source device. The source device is important since there could be + * ambiguity in the destination device without the attachment point + * information. + * + * @param reference + * the source device's entity class. The returned destination + * will be in the same entity class as the source. + * @param dstEntity + * the entity to look up + * @return an {@link Device} or null if no device is found. + */ + protected Device findDestByEntity(IEntityClass reference, Entity dstEntity) { + + // Look up the fully-qualified entity to see if it + // exists in the primary entity index + Long deviceKey = primaryIndex.findByEntity(dstEntity); + + if (deviceKey == null) { + // This could happen because: + // 1) no destination known, or a broadcast destination + // 2) if we have attachment point key fields since + // attachment point information isn't available for + // destination devices. + // For the second case, we'll need to match up the + // destination device with the class of the source + // device. + ClassState classState = getClassState(reference); + if (classState.classIndex == null) { + return null; + } + deviceKey = classState.classIndex.findByEntity(dstEntity); + } + if (deviceKey == null) + return null; + return deviceMap.get(deviceKey); + } + + /** + * Look up a {@link Device} within a particular entity class based on the + * provided {@link Entity}. + * + * @param clazz + * the entity class to search for the entity + * @param entity + * the entity to search for + * @return The {@link Device} object if found private Device + * findDeviceInClassByEntity(IEntityClass clazz, Entity entity) { // + * XXX - TODO throw new UnsupportedOperationException(); } + */ + + /** + * Look up a {@link Device} based on the provided {@link Entity}. Also + * learns based on the new entity, and will update existing devices as + * required. + * + * @param entity + * the {@link Entity} + * @return The {@link Device} object if found + */ + protected Device learnDeviceByEntity(Entity entity) { + logger.info("Primary index {}", primaryIndex); + ArrayList deleteQueue = null; + LinkedList deviceUpdates = null; + Device device = null; + + // we may need to restart the learning process if we detect + // concurrent modification. Note that we ensure that at least + // one thread should always succeed so we don't get into infinite + // starvation loops + while (true) { + deviceUpdates = null; + + // Look up the fully-qualified entity to see if it already + // exists in the primary entity index. + Long deviceKey = primaryIndex.findByEntity(entity); + IEntityClass entityClass = null; + + if (deviceKey == null) { + // If the entity does not exist in the primary entity index, + // use the entity classifier for find the classes for the + // entity. Look up the entity in the returned class' + // class entity index. + entityClass = entityClassifier.classifyEntity(entity); + if (entityClass == null) { + // could not classify entity. No device + device = null; + break; + } + ClassState classState = getClassState(entityClass); + + if (classState.classIndex != null) { + deviceKey = classState.classIndex.findByEntity(entity); + } + } + if (deviceKey != null) { + // If the primary or secondary index contains the entity + // use resulting device key to look up the device in the + // device map, and use the referenced Device below. + device = deviceMap.get(deviceKey); + if (device == null) { + // This can happen due to concurrent modification + if (logger.isDebugEnabled()) { + logger.debug("No device for deviceKey {} while " + + "while processing entity {}", deviceKey, + entity); + } + // if so, then try again till we don't even get the device + // key + // and so we recreate the device + continue; + } + } else { + // If the secondary index does not contain the entity, + // create a new Device object containing the entity, and + // generate a new device ID if the the entity is on an + // attachment point port. Otherwise ignore. + if (entity.hasSwitchPort() + && !isValidAttachmentPoint(entity.getPort())) { + // debugCounters.updateCounter(CNT_DEVICE_ON_INTERAL_PORT_NOT_LEARNED); + if (logger.isDebugEnabled()) { + logger.debug("Not learning new device on internal" + + " link: {}", entity); + } + device = null; + break; + } + // Before we create the new device also check if + // the entity is allowed (e.g., for spoofing protection) + if (!isEntityAllowed(entity, entityClass)) { + // debugCounters.updateCounter(CNT_PACKET_NOT_ALLOWED); + if (logger.isDebugEnabled()) { + logger.debug("PacketIn is not allowed {} {}", + entityClass.getName(), entity); + } + device = null; + break; + } + synchronized (deviceKeyLock) { + deviceKey = Long.valueOf(deviceKeyCounter++); + } + device = allocateDevice(deviceKey, entity, entityClass); + + // Add the new device to the primary map with a simple put + deviceMap.put(deviceKey, device); + + // update indices + if (!updateIndices(device, deviceKey)) { + if (deleteQueue == null) + deleteQueue = new ArrayList(); + deleteQueue.add(deviceKey); + continue; + } + + updateSecondaryIndices(entity, entityClass, deviceKey); + + // We need to count and log here. If we log earlier we could + // hit a concurrent modification and restart the dev creation + // and potentially count the device twice. + // debugCounters.updateCounter(CNT_NEW_DEVICE); + if (logger.isDebugEnabled()) { + logger.debug( + "New device created: {} deviceKey={}, entity={}", + new Object[] { device, deviceKey, entity }); + } + // generate new device update + deviceUpdates = updateUpdates(deviceUpdates, new DeviceUpdate( + device, ADD, null)); + + break; + } + // if it gets here, we have a pre-existing Device for this Entity + if (!isEntityAllowed(entity, device.getEntityClass())) { + // debugCounters.updateCounter(CNT_PACKET_NOT_ALLOWED); + if (logger.isDebugEnabled()) { + logger.info("PacketIn is not allowed {} {}", device + .getEntityClass().getName(), entity); + } + return null; + } + // If this is not an attachment point port we don't learn the new + // entity + // and don't update indexes. But we do allow the device to continue + // up + // the chain. + if (entity.hasSwitchPort() + && !isValidAttachmentPoint(entity.getPort())) { + // debugCounters.updateCounter(CNT_PACKET_ON_INTERNAL_PORT_FOR_KNOWN_DEVICE); + break; + } + int entityindex = -1; + if ((entityindex = device.entityIndex(entity)) >= 0) { + // Entity already exists + // update timestamp on the found entity + Date lastSeen = entity.getLastSeenTimestamp(); + if (lastSeen == null) { + lastSeen = new Date(); + entity.setLastSeenTimestamp(lastSeen); + } + device.entities[entityindex].setLastSeenTimestamp(lastSeen); + // we break the loop after checking for changes to the AP + } else { + // New entity for this device + // compute the insertion point for the entity. + // see Arrays.binarySearch() + entityindex = -(entityindex + 1); + Device newDevice = allocateDevice(device, entity, entityindex); + + // generate updates + EnumSet changedFields = findChangedFields(device, + entity); + + // update the device map with a replace call + boolean res = deviceMap.replace(deviceKey, device, newDevice); + // If replace returns false, restart the process from the + // beginning (this implies another thread concurrently + // modified this Device). + if (!res) + continue; + + device = newDevice; + // update indices + if (!updateIndices(device, deviceKey)) { + continue; + } + updateSecondaryIndices(entity, device.getEntityClass(), + deviceKey); + + // We need to count here after all the possible "continue" + // statements in this branch + // debugCounters.updateCounter(CNT_NEW_ENTITY); + if (changedFields.size() > 0) { + // debugCounters.updateCounter(CNT_DEVICE_CHANGED); + deviceUpdates = updateUpdates(deviceUpdates, + new DeviceUpdate(newDevice, CHANGE, changedFields)); + } + // we break the loop after checking for changed AP + } + // Update attachment point (will only be hit if the device + // already existed and no concurrent modification) + if (entity.hasSwitchPort()) { + boolean moved = device.updateAttachmentPoint(entity.getPort(), + entity.getLastSeenTimestamp().getTime()); + // TODO: use update mechanism instead of sending the + // notification directly + if (moved) { + // we count device moved events in + // sendDeviceMovedNotification() + sendDeviceMovedNotification(device); + if (logger.isTraceEnabled()) { + logger.trace("Device moved: attachment points {}," + + "entities {}", device.attachmentPoints, + device.entities); + } + } else { + if (logger.isTraceEnabled()) { + logger.trace("Device attachment point updated: " + + "attachment points {}," + "entities {}", + device.attachmentPoints, device.entities); + } + } + } + break; + } + + if (deleteQueue != null) { + for (Long l : deleteQueue) { + Device dev = deviceMap.get(l); + this.deleteDevice(dev); + } + } + + processUpdates(deviceUpdates); + // deviceSyncManager.storeDeviceThrottled(device); + + return device; + } + + protected boolean isEntityAllowed(Entity entity, IEntityClass entityClass) { + return true; + } + + protected EnumSet findChangedFields(Device device, + Entity newEntity) { + EnumSet changedFields = EnumSet.of(DeviceField.IPV4, + DeviceField.VLAN, DeviceField.SWITCHPORT); + + if (newEntity.getIpv4Address() == null) + changedFields.remove(DeviceField.IPV4); + if (newEntity.getVlan() == null) + changedFields.remove(DeviceField.VLAN); + if (newEntity.getPort() == null) + changedFields.remove(DeviceField.SWITCHPORT); + + if (changedFields.size() == 0) + return changedFields; + + for (Entity entity : device.getEntities()) { + if (newEntity.getIpv4Address() == null + || (entity.getIpv4Address() != null && entity + .getIpv4Address() + .equals(newEntity.getIpv4Address()))) + changedFields.remove(DeviceField.IPV4); + if (newEntity.getVlan() == null + || (entity.getVlan() != null && entity.getVlan().equals( + newEntity.getVlan()))) + changedFields.remove(DeviceField.VLAN); + if (newEntity.getPort() == null + || (entity.getPort() != null && entity.getPort().equals( + newEntity.getPort()))) + changedFields.remove(DeviceField.SWITCHPORT); + } + + return changedFields; + } + + /** + * Send update notifications to listeners + * + * @param updates + * the updates to process. + */ + protected void processUpdates(Queue updates) { + if (updates == null) + return; + DeviceUpdate update = null; + while (null != (update = updates.poll())) { + if (logger.isTraceEnabled()) { + logger.trace("Dispatching device update: {}", update); + } + // if (update.change == DeviceUpdate.Change.DELETE) + // deviceSyncManager.removeDevice(update.device); + // else + // deviceSyncManager.storeDevice(update.device); + List listeners = deviceListeners + .getOrderedListeners(); + notifyListeners(listeners, update); + } + } + + protected void notifyListeners(List listeners, + DeviceUpdate update) { + if (listeners == null) { + return; + } + for (IDeviceListener listener : listeners) { + switch (update.change) { + case ADD: + listener.deviceAdded(update.device); + break; + case DELETE: + listener.deviceRemoved(update.device); + break; + case CHANGE: + for (DeviceField field : update.fieldsChanged) { + switch (field) { + case IPV4: + listener.deviceIPV4AddrChanged(update.device); + break; + case SWITCHPORT: + // listener.deviceMoved(update.device); + break; + case VLAN: + listener.deviceVlanChanged(update.device); + break; + default: + logger.debug("Unknown device field changed {}", + update.fieldsChanged.toString()); + break; + } + } + break; + } + } + } + + /** + * Check if the entity e has all the keyFields set. Returns false if not + * + * @param e + * entity to check + * @param keyFields + * the key fields to check e against + * @return + */ + protected boolean allKeyFieldsPresent(Entity e, + EnumSet keyFields) { + for (DeviceField f : keyFields) { + switch (f) { + case MAC: + // MAC address is always present + break; + case IPV4: + if (e.getIpv4Address() == null) + return false; + break; + case SWITCHPORT: + if (e.getPort() == null) + return false; + break; + case VLAN: + // FIXME: vlan==null is ambiguous: it can mean: not present + // or untagged + // if (e.vlan == null) return false; + break; + default: + // we should never get here. unless somebody extended + // DeviceFields + throw new IllegalStateException(); + } + } + return true; + } + + private LinkedList updateUpdates( + LinkedList list, DeviceUpdate update) { + if (update == null) + return list; + if (list == null) + list = new LinkedList(); + list.add(update); + + return list; + } + + /** + * Get the secondary index for a class. Will return null if the secondary + * index was created concurrently in another thread. + * + * @param clazz + * the class for the index + * @return + */ + private ClassState getClassState(IEntityClass clazz) { + ClassState classState = classStateMap.get(clazz.getName()); + if (classState != null) + return classState; + + classState = new ClassState(clazz); + ClassState r = classStateMap.putIfAbsent(clazz.getName(), classState); + if (r != null) { + // concurrent add + return r; + } + return classState; + } + + /** + * Update both the primary and class indices for the provided device. If the + * update fails because of an concurrent update, will return false. + * + * @param device + * the device to update + * @param deviceKey + * the device key for the device + * @return true if the update succeeded, false otherwise. + */ + private boolean updateIndices(Device device, Long deviceKey) { + if (!primaryIndex.updateIndex(device, deviceKey)) { + return false; + } + IEntityClass entityClass = device.getEntityClass(); + ClassState classState = getClassState(entityClass); + + if (classState.classIndex != null) { + if (!classState.classIndex.updateIndex(device, deviceKey)) + return false; + } + return true; + } + + /** + * Update the secondary indices for the given entity and associated entity + * classes + * + * @param entity + * the entity to update + * @param entityClass + * the entity class for the entity + * @param deviceKey + * the device key to set up + */ + private void updateSecondaryIndices(Entity entity, + IEntityClass entityClass, Long deviceKey) { + for (DeviceIndex index : secondaryIndexMap.values()) { + index.updateIndex(entity, deviceKey); + } + ClassState state = getClassState(entityClass); + for (DeviceIndex index : state.secondaryIndexMap.values()) { + index.updateIndex(entity, deviceKey); + } + } + + /** + * Clean up expired entities/devices + */ + protected void cleanupEntities() { + // debugCounters.updateCounter(CNT_CLEANUP_ENTITIES_RUNS); + + Calendar c = Calendar.getInstance(); + c.add(Calendar.MILLISECOND, -ENTITY_TIMEOUT); + Date cutoff = c.getTime(); + + ArrayList toRemove = new ArrayList(); + ArrayList toKeep = new ArrayList(); + + Iterator diter = deviceMap.values().iterator(); + LinkedList deviceUpdates = new LinkedList(); + + while (diter.hasNext()) { + Device d = diter.next(); + + while (true) { + deviceUpdates.clear(); + toRemove.clear(); + toKeep.clear(); + for (Entity e : d.getEntities()) { + if (e.getLastSeenTimestamp() != null + && 0 > e.getLastSeenTimestamp().compareTo(cutoff)) { + // individual entity needs to be removed + toRemove.add(e); + } else { + toKeep.add(e); + } + } + if (toRemove.size() == 0) { + break; + } + + // debugCounters.updateCounter(CNT_ENTITY_REMOVED_TIMEOUT); + for (Entity e : toRemove) { + removeEntity(e, d.getEntityClass(), d.getDeviceKey(), + toKeep); + } + + if (toKeep.size() > 0) { + Device newDevice = allocateDevice(d.getDeviceKey(), + d.getDHCPClientName(), d.oldAPs, + d.attachmentPoints, toKeep, d.getEntityClass()); + + EnumSet changedFields = EnumSet + .noneOf(DeviceField.class); + for (Entity e : toRemove) { + changedFields.addAll(findChangedFields(newDevice, e)); + } + DeviceUpdate update = null; + if (changedFields.size() > 0) { + update = new DeviceUpdate(d, CHANGE, changedFields); + } + + if (!deviceMap.replace(newDevice.getDeviceKey(), d, + newDevice)) { + // concurrent modification; try again + // need to use device that is the map now for the next + // iteration + d = deviceMap.get(d.getDeviceKey()); + if (null != d) + continue; + } + if (update != null) { + // need to count after all possibly continue stmts in + // this branch + // debugCounters.updateCounter(CNT_DEVICE_CHANGED); + deviceUpdates.add(update); + } + } else { + DeviceUpdate update = new DeviceUpdate(d, DELETE, null); + if (!deviceMap.remove(d.getDeviceKey(), d)) { + // concurrent modification; try again + // need to use device that is the map now for the next + // iteration + d = deviceMap.get(d.getDeviceKey()); + if (null != d) + continue; + // debugCounters.updateCounter(CNT_DEVICE_DELETED); + } + deviceUpdates.add(update); + } + processUpdates(deviceUpdates); + break; + } + } + } + + protected void removeEntity(Entity removed, IEntityClass entityClass, + Long deviceKey, Collection others) { + // Don't count in this method. This method CAN BE called to clean-up + // after concurrent device adds/updates and thus counting here + // is misleading + for (DeviceIndex index : secondaryIndexMap.values()) { + index.removeEntityIfNeeded(removed, deviceKey, others); + } + ClassState classState = getClassState(entityClass); + for (DeviceIndex index : classState.secondaryIndexMap.values()) { + index.removeEntityIfNeeded(removed, deviceKey, others); + } + + primaryIndex.removeEntityIfNeeded(removed, deviceKey, others); + + if (classState.classIndex != null) { + classState.classIndex.removeEntityIfNeeded(removed, deviceKey, + others); + } + } + + /** + * method to delete a given device, remove all entities first and then + * finally delete the device itself. + * + * @param device + */ + protected void deleteDevice(Device device) { + // Don't count in this method. This method CAN BE called to clean-up + // after concurrent device adds/updates and thus counting here + // is misleading + ArrayList emptyToKeep = new ArrayList(); + for (Entity entity : device.getEntities()) { + this.removeEntity(entity, device.getEntityClass(), + device.getDeviceKey(), emptyToKeep); + } + if (!deviceMap.remove(device.getDeviceKey(), device)) { + if (logger.isDebugEnabled()) + logger.debug("device map does not have this device -" + + device.toString()); + } + } + + private EnumSet getEntityKeys(Long macAddress, Short vlan, + Integer ipv4Address, NodeConnector port) { + // FIXME: vlan==null is a valid search. Need to handle this + // case correctly. Note that the code will still work correctly. + // But we might do a full device search instead of using an index. + EnumSet keys = EnumSet.noneOf(DeviceField.class); + if (macAddress != null) + keys.add(DeviceField.MAC); + if (vlan != null) + keys.add(DeviceField.VLAN); + if (ipv4Address != null) + keys.add(DeviceField.IPV4); + if (port != null) + keys.add(DeviceField.SWITCHPORT); + return keys; + } + + protected Iterator queryClassByEntity(IEntityClass clazz, + EnumSet keyFields, Entity entity) { + ClassState classState = getClassState(clazz); + DeviceIndex index = classState.secondaryIndexMap.get(keyFields); + if (index == null) + return Collections. emptySet().iterator(); + return new DeviceIndexInterator(this, index.queryByEntity(entity)); + } + + protected Device allocateDevice(Long deviceKey, Entity entity, + IEntityClass entityClass) { + return new Device(this, deviceKey, entity, entityClass); + } + + // TODO: FIX THIS. + protected Device allocateDevice(Long deviceKey, String dhcpClientName, + List aps, List trueAPs, + Collection entities, IEntityClass entityClass) { + return new Device(this, deviceKey, dhcpClientName, aps, trueAPs, + entities, entityClass); + } + + protected Device allocateDevice(Device device, Entity entity, + int insertionpoint) { + return new Device(device, entity, insertionpoint); + } + + // not used + protected Device allocateDevice(Device device, Set entities) { + List newPossibleAPs = new ArrayList(); + List newAPs = new ArrayList(); + for (Entity entity : entities) { + if (entity.getPort() != null) { + AttachmentPoint aP = new AttachmentPoint(entity.getPort(), 0); + newPossibleAPs.add(aP); + } + } + if (device.attachmentPoints != null) { + for (AttachmentPoint oldAP : device.attachmentPoints) { + if (newPossibleAPs.contains(oldAP)) { + newAPs.add(oldAP); + } + } + } + if (newAPs.isEmpty()) + newAPs = null; + Device d = new Device(this, device.getDeviceKey(), + device.getDHCPClientName(), newAPs, null, entities, + device.getEntityClass()); + d.updateAttachmentPoint(); + return d; + } + + // ********************* + // ITopologyManagerAware + // ********************* + + @Override + public void edgeUpdate(List topoedgeupdateList) { + Iterator diter = deviceMap.values().iterator(); + + while (diter.hasNext()) { + Device d = diter.next(); + if (d.updateAttachmentPoint()) { + if (logger.isDebugEnabled()) { + logger.debug("Attachment point changed for device: {}", d); + } + sendDeviceMovedNotification(d); + } + } + } + + @Override + public void edgeOverUtilized(Edge edge) { + // nothing to do + } + + @Override + public void edgeUtilBackToNormal(Edge edge) { + // nothing to do + } + + // ********************* + // IEntityClassListener + // ********************* + + @Override + public void entityClassChanged(Set entityClassNames) { + /* + * iterate through the devices, reclassify the devices that belong to + * these entity class names + */ + Iterator diter = deviceMap.values().iterator(); + while (diter.hasNext()) { + Device d = diter.next(); + if (d.getEntityClass() == null + || entityClassNames.contains(d.getEntityClass().getName())) + reclassifyDevice(d); + } + } + + // ************* + // Local methods + // ************* + /** + * Send update notifications to listeners + * + * @param updates + * the updates to process. + */ + protected void sendDeviceMovedNotification(Device d) { + // debugCounters.updateCounter(CNT_DEVICE_MOVED); + // deviceSyncManager.storeDevice(d); + List listeners = deviceListeners.getOrderedListeners(); + if (listeners != null) { + for (IDeviceListener listener : listeners) { + listener.deviceMoved(d); + } + } + } + + /** + * this method will reclassify and reconcile a device - possibilities are - + * create new device(s), remove entities from this device. If the device + * entity class did not change then it returns false else true. + * + * @param device + */ + protected boolean reclassifyDevice(Device device) { + // first classify all entities of this device + if (device == null) { + logger.debug("In reclassify for null device"); + return false; + } + boolean needToReclassify = false; + for (Entity entity : device.entities) { + IEntityClass entityClass = this.entityClassifier + .classifyEntity(entity); + if (entityClass == null || device.getEntityClass() == null) { + needToReclassify = true; + break; + } + if (!entityClass.getName() + .equals(device.getEntityClass().getName())) { + needToReclassify = true; + break; + } + } + if (needToReclassify == false) { + return false; + } + + // debugCounters.updateCounter(CNT_DEVICE_RECLASSIFY_DELETE); + LinkedList deviceUpdates = new LinkedList(); + // delete this device and then re-learn all the entities + this.deleteDevice(device); + deviceUpdates.add(new DeviceUpdate(device, DeviceUpdate.Change.DELETE, + null)); + if (!deviceUpdates.isEmpty()) + processUpdates(deviceUpdates); + for (Entity entity : device.entities) { + this.learnDeviceByEntity(entity); + } + return true; + } + + /** + * For testing: sets the interval between writes of the same device to the + * device store. + * + * @param intervalMs + */ + // void setSyncStoreWriteInterval(int intervalMs) { + // this.syncStoreWriteIntervalMs = intervalMs; + // } + + /** + * For testing: sets the time between transition to MASTER and consolidate + * store + * + * @param intervalMs + */ + // void setInitialSyncStoreConsolidateMs(int intervalMs) { + // this.initialSyncStoreConsolidateMs = intervalMs; + // } + + private long toLong(byte[] address) { + long mac = 0; + for (int i = 0; i < 6; i++) { + long t = (address[i] & 0xffL) << ((5 - i) * 8); + mac |= t; + } + return mac; + } + + /** + * Accepts an IPv4 address in a byte array and returns the corresponding + * 32-bit integer value. + * + * @param ipAddress + * @return + */ + private static int toIPv4Address(byte[] ipAddress) { + int ip = 0; + for (int i = 0; i < 4; i++) { + int t = (ipAddress[i] & 0xff) << ((3 - i) * 8); + ip |= t; + } + return ip; + } + + private void registerDeviceManagerDebugCounters() { + /* + * XXX Missing functionality if (debugCounters == null) { + * logger.error("Debug Counter Service not found."); debugCounters = new + * NullDebugCounter(); return; } + * debugCounters.registerCounter(CNT_INCOMING, + * "All incoming packets seen by this module", + * CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_RECONCILE_REQUEST, + * "Number of flows that have been received for reconciliation by " + + * "this module", CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_RECONCILE_NO_SOURCE, + * "Number of flow reconcile events that failed because no source " + + * "device could be identified", CounterType.WARN); // is this really a + * warning debugCounters.registerCounter(CNT_RECONCILE_NO_DEST, + * "Number of flow reconcile events that failed because no " + + * "destination device could be identified", CounterType.WARN); // is + * this really a warning + * debugCounters.registerCounter(CNT_BROADCAST_SOURCE, + * "Number of packetIns that were discarded because the source " + + * "MAC was broadcast or multicast", CounterType.WARN); + * debugCounters.registerCounter(CNT_NO_SOURCE, + * "Number of packetIns that were discarded because the " + + * "could not identify a source device. This can happen if a " + + * "packet is not allowed, appears on an illegal port, does not " + + * "have a valid address space, etc.", CounterType.WARN); + * debugCounters.registerCounter(CNT_NO_DEST, + * "Number of packetIns that did not have an associated " + + * "destination device. E.g., because the destination MAC is " + + * "broadcast/multicast or is not yet known to the controller.", + * CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_DHCP_CLIENT_NAME_SNOOPED, + * "Number of times a DHCP client name was snooped from a " + + * "packetIn.", CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_DEVICE_ON_INTERAL_PORT_NOT_LEARNED, + * "Number of times packetIn was received on an internal port and" + + * "no source device is known for the source MAC. The packetIn is " + + * "discarded.", CounterType.WARN); + * debugCounters.registerCounter(CNT_PACKET_NOT_ALLOWED, + * "Number of times a packetIn was not allowed due to spoofing " + + * "protection configuration.", CounterType.WARN); // is this really a + * warning? debugCounters.registerCounter(CNT_NEW_DEVICE, + * "Number of times a new device was learned", + * CounterType.ALWAYS_COUNT); debugCounters.registerCounter( + * CNT_PACKET_ON_INTERNAL_PORT_FOR_KNOWN_DEVICE, + * "Number of times a packetIn was received on an internal port " + + * "for a known device.", CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_NEW_ENTITY, + * "Number of times a new entity was learned for an existing device", + * CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_DEVICE_CHANGED, + * "Number of times device properties have changed", + * CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_DEVICE_MOVED, + * "Number of times devices have moved", CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_CLEANUP_ENTITIES_RUNS, + * "Number of times the entity cleanup task has been run", + * CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_ENTITY_REMOVED_TIMEOUT, + * "Number of times entities have been removed due to timeout " + + * "(entity has been inactive for " + ENTITY_TIMEOUT/1000 + "s)", + * CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_DEVICE_DELETED, + * "Number of devices that have been removed due to inactivity", + * CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_DEVICE_RECLASSIFY_DELETE, + * "Number of devices that required reclassification and have been " + + * "temporarily delete for reclassification", CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_DEVICE_STORED, + * "Number of device entries written or updated to the sync store", + * CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_DEVICE_STORE_THROTTLED, + * "Number of times a device update to the sync store was " + + * "requested but not performed because the same device entities " + + * "have recently been updated already", CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_DEVICE_REMOVED_FROM_STORE, + * "Number of devices that were removed from the sync store " + + * "because the local controller removed the device due to " + + * "inactivity", CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_SYNC_EXCEPTION, + * "Number of times an operation on the sync store resulted in " + + * "sync exception", CounterType.WARN); // it this an error? + * debugCounters.registerCounter(CNT_DEVICES_FROM_STORE, + * "Number of devices that were read from the sync store after " + + * "the local controller transitioned from SLAVE to MASTER", + * CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_CONSOLIDATE_STORE_RUNS, + * "Number of times the task to consolidate entries in the " + + * "store witch live known devices has been run", + * CounterType.ALWAYS_COUNT); + * debugCounters.registerCounter(CNT_CONSOLIDATE_STORE_DEVICES_REMOVED, + * "Number of times a device has been removed from the sync " + + * "store because no corresponding live device is known. " + + * "This indicates a remote controller still writing device " + + * "entries despite the local controller being MASTER or an " + + * "incosistent store update from the local controller.", + * CounterType.WARN); + * debugCounters.registerCounter(CNT_TRANSITION_TO_MASTER, + * "Number of times this controller has transitioned from SLAVE " + + * "to MASTER role. Will be 0 or 1.", CounterType.ALWAYS_COUNT); + */ + } + + @Override + public HostNodeConnector hostFind(InetAddress networkAddress) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HostNodeConnector hostQuery(InetAddress networkAddress) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Future discoverHost(InetAddress networkAddress) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List> getHostNetworkHierarchy(InetAddress hostAddress) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getAllHosts() { + Collection devices = Collections + .unmodifiableCollection(deviceMap.values()); + Iterator i = devices.iterator(); + Set nc = new HashSet(); + while (i.hasNext()) { + Device device = i.next(); + nc.add(device.toHostNodeConnector()); + } + return nc; + } + + @Override + public Set getActiveStaticHosts() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getInactiveStaticHosts() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Status addStaticHost(String networkAddress, String dataLayerAddress, + NodeConnector nc, String vlan) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Status removeStaticHost(String networkAddress) { + // TODO Auto-generated method stub + return null; + } + + /** + * For testing: consolidate the store NOW + */ + // void scheduleConsolidateStoreNow() { + // this.storeConsolidateTask.reschedule(0, TimeUnit.MILLISECONDS); + // } + + // private class DeviceSyncManager { + // // maps (opaque) deviceKey to the time in System.nanoTime() when we + // // last wrote the device to the sync store + // private ConcurrentMap lastWriteTimes = + // new ConcurrentHashMap(); + // + // /** + // * Write the given device to storage if we are MASTER. + // * Use this method if the device has significantly changed (e.g., + // * new AP, new IP, entities removed). + // * @param d the device to store + // */ + // public void storeDevice(Device d) { + // if (!isMaster) + // return; + // if (d == null) + // return; + // long now = System.nanoTime(); + // writeUpdatedDeviceToStorage(d); + // lastWriteTimes.put(d.getDeviceKey(), now); + // } + // + // /** + // * Write the given device to storage if we are MASTER and if the + // * last write for the device was more than this.syncStoreIntervalNs + // * time ago. + // * Use this method to updated last active times in the store. + // * @param d the device to store + // */ + // public void storeDeviceThrottled(Device d) { + // long intervalNs = syncStoreWriteIntervalMs*1000L*1000L; + // if (!isMaster) + // return; + // if (d == null) + // return; + // long now = System.nanoTime(); + // Long last = lastWriteTimes.get(d.getDeviceKey()); + // if (last == null || + // now - last > intervalNs) { + // writeUpdatedDeviceToStorage(d); + // lastWriteTimes.put(d.getDeviceKey(), now); + // } else { + // debugCounters.updateCounter(CNT_DEVICE_STORE_THROTTLED); + // } + // } + // + // /** + // * Remove the given device from the store. If only some entities have + // * been removed the updated device should be written using + // * {@link #storeDevice(Device)} + // * @param d + // */ + // public void removeDevice(Device d) { + // if (!isMaster) + // return; + // // FIXME: could we have a problem with concurrent put to the + // // hashMap? I.e., we write a stale entry to the map after the + // // delete and now are left with an entry we'll never clean up + // lastWriteTimes.remove(d.getDeviceKey()); + // try { + // // TODO: should probably do versioned delete. OTOH, even + // // if we accidentally delete, we'll write it again after + // // the next entity .... + // debugCounters.updateCounter(CNT_DEVICE_REMOVED_FROM_STORE); + // storeClient.delete(DeviceSyncRepresentation.computeKey(d)); + // } catch(ObsoleteVersionException e) { + // // FIXME + // } catch (SyncException e) { + // debugCounters.updateCounter(CNT_SYNC_EXCEPTION); + // logger.error("Could not remove device " + d + " from store", e); + // } + // } + // + // /** + // * Remove the given Versioned device from the store. If the device + // * was locally modified ignore the delete request. + // * @param syncedDeviceKey + // */ + // private void removeDevice(Versioned dev) { + // try { + // debugCounters.updateCounter(CNT_DEVICE_REMOVED_FROM_STORE); + // storeClient.delete(dev.getValue().getKey(), + // dev.getVersion()); + // } catch(ObsoleteVersionException e) { + // // Key was locally modified by another thread. + // // Do not delete and ignore. + // } catch(SyncException e) { + // debugCounters.updateCounter(CNT_SYNC_EXCEPTION); + // logger.error("Failed to remove device entry for " + + // dev.toString() + " from store.", e); + // } + // } + // + // /** + // * Synchronously transition from SLAVE to MASTER. By iterating through + // * the store and learning all devices from the store + // */ + // private void goToMaster() { + // if (logger.isDebugEnabled()) { + // logger.debug("Transitioning to MASTER role"); + // } + // debugCounters.updateCounter(CNT_TRANSITION_TO_MASTER); + // IClosableIterator>> + // iter = null; + // try { + // iter = storeClient.entries(); + // } catch (SyncException e) { + // debugCounters.updateCounter(CNT_SYNC_EXCEPTION); + // logger.error("Failed to read devices from sync store", e); + // return; + // } + // try { + // while(iter.hasNext()) { + // Versioned versionedDevice = + // iter.next().getValue(); + // DeviceSyncRepresentation storedDevice = + // versionedDevice.getValue(); + // if (storedDevice == null) + // continue; + // debugCounters.updateCounter(CNT_DEVICES_FROM_STORE); + // for(SyncEntity se: storedDevice.getEntities()) { + // learnDeviceByEntity(se.asEntity()); + // } + // } + // } finally { + // if (iter != null) + // iter.close(); + // } + // storeConsolidateTask.reschedule(initialSyncStoreConsolidateMs, + // TimeUnit.MILLISECONDS); + // } + // + // /** + // * Actually perform the write of the device to the store + // * FIXME: concurrent modification behavior + // * @param device The device to write + // */ + // private void writeUpdatedDeviceToStorage(Device device) { + // try { + // debugCounters.updateCounter(CNT_DEVICE_STORED); + // // FIXME: use a versioned put + // DeviceSyncRepresentation storeDevice = + // new DeviceSyncRepresentation(device); + // storeClient.put(storeDevice.getKey(), storeDevice); + // } catch (ObsoleteVersionException e) { + // // FIXME: what's the right behavior here. Can the store client + // // even throw this error? + // } catch (SyncException e) { + // debugCounters.updateCounter(CNT_SYNC_EXCEPTION); + // logger.error("Could not write device " + device + + // " to sync store:", e); + // } + // } + // + // /** + // * Iterate through all entries in the sync store. For each device + // * in the store check if any stored entity matches a live device. If + // * no entities match a live device we remove the entry from the store. + // * + // * Note: we do not check if all devices known to device manager are + // * in the store. We rely on regular packetIns for that. + // * Note: it's possible that multiple entries in the store map to the + // * same device. We don't check or handle this case. + // * + // * We need to perform this check after a SLAVE->MASTER transition to + // * get rid of all entries the old master might have written to the + // * store after we took over. We also run it regularly in MASTER + // * state to ensure we don't have stale entries in the store + // */ + // private void consolidateStore() { + // if (!isMaster) + // return; + // debugCounters.updateCounter(CNT_CONSOLIDATE_STORE_RUNS); + // if (logger.isDebugEnabled()) { + // logger.debug("Running consolidateStore."); + // } + // IClosableIterator>> + // iter = null; + // try { + // iter = storeClient.entries(); + // } catch (SyncException e) { + // debugCounters.updateCounter(CNT_SYNC_EXCEPTION); + // logger.error("Failed to read devices from sync store", e); + // return; + // } + // try { + // while(iter.hasNext()) { + // boolean found = false; + // Versioned versionedDevice = + // iter.next().getValue(); + // DeviceSyncRepresentation storedDevice = + // versionedDevice.getValue(); + // if (storedDevice == null) + // continue; + // for(SyncEntity se: storedDevice.getEntities()) { + // try { + // // Do we have a device for this entity?? + // IDevice d = findDevice(se.macAddress, se.vlan, + // se.ipv4Address, + // se.switchDPID, + // se.switchPort); + // if (d != null) { + // found = true; + // break; + // } + // } catch (IllegalArgumentException e) { + // // not all key fields provided. Skip entity + // } + // } + // if (!found) { + // // We currently DO NOT have a live device that + // // matches the current device from the store. + // // Delete device from store. + // if (logger.isDebugEnabled()) { + // logger.debug("Removing device {} from store. No " + // + "corresponding live device", + // storedDevice.getKey()); + // } + // debugCounters.updateCounter(CNT_CONSOLIDATE_STORE_DEVICES_REMOVED); + // removeDevice(versionedDevice); + // } + // } + // } finally { + // if (iter != null) + // iter.close(); + // } + // } + // } + // + // + // /** + // * For testing. Sets the syncService. Only call after init but before + // * startUp. Used by MockDeviceManager + // * @param syncService + // */ + // protected void setSyncServiceIfNotSet(ISyncService syncService) { + // if (this.syncService == null) + // this.syncService = syncService; + // } +} diff --git a/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceMultiIndex.java b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceMultiIndex.java new file mode 100644 index 0000000000..85cb094874 --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceMultiIndex.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker.internal; + +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.opendaylight.controller.hosttracker.Entity; +import org.opendaylight.controller.hosttracker.IDeviceService.DeviceField; +import org.opendaylight.controller.sal.utils.IterableIterator; + +/** + * An index that maps key fields of an entity to device keys, with multiple + * device keys allowed per entity + */ +public class DeviceMultiIndex extends DeviceIndex { + /** + * The index + */ + private ConcurrentHashMap> index; + + /** + * @param keyFields + */ + public DeviceMultiIndex(EnumSet keyFields) { + super(keyFields); + index = new ConcurrentHashMap>(); + } + + // *********** + // DeviceIndex + // *********** + + @Override + public Iterator queryByEntity(Entity entity) { + IndexedEntity ie = new IndexedEntity(keyFields, entity); + Collection devices = index.get(ie); + if (devices != null) + return devices.iterator(); + + return Collections. emptySet().iterator(); + } + + @Override + public Iterator getAll() { + Iterator> iter = index.values().iterator(); + return new IterableIterator(iter); + } + + @Override + public boolean updateIndex(Device device, Long deviceKey) { + for (Entity e : device.entities) { + updateIndex(e, deviceKey); + } + return true; + } + + @Override + public void updateIndex(Entity entity, Long deviceKey) { + Collection devices = null; + + IndexedEntity ie = new IndexedEntity(keyFields, entity); + if (!ie.hasNonNullKeys()) + return; + + devices = index.get(ie); + if (devices == null) { + Map chm = new ConcurrentHashMap(); + devices = Collections.newSetFromMap(chm); + Collection r = index.putIfAbsent(ie, devices); + if (r != null) + devices = r; + } + + devices.add(deviceKey); + } + + @Override + public void removeEntity(Entity entity) { + IndexedEntity ie = new IndexedEntity(keyFields, entity); + index.remove(ie); + } + + @Override + public void removeEntity(Entity entity, Long deviceKey) { + IndexedEntity ie = new IndexedEntity(keyFields, entity); + Collection devices = index.get(ie); + if (devices != null) + devices.remove(deviceKey); + } +} diff --git a/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceUniqueIndex.java b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceUniqueIndex.java new file mode 100644 index 0000000000..6ca0556292 --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceUniqueIndex.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker.internal; + +import java.util.Collections; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.concurrent.ConcurrentHashMap; + +import org.opendaylight.controller.hosttracker.Entity; +import org.opendaylight.controller.hosttracker.IDeviceService; + +/** + * An index that maps key fields of an entity uniquely to a device key + */ +public class DeviceUniqueIndex extends DeviceIndex { + /** + * The index + */ + private final ConcurrentHashMap index; + + /** + * Construct a new device index using the provided key fields + * + * @param keyFields + * the key fields to use + */ + public DeviceUniqueIndex(EnumSet keyFields) { + super(keyFields); + index = new ConcurrentHashMap(); + } + + // *********** + // DeviceIndex + // *********** + + @Override + public Iterator queryByEntity(Entity entity) { + final Long deviceKey = findByEntity(entity); + if (deviceKey != null) + return Collections. singleton(deviceKey).iterator(); + + return Collections. emptySet().iterator(); + } + + @Override + public Iterator getAll() { + return index.values().iterator(); + } + + @Override + public boolean updateIndex(Device device, Long deviceKey) { + for (Entity e : device.entities) { + IndexedEntity ie = new IndexedEntity(keyFields, e); + if (!ie.hasNonNullKeys()) + continue; + + Long ret = index.putIfAbsent(ie, deviceKey); + if (ret != null && !ret.equals(deviceKey)) { + // If the return value is non-null, then fail the insert + // (this implies that a device using this entity has + // already been created in another thread). + return false; + } + } + return true; + } + + @Override + public void updateIndex(Entity entity, Long deviceKey) { + IndexedEntity ie = new IndexedEntity(keyFields, entity); + if (!ie.hasNonNullKeys()) + return; + index.put(ie, deviceKey); + } + + @Override + public void removeEntity(Entity entity) { + IndexedEntity ie = new IndexedEntity(keyFields, entity); + index.remove(ie); + } + + @Override + public void removeEntity(Entity entity, Long deviceKey) { + IndexedEntity ie = new IndexedEntity(keyFields, entity); + index.remove(ie, deviceKey); + } + + // ************** + // Public Methods + // ************** + + /** + * Look up a {@link Device} based on the provided {@link Entity}. + * + * @param entity + * the entity to search for + * @return The key for the {@link Device} object if found + */ + public Long findByEntity(Entity entity) { + IndexedEntity ie = new IndexedEntity(keyFields, entity); + Long deviceKey = index.get(ie); + if (deviceKey == null) + return null; + return deviceKey; + } + +} diff --git a/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/IndexedEntity.java b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/IndexedEntity.java new file mode 100644 index 0000000000..fa9fad881c --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/IndexedEntity.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2013 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker.internal; + +import java.util.EnumSet; + +import org.opendaylight.controller.hosttracker.Entity; +import org.opendaylight.controller.hosttracker.IDeviceService; +import org.opendaylight.controller.hosttracker.IDeviceService.DeviceField; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This is a thin wrapper around {@link Entity} that allows overriding the + * behavior of {@link Object#hashCode()} and {@link Object#equals(Object)} so + * that the keying behavior in a hash map can be changed dynamically + * + * @author readams + */ +public class IndexedEntity { + protected EnumSet keyFields; + protected Entity entity; + private int hashCode = 0; + protected static Logger logger = LoggerFactory + .getLogger(IndexedEntity.class); + + /** + * Create a new {@link IndexedEntity} for the given {@link Entity} using the + * provided key fields. + * + * @param keyFields + * The key fields that will be used for computing + * {@link IndexedEntity#hashCode()} and + * {@link IndexedEntity#equals(Object)} + * @param entity + * the entity to wrap + */ + public IndexedEntity(EnumSet keyFields, Entity entity) { + super(); + this.keyFields = keyFields; + this.entity = entity; + } + + /** + * Check whether this entity has non-null values in any of its key fields + * + * @return true if any key fields have a non-null value + */ + public boolean hasNonNullKeys() { + for (DeviceField f : keyFields) { + switch (f) { + case MAC: + return true; + case IPV4: + if (entity.getIpv4Address() != null) + return true; + break; + case SWITCHPORT: + if (entity.getPort() != null) + return true; + break; + case VLAN: + if (entity.getVlan() != null) + return true; + break; + } + } + return false; + } + + @Override + public int hashCode() { + + if (hashCode != 0) { + return hashCode; + } + + final int prime = 31; + hashCode = 1; + for (DeviceField f : keyFields) { + switch (f) { + case MAC: + hashCode = prime + * hashCode + + (int) (entity.getMacAddress() ^ (entity + .getMacAddress() >>> 32)); + break; + case IPV4: + hashCode = prime + * hashCode + + ((entity.getIpv4Address() == null) ? 0 : entity + .getIpv4Address().hashCode()); + break; + case SWITCHPORT: + hashCode = prime + * hashCode + + ((entity.getPort() == null) ? 0 : entity.getPort() + .hashCode()); + break; + case VLAN: + hashCode = prime + * hashCode + + ((entity.getVlan() == null) ? 0 : entity.getVlan() + .hashCode()); + break; + } + } + return hashCode; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + IndexedEntity other = (IndexedEntity) obj; + + if (!keyFields.equals(other.keyFields)) + return false; + + for (IDeviceService.DeviceField f : keyFields) { + switch (f) { + case MAC: + if (entity.getMacAddress() != other.entity.getMacAddress()) + return false; + break; + case IPV4: + if (entity.getIpv4Address() == null) { + if (other.entity.getIpv4Address() != null) + return false; + } else if (!entity.getIpv4Address().equals( + other.entity.getIpv4Address())) + return false; + break; + case SWITCHPORT: + if (entity.getPort() == null) { + if (other.entity.getPort() != null) + return false; + } else if (!entity.getPort().equals(other.entity.getPort())) + return false; + break; + case VLAN: + if (entity.getVlan() == null) { + if (other.entity.getVlan() != null) + return false; + } else if (!entity.getVlan().equals(other.entity.getVlan())) + return false; + break; + } + } + + return true; + } + +} diff --git a/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/internal/DeviceManagerImplTest.java b/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/internal/DeviceManagerImplTest.java new file mode 100644 index 0000000000..3bed3a513a --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/internal/DeviceManagerImplTest.java @@ -0,0 +1,2644 @@ +package org.opendaylight.controller.hosttracker.internal; + +///* +// * Copyright (c) 2011,2013 Big Switch Networks, Inc. +// * +// * Licensed under the Eclipse Public License, Version 1.0 (the +// * "License"); you may not use this file except in compliance with the +// * License. You may obtain a copy of the License at +// * +// * http://www.eclipse.org/legal/epl-v10.html +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// * implied. See the License for the specific language governing +// * permissions and limitations under the License. +// * +// * This file incorporates work covered by the following copyright and +// * permission notice: +// * +// * Originally created by David Erickson, Stanford University +// * +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the +// * License. You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, +// * software distributed under the License is distributed on an "AS +// * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +// * express or implied. See the License for the specific language +// * governing permissions and limitations under the License. +// */ +// +//package org.opendaylight.controller.hosttracker.internal; +// +//import static org.easymock.EasyMock.anyLong; +//import static org.easymock.EasyMock.anyObject; +//import static org.easymock.EasyMock.anyShort; +//import static org.easymock.EasyMock.createMock; +//import static org.easymock.EasyMock.createNiceMock; +//import static org.easymock.EasyMock.eq; +//import static org.easymock.EasyMock.expect; +//import static org.easymock.EasyMock.expectLastCall; +//import static org.easymock.EasyMock.isA; +//import static org.easymock.EasyMock.or; +//import static org.easymock.EasyMock.replay; +//import static org.easymock.EasyMock.reset; +//import static org.easymock.EasyMock.verify; +//import static org.junit.Assert.*; +// +//import java.util.ArrayList; +//import java.util.Arrays; +//import java.util.Calendar; +//import java.util.Collection; +//import java.util.Collections; +//import java.util.Date; +//import java.util.EnumSet; +//import java.util.HashMap; +//import java.util.HashSet; +//import java.util.Iterator; +//import java.util.List; +//import java.util.Map; +//import java.util.Map.Entry; +//import java.util.Set; +//import java.util.concurrent.ConcurrentHashMap; +// +//import org.junit.Before; +//import org.junit.Test; +// +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +// +//public class DeviceManagerImplTest { +// +// protected static Logger logger = +// LoggerFactory.getLogger(DeviceManagerImplTest.class); +// +// protected OFPacketIn packetIn_1, packetIn_2, packetIn_3; +// protected IPacket testARPReplyPacket_1, testARPReplyPacket_2, +// testARPReplyPacket_3; +// protected IPacket testARPReqPacket_1, testARPReqPacket_2; +// protected byte[] testARPReplyPacket_1_Srld, testARPReplyPacket_2_Srld; +// private MockSyncService syncService; +// private IStoreClient storeClient; +// +// DeviceManagerImpl deviceManager; +// MemoryStorageSource storageSource; +// FlowReconcileManager flowReconcileMgr; +// +// private IOFSwitch makeSwitchMock(long id) { +// IOFSwitch mockSwitch = createMock(IOFSwitch.class); +// ImmutablePort port = ImmutablePort.create("p1", (short)1); +// expect(mockSwitch.getId()).andReturn(id).anyTimes(); +// expect(mockSwitch.getStringId()) +// .andReturn(HexString.toHexString(id, 6)).anyTimes(); +// expect(mockSwitch.getPort(anyShort())) +// .andReturn(port).anyTimes(); +// return mockSwitch; +// } +// +// /* +// * return an EasyMock ITopologyService that's setup so that it will +// * answer all questions a device or device manager will ask +// * (isAttachmentPointPort, etc.) in a way so that every port is a +// * non-BD, attachment point port. +// * The returned mock is still in record mode +// */ +// private ITopologyService makeMockTopologyAllPortsAp() { +// ITopologyService mockTopology = createMock(ITopologyService.class); +// mockTopology.isAttachmentPointPort(anyLong(), anyShort()); +// expectLastCall().andReturn(true).anyTimes(); +// mockTopology.getL2DomainId(anyLong()); +// expectLastCall().andReturn(1L).anyTimes(); +// mockTopology.isBroadcastDomainPort(anyLong(), anyShort()); +// expectLastCall().andReturn(false).anyTimes(); +// mockTopology.isConsistent(anyLong(), anyShort(), anyLong(), anyShort()); +// expectLastCall().andReturn(false).anyTimes(); +// mockTopology.isInSameBroadcastDomain(anyLong(), anyShort(), +// anyLong(), anyShort()); +// expectLastCall().andReturn(false).anyTimes(); +// return mockTopology; +// } +// +// @Override +// @Before +// public void setUp() throws Exception { +// doSetUp(Role.MASTER); +// } +// +// public void doSetUp(Role initialRole) throws Exception { +// super.setUp(); +// +// this.syncService = new MockSyncService(); +// +// FloodlightModuleContext fmc = new FloodlightModuleContext(); +// RestApiServer restApi = new RestApiServer(); +// MockThreadPoolService tp = new MockThreadPoolService(); +// ITopologyService topology = createMock(ITopologyService.class); +// fmc.addService(IThreadPoolService.class, tp); +// mockFloodlightProvider = getMockFloodlightProvider(); +// mockFloodlightProvider.setRole(initialRole, ""); +// +// deviceManager = new DeviceManagerImpl(); +// flowReconcileMgr = new FlowReconcileManager(); +// DefaultEntityClassifier entityClassifier = new DefaultEntityClassifier(); +// fmc.addService(IDeviceService.class, deviceManager); +// storageSource = new MemoryStorageSource(); +// fmc.addService(IStorageSourceService.class, storageSource); +// fmc.addService(IFloodlightProviderService.class, mockFloodlightProvider); +// fmc.addService(IRestApiService.class, restApi); +// fmc.addService(IFlowReconcileService.class, flowReconcileMgr); +// fmc.addService(IEntityClassifierService.class, entityClassifier); +// fmc.addService(ITopologyService.class, topology); +// fmc.addService(ISyncService.class, syncService); +// tp.init(fmc); +// restApi.init(fmc); +// storageSource.init(fmc); +// deviceManager.init(fmc); +// flowReconcileMgr.init(fmc); +// entityClassifier.init(fmc); +// syncService.init(fmc); +// storageSource.startUp(fmc); +// deviceManager.startUp(fmc); +// flowReconcileMgr.startUp(fmc); +// tp.startUp(fmc); +// entityClassifier.startUp(fmc); +// syncService.startUp(fmc); +// +// this.storeClient = +// this.syncService.getStoreClient(DeviceManagerImpl.DEVICE_SYNC_STORE_NAME, +// String.class, DeviceSyncRepresentation.class); +// +// reset(topology); +// topology.addListener(deviceManager); +// expectLastCall().anyTimes(); +// replay(topology); +// +// IOFSwitch mockSwitch1 = makeSwitchMock(1L); +// IOFSwitch mockSwitch10 = makeSwitchMock(10L); +// IOFSwitch mockSwitch5 = makeSwitchMock(5L); +// IOFSwitch mockSwitch50 = makeSwitchMock(50L); +// Map switches = new HashMap(); +// switches.put(1L, mockSwitch1); +// switches.put(10L, mockSwitch10); +// switches.put(5L, mockSwitch5); +// switches.put(50L, mockSwitch50); +// mockFloodlightProvider.setSwitches(switches); +// +// replay(mockSwitch1, mockSwitch5, mockSwitch10, mockSwitch50); +// +// // Build our test packet +// this.testARPReplyPacket_1 = new Ethernet() +// .setSourceMACAddress("00:44:33:22:11:01") +// .setDestinationMACAddress("00:11:22:33:44:55") +// .setEtherType(Ethernet.TYPE_ARP) +// .setVlanID((short)5) +// .setPayload( +// new ARP() +// .setHardwareType(ARP.HW_TYPE_ETHERNET) +// .setProtocolType(ARP.PROTO_TYPE_IP) +// .setHardwareAddressLength((byte) 6) +// .setProtocolAddressLength((byte) 4) +// .setOpCode(ARP.OP_REPLY) +// .setSenderHardwareAddress(Ethernet.toMACAddress("00:44:33:22:11:01")) +// .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.1")) +// .setTargetHardwareAddress(Ethernet.toMACAddress("00:11:22:33:44:55")) +// .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2"))); +// this.testARPReplyPacket_1_Srld = testARPReplyPacket_1.serialize(); +// +// // Another test packet with a different source IP +// this.testARPReplyPacket_2 = new Ethernet() +// .setSourceMACAddress("00:99:88:77:66:55") +// .setDestinationMACAddress("00:11:22:33:44:55") +// .setEtherType(Ethernet.TYPE_ARP) +// .setVlanID((short)5) +// .setPayload( +// new ARP() +// .setHardwareType(ARP.HW_TYPE_ETHERNET) +// .setProtocolType(ARP.PROTO_TYPE_IP) +// .setHardwareAddressLength((byte) 6) +// .setProtocolAddressLength((byte) 4) +// .setOpCode(ARP.OP_REPLY) +// .setSenderHardwareAddress(Ethernet.toMACAddress("00:44:33:22:11:01")) +// .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.1")) +// .setTargetHardwareAddress(Ethernet.toMACAddress("00:11:22:33:44:55")) +// .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2"))); +// this.testARPReplyPacket_2_Srld = testARPReplyPacket_2.serialize(); +// +// // Build the PacketIn +// this.packetIn_1 = ((OFPacketIn) mockFloodlightProvider. +// getOFMessageFactory().getMessage(OFType.PACKET_IN)) +// .setBufferId(-1) +// .setInPort((short) 1) +// .setPacketData(this.testARPReplyPacket_1_Srld) +// .setReason(OFPacketInReason.NO_MATCH) +// .setTotalLength((short) this.testARPReplyPacket_1_Srld.length); +// +// // Build the PacketIn +// this.packetIn_2 = ((OFPacketIn) mockFloodlightProvider. +// getOFMessageFactory().getMessage(OFType.PACKET_IN)) +// .setBufferId(-1) +// .setInPort((short) 1) +// .setPacketData(this.testARPReplyPacket_2_Srld) +// .setReason(OFPacketInReason.NO_MATCH) +// .setTotalLength((short) this.testARPReplyPacket_2_Srld.length); +// } +// +// +// +// +// +// @Test +// public void testLastSeen() throws Exception { +// Calendar c = Calendar.getInstance(); +// Date d1 = c.getTime(); +// Entity entity1 = new Entity(1L, null, null, null, null, d1); +// c.add(Calendar.SECOND, 1); +// Entity entity2 = new Entity(1L, null, 1, null, null, c.getTime()); +// +// IDevice d = deviceManager.learnDeviceByEntity(entity2); +// assertEquals(c.getTime(), d.getLastSeen()); +// d = deviceManager.learnDeviceByEntity(entity1); +// assertEquals(c.getTime(), d.getLastSeen()); +// +// deviceManager.startUp(null); +// d = deviceManager.learnDeviceByEntity(entity1); +// assertEquals(d1, d.getLastSeen()); +// d = deviceManager.learnDeviceByEntity(entity2); +// assertEquals(c.getTime(), d.getLastSeen()); +// } +// +// @Test +// public void testEntityLearning() throws Exception { +// IDeviceListener mockListener = +// createMock(IDeviceListener.class); +// expect(mockListener.getName()).andReturn("mockListener").atLeastOnce(); +// expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) +// .andReturn(false).atLeastOnce(); +// expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) +// .andReturn(false).atLeastOnce(); +// +// replay(mockListener); +// deviceManager.addListener(mockListener); +// verify(mockListener); +// reset(mockListener); +// deviceManager.entityClassifier= new MockEntityClassifier(); +// deviceManager.startUp(null); +// +// ITopologyService mockTopology = createMock(ITopologyService.class); +// expect(mockTopology.getL2DomainId(anyLong())). +// andReturn(1L).anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(anyLong(), anyShort())). +// andReturn(false).anyTimes(); +// +// expect(mockTopology.isAttachmentPointPort(anyLong(), +// anyShort())).andReturn(true).anyTimes(); +// expect(mockTopology.isConsistent(10L, (short)1, 10L, (short)1)). +// andReturn(true).anyTimes(); +// expect(mockTopology.isConsistent(1L, (short)1, 1L, (short)1)). +// andReturn(true).anyTimes(); +// expect(mockTopology.isConsistent(50L, (short)3, 50L, (short)3)). +// andReturn(true).anyTimes(); +// +// Date topologyUpdateTime = new Date(); +// expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). +// anyTimes(); +// +// deviceManager.topology = mockTopology; +// +// Entity entity1 = new Entity(1L, null, null, 1L, 1, new Date()); +// Entity entity2 = new Entity(1L, null, null, 10L, 1, new Date()); +// Entity entity3 = new Entity(1L, null, 1, 10L, 1, new Date()); +// Entity entity4 = new Entity(1L, null, 1, 1L, 1, new Date()); +// Entity entity5 = new Entity(2L, (short)4, 1, 5L, 2, new Date()); +// Entity entity6 = new Entity(2L, (short)4, 1, 50L, 3, new Date()); +// Entity entity7 = new Entity(2L, (short)4, 2, 50L, 3, new Date()); +// +// mockListener.deviceAdded(isA(IDevice.class)); +// replay(mockListener, mockTopology); +// +// Device d1 = deviceManager.learnDeviceByEntity(entity1); +// assertSame(d1, deviceManager.learnDeviceByEntity(entity1)); +// assertSame(d1, deviceManager.findDeviceByEntity(entity1)); +// assertEquals(DefaultEntityClassifier.entityClass , +// d1.getEntityClass()); +// assertArrayEquals(new Short[] { -1 }, d1.getVlanId()); +// assertArrayEquals(new Integer[] { }, d1.getIPv4Addresses()); +// +// assertEquals(1, deviceManager.getAllDevices().size()); +// verify(mockListener); +// +// reset(mockListener); +// mockListener.deviceAdded(isA(IDevice.class)); +// replay(mockListener); +// +// Device d2 = deviceManager.learnDeviceByEntity(entity2); +// assertFalse(d1.equals(d2)); +// assertNotSame(d1, d2); +// assertNotSame(d1.getDeviceKey(), d2.getDeviceKey()); +// assertEquals(MockEntityClassifier.testEC, d2.getEntityClass()); +// assertArrayEquals(new Short[] { -1 }, d2.getVlanId()); +// assertArrayEquals(new Integer[] { }, d2.getIPv4Addresses()); +// +// assertEquals(2, deviceManager.getAllDevices().size()); +// verify(mockListener); +// +// reset(mockListener); +// mockListener.deviceIPV4AddrChanged(isA(IDevice.class)); +// replay(mockListener); +// +// Device d3 = deviceManager.learnDeviceByEntity(entity3); +// assertNotSame(d2, d3); +// assertEquals(d2.getDeviceKey(), d3.getDeviceKey()); +// assertEquals(MockEntityClassifier.testEC, d3.getEntityClass()); +// assertArrayEquals(new Integer[] { 1 }, +// d3.getIPv4Addresses()); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(10L, 1) }, +// d3.getAttachmentPoints()); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(10L, 1) }, +// d3.getAttachmentPoints(true)); +// assertArrayEquals(new Short[] { -1 }, +// d3.getVlanId()); +// +// assertEquals(2, deviceManager.getAllDevices().size()); +// verify(mockListener); +// +// reset(mockListener); +// mockListener.deviceIPV4AddrChanged(isA(IDevice.class)); +// replay(mockListener); +// +// Device d4 = deviceManager.learnDeviceByEntity(entity4); +// assertNotSame(d1, d4); +// assertEquals(d1.getDeviceKey(), d4.getDeviceKey()); +// assertEquals(DefaultEntityClassifier.entityClass, d4.getEntityClass()); +// assertArrayEquals(new Integer[] { 1 }, +// d4.getIPv4Addresses()); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, +// d4.getAttachmentPoints()); +// assertArrayEquals(new Short[] { -1 }, +// d4.getVlanId()); +// +// assertEquals(2, deviceManager.getAllDevices().size()); +// verify(mockListener); +// +// reset(mockListener); +// mockListener.deviceAdded((isA(IDevice.class))); +// replay(mockListener); +// +// Device d5 = deviceManager.learnDeviceByEntity(entity5); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(5L, 2) }, +// d5.getAttachmentPoints()); +// assertArrayEquals(new Short[] { (short) 4 }, +// d5.getVlanId()); +// assertEquals(2L, d5.getMACAddress()); +// assertEquals("00:00:00:00:00:02", d5.getMACAddressString()); +// verify(mockListener); +// +// reset(mockListener); +// mockListener.deviceAdded(isA(IDevice.class)); +// replay(mockListener); +// +// Device d6 = deviceManager.learnDeviceByEntity(entity6); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(50L, 3) }, +// d6.getAttachmentPoints()); +// assertArrayEquals(new Short[] { (short) 4 }, +// d6.getVlanId()); +// +// assertEquals(4, deviceManager.getAllDevices().size()); +// verify(mockListener); +// +// reset(mockListener); +// mockListener.deviceIPV4AddrChanged(isA(IDevice.class)); +// replay(mockListener); +// +// Device d7 = deviceManager.learnDeviceByEntity(entity7); +// assertNotSame(d6, d7); +// assertEquals(d6.getDeviceKey(), d7.getDeviceKey()); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(50L, 3) }, +// d7.getAttachmentPoints()); +// assertArrayEquals(new Short[] { (short) 4 }, +// d7.getVlanId()); +// +// assertEquals(4, deviceManager.getAllDevices().size()); +// verify(mockListener); +// +// +// reset(mockListener); +// replay(mockListener); +// +// reset(deviceManager.topology); +// deviceManager.topology.addListener(deviceManager); +// expectLastCall().times(1); +// replay(deviceManager.topology); +// +// deviceManager.entityClassifier = new MockEntityClassifierMac(); +// deviceManager.startUp(null); +// Entity entityNoClass = new Entity(5L, (short)1, 5, -1L, 1, new Date()); +// assertEquals(null, deviceManager.learnDeviceByEntity(entityNoClass)); +// +// verify(mockListener); +// } +// +// +// private void doTestEntityOrdering(boolean computeInsertionPoint) throws Exception { +// Entity e = new Entity(10L, null, null, null, null, null); +// IEntityClass ec = createNiceMock(IEntityClass.class); +// Device d = new Device(deviceManager, 1L, e, ec); +// +// int expectedLength = 1; +// Long[] macs = new Long[] { 5L, // new first element +// 15L, // new last element +// 7L, // insert in middle +// 12L, // insert in middle +// 6L, // insert at idx 1 +// 14L, // insert at idx length-2 +// 1L, +// 20L +// }; +// +// for (Long mac: macs) { +// e = new Entity(mac, null, null, null, null, null); +// int insertionPoint; +// if (computeInsertionPoint) { +// insertionPoint = -(Arrays.binarySearch(d.entities, e)+1); +// } else { +// insertionPoint = -1; +// } +// d = deviceManager.allocateDevice(d, e, insertionPoint); +// expectedLength++; +// assertEquals(expectedLength, d.entities.length); +// for (int i = 0; i < d.entities.length-1; i++) +// assertEquals(-1, d.entities[i].compareTo(d.entities[i+1])); +// } +// } +// +// @Test +// public void testEntityOrderingExternal() throws Exception { +// doTestEntityOrdering(true); +// } +// +// @Test +// public void testEntityOrderingInternal() throws Exception { +// doTestEntityOrdering(false); +// } +// +// @Test +// public void testAttachmentPointLearning() throws Exception { +// IDeviceListener mockListener = +// createMock(IDeviceListener.class); +// expect(mockListener.getName()).andReturn("mockListener").atLeastOnce(); +// expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) +// .andReturn(false).atLeastOnce(); +// expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) +// .andReturn(false).atLeastOnce(); +// +// replay(mockListener); +// deviceManager.addListener(mockListener); +// verify(mockListener); +// reset(mockListener); +// +// ITopologyService mockTopology = createMock(ITopologyService.class); +// expect(mockTopology.getL2DomainId(1L)). +// andReturn(1L).anyTimes(); +// expect(mockTopology.getL2DomainId(5L)). +// andReturn(1L).anyTimes(); +// expect(mockTopology.getL2DomainId(10L)). +// andReturn(10L).anyTimes(); +// expect(mockTopology.getL2DomainId(50L)). +// andReturn(10L).anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(anyLong(), anyShort())). +// andReturn(false).anyTimes(); +// expect(mockTopology.isInSameBroadcastDomain(anyLong(), anyShort(), +// anyLong(), anyShort())).andReturn(false).anyTimes(); +// +// expect(mockTopology.isAttachmentPointPort(anyLong(), +// anyShort())).andReturn(true).anyTimes(); +// expect(mockTopology.isConsistent(1L, (short)1, 5L, (short)1)). +// andReturn(false).anyTimes(); +// expect(mockTopology.isConsistent(5L, (short)1, 10L, (short)1)). +// andReturn(false).anyTimes(); +// expect(mockTopology.isConsistent(10L, (short)1, 50L, (short)1)). +// andReturn(false).anyTimes(); +// +// Date topologyUpdateTime = new Date(); +// expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). +// anyTimes(); +// +// replay(mockTopology); +// +// deviceManager.topology = mockTopology; +// +// Calendar c = Calendar.getInstance(); +// Entity entity1 = new Entity(1L, null, 1, 1L, 1, c.getTime()); +// Entity entity0 = new Entity(1L, null, null, null, null, c.getTime()); +// c.add(Calendar.SECOND, 1); +// Entity entity2 = new Entity(1L, null, null, 5L, 1, c.getTime()); +// c.add(Calendar.SECOND, 1); +// Entity entity3 = new Entity(1L, null, null, 10L, 1, c.getTime()); +// c.add(Calendar.SECOND, 1); +// Entity entity4 = new Entity(1L, null, null, 50L, 1, c.getTime()); +// +// IDevice d; +// SwitchPort[] aps; +// Integer[] ips; +// +// mockListener.deviceAdded(isA(IDevice.class)); +// replay(mockListener); +// +// deviceManager.learnDeviceByEntity(entity1); +// d = deviceManager.learnDeviceByEntity(entity0); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps); +// ips = d.getIPv4Addresses(); +// assertArrayEquals(new Integer[] { 1 }, ips); +// verify(mockListener); +// +// reset(mockListener); +// mockListener.deviceMoved((isA(IDevice.class))); +// replay(mockListener); +// +// d = deviceManager.learnDeviceByEntity(entity2); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// +// assertArrayEquals(new SwitchPort[] { new SwitchPort(5L, 1) }, aps); +// ips = d.getIPv4Addresses(); +// assertArrayEquals(new Integer[] { 1 }, ips); +// verify(mockListener); +// +// reset(mockListener); +// mockListener.deviceMoved((isA(IDevice.class))); +// replay(mockListener); +// +// d = deviceManager.learnDeviceByEntity(entity3); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] {new SwitchPort(5L, 1), new SwitchPort(10L, 1)}, aps); +// ips = d.getIPv4Addresses(); +// assertArrayEquals(new Integer[] { 1 }, ips); +// verify(mockListener); +// +// reset(mockListener); +// mockListener.deviceMoved((isA(IDevice.class))); +// replay(mockListener); +// +// d = deviceManager.learnDeviceByEntity(entity4); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(5L, 1), +// new SwitchPort(50L, 1) }, aps); +// ips = d.getIPv4Addresses(); +// assertArrayEquals(new Integer[] { 1 }, ips); +// verify(mockListener); +// } +// +// private void verifyEntityArray(Entity[] expected, Device d) { +// Arrays.sort(expected); +// assertArrayEquals(expected, d.entities); +// } +// +// @Test +// public void testNoLearningOnInternalPorts() throws Exception { +// IDeviceListener mockListener = +// createMock(IDeviceListener.class); +// +// expect(mockListener.getName()).andReturn("mockListener").anyTimes(); +// expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) +// .andReturn(false).atLeastOnce(); +// expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) +// .andReturn(false).atLeastOnce(); +// +// replay(mockListener); +// deviceManager.addListener(mockListener); +// verify(mockListener); +// reset(mockListener); +// +// ITopologyService mockTopology = createMock(ITopologyService.class); +// expect(mockTopology.getL2DomainId(1L)). +// andReturn(1L).anyTimes(); +// expect(mockTopology.getL2DomainId(2L)). +// andReturn(1L).anyTimes(); +// expect(mockTopology.getL2DomainId(3L)). +// andReturn(1L).anyTimes(); +// expect(mockTopology.getL2DomainId(4L)). +// andReturn(1L).anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(anyLong(), anyShort())) +// .andReturn(false).anyTimes(); +// expect(mockTopology.isInSameBroadcastDomain(anyLong(), anyShort(), +// anyLong(), anyShort())) +// .andReturn(false).anyTimes(); +// +// expect(mockTopology.isAttachmentPointPort(or(eq(1L), eq(3L)), anyShort())) +// .andReturn(true).anyTimes(); +// // Switches 2 and 4 have only internal ports +// expect(mockTopology.isAttachmentPointPort(or(eq(2L), eq(4L)), anyShort())) +// .andReturn(false).anyTimes(); +// +// expect(mockTopology.isConsistent(1L, (short)1, 3L, (short)1)) +// .andReturn(false).once(); +// +// Date topologyUpdateTime = new Date(); +// expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). +// anyTimes(); +// +// replay(mockTopology); +// +// deviceManager.topology = mockTopology; +// +// Calendar c = Calendar.getInstance(); +// Entity entity1 = new Entity(1L, null, 1, 1L, 1, c.getTime()); +// c.add(Calendar.SECOND, 1); +// Entity entity2 = new Entity(1L, null, 2, 2L, 1, c.getTime()); +// c.add(Calendar.SECOND, 1); +// Entity entity3 = new Entity(1L, null, 3, 3L, 1, c.getTime()); +// c.add(Calendar.SECOND, 1); +// Entity entity4 = new Entity(1L, null, 4, 4L, 1, c.getTime()); +// +// IDevice d; +// SwitchPort[] aps; +// Integer[] ips; +// +// mockListener.deviceAdded(isA(IDevice.class)); +// expectLastCall().once(); +// replay(mockListener); +// +// // cannot learn device internal ports +// d = deviceManager.learnDeviceByEntity(entity2); +// assertNull(d); +// d = deviceManager.learnDeviceByEntity(entity4); +// assertNull(d); +// +// d = deviceManager.learnDeviceByEntity(entity1); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps); +// verifyEntityArray(new Entity[] { entity1 } , (Device)d); +// ips = d.getIPv4Addresses(); +// assertArrayEquals(new Integer[] { 1 }, ips); +// verify(mockListener); +// +// reset(mockListener); +// replay(mockListener); +// +// // don't learn +// d = deviceManager.learnDeviceByEntity(entity2); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps); +// verifyEntityArray(new Entity[] { entity1 } , (Device)d); +// ips = d.getIPv4Addresses(); +// assertArrayEquals(new Integer[] { 1 }, ips); +// verify(mockListener); +// +// reset(mockListener); +// mockListener.deviceMoved(isA(IDevice.class)); +// mockListener.deviceIPV4AddrChanged(isA(IDevice.class)); +// replay(mockListener); +// +// // learn +// d = deviceManager.learnDeviceByEntity(entity3); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(3L, 1) }, aps); +// verifyEntityArray(new Entity[] { entity1, entity3 } , (Device)d); +// ips = d.getIPv4Addresses(); +// Arrays.sort(ips); +// assertArrayEquals(new Integer[] { 1, 3 }, ips); +// verify(mockListener); +// +// reset(mockListener); +// replay(mockListener); +// +// // don't learn +// d = deviceManager.learnDeviceByEntity(entity4); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(3L, 1) }, aps); +// verifyEntityArray(new Entity[] { entity1, entity3 } , (Device)d); +// ips = d.getIPv4Addresses(); +// Arrays.sort(ips); +// assertArrayEquals(new Integer[] { 1, 3 }, ips); +// verify(mockListener); +// } +// +// @Test +// public void testAttachmentPointSuppression() throws Exception { +// IDeviceListener mockListener = +// createMock(IDeviceListener.class); +// +// expect(mockListener.getName()).andReturn("mockListener").anyTimes(); +// expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) +// .andReturn(false).atLeastOnce(); +// expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) +// .andReturn(false).atLeastOnce(); +// +// replay(mockListener); +// deviceManager.addListener(mockListener); +// verify(mockListener); +// reset(mockListener); +// +// ITopologyService mockTopology = createMock(ITopologyService.class); +// expect(mockTopology.getL2DomainId(1L)). +// andReturn(1L).anyTimes(); +// expect(mockTopology.getL2DomainId(5L)). +// andReturn(1L).anyTimes(); +// expect(mockTopology.getL2DomainId(10L)). +// andReturn(10L).anyTimes(); +// expect(mockTopology.getL2DomainId(50L)). +// andReturn(10L).anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(anyLong(), anyShort())) +// .andReturn(false).anyTimes(); +// expect(mockTopology.isInSameBroadcastDomain(anyLong(), anyShort(), +// anyLong(), anyShort())) +// .andReturn(false).anyTimes(); +// +// expect(mockTopology.isAttachmentPointPort(anyLong(), anyShort())) +// .andReturn(true).anyTimes(); +// expect(mockTopology.isConsistent(5L, (short)1, 50L, (short)1)) +// .andReturn(false).anyTimes(); +// +// Date topologyUpdateTime = new Date(); +// expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). +// anyTimes(); +// +// replay(mockTopology); +// +// deviceManager.topology = mockTopology; +// // suppress (1L, 1) and (10L, 1) +// deviceManager.addSuppressAPs(1L, (short)1); +// deviceManager.addSuppressAPs(10L, (short)1); +// +// Calendar c = Calendar.getInstance(); +// Entity entity0 = new Entity(1L, null, null, null, null, c.getTime()); +// // No attachment point should be learnt on 1L, 1 +// Entity entity1 = new Entity(1L, null, 1, 1L, 1, c.getTime()); +// c.add(Calendar.SECOND, 1); +// Entity entity2 = new Entity(1L, null, 1, 5L, 1, c.getTime()); +// c.add(Calendar.SECOND, 1); +// Entity entity3 = new Entity(1L, null, null, 10L, 1, c.getTime()); +// c.add(Calendar.SECOND, 1); +// Entity entity4 = new Entity(1L, null, null, 50L, 1, c.getTime()); +// +// IDevice d; +// SwitchPort[] aps; +// Integer[] ips; +// +// mockListener.deviceAdded(isA(IDevice.class)); +// mockListener.deviceIPV4AddrChanged((isA(IDevice.class))); +// replay(mockListener); +// +// // TODO: we currently do learn entities on suppressed APs +// // // cannot learn device on suppressed AP +// // d = deviceManager.learnDeviceByEntity(entity1); +// // assertNull(d); +// +// deviceManager.learnDeviceByEntity(entity0); +// d = deviceManager.learnDeviceByEntity(entity1); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertEquals(aps.length, 0); +// verifyEntityArray(new Entity[] { entity0, entity1} , (Device)d); +// ips = d.getIPv4Addresses(); +// assertArrayEquals(new Integer[] { 1 }, ips); +// verify(mockListener); +// +// reset(mockListener); +// mockListener.deviceMoved((isA(IDevice.class))); +// //mockListener.deviceIPV4AddrChanged((isA(IDevice.class))); +// replay(mockListener); +// d = deviceManager.learnDeviceByEntity(entity2); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(5L, 1) }, aps); +// verifyEntityArray(new Entity[] { entity0, entity1, entity2 } , (Device)d); +// ips = d.getIPv4Addresses(); +// assertArrayEquals(new Integer[] { 1 }, ips); +// verify(mockListener); +// +// reset(mockListener); +// replay(mockListener); +// +// d = deviceManager.learnDeviceByEntity(entity3); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(5L, 1) }, aps); +// verifyEntityArray(new Entity[] { entity0, entity1, entity2, entity3 } , (Device)d); +// ips = d.getIPv4Addresses(); +// assertArrayEquals(new Integer[] { 1 }, ips); +// verify(mockListener); +// +// reset(mockListener); +// mockListener.deviceMoved((isA(IDevice.class))); +// replay(mockListener); +// +// d = deviceManager.learnDeviceByEntity(entity4); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(5L, 1), +// new SwitchPort(50L, 1) }, aps); +// verifyEntityArray(new Entity[] { entity0, entity1, entity2, entity3, entity4} , (Device)d); +// ips = d.getIPv4Addresses(); +// assertArrayEquals(new Integer[] { 1 }, ips); +// verify(mockListener); +// } +// +// @Test +// public void testBDAttachmentPointLearning() throws Exception { +// ITopologyService mockTopology = createMock(ITopologyService.class); +// expect(mockTopology.getL2DomainId(anyLong())). +// andReturn(1L).anyTimes(); +// expect(mockTopology.isAttachmentPointPort(anyLong(), anyShort())). +// andReturn(true).anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(1L, (short)1)). +// andReturn(false).anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(1L, (short)2)). +// andReturn(true).anyTimes(); +// expect(mockTopology.isInSameBroadcastDomain(1L, (short)1, +// 1L, (short)2)).andReturn(true).anyTimes(); +// expect(mockTopology.isInSameBroadcastDomain(1L, (short)2, +// 1L, (short)1)).andReturn(true).anyTimes(); +// expect(mockTopology.isConsistent(anyLong(), anyShort(), anyLong(), anyShort())).andReturn(false).anyTimes(); +// +// Date topologyUpdateTime = new Date(); +// expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). +// anyTimes(); +// +// replay(mockTopology); +// +// deviceManager.topology = mockTopology; +// +// Calendar c = Calendar.getInstance(); +// Entity entity1 = new Entity(1L, null, 1, 1L, 1, c.getTime()); +// c.add(Calendar.MILLISECOND, +// (int)AttachmentPoint.OPENFLOW_TO_EXTERNAL_TIMEOUT/ 2); +// Entity entity2 = new Entity(1L, null, null, 1L, 2, c.getTime()); +// c.add(Calendar.MILLISECOND, +// (int)AttachmentPoint.OPENFLOW_TO_EXTERNAL_TIMEOUT / 2 + 1); +// Entity entity3 = new Entity(1L, null, null, 1L, 2, c.getTime()); +// +// IDevice d; +// SwitchPort[] aps; +// +// d = deviceManager.learnDeviceByEntity(entity1); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps); +// +// // this timestamp is too soon; don't switch +// d = deviceManager.learnDeviceByEntity(entity2); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps); +// +// // it should switch when we learn with a timestamp after the +// // timeout +// d = deviceManager.learnDeviceByEntity(entity3); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 2) }, aps); +// } +// +// /** +// * This test verifies that the learning behavior on OFPP_LOCAL ports. +// * Once a host is learned on OFPP_LOCAL, it is allowed to move only from +// * one OFPP_LOCAL to another OFPP_LOCAL port. +// * @throws Exception +// */ +// @Test +// public void testLOCALAttachmentPointLearning() throws Exception { +// ITopologyService mockTopology = createMock(ITopologyService.class); +// expect(mockTopology.getL2DomainId(anyLong())). +// andReturn(1L).anyTimes(); +// expect(mockTopology.isAttachmentPointPort(anyLong(), anyShort())). +// andReturn(true).anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(1L, (short)1)). +// andReturn(false).anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(1L, OFPort.OFPP_LOCAL.getValue())). +// andReturn(false).anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(1L, (short)2)). +// andReturn(true).anyTimes(); +// expect(mockTopology.isInSameBroadcastDomain(1L, (short)1, +// 1L, OFPort.OFPP_LOCAL.getValue())).andReturn(true).anyTimes(); +// expect(mockTopology.isInSameBroadcastDomain(1L, OFPort.OFPP_LOCAL.getValue(), +// 1L, (short)2)).andReturn(true).anyTimes(); +// expect(mockTopology.isInSameBroadcastDomain(1L, (short)2, +// 1L, OFPort.OFPP_LOCAL.getValue())).andReturn(true).anyTimes(); +// expect(mockTopology.isConsistent(anyLong(), anyShort(), anyLong(), anyShort())).andReturn(false).anyTimes(); +// +// Date topologyUpdateTime = new Date(); +// expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). +// anyTimes(); +// +// replay(mockTopology); +// +// deviceManager.topology = mockTopology; +// +// Calendar c = Calendar.getInstance(); +// Entity entity1 = new Entity(1L, null, 1, 1L, 1, c.getTime()); +// c.add(Calendar.MILLISECOND, +// (int)AttachmentPoint.OPENFLOW_TO_EXTERNAL_TIMEOUT/ 2); +// Entity entity2 = new Entity(1L, null, null, 1L, (int)OFPort.OFPP_LOCAL.getValue(), c.getTime()); +// c.add(Calendar.MILLISECOND, +// (int)AttachmentPoint.OPENFLOW_TO_EXTERNAL_TIMEOUT + 1); +// Entity entity3 = new Entity(1L, null, null, 1L, 2, c.getTime()); +// +// IDevice d; +// SwitchPort[] aps; +// +// d = deviceManager.learnDeviceByEntity(entity1); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps); +// +// // Ensure that the attachment point changes to OFPP_LOCAL +// d = deviceManager.learnDeviceByEntity(entity2); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, OFPort.OFPP_LOCAL.getValue()) }, aps); +// +// // Even though the new attachment point is consistent with old +// // and the time has elapsed, OFPP_LOCAL attachment point should +// // be maintained. +// d = deviceManager.learnDeviceByEntity(entity3); +// assertEquals(1, deviceManager.getAllDevices().size()); +// aps = d.getAttachmentPoints(); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, OFPort.OFPP_LOCAL.getValue()) }, aps); +// } +// +// @Test +// public void testPacketInBasic(byte[] deviceMac, OFPacketIn packetIn) { +// // Mock up our expected behavior +// ITopologyService mockTopology = createMock(ITopologyService.class); +// deviceManager.topology = mockTopology; +// expect(mockTopology.isAttachmentPointPort(EasyMock.anyLong(), +// EasyMock.anyShort())). +// andReturn(true).anyTimes(); +// expect(mockTopology.isConsistent(EasyMock.anyLong(), +// EasyMock.anyShort(), +// EasyMock.anyLong(), +// EasyMock.anyShort())).andReturn(false). +// anyTimes(); +// expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes(); +// replay(mockTopology); +// +// Date currentDate = new Date(); +// +// // build our expected Device +// Integer ipaddr = IPv4.toIPv4Address("192.168.1.1"); +// Device device = +// new Device(deviceManager, +// new Long(deviceManager.deviceKeyCounter), +// new Entity(Ethernet.toLong(deviceMac), +// (short)5, +// ipaddr, +// 1L, +// 1, +// currentDate), +// DefaultEntityClassifier.entityClass); +// +// // Get the listener and trigger the packet in +// IOFSwitch switch1 = mockFloodlightProvider.getSwitch(1L); +// mockFloodlightProvider.dispatchMessage(switch1, packetIn); +// +// // Verify the replay matched our expectations +// // verify(mockTopology); +// +// // Verify the device +// Device rdevice = (Device) +// deviceManager.findDevice(Ethernet.toLong(deviceMac), +// (short)5, null, null, null); +// +// assertEquals(device, rdevice); +// assertEquals(new Short((short)5), rdevice.getVlanId()[0]); +// +// Device result = null; +// Iterator dstiter = +// deviceManager.queryClassDevices(device.getEntityClass(), +// null, null, ipaddr, +// null, null); +// if (dstiter.hasNext()) { +// result = (Device)dstiter.next(); +// } +// +// assertEquals(device, result); +// +// device = +// new Device(device, +// new Entity(Ethernet.toLong(deviceMac), +// (short)5, +// ipaddr, +// 5L, +// 2, +// currentDate), +// -1); +// +// reset(mockTopology); +// expect(mockTopology.isAttachmentPointPort(anyLong(), +// anyShort())). +// andReturn(true). +// anyTimes(); +// expect(mockTopology.isConsistent(EasyMock.anyLong(), +// EasyMock.anyShort(), +// EasyMock.anyLong(), +// EasyMock.anyShort())).andReturn(false). +// anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(EasyMock.anyLong(), +// EasyMock.anyShort())) +// .andReturn(false) +// .anyTimes(); +// expect(mockTopology.getL2DomainId(1L)).andReturn(1L).anyTimes(); +// expect(mockTopology.getL2DomainId(5L)).andReturn(1L).anyTimes(); +// expect(mockTopology.isInSameBroadcastDomain(1L, (short)1, 5L, (short)2)). +// andReturn(false).anyTimes(); +// +// // Start recording the replay on the mocks +// replay(mockTopology); +// // Get the listener and trigger the packet in +// IOFSwitch switch5 = mockFloodlightProvider.getSwitch(5L); +// mockFloodlightProvider. +// dispatchMessage(switch5, this.packetIn_1.setInPort((short)2)); +// +// // Verify the replay matched our expectations +// verify(mockTopology); +// +// // Verify the device +// rdevice = (Device) +// deviceManager.findDevice(Ethernet.toLong(deviceMac), +// (short)5, null, null, null); +// assertEquals(device, rdevice); +// } +// +// @Test +// public void testPacketIn() throws Exception { +// byte[] deviceMac1 = +// ((Ethernet)this.testARPReplyPacket_1).getSourceMACAddress(); +// testPacketInBasic(deviceMac1, packetIn_1); +// } +// +// /** +// * This test ensures the device manager learns the source device +// * corresponding to the senderHardwareAddress and senderProtocolAddress +// * in an ARP response whenever the senderHardwareAddress is different +// * from the source MAC address of the Ethernet frame. +// * +// * This test is the same as testPacketIn method, except for the +// * packet-in that's used. +// * @throws Exception +// */ +// @Test +// public void testDeviceLearningFromArpResponseData() throws Exception { +// ARP arp = (ARP)((Ethernet)this.testARPReplyPacket_2).getPayload(); +// byte[] deviceMac2 = arp.getSenderHardwareAddress(); +// +// testPacketInBasic(deviceMac2, packetIn_2); +// } +// +// /** +// * Note: Entity expiration does not result in device moved notification. +// * @throws Exception +// */ +// public void doTestEntityExpiration() throws Exception { +// IDeviceListener mockListener = +// createMock(IDeviceListener.class); +// expect(mockListener.getName()).andReturn("mockListener").anyTimes(); +// expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) +// .andReturn(false).atLeastOnce(); +// expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) +// .andReturn(false).atLeastOnce(); +// +// ITopologyService mockTopology = createMock(ITopologyService.class); +// expect(mockTopology.isAttachmentPointPort(anyLong(), +// anyShort())). +// andReturn(true).anyTimes(); +// +// expect(mockTopology.isBroadcastDomainPort(1L, (short)1)).andReturn(false).anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(5L, (short)1)).andReturn(false).anyTimes(); +// expect(mockTopology.getL2DomainId(1L)).andReturn(1L).anyTimes(); +// expect(mockTopology.getL2DomainId(5L)).andReturn(5L).anyTimes(); +// expect(mockTopology.isConsistent(1L, (short)1, 5L, (short)1)). +// andReturn(false).anyTimes(); +// +// Date topologyUpdateTime = new Date(); +// expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). +// anyTimes(); +// +// replay(mockTopology); +// deviceManager.topology = mockTopology; +// +// Calendar c = Calendar.getInstance(); +// Entity entity1 = new Entity(1L, null, 2, 1L, 1, c.getTime()); +// c.add(Calendar.MILLISECOND, -DeviceManagerImpl.ENTITY_TIMEOUT-1); +// Entity entity2 = new Entity(1L, null, 1, 5L, 1, c.getTime()); +// +// deviceManager.learnDeviceByEntity(entity1); +// IDevice d = deviceManager.learnDeviceByEntity(entity2); +// assertArrayEquals(new Integer[] { 1, 2 }, d.getIPv4Addresses()); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), +// new SwitchPort(5L, 1)}, +// d.getAttachmentPoints()); +// Iterator diter = +// deviceManager.queryClassDevices(d.getEntityClass(), +// null, null, 1, null, null); +// assertTrue(diter.hasNext()); +// assertEquals(d.getDeviceKey(), diter.next().getDeviceKey()); +// diter = deviceManager.queryClassDevices(d.getEntityClass(), +// null, null, 2, null, null); +// assertTrue(diter.hasNext()); +// assertEquals(d.getDeviceKey(), diter.next().getDeviceKey()); +// +// replay(mockListener); +// deviceManager.addListener(mockListener); +// verify(mockListener); +// reset(mockListener); +// +// mockListener.deviceIPV4AddrChanged(isA(IDevice.class)); +// replay(mockListener); +// deviceManager.entityCleanupTask.reschedule(0, null); +// +// d = deviceManager.getDevice(d.getDeviceKey()); +// assertArrayEquals(new Integer[] { 2 }, d.getIPv4Addresses()); +// +// // Attachment points are not removed, previous ones are still valid. +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), +// new SwitchPort(5L, 1) }, +// d.getAttachmentPoints()); +// diter = deviceManager.queryClassDevices(d.getEntityClass(), +// null, null, 2, null, null); +// assertTrue(diter.hasNext()); +// assertEquals(d.getDeviceKey(), diter.next().getDeviceKey()); +// diter = deviceManager.queryClassDevices(d.getEntityClass(), +// null, null, 1, null, null); +// assertFalse(diter.hasNext()); +// +// d = deviceManager.findDevice(1L, null, null, null, null); +// assertArrayEquals(new Integer[] { 2 }, d.getIPv4Addresses()); +// +// // Attachment points are not removed, previous ones are still valid. +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), +// new SwitchPort(5L, 1) }, +// d.getAttachmentPoints()); +// +// verify(mockListener); +// } +// +// public void doTestDeviceExpiration() throws Exception { +// IDeviceListener mockListener = +// createMock(IDeviceListener.class); +// expect(mockListener.getName()).andReturn("mockListener").anyTimes(); +// expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) +// .andReturn(false).atLeastOnce(); +// expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) +// .andReturn(false).atLeastOnce(); +// +// Calendar c = Calendar.getInstance(); +// c.add(Calendar.MILLISECOND, -DeviceManagerImpl.ENTITY_TIMEOUT-1); +// Entity entity1 = new Entity(1L, null, 1, 1L, 1, c.getTime()); +// Entity entity2 = new Entity(1L, null, 2, 5L, 1, c.getTime()); +// +// ITopologyService mockTopology = createMock(ITopologyService.class); +// deviceManager.topology = mockTopology; +// +// expect(mockTopology.isAttachmentPointPort(EasyMock.anyLong(), +// EasyMock.anyShort())). +// andReturn(true). +// anyTimes(); +// expect(mockTopology.getL2DomainId(1L)).andReturn(1L).anyTimes(); +// expect(mockTopology.getL2DomainId(5L)).andReturn(1L).anyTimes(); +// expect(mockTopology.isConsistent(EasyMock.anyLong(), +// EasyMock.anyShort(), +// EasyMock.anyLong(), +// EasyMock.anyShort())).andReturn(false). +// anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(EasyMock.anyLong(), +// EasyMock.anyShort())). +// andReturn(false).anyTimes(); +// replay(mockTopology); +// +// IDevice d = deviceManager.learnDeviceByEntity(entity2); +// d = deviceManager.learnDeviceByEntity(entity1); +// assertArrayEquals(new Integer[] { 1, 2 }, d.getIPv4Addresses()); +// +// replay(mockListener); +// deviceManager.addListener(mockListener); +// verify(mockListener); +// reset(mockListener); +// +// mockListener.deviceRemoved(isA(IDevice.class)); +// replay(mockListener); +// deviceManager.entityCleanupTask.reschedule(0, null); +// +// IDevice r = deviceManager.getDevice(d.getDeviceKey()); +// assertNull(r); +// Iterator diter = +// deviceManager.queryClassDevices(d.getEntityClass(), +// null, null, 1, null, null); +// assertFalse(diter.hasNext()); +// +// r = deviceManager.findDevice(1L, null, null, null, null); +// assertNull(r); +// +// verify(mockListener); +// } +// +// /* +// * A ConcurrentHashMap for devices (deviceMap) that can be used to test +// * code that specially handles concurrent modification situations. In +// * particular, we overwrite values() and will replace / remove all the +// * elements returned by values. +// * +// * The remove flag in the constructor specifies if devices returned by +// * values() should be removed or replaced. +// */ +// protected static class ConcurrentlyModifiedDeviceMap +// extends ConcurrentHashMap { +// private static final long serialVersionUID = 7784938535441180562L; +// protected boolean remove; +// public ConcurrentlyModifiedDeviceMap(boolean remove) { +// super(); +// this.remove = remove; +// } +// +// @Override +// public Collection values() { +// // Get the values from the real map and copy them since +// // the collection returned by values can reflect changed +// Collection devs = new ArrayList(super.values()); +// for (Device d: devs) { +// if (remove) { +// // We remove the device from the underlying map +// super.remove(d.getDeviceKey()); +// } else { +// super.remove(d.getDeviceKey()); +// // We add a different Device instance with the same +// // key to the map. We'll do some hackery so the device +// // is different enough to compare differently in equals +// // but otherwise looks the same. +// // It's ugly but it works. +// // clone entities +// Device newDevice = d; +// for (Entity e: d.getEntities()) { +// Entity newEntity = new Entity (e.macAddress, +// e.vlan, +// e.ipv4Address, +// e.switchDPID, +// e.switchPort, +// e.lastSeenTimestamp); +// if (e.vlan == null) +// newEntity.vlan = (short)1; +// else +// newEntity.vlan = (short)((e.vlan + 1 % 4095)+1); +// newDevice = new Device(newDevice, newEntity, -1); +// } +// assertEquals(false, newDevice.equals(d)); +// super.put(newDevice.getDeviceKey(), newDevice); +// } +// } +// return devs; +// } +// } +// +// @Test +// public void testEntityExpiration() throws Exception { +// doTestEntityExpiration(); +// } +// +// @Test +// public void testDeviceExpiration() throws Exception { +// doTestDeviceExpiration(); +// } +// +// /* Test correct entity cleanup behavior when a concurrent modification +// * occurs. +// */ +// @Test +// public void testEntityExpirationConcurrentModification() throws Exception { +// deviceManager.deviceMap = new ConcurrentlyModifiedDeviceMap(false); +// doTestEntityExpiration(); +// } +// +// /* Test correct entity cleanup behavior when a concurrent remove +// * occurs. +// */ +// @Test +// public void testDeviceExpirationConcurrentRemove() throws Exception { +// deviceManager.deviceMap = new ConcurrentlyModifiedDeviceMap(true); +// doTestDeviceExpiration(); +// } +// +// /* Test correct entity cleanup behavior when a concurrent modification +// * occurs. +// */ +// @Test +// public void testDeviceExpirationConcurrentModification() throws Exception { +// deviceManager.deviceMap = new ConcurrentlyModifiedDeviceMap(false); +// doTestDeviceExpiration(); +// } +// +// +// @Test +// public void testAttachmentPointFlapping() throws Exception { +// Calendar c = Calendar.getInstance(); +// +// ITopologyService mockTopology = createMock(ITopologyService.class); +// expect(mockTopology.isAttachmentPointPort(anyLong(), +// anyShort())).andReturn(true).anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(anyLong(), +// anyShort())). +// andReturn(false).anyTimes(); +// expect(mockTopology.isInSameBroadcastDomain(anyLong(), anyShort(), +// anyLong(), anyShort())).andReturn(false).anyTimes(); +// expect(mockTopology.getL2DomainId(anyLong())). +// andReturn(1L).anyTimes(); +// expect(mockTopology.isConsistent(1L, (short)1, 1L, (short)1)). +// andReturn(true).anyTimes(); +// expect(mockTopology.isConsistent(1L, (short)1, 5L, (short)1)). +// andReturn(false).anyTimes(); +// expect(mockTopology.isConsistent(1L, (short)1, 10L, (short)1)). +// andReturn(false).anyTimes(); +// expect(mockTopology.isConsistent(5L, (short)1, 10L, (short)1)). +// andReturn(false).anyTimes(); +// expect(mockTopology.isConsistent(10L, (short)1, 1L, (short)1)). +// andReturn(false).anyTimes(); +// expect(mockTopology.isConsistent(5L, (short)1, 1L, (short)1)). +// andReturn(false).anyTimes(); +// expect(mockTopology.isConsistent(10L, (short)1, 5L, (short)1)). +// andReturn(false).anyTimes(); +// +// Date topologyUpdateTime = new Date(); +// expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). +// anyTimes(); +// +// +// replay(mockTopology); +// deviceManager.topology = mockTopology; +// +// Entity entity1 = new Entity(1L, null, null, 1L, 1, c.getTime()); +// Entity entity1a = new Entity(1L, null, 1, 1L, 1, c.getTime()); +// Entity entity2 = new Entity(1L, null, null, 5L, 1, c.getTime()); +// Entity entity3 = new Entity(1L, null, null, 10L, 1, c.getTime()); +// entity1.setLastSeenTimestamp(c.getTime()); +// c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT/2); +// entity1a.setLastSeenTimestamp(c.getTime()); +// c.add(Calendar.MILLISECOND, 1); +// entity2.setLastSeenTimestamp(c.getTime()); +// c.add(Calendar.MILLISECOND, 1); +// entity3.setLastSeenTimestamp(c.getTime()); +// +// +// +// IDevice d; +// d = deviceManager.learnDeviceByEntity(entity1); +// d = deviceManager.learnDeviceByEntity(entity1a); +// d = deviceManager.learnDeviceByEntity(entity2); +// d = deviceManager.learnDeviceByEntity(entity3); +// +// // all entities are active, so entity3 should win +// assertArrayEquals(new SwitchPort[] { new SwitchPort(10L, 1) }, +// d.getAttachmentPoints()); +// +// assertArrayEquals(new SwitchPort[] { new SwitchPort(10L, 1),}, +// d.getAttachmentPoints(true)); +// +// c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT/4); +// entity1.setLastSeenTimestamp(c.getTime()); +// d = deviceManager.learnDeviceByEntity(entity1); +// +// // all are still active; entity3 should still win +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, +// d.getAttachmentPoints()); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), +// new SwitchPort(5L, 1, +// ErrorStatus.DUPLICATE_DEVICE), +// new SwitchPort(10L, 1, +// ErrorStatus.DUPLICATE_DEVICE) }, +// d.getAttachmentPoints(true)); +// +// c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT+2000); +// entity1.setLastSeenTimestamp(c.getTime()); +// d = deviceManager.learnDeviceByEntity(entity1); +// +// assertEquals(entity1.getActiveSince(), entity1.getLastSeenTimestamp()); +// // entity1 should now be the only active entity +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, +// d.getAttachmentPoints()); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, +// d.getAttachmentPoints(true)); +// } +// +// +// @Test +// public void testAttachmentPointFlappingTwoCluster() throws Exception { +// Calendar c = Calendar.getInstance(); +// +// ITopologyService mockTopology = createMock(ITopologyService.class); +// expect(mockTopology.isAttachmentPointPort(anyLong(), +// anyShort())).andReturn(true).anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(anyLong(), +// anyShort())). +// andReturn(false).anyTimes(); +// expect(mockTopology.isInSameBroadcastDomain(anyLong(), anyShort(), +// anyLong(), anyShort())).andReturn(false).anyTimes(); +// expect(mockTopology.getL2DomainId(1L)). +// andReturn(1L).anyTimes(); +// expect(mockTopology.getL2DomainId(5L)). +// andReturn(5L).anyTimes(); +// expect(mockTopology.isConsistent(1L, (short)1, 1L, (short)2)). +// andReturn(false).anyTimes(); +// expect(mockTopology.isConsistent(1L, (short)2, 5L, (short)1)). +// andReturn(false).anyTimes(); +// expect(mockTopology.isConsistent(5L, (short)1, 5L, (short)2)). +// andReturn(false).anyTimes(); +// expect(mockTopology.isConsistent(1L, (short)2, 1L, (short)1)). +// andReturn(false).anyTimes(); +// expect(mockTopology.isConsistent(1L, (short)1, 5L, (short)1)). +// andReturn(false).anyTimes(); +// expect(mockTopology.isConsistent(1L, (short)1, 5L, (short)2)). +// andReturn(false).anyTimes(); +// expect(mockTopology.isConsistent(5L, (short)2, 5L, (short)1)). +// andReturn(false).anyTimes(); +// +// Date topologyUpdateTime = new Date(); +// expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). +// anyTimes(); +// +// replay(mockTopology); +// deviceManager.topology = mockTopology; +// +// Entity entity1 = new Entity(1L, null, null, 1L, 1, c.getTime()); +// Entity entity2 = new Entity(1L, null, null, 1L, 2, c.getTime()); +// Entity entity3 = new Entity(1L, null, null, 5L, 1, c.getTime()); +// Entity entity4 = new Entity(1L, null, null, 5L, 2, c.getTime()); +// entity1.setLastSeenTimestamp(c.getTime()); +// c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT/2); +// c.add(Calendar.MILLISECOND, 1); +// entity2.setLastSeenTimestamp(c.getTime()); +// c.add(Calendar.MILLISECOND, 1); +// entity3.setLastSeenTimestamp(c.getTime()); +// c.add(Calendar.MILLISECOND, 1); +// entity4.setLastSeenTimestamp(c.getTime()); +// +// deviceManager.learnDeviceByEntity(entity1); +// deviceManager.learnDeviceByEntity(entity2); +// deviceManager.learnDeviceByEntity(entity3); +// IDevice d = deviceManager.learnDeviceByEntity(entity4); +// +// // all entities are active, so entities 2,4 should win +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 2), +// new SwitchPort(5L, 2) }, +// d.getAttachmentPoints()); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 2), +// new SwitchPort(5L, 2)}, +// d.getAttachmentPoints(true)); +// +// c.add(Calendar.MILLISECOND, 1); +// entity1.setLastSeenTimestamp(c.getTime()); +// d = deviceManager.learnDeviceByEntity(entity1); +// +// // all entities are active, so entities 2,4 should win +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), +// new SwitchPort(5L, 2) }, +// d.getAttachmentPoints()); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), +// new SwitchPort(5L, 2), +// new SwitchPort(1L, 2, ErrorStatus.DUPLICATE_DEVICE)}, +// d.getAttachmentPoints(true)); +// +// c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT+1); +// entity1.setLastSeenTimestamp(c.getTime()); +// d = deviceManager.learnDeviceByEntity(entity1); +// +// // entities 3,4 are still in conflict, but 1 should be resolved +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), +// new SwitchPort(5L, 2) }, +// d.getAttachmentPoints()); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), +// new SwitchPort(5L, 2)}, +// d.getAttachmentPoints(true)); +// +// entity3.setLastSeenTimestamp(c.getTime()); +// d = deviceManager.learnDeviceByEntity(entity3); +// +// // no conflicts, 1 and 3 will win +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), +// new SwitchPort(5L, 1) }, +// d.getAttachmentPoints()); +// assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), +// new SwitchPort(5L, 1) }, +// d.getAttachmentPoints(true)); +// +// } +// +// protected void doTestDeviceQuery() throws Exception { +// Entity entity1 = new Entity(1L, (short)1, 1, 1L, 1, new Date()); +// Entity entity2 = new Entity(2L, (short)2, 2, 1L, 2, new Date()); +// Entity entity3 = new Entity(3L, (short)3, 3, 5L, 1, new Date()); +// Entity entity4 = new Entity(4L, (short)4, 3, 5L, 2, new Date()); +// Entity entity5 = new Entity(1L, (short)4, 3, 5L, 2, new Date()); +// +// Device d1 = deviceManager.learnDeviceByEntity(entity1); +// deviceManager.learnDeviceByEntity(entity2); +// Device d3 = deviceManager.learnDeviceByEntity(entity3); +// Device d4 = deviceManager.learnDeviceByEntity(entity4); +// +// IDevice d; +// +// Iterator iter = +// deviceManager.queryDevices(null, (short)1, 1, null, null); +// int count = 0; +// while (iter.hasNext()) { +// count += 1; +// d = iter.next(); +// assertEquals(d1.getDeviceKey(), d.getDeviceKey()); +// } +// assertEquals(1, count); +// +// iter = deviceManager.queryDevices(null, (short)3, 3, null, null); +// count = 0; +// while (iter.hasNext()) { +// count += 1; +// d = iter.next(); +// assertEquals(d3.getDeviceKey(), d.getDeviceKey()); +// } +// assertEquals(1, count); +// +// iter = deviceManager.queryDevices(null, (short)1, 3, null, null); +// count = 0; +// while (iter.hasNext()) { +// count += 1; +// iter.next(); +// } +// assertEquals(0, count); +// +// Device d5 = deviceManager.learnDeviceByEntity(entity5); +// iter = deviceManager.queryDevices(null, (short)4, 3, null, null); +// count = 0; +// Set deviceKeysFromIterator = new HashSet(); +// while (iter.hasNext()) { +// count += 1; +// d = iter.next(); +// deviceKeysFromIterator.add(d.getDeviceKey()); +// } +// Set expectedDeviceKeys = new HashSet(); +// expectedDeviceKeys.add(d4.getDeviceKey()); +// expectedDeviceKeys.add(d5.getDeviceKey()); +// assertEquals(expectedDeviceKeys, deviceKeysFromIterator); +// assertEquals(2, count); +// +// +// iter = deviceManager.queryDevices(1L, null, null, null, null); +// count = 0; +// deviceKeysFromIterator = new HashSet(); +// while (iter.hasNext()) { +// count += 1; +// d = iter.next(); +// deviceKeysFromIterator.add(d.getDeviceKey()); +// } +// expectedDeviceKeys = new HashSet(); +// expectedDeviceKeys.add(d1.getDeviceKey()); +// expectedDeviceKeys.add(d5.getDeviceKey()); +// assertEquals(expectedDeviceKeys, deviceKeysFromIterator); +// assertEquals(2, count); +// } +// +// @Test +// public void testDeviceIndex() throws Exception { +// EnumSet indexFields = +// EnumSet.noneOf(IDeviceService.DeviceField.class); +// indexFields.add(IDeviceService.DeviceField.IPV4); +// indexFields.add(IDeviceService.DeviceField.VLAN); +// deviceManager.addIndex(false, indexFields); +// +// indexFields = EnumSet.noneOf(IDeviceService.DeviceField.class); +// deviceManager.addIndex(false, indexFields); +// +// ITopologyService mockTopology = createMock(ITopologyService.class); +// deviceManager.topology = mockTopology; +// expect(mockTopology.isAttachmentPointPort(anyLong(), +// anyShort())). +// andReturn(true).anyTimes(); +// expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes(); +// replay(mockTopology); +// doTestDeviceQuery(); +// } +// +// @Test +// public void testDeviceQuery() throws Exception { +// ITopologyService mockTopology = createMock(ITopologyService.class); +// deviceManager.topology = mockTopology; +// expect(mockTopology.isAttachmentPointPort(anyLong(), +// anyShort())). +// andReturn(true).anyTimes(); +// expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes(); +// replay(mockTopology); +// +// doTestDeviceQuery(); +// } +// +// protected void doTestDeviceClassQuery() throws Exception { +// Entity entity1 = new Entity(1L, (short)1, 1, 1L, 1, new Date()); +// Entity entity2 = new Entity(2L, (short)2, 2, 1L, 2, new Date()); +// Entity entity3 = new Entity(3L, (short)3, 3, 5L, 1, new Date()); +// Entity entity4 = new Entity(4L, (short)4, 3, 5L, 2, new Date()); +// Entity entity5 = new Entity(1L, (short)4, 3, 5L, 2, new Date()); +// +// IDevice d1 = deviceManager.learnDeviceByEntity(entity1); +// IDevice d2 = deviceManager.learnDeviceByEntity(entity2); +// IDevice d3 = deviceManager.learnDeviceByEntity(entity3); +// IDevice d4 = deviceManager.learnDeviceByEntity(entity4); +// assertEquals(d1.getEntityClass(), d2.getEntityClass()); +// assertEquals(d1.getEntityClass(), d3.getEntityClass()); +// assertEquals(d1.getEntityClass(), d4.getEntityClass()); +// +// IDevice d; +// +// Iterator iter = +// deviceManager.queryClassDevices(d1.getEntityClass(), null, +// (short)1, 1, null, null); +// int count = 0; +// while (iter.hasNext()) { +// count += 1; +// d = iter.next(); +// assertEquals(d1.getDeviceKey(), d.getDeviceKey()); +// } +// assertEquals(1, count); +// +// iter = deviceManager.queryClassDevices(d1.getEntityClass(), null, +// (short)3, 3, null, null); +// count = 0; +// while (iter.hasNext()) { +// count += 1; +// d = iter.next(); +// assertEquals(d3.getDeviceKey(), d.getDeviceKey()); +// +// } +// assertEquals(1, count); +// +// iter = deviceManager.queryClassDevices(d1.getEntityClass(), null, +// (short)1, 3, null, null); +// count = 0; +// while (iter.hasNext()) { +// count += 1; +// iter.next(); +// } +// assertEquals(0, count); +// +// IDevice d5 = deviceManager.learnDeviceByEntity(entity5); +// assertEquals(d1.getEntityClass(), d5.getEntityClass()); +// iter = deviceManager.queryClassDevices(d1.getEntityClass(), null, +// (short)4, 3, null, null); +// count = 0; +// Set deviceKeysFromIterator = new HashSet(); +// while (iter.hasNext()) { +// count += 1; +// d = iter.next(); +// deviceKeysFromIterator.add(d.getDeviceKey()); +// } +// Set expectedDeviceKeys = new HashSet(); +// expectedDeviceKeys.add(d4.getDeviceKey()); +// expectedDeviceKeys.add(d5.getDeviceKey()); +// assertEquals(expectedDeviceKeys, deviceKeysFromIterator); +// assertEquals(2, count); +// } +// +// @Test +// public void testDeviceClassIndex() throws Exception { +// EnumSet indexFields = +// EnumSet.noneOf(IDeviceService.DeviceField.class); +// indexFields.add(IDeviceService.DeviceField.IPV4); +// indexFields.add(IDeviceService.DeviceField.VLAN); +// deviceManager.addIndex(true, indexFields); +// +// ITopologyService mockTopology = createMock(ITopologyService.class); +// deviceManager.topology = mockTopology; +// expect(mockTopology.isAttachmentPointPort(anyLong(), +// anyShort())). +// andReturn(true).anyTimes(); +// expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes(); +// replay(mockTopology); +// +// doTestDeviceClassQuery(); +// } +// +// @Test +// public void testDeviceClassQuery() throws Exception { +// ITopologyService mockTopology = createMock(ITopologyService.class); +// deviceManager.topology = mockTopology; +// expect(mockTopology.isAttachmentPointPort(anyLong(), +// anyShort())). +// andReturn(true).anyTimes(); +// expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes(); +// replay(mockTopology); +// +// doTestDeviceClassQuery(); +// } +// +// @Test +// public void testFindDevice() throws FloodlightModuleException { +// boolean exceptionCaught; +// deviceManager.entityClassifier= new MockEntityClassifierMac(); +// deviceManager.startUp(null); +// +// ITopologyService mockTopology = createMock(ITopologyService.class); +// deviceManager.topology = mockTopology; +// expect(mockTopology.isAttachmentPointPort(anyLong(), +// anyShort())). +// andReturn(true).anyTimes(); +// expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes(); +// replay(mockTopology); +// +// Entity entity1 = new Entity(1L, (short)1, 1, 1L, 1, new Date()); +// Entity entity2 = new Entity(2L, (short)2, 2, 1L, 2, new Date()); +// Entity entity2b = new Entity(22L, (short)2, 2, 1L, 2, new Date()); +// +// Entity entity3 = new Entity(3L, (short)1, 3, 2L, 1, new Date()); +// Entity entity4 = new Entity(4L, (short)2, 4, 2L, 2, new Date()); +// +// Entity entity5 = new Entity(5L, (short)1, 5, 3L, 1, new Date()); +// +// +// IDevice d1 = deviceManager.learnDeviceByEntity(entity1); +// IDevice d2 = deviceManager.learnDeviceByEntity(entity2); +// IDevice d3 = deviceManager.learnDeviceByEntity(entity3); +// IDevice d4 = deviceManager.learnDeviceByEntity(entity4); +// IDevice d5 = deviceManager.learnDeviceByEntity(entity5); +// +// // Make sure the entity classifier worked as expected +// assertEquals(MockEntityClassifierMac.testECMac1, d1.getEntityClass()); +// assertEquals(MockEntityClassifierMac.testECMac1, d2.getEntityClass()); +// assertEquals(MockEntityClassifierMac.testECMac2, d3.getEntityClass()); +// assertEquals(MockEntityClassifierMac.testECMac2, d4.getEntityClass()); +// assertEquals(DefaultEntityClassifier.entityClass, +// d5.getEntityClass()); +// +// // Look up the device using findDevice() which uses only the primary +// // index +// assertEquals(d1, deviceManager.findDevice(entity1.getMacAddress(), +// entity1.getVlan(), +// entity1.getIpv4Address(), +// entity1.getSwitchDPID(), +// entity1.getSwitchPort())); +// // port changed. Device will be found through class index +// assertEquals(d1, deviceManager.findDevice(entity1.getMacAddress(), +// entity1.getVlan(), +// entity1.getIpv4Address(), +// entity1.getSwitchDPID(), +// entity1.getSwitchPort()+1)); +// // VLAN changed. No device matches +// assertEquals(null, deviceManager.findDevice(entity1.getMacAddress(), +// (short)42, +// entity1.getIpv4Address(), +// entity1.getSwitchDPID(), +// entity1.getSwitchPort())); +// assertEquals(null, deviceManager.findDevice(entity1.getMacAddress(), +// null, +// entity1.getIpv4Address(), +// entity1.getSwitchDPID(), +// entity1.getSwitchPort())); +// assertEquals(d2, deviceManager.findDeviceByEntity(entity2)); +// assertEquals(null, deviceManager.findDeviceByEntity(entity2b)); +// assertEquals(d3, deviceManager.findDevice(entity3.getMacAddress(), +// entity3.getVlan(), +// entity3.getIpv4Address(), +// entity3.getSwitchDPID(), +// entity3.getSwitchPort())); +// // switch and port not set. throws exception +// exceptionCaught = false; +// try { +// assertEquals(null, deviceManager.findDevice(entity3.getMacAddress(), +// entity3.getVlan(), +// entity3.getIpv4Address(), +// null, +// null)); +// } +// catch (IllegalArgumentException e) { +// exceptionCaught = true; +// } +// if (!exceptionCaught) +// fail("findDevice() did not throw IllegalArgumentException"); +// assertEquals(d4, deviceManager.findDeviceByEntity(entity4)); +// assertEquals(d5, deviceManager.findDevice(entity5.getMacAddress(), +// entity5.getVlan(), +// entity5.getIpv4Address(), +// entity5.getSwitchDPID(), +// entity5.getSwitchPort())); +// // switch and port not set. throws exception (swith/port are key +// // fields of IEntityClassifier but not d5.entityClass +// exceptionCaught = false; +// try { +// assertEquals(d5, deviceManager.findDevice(entity5.getMacAddress(), +// entity5.getVlan(), +// entity5.getIpv4Address(), +// null, +// null)); +// } +// catch (IllegalArgumentException e) { +// exceptionCaught = true; +// } +// if (!exceptionCaught) +// fail("findDevice() did not throw IllegalArgumentException"); +// +// +// Entity entityNoClass = new Entity(5L, (short)1, 5, -1L, 1, new Date()); +// assertEquals(null, deviceManager.findDeviceByEntity(entityNoClass)); +// +// +// // Now look up destination devices +// assertEquals(d1, deviceManager.findClassDevice(d2.getEntityClass(), +// entity1.getMacAddress(), +// entity1.getVlan(), +// entity1.getIpv4Address())); +// assertEquals(d1, deviceManager.findClassDevice(d2.getEntityClass(), +// entity1.getMacAddress(), +// entity1.getVlan(), +// null)); +// assertEquals(null, deviceManager.findClassDevice(d2.getEntityClass(), +// entity1.getMacAddress(), +// (short) -1, +// 0)); +// } +// +// +// +// @Test +// public void testGetIPv4Addresses() { +// // Looks like Date is only 1s granularity +// +// ITopologyService mockTopology = createMock(ITopologyService.class); +// deviceManager.topology = mockTopology; +// expect(mockTopology.isAttachmentPointPort(anyLong(), +// anyShort())). +// andReturn(true).anyTimes(); +// expect(mockTopology.getL2DomainId(anyLong())).andReturn(1L).anyTimes(); +// expect(mockTopology.isConsistent(EasyMock.anyLong(), +// EasyMock.anyShort(), +// EasyMock.anyLong(), +// EasyMock.anyShort())) +// .andReturn(false) +// .anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(EasyMock.anyLong(), +// EasyMock.anyShort())) +// .andReturn(false) +// .anyTimes(); +// expect(mockTopology.isInSameBroadcastDomain(EasyMock.anyLong(), +// EasyMock.anyShort(), +// EasyMock.anyLong(), +// EasyMock.anyShort())). +// andReturn(false).anyTimes(); +// replay(mockTopology); +// +// Entity e1 = new Entity(1L, (short)1, null, null, null, new Date(2000)); +// Device d1 = deviceManager.learnDeviceByEntity(e1); +// assertArrayEquals(new Integer[0], d1.getIPv4Addresses()); +// +// +// Entity e2 = new Entity(2L, (short)2, 2, null, null, new Date(2000)); +// Device d2 = deviceManager.learnDeviceByEntity(e2); +// d2 = deviceManager.learnDeviceByEntity(e2); +// assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); +// // More than one entity +// Entity e2b = new Entity(2L, (short)2, null, 2L, 2, new Date(3000)); +// d2 = deviceManager.learnDeviceByEntity(e2b); +// assertEquals(2, d2.entities.length); +// assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); +// // and now add an entity with an IP +// Entity e2c = new Entity(2L, (short)2, 2, 2L, 3, new Date(3000)); +// d2 = deviceManager.learnDeviceByEntity(e2c); +// assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); +// assertEquals(3, d2.entities.length); +// +// // Other devices with different IPs shouldn't interfere +// Entity e3 = new Entity(3L, (short)3, 3, null, null, new Date(4000)); +// Entity e3b = new Entity(3L, (short)3, 3, 3L, 3, new Date(4400)); +// Device d3 = deviceManager.learnDeviceByEntity(e3); +// d3 = deviceManager.learnDeviceByEntity(e3b); +// assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); +// assertArrayEquals(new Integer[] { 3 }, d3.getIPv4Addresses()); +// +// // Add another IP to d3 +// Entity e3c = new Entity(3L, (short)3, 33, 3L, 3, new Date(4400)); +// d3 = deviceManager.learnDeviceByEntity(e3c); +// Integer[] ips = d3.getIPv4Addresses(); +// Arrays.sort(ips); +// assertArrayEquals(new Integer[] { 3, 33 }, ips); +// +// // Add another device that also claims IP2 but is older than e2 +// Entity e4 = new Entity(4L, (short)4, 2, null, null, new Date(1000)); +// Entity e4b = new Entity(4L, (short)4, null, 4L, 4, new Date(1000)); +// Device d4 = deviceManager.learnDeviceByEntity(e4); +// assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); +// assertArrayEquals(new Integer[0], d4.getIPv4Addresses()); +// // add another entity to d4 +// d4 = deviceManager.learnDeviceByEntity(e4b); +// assertArrayEquals(new Integer[0], d4.getIPv4Addresses()); +// +// // Make e4 and e4a newer +// Entity e4c = new Entity(4L, (short)4, 2, null, null, new Date(5000)); +// Entity e4d = new Entity(4L, (short)4, null, 4L, 5, new Date(5000)); +// d4 = deviceManager.learnDeviceByEntity(e4c); +// d4 = deviceManager.learnDeviceByEntity(e4d); +// assertArrayEquals(new Integer[0], d2.getIPv4Addresses()); +// // FIXME: d4 should not return IP4 +// assertArrayEquals(new Integer[] { 2 }, d4.getIPv4Addresses()); +// +// // Add another newer entity to d2 but with different IP +// Entity e2d = new Entity(2L, (short)2, 22, 4L, 6, new Date(6000)); +// d2 = deviceManager.learnDeviceByEntity(e2d); +// assertArrayEquals(new Integer[] { 22 }, d2.getIPv4Addresses()); +// assertArrayEquals(new Integer[] { 2 }, d4.getIPv4Addresses()); +// +// // new IP for d2,d4 but with same timestamp. Both devices get the IP +// Entity e2e = new Entity(2L, (short)2, 42, 2L, 4, new Date(7000)); +// d2 = deviceManager.learnDeviceByEntity(e2e); +// ips= d2.getIPv4Addresses(); +// Arrays.sort(ips); +// assertArrayEquals(new Integer[] { 22, 42 }, ips); +// Entity e4e = new Entity(4L, (short)4, 42, 4L, 7, new Date(7000)); +// d4 = deviceManager.learnDeviceByEntity(e4e); +// ips= d4.getIPv4Addresses(); +// Arrays.sort(ips); +// assertArrayEquals(new Integer[] { 2, 42 }, ips); +// +// // add a couple more IPs +// Entity e2f = new Entity(2L, (short)2, 4242, 2L, 5, new Date(8000)); +// d2 = deviceManager.learnDeviceByEntity(e2f); +// ips= d2.getIPv4Addresses(); +// Arrays.sort(ips); +// assertArrayEquals(new Integer[] { 22, 42, 4242 }, ips); +// Entity e4f = new Entity(4L, (short)4, 4242, 4L, 8, new Date(9000)); +// d4 = deviceManager.learnDeviceByEntity(e4f); +// ips= d4.getIPv4Addresses(); +// Arrays.sort(ips); +// assertArrayEquals(new Integer[] { 2, 42, 4242 }, ips); +// } +// +// // TODO: this test should really go into a separate class that collects +// // unit tests for Device +// @Test +// public void testGetSwitchPortVlanId() { +// Entity entity1 = new Entity(1L, (short)1, null, 10L, 1, new Date()); +// Entity entity2 = new Entity(1L, null, null, 10L, 1, new Date()); +// Entity entity3 = new Entity(1L, (short)3, null, 1L, 1, new Date()); +// Entity entity4 = new Entity(1L, (short)42, null, 1L, 1, new Date()); +// Entity[] entities = new Entity[] { entity1, entity2, +// entity3, entity4 +// }; +// Device d = new Device(null,1L, null, null, null, +// Arrays.asList(entities), null); +// SwitchPort swp1x1 = new SwitchPort(1L, 1); +// SwitchPort swp1x2 = new SwitchPort(1L, 2); +// SwitchPort swp2x1 = new SwitchPort(2L, 1); +// SwitchPort swp10x1 = new SwitchPort(10L, 1); +// assertArrayEquals(new Short[] { -1, 1}, +// d.getSwitchPortVlanIds(swp10x1)); +// assertArrayEquals(new Short[] { 3, 42}, +// d.getSwitchPortVlanIds(swp1x1)); +// assertArrayEquals(new Short[0], +// d.getSwitchPortVlanIds(swp1x2)); +// assertArrayEquals(new Short[0], +// d.getSwitchPortVlanIds(swp2x1)); +// } +// +// @Test +// public void testReclassifyDevice() throws FloodlightModuleException { +// MockFlexEntityClassifier flexClassifier = +// new MockFlexEntityClassifier(); +// deviceManager.entityClassifier= flexClassifier; +// deviceManager.startUp(null); +// +// ITopologyService mockTopology = createMock(ITopologyService.class); +// deviceManager.topology = mockTopology; +// expect(mockTopology.isAttachmentPointPort(anyLong(), +// anyShort())). +// andReturn(true).anyTimes(); +// expect(mockTopology.getL2DomainId(anyLong())).andReturn(1L).anyTimes(); +// expect(mockTopology.isConsistent(EasyMock.anyLong(), +// EasyMock.anyShort(), +// EasyMock.anyLong(), +// EasyMock.anyShort())) +// .andReturn(false) +// .anyTimes(); +// expect(mockTopology.isBroadcastDomainPort(EasyMock.anyLong(), +// EasyMock.anyShort())) +// .andReturn(false) +// .anyTimes(); +// replay(mockTopology); +// +// //flexClassifier.createTestEntityClass("Class1"); +// +// Entity entity1 = new Entity(1L, (short)1, 1, 1L, 1, new Date()); +// Entity entity1b = new Entity(1L, (short)2, 1, 1L, 1, new Date()); +// Entity entity2 = new Entity(2L, (short)1, 2, 2L, 2, new Date()); +// Entity entity2b = new Entity(2L, (short)2, 2, 2L, 2, new Date()); +// +// +// Device d1 = deviceManager.learnDeviceByEntity(entity1); +// Device d2 = deviceManager.learnDeviceByEntity(entity2); +// Device d1b = deviceManager.learnDeviceByEntity(entity1b); +// Device d2b = deviceManager.learnDeviceByEntity(entity2b); +// +// d1 = deviceManager.getDeviceIteratorForQuery(entity1.getMacAddress(), +// entity1.getVlan(), entity1.getIpv4Address(), +// entity1.getSwitchDPID(), entity1.getSwitchPort()) +// .next(); +// d1b = deviceManager.getDeviceIteratorForQuery(entity1b.getMacAddress(), +// entity1b.getVlan(), entity1b.getIpv4Address(), +// entity1b.getSwitchDPID(), entity1b.getSwitchPort()).next(); +// +// assertEquals(d1, d1b); +// +// d2 = deviceManager.getDeviceIteratorForQuery(entity2.getMacAddress(), +// entity2.getVlan(), entity2.getIpv4Address(), +// entity2.getSwitchDPID(), entity2.getSwitchPort()).next(); +// d2b = deviceManager.getDeviceIteratorForQuery(entity2b.getMacAddress(), +// entity2b.getVlan(), entity2b.getIpv4Address(), +// entity2b.getSwitchDPID(), entity2b.getSwitchPort()).next(); +// assertEquals(d2, d2b); +// +// IEntityClass eC1 = flexClassifier.createTestEntityClass("C1"); +// IEntityClass eC2 = flexClassifier.createTestEntityClass("C2"); +// +// flexClassifier.addVlanEntities((short)1, eC1); +// flexClassifier.addVlanEntities((short)2, eC1); +// +// deviceManager.reclassifyDevice(d1); +// deviceManager.reclassifyDevice(d2); +// +// d1 = deviceManager.deviceMap.get( +// deviceManager.primaryIndex.findByEntity(entity1)); +// d1b = deviceManager.deviceMap.get( +// deviceManager.primaryIndex.findByEntity(entity1b)); +// +// assertEquals(d1, d1b); +// +// d2 = deviceManager.deviceMap.get( +// deviceManager.primaryIndex.findByEntity(entity2)); +// d2b = deviceManager.deviceMap.get( +// deviceManager.primaryIndex.findByEntity(entity2b)); +// +// assertEquals(d2, d2b); +// +// flexClassifier.addVlanEntities((short)1, eC2); +// +// deviceManager.reclassifyDevice(d1); +// deviceManager.reclassifyDevice(d2); +// d1 = deviceManager.deviceMap.get( +// deviceManager.primaryIndex.findByEntity(entity1)); +// d1b = deviceManager.deviceMap.get( +// deviceManager.primaryIndex.findByEntity(entity1b)); +// d2 = deviceManager.deviceMap.get( +// deviceManager.primaryIndex.findByEntity(entity2)); +// d2b = deviceManager.deviceMap.get( +// deviceManager.primaryIndex.findByEntity(entity2b)); +// +// assertNotSame(d1, d1b); +// +// assertNotSame(d2, d2b); +// +// flexClassifier.addVlanEntities((short)1, eC1); +// deviceManager.reclassifyDevice(d1); +// deviceManager.reclassifyDevice(d2); +// ClassState classState = deviceManager.classStateMap.get(eC1.getName()); +// +// Long deviceKey1 = null; +// Long deviceKey1b = null; +// Long deviceKey2 = null; +// Long deviceKey2b = null; +// +// deviceKey1 = +// classState.classIndex.findByEntity(entity1); +// deviceKey1b = +// classState.classIndex.findByEntity(entity1b); +// deviceKey2 = +// classState.classIndex.findByEntity(entity2); +// deviceKey2b = +// classState.classIndex.findByEntity(entity2b); +// +// assertEquals(deviceKey1, deviceKey1b); +// +// assertEquals(deviceKey2, deviceKey2b); +// } +// +// @Test +// public void testSyncEntity() { +// Date d1 = new Date(); +// Date d2 = new Date(0); +// Entity e1 = new Entity(1L, (short)2, 3, 4L, 5, d1); +// e1.setActiveSince(d2); +// SyncEntity se1 = new SyncEntity(e1); +// assertEntityEquals(e1, se1); +// assertEquals(1L, se1.macAddress); +// assertEquals(Short.valueOf((short)2), se1.vlan); +// assertEquals(Integer.valueOf(3), se1.ipv4Address); +// assertEquals(Long.valueOf(4L), se1.switchDPID); +// assertEquals(Integer.valueOf(5), se1.switchPort); +// assertEquals(d1, se1.lastSeenTimestamp); +// assertEquals(d2, se1.activeSince); +// assertNotSame(d1, se1.lastSeenTimestamp); +// assertNotSame(d2, se1.activeSince); +// +// Entity e2 = new Entity(42L, null, null, null, null, null); +// SyncEntity se2 = new SyncEntity(e2); +// assertEntityEquals(e2, se2); +// +// SyncEntity se3 = new SyncEntity(); +// SyncEntity se4 = new SyncEntity(); +// se3.lastSeenTimestamp = new Date(1000); +// se4.lastSeenTimestamp = new Date(2000); +// assertTrue("", se3.compareTo(se4) < 0); +// assertTrue("", se4.compareTo(se3) > 0); +// se4.lastSeenTimestamp = new Date(1000); +// assertTrue("", se3.compareTo(se4) == 0); +// assertTrue("", se4.compareTo(se3) == 0); +// se4.lastSeenTimestamp = new Date(500); +// assertTrue("", se3.compareTo(se4) > 0); +// assertTrue("", se4.compareTo(se3) < 0); +// } +// +// /* Test basic DeviceSyncRepresentation behavior */ +// @Test +// public void testDeviceSyncRepresentationBasics() { +// DeviceSyncRepresentation dsr = new DeviceSyncRepresentation(); +// assertNull(dsr.getKey()); +// assertNull(dsr.getEntities()); +// dsr.setKey("MyKey"); +// assertEquals("MyKey", dsr.getKey()); +// assertEquals("MyKey", dsr.toString()); +// +// List entities = new ArrayList(); +// Entity e1a = new Entity(1L, (short)2, 3, 4L, 5, new Date(1000)); +// Entity e1b = new Entity(1L, (short)2, null, 4L, 5, new Date(0)); +// entities.add(new SyncEntity(e1a)); +// entities.add(new SyncEntity(e1b)); +// // e1b comes before e1 (lastSeen) but we add it after it to test +// // sorting +// dsr.setEntities(entities); +// +// assertEquals(2, dsr.getEntities().size()); +// // e1b has earlier time +// assertEquals(e1b, dsr.getEntities().get(0).asEntity()); +// assertEquals(e1a, dsr.getEntities().get(1).asEntity()); +// +// dsr.setKey(null); +// dsr.setEntities(null); +// assertNull(dsr.getKey()); +// assertNull(dsr.getEntities()); +// } +// +// @Test +// public void testDeviceSyncRepresentationFromDevice() { +// ITopologyService mockTopology = makeMockTopologyAllPortsAp(); +// replay(mockTopology); +// deviceManager.topology = mockTopology; +// +// deviceManager.entityClassifier = new MockEntityClassifier(); +// +// //************************************** +// // Test 1: a single entity +// Entity e1 = new Entity(1L, (short)2, 3, 4L, 5, new Date(1000)); +// Device d1 = deviceManager.learnDeviceByEntity(e1); +// assertEquals("Sanity check failed. Device doesn't have the expected " + +// "entity class. Something with the test setup is strange", +// "DefaultEntityClass", d1.getEntityClass().getName()); +// assertEquals("Sanity check failed. Device doesn't have the expected " + +// "entity class. Something with the test setup is strange", +// EnumSet.of(DeviceField.MAC, DeviceField.VLAN), +// d1.getEntityClass().getKeyFields()); +// +// Long deviceKey = d1.getDeviceKey(); +// DeviceSyncRepresentation dsr1 = new DeviceSyncRepresentation(d1); +// assertEquals("DefaultEntityClass::00:00:00:00:00:01::[2]::", +// dsr1.getKey()); +// assertEquals(1, dsr1.getEntities().size()); +// assertEquals(e1, dsr1.getEntities().get(0).asEntity()); +// +// //************************************** +// // Test 1b: same device, now with a second entity (no IP). +// // this second entity has a lastSeen time that is earlier than the +// // first entity +// Entity e1b = new Entity(1L, (short)2, null, 4L, 5, new Date(0)); +// d1 = deviceManager.learnDeviceByEntity(e1b); +// assertEquals("Sanity check failed. Should still be same device but " + +// "deviceKeys differs", deviceKey, d1.getDeviceKey()); +// dsr1 = new DeviceSyncRepresentation(d1); +// assertEquals("DefaultEntityClass::00:00:00:00:00:01::[2]::", +// dsr1.getKey()); +// assertEquals(2, dsr1.getEntities().size()); +// // Entities are ordered by their lastSeen time. e1b should come +// // before e1. +// assertEquals(e1, dsr1.getEntities().get(1).asEntity()); +// assertEquals(e1b, dsr1.getEntities().get(0).asEntity()); +// +// //************************************** +// // Test 1c: same device with a third entity that does not have a +// // switch port. It should be added to the DeviceSyncRepresentation +// Entity e1c = new Entity(1L, (short)2, 33, null, null, new Date(2000)); +// d1 = deviceManager.learnDeviceByEntity(e1c); +// assertEquals("Sanity check failed. Should still be same device but " + +// "deviceKeys differs", deviceKey, d1.getDeviceKey()); +// dsr1 = new DeviceSyncRepresentation(d1); +// assertEquals("DefaultEntityClass::00:00:00:00:00:01::[2]::", +// dsr1.getKey()); +// assertEquals(3, dsr1.getEntities().size()); +// // Entities are ordered by their lastSeen time +// assertEquals(e1c, dsr1.getEntities().get(2).asEntity()); +// assertEquals(e1, dsr1.getEntities().get(1).asEntity()); +// assertEquals(e1b, dsr1.getEntities().get(0).asEntity()); +// +// //************************************** +// // Test 1d: same device with a fourth entity that has a different +// // attachment point and that is newer. Device should move and +// // non-attachment point entities should be removed (e1b). Although +// // e1 is non-attachment point it will remain because it has an IP +// Entity e1d = new Entity(1L, (short)2, 33, 4L, 6, new Date(3000)); +// d1 = deviceManager.learnDeviceByEntity(e1d); +// assertEquals("Sanity check failed. Should still be same device but " + +// "deviceKeys differs", deviceKey, d1.getDeviceKey()); +// dsr1 = new DeviceSyncRepresentation(d1); +// assertEquals("DefaultEntityClass::00:00:00:00:00:01::[2]::", +// dsr1.getKey()); +// assertEquals(3, dsr1.getEntities().size()); +// assertEquals(e1, dsr1.getEntities().get(0).asEntity()); +// assertEquals(e1c, dsr1.getEntities().get(1).asEntity()); +// assertEquals(e1d, dsr1.getEntities().get(2).asEntity()); +// +// d1 = null; +// +// +// //************************************** +// // Test 2: a second device with a different entity class. The +// // mock entity classifier will return an entity class where all +// // fields are keys if the DPID is > 10L +// Entity e2 = new Entity(2L, (short)23, 24, 11L, 1, new Date(0)); +// Device d2 = deviceManager.learnDeviceByEntity(e2); +// DeviceSyncRepresentation dsr2 = new DeviceSyncRepresentation(d2); +// assertEquals("Sanity check failed. Device doesn't have the expected " + +// "entity class. Something with the test setup is strange", +// "TestEntityClass", d2.getEntityClass().getName()); +// assertEquals("Sanity check failed. Device doesn't have the expected " + +// "entity class. Something with the test setup is strange", +// EnumSet.of(DeviceField.MAC, DeviceField.VLAN, +// DeviceField.SWITCH, DeviceField.PORT), +// d2.getEntityClass().getKeyFields()); +// SwitchPort swp = new SwitchPort(11L, 1, null); +// assertEquals("TestEntityClass::00:00:00:00:00:02::[23]::[" + +// swp.toString() + "]::", +// dsr2.getKey()); +// } +// +// /* interate through all entries in the sync store and return them as +// * list. We don't return the key from the store however, we assert +// * that the key from the store matches the key in the representation. +// * If we have a null value (tombstone) we simply add the null value to +// * the list to return. +// */ +// private List getEntriesFromStore() +// throws Exception { +// List entries = +// new ArrayList(); +// IClosableIterator>> iter = +// storeClient.entries(); +// try { +// while(iter.hasNext()) { +// Entry> entry = +// iter.next(); +// DeviceSyncRepresentation dsr = entry.getValue().getValue(); +// if (dsr != null) +// assertEquals(entry.getKey(), dsr.getKey()); +// entries.add(dsr); +// } +// } finally { +// if (iter != null) +// iter.close(); +// } +// return entries; +// } +// +// /* +// * assert whether the given Entity expected is equals to the given +// * SyncEntity actual. This method also compares the times (lastSeen, +// * activeSince). Entity.equals will not do that! +// */ +// private static void assertEntityEquals(Entity expected, SyncEntity actual) { +// assertNotNull(actual); +// assertNotNull(expected); +// Entity actualEntity = actual.asEntity(); +// assertEquals("entityFields", expected, actualEntity); +// assertEquals("lastSeenTimestamp", +// expected.getLastSeenTimestamp(), +// actualEntity.getLastSeenTimestamp()); +// assertEquals("activeSince", +// expected.getActiveSince(), actualEntity.getActiveSince()); +// } +// +// /* This test tests the normal operation as master when we write to the sync +// * store or delete from the store. +// */ +// @Test +// public void testWriteToSyncStore() throws Exception { +// int syncStoreIntervalMs = 50; +// ITopologyService mockTopology = makeMockTopologyAllPortsAp(); +// replay(mockTopology); +// deviceManager.topology = mockTopology; +// deviceManager.setSyncStoreWriteInterval(syncStoreIntervalMs); +// +// Entity e1a = new Entity(1L, (short)2, 3, 4L, 5, new Date(1000)); +// e1a.setActiveSince(new Date(0)); +// deviceManager.learnDeviceByEntity(e1a); +// +// //storeClient.put("FooBar", new DeviceSyncRepresentation()); +// +// List entries = getEntriesFromStore(); +// assertEquals(1, entries.size()); +// DeviceSyncRepresentation dsr1 = entries.get(0); +// assertEquals(1, dsr1.getEntities().size()); +// assertEntityEquals(e1a, dsr1.getEntities().get(0)); +// +// // Same entity but newer timestamp. Since the device hasn't changed, +// // only the timestamp is updated and the write should be throttled. +// Entity e1b = new Entity(1L, (short)2, 3, 4L, 5, new Date(2000)); +// e1b.setActiveSince(new Date(0)); +// deviceManager.learnDeviceByEntity(e1a); +// entries = getEntriesFromStore(); +// assertEquals(1, entries.size()); +// dsr1 = entries.get(0); +// assertEquals(1, dsr1.getEntities().size()); +// assertEntityEquals(e1a, dsr1.getEntities().get(0)); //e1a not e1b !!! +// +// // Wait for the write interval to expire then write again. +// Thread.sleep(syncStoreIntervalMs+5); +// Entity e1c = new Entity(1L, (short)2, 3, 4L, 5, new Date(3000)); +// e1c.setActiveSince(new Date(0)); +// deviceManager.learnDeviceByEntity(e1c); +// entries = getEntriesFromStore(); +// assertEquals(1, entries.size()); +// dsr1 = entries.get(0); +// assertEquals(1, dsr1.getEntities().size()); +// assertEntityEquals(e1c, dsr1.getEntities().get(0)); // e1c !! +// +// // Entity for same device but with different IP. should be added +// // immediately +// Entity e1d = new Entity(1L, (short)2, 33, 4L, 5, new Date(4000)); +// e1d.setActiveSince(new Date(0)); +// deviceManager.learnDeviceByEntity(e1d); +// entries = getEntriesFromStore(); +// assertEquals(1, entries.size()); +// dsr1 = entries.get(0); +// assertEquals(2, dsr1.getEntities().size()); +// assertEntityEquals(e1c, dsr1.getEntities().get(0)); // e1c !! +// assertEntityEquals(e1d, dsr1.getEntities().get(1)); // e1d !! +// +// // Entity for same device with new switch port ==> moved ==> write +// // update immediately without throttle. +// // Note: the previous entities will still be there because they have +// // IPs (even though they aren't for the current attachment point) +// Entity e1e = new Entity(1L, (short)2, 33, 4L, 6, new Date(5000)); +// e1e.setActiveSince(new Date(0)); +// deviceManager.learnDeviceByEntity(e1e); +// entries = getEntriesFromStore(); +// assertEquals(1, entries.size()); +// dsr1 = entries.get(0); +// assertEquals(3, dsr1.getEntities().size()); +// assertEntityEquals(e1c, dsr1.getEntities().get(0)); +// assertEntityEquals(e1d, dsr1.getEntities().get(1)); +// assertEntityEquals(e1e, dsr1.getEntities().get(2)); +// +// // Add a second device +// Entity e2 = new Entity(2L, null, null, 5L, 5, new Date()); +// deviceManager.learnDeviceByEntity(e2); +// entries = getEntriesFromStore(); +// assertEquals(2, entries.size()); +// for (DeviceSyncRepresentation dsr: entries) { +// // This is a kinda ugly way to ensure we have the two +// // devices we need..... but it will work for now +// if (dsr.getKey().contains("::00:00:00:00:00:01::")) { +// assertEquals(3, dsr.getEntities().size()); +// assertEntityEquals(e1c, dsr.getEntities().get(0)); +// assertEntityEquals(e1d, dsr.getEntities().get(1)); +// assertEntityEquals(e1e, dsr.getEntities().get(2)); +// } else if (dsr.getKey().contains("::00:00:00:00:00:02::")) { +// assertEquals(1, dsr.getEntities().size()); +// assertEntityEquals(e2, dsr.getEntities().get(0)); +// } else { +// fail("Unknown entry in store: " + dsr); +// } +// } +// +// +// // Run entity cleanup. Since we've used phony time stamps for +// // device 1 its entities should be cleared and the device should be +// // removed from the store. Device 2 should remain in the store. +// deviceManager.cleanupEntities(); +// entries = getEntriesFromStore(); +// assertEquals(2, entries.size()); +// for (DeviceSyncRepresentation dsr: entries) { +// if (dsr == null) { +// // pass +// } else if (dsr.getKey().contains("::00:00:00:00:00:02::")) { +// assertEquals(1, dsr.getEntities().size()); +// assertEntityEquals(e2, dsr.getEntities().get(0)); +// } else { +// fail("Unknown entry in store: " + dsr); +// } +// } +// } +// +// +// private void assertDeviceIps(Integer[] expected, IDevice d) { +// List expectedList = Arrays.asList(expected); +// Collections.sort(expectedList); +// List actualList = Arrays.asList(d.getIPv4Addresses()); +// Collections.sort(actualList); +// assertEquals(expectedList, actualList); +// } +// +// private IDevice getSingleDeviceFromDeviceManager(long mac) { +// Iterator diter = +// deviceManager.queryDevices(mac, null, null, null, null); +// assertTrue("Query didn't return a device", diter.hasNext()); +// IDevice d = diter.next(); +// assertFalse("Query returned more than one device", diter.hasNext()); +// return d; +// } +// +// @Test +// public void testToMaster() throws Exception { +// int syncStoreWriteIntervalMs = 0; +// int initialSyncStoreConsolidateIntervalMs = 50; +// ITopologyService mockTopology = makeMockTopologyAllPortsAp(); +// replay(mockTopology); +// deviceManager.topology = mockTopology; +// // We want an EntityClassifier that has switch/port as key fields +// deviceManager.entityClassifier = new MockEntityClassifier(); +// deviceManager.setSyncStoreWriteInterval(syncStoreWriteIntervalMs); +// deviceManager.setInitialSyncStoreConsolidateMs(initialSyncStoreConsolidateIntervalMs); +// +// // Add Device1 with two entities with two different IPs +// Entity e1a = new Entity(1L, null, 3, 4L, 5, new Date(1000)); +// Entity e1b = new Entity(1L, null, 33, 4L, 5, new Date(2000)); +// Device d1 = deviceManager.allocateDevice(1L, e1a, +// DefaultEntityClassifier.entityClass); +// d1 = deviceManager.allocateDevice(d1, e1b, -1); +// DeviceSyncRepresentation dsr = new DeviceSyncRepresentation(d1); +// storeClient.put(dsr.getKey(), dsr); +// +// // Add Device2 with different switch-ports. Only the most recent +// // one should be the attachment point +// Entity e2a = new Entity(2L, null, null, 4L, 4, new Date(1000)); +// Entity e2b = new Entity(2L, null, null, 4L, 5, new Date(2000)); +// Device d2 = deviceManager.allocateDevice(2L, e2a, +// DefaultEntityClassifier.entityClass); +// d2 = deviceManager.allocateDevice(d2, e2b, -1); +// d2.updateAttachmentPoint(4L, (short)5, +// e2b.getLastSeenTimestamp().getTime()); +// SwitchPort swp = new SwitchPort(4L, 5); +// SwitchPort[] aps = d2.getAttachmentPoints(); +// // sanity check +// assertArrayEquals("Sanity check: should only have AP(4L,5)", +// new SwitchPort[] {swp}, aps); +// dsr = new DeviceSyncRepresentation(d2); +// storeClient.put(dsr.getKey(), dsr); +// +// // Add a tombstone entry to the store to make sure we don't trip a +// // NPE +// dsr = null; +// Versioned versionedDsr = +// storeClient.get("FooBar"); +// storeClient.put("FooBar", versionedDsr); +// +// deviceManager.getHAListener().transitionToMaster(); +// +// // Query for the Device1. Make sure we have the two IPs we stored. +// IDevice d = getSingleDeviceFromDeviceManager(1L); +// assertDeviceIps(new Integer[] {3, 33}, d); +// assertArrayEquals(new Short[] { Ethernet.VLAN_UNTAGGED }, d.getVlanId()); +// swp = new SwitchPort(4L, 5); +// assertArrayEquals(new SwitchPort[] { swp }, d.getAttachmentPoints()); +// +// // Query for Device2. Make sure we only have the more recent AP +// // Query for the Device1. Make sure we have the two IPs we stored. +// d = getSingleDeviceFromDeviceManager(2L); +// assertArrayEquals(new Integer[0], d.getIPv4Addresses()); +// assertArrayEquals(new Short[] { Ethernet.VLAN_UNTAGGED }, d.getVlanId()); +// swp = new SwitchPort(4L, 5); +// assertArrayEquals(new SwitchPort[] { swp }, d.getAttachmentPoints()); +// +// //---------------------------- +// // add another entry device to the store. since device manager is +// // already master we won't read this device and it should be +// // removed from the store by the consolidate task +// Entity e3 = new Entity(3L, null, null, 1L, 1, null); +// dsr = new DeviceSyncRepresentation(); +// dsr.setKey("Device3"); +// dsr.setEntities(Collections.singletonList(new SyncEntity(e3))); +// storeClient.put(dsr.getKey(), dsr); +// +// // make sure it's in the store +// List entries = getEntriesFromStore(); +// boolean found = false; +// for (DeviceSyncRepresentation entry: entries) { +// if (entry!=null && entry.getKey().equals("Device3")) +// found = true; +// } +// assertTrue("Device3 not in store. Entries in store: " + entries, found); +// // make sure it's not in DevManager +// Iterator diter = +// deviceManager.queryDevices(3L, null, null, null, null); +// assertFalse("Device3 found in DeviceManager. Should be there", +// diter.hasNext()); +// +// // Wait for consolidate +// Thread.sleep(initialSyncStoreConsolidateIntervalMs + 5); +// // make sure it's in NOT the store +// entries = getEntriesFromStore(); +// found = false; +// for (DeviceSyncRepresentation entry: entries) { +// if (entry!=null && entry.getKey().equals("Device3")) +// found = true; +// } +// assertFalse("Device3 not is still in the store. Entries in store: " +// + entries, found); +// // make sure it's not in DevManager +// diter = deviceManager.queryDevices(3L, null, null, null, null); +// assertFalse("Device3 found in DeviceManager. Should be there", +// diter.hasNext()); +// } +// +// +// @Test +// public void testConsolitateStore() throws Exception { +// int syncStoreInternalMs = 0; +// ITopologyService mockTopology = makeMockTopologyAllPortsAp(); +// replay(mockTopology); +// deviceManager.topology = mockTopology; +// // We want an EntityClassifier that has switch/port as key fields +// deviceManager.entityClassifier = new MockEntityClassifier(); +// deviceManager.setSyncStoreWriteInterval(syncStoreInternalMs); +// +// // Add Device1 with two entities to store and let device manager +// // learn +// Entity e1a = new Entity(1L, null, null, 4L, 5, new Date(1000)); +// Entity e1b = new Entity(1L, null, 3, 4L, 5, new Date(2000)); +// Device d1 = deviceManager.learnDeviceByEntity(e1a); +// deviceManager.learnDeviceByEntity(e1b); +// String dev1Key = DeviceSyncRepresentation.computeKey(d1); +// +// +// // Add a second device to the store but do NOT add to device manager +// Entity e2 = new Entity(2L, null, null, 5L, 5, new Date()); +// Device d2 = deviceManager.allocateDevice(42L, e2, +// DefaultEntityClassifier.entityClass); +// DeviceSyncRepresentation dsr = new DeviceSyncRepresentation(d2); +// storeClient.put(dsr.getKey(), dsr); +// String dev2Key = DeviceSyncRepresentation.computeKey(d2); +// +// // Make sure we have two devices in the store +// List entries = getEntriesFromStore(); +// assertEquals(2, entries.size()); +// +// deviceManager.scheduleConsolidateStoreNow(); +// Thread.sleep(25); // give the scheduler time to run the task +// +// // We should still have two entries, however one of them will be a +// // tombstone +// entries = getEntriesFromStore(); +// assertEquals(2, entries.size()); +// +// // Device 1 should still be in store +// Versioned versioned = +// storeClient.get(dev1Key); +// dsr = versioned.getValue(); +// assertNotNull(dsr); +// assertEquals(2, dsr.getEntities().size()); +// assertEntityEquals(e1a, dsr.getEntities().get(0)); +// assertEntityEquals(e1b, dsr.getEntities().get(1)); +// +// // Device2 should be gone +// versioned = storeClient.get(dev2Key); +// assertNull(versioned.getValue()); +// +// // Run consolitate again. This time we check that tombstones in +// // the store are handled correctly +// deviceManager.scheduleConsolidateStoreNow(); +// Thread.sleep(25); // give the scheduler time to run the task +// +// // Now write a device to the store that doesn't have any switch-port +// // it should be removed +// Entity e3 = new Entity(3L, null, null, null, null, null); +// dsr.setKey("Device3"); +// dsr.setEntities(Collections.singletonList(new SyncEntity(e3))); +// storeClient.put(dsr.getKey(), dsr); +// +// // Run consolitate again. This time we check that tombstones in +// // the store are handled correctly +// deviceManager.scheduleConsolidateStoreNow(); +// Thread.sleep(25); // give the scheduler time to run the task +// versioned = storeClient.get("Device3"); +// assertNull(versioned.getValue()); +// +// } +// +// } diff --git a/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/internal/DeviceUniqueIndexTest.java b/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/internal/DeviceUniqueIndexTest.java new file mode 100644 index 0000000000..a2a10048eb --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/internal/DeviceUniqueIndexTest.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker.internal; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import junit.framework.TestCase; + +import org.junit.Test; +import org.opendaylight.controller.hosttracker.Entity; +import org.opendaylight.controller.hosttracker.IDeviceService.DeviceField; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType; + +/** + * + * @author gregor + * + */ +public class DeviceUniqueIndexTest extends TestCase { + protected Entity e1a; + protected Entity e1b; + protected Device d1; + protected Entity e2; + protected Entity e2alt; + protected Entity e3; + protected Entity e3_ip; + protected Entity e4; + + @Override + protected void setUp() throws Exception { + super.setUp(); + Node n1 = new Node(Node.NodeIDType.OPENFLOW, Long.valueOf(1L)); + NodeConnector n1_1 = new NodeConnector(NodeConnectorIDType.OPENFLOW, + Short.valueOf((short) 1), n1); + e1a = new Entity(1L, (short) 1, 1, n1_1, new Date()); + e1b = new Entity(1L, (short) 2, 1, n1_1, new Date()); + List d1Entities = new ArrayList(2); + d1Entities.add(e1a); + d1Entities.add(e1b); + d1 = new Device(null, Long.valueOf(1), null, null, null, d1Entities, + null); + + Node n2 = new Node(Node.NodeIDType.OPENFLOW, Long.valueOf(2L)); + NodeConnector n2_2 = new NodeConnector(NodeConnectorIDType.OPENFLOW, + Short.valueOf((short) 2), n2); + Node n3 = new Node(Node.NodeIDType.OPENFLOW, Long.valueOf(3L)); + NodeConnector n3_3 = new NodeConnector(NodeConnectorIDType.OPENFLOW, + Short.valueOf((short) 3), n3); + + // e2 and e2 alt match in MAC and VLAN + e2 = new Entity(2L, (short) 2, 2, n2_2, new Date()); + e2alt = new Entity(2, (short) 2, null, null, null); + + // IP is null + e3 = new Entity(3L, (short) 3, null, n3_3, new Date()); + e3_ip = new Entity(3L, (short) 3, 3, n3_3, new Date()); + + // IP and switch and port are null + e4 = new Entity(4L, (short) 4, null, null, new Date()); + } + + /* + * Checks that the iterator it returns the elements in the Set expected + * Doesn't check how often an element is returned as long it's at least once + */ + protected void verifyIterator(Set expected, Iterator it) { + HashSet actual = new HashSet(); + while (it.hasNext()) { + actual.add(it.next()); + } + assertEquals(expected, actual); + } + + @Test + public void testDeviceUniqueIndex() { + DeviceUniqueIndex idx1 = new DeviceUniqueIndex(EnumSet.of( + DeviceField.MAC, DeviceField.VLAN)); + + idx1.updateIndex(d1, d1.getDeviceKey()); + idx1.updateIndex(e2, 2L); + + // ------------- + // Test findByEntity lookups + assertEquals(Long.valueOf(1L), idx1.findByEntity(e1a)); + assertEquals(Long.valueOf(1L), idx1.findByEntity(e1b)); + assertEquals(Long.valueOf(2L), idx1.findByEntity(e2)); + // we didn't add e2alt but since they key fields are the same we + // should find it + assertEquals(Long.valueOf(2L), idx1.findByEntity(e2alt)); + assertEquals(null, idx1.findByEntity(e3)); + assertEquals(null, idx1.findByEntity(e4)); + + // ------------- + // Test getAll() + HashSet expectedKeys = new HashSet(); + expectedKeys.add(1L); + expectedKeys.add(2L); + verifyIterator(expectedKeys, idx1.getAll()); + + // ------------- + // Test queryByEntity() + verifyIterator(Collections. singleton(1L), + idx1.queryByEntity(e1a)); + verifyIterator(Collections. singleton(1L), + idx1.queryByEntity(e1b)); + verifyIterator(Collections. singleton(2L), idx1.queryByEntity(e2)); + verifyIterator(Collections. singleton(2L), + idx1.queryByEntity(e2alt)); + assertEquals(false, idx1.queryByEntity(e3).hasNext()); + assertEquals(false, idx1.queryByEntity(e3).hasNext()); + + // ------------- + // Test removal + idx1.removeEntity(e1a, 42L); // No-op. e1a isn't mapped to this key + assertEquals(Long.valueOf(1L), idx1.findByEntity(e1a)); + idx1.removeEntity(e1a, 1L); + assertEquals(null, idx1.findByEntity(e1a)); + assertEquals(Long.valueOf(1L), idx1.findByEntity(e1b)); + assertEquals(Long.valueOf(2L), idx1.findByEntity(e2)); + idx1.removeEntity(e2); + assertEquals(null, idx1.findByEntity(e2)); + assertEquals(Long.valueOf(1L), idx1.findByEntity(e1b)); + + // ------------- + // Test null keys + DeviceUniqueIndex idx2 = new DeviceUniqueIndex(EnumSet.of( + DeviceField.IPV4, DeviceField.SWITCHPORT)); + // only one key field is null + idx2.updateIndex(e3, 3L); + assertEquals(Long.valueOf(3L), idx2.findByEntity(e3)); + assertEquals(null, idx2.findByEntity(e3_ip)); + // all key fields are null + idx2.updateIndex(e4, 4L); + assertEquals(null, idx2.findByEntity(e4)); + Device d4 = new Device(null, 4L, null, null, null, + Collections. singleton(e4), null); + idx2.updateIndex(d4, 4L); + assertEquals(null, idx2.findByEntity(e4)); + + // ------------- + // entity already exists with different deviceKey + DeviceUniqueIndex idx3 = new DeviceUniqueIndex(EnumSet.of( + DeviceField.MAC, DeviceField.VLAN)); + idx3.updateIndex(e1a, 42L); + assertEquals(false, idx3.updateIndex(d1, 1L)); + // TODO: shouldn't this fail as well so that the behavior + // is consistent? + idx3.updateIndex(e1a, 1L); + // anyways. We can now add d1 ;-) + assertEquals(true, idx3.updateIndex(d1, 1L)); + } +} diff --git a/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/test/MockDevice.java b/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/test/MockDevice.java new file mode 100644 index 0000000000..03f0598df8 --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/test/MockDevice.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2011,2012 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS + * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker.test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.TreeSet; + +import org.opendaylight.controller.hosttracker.Entity; +import org.opendaylight.controller.hosttracker.IEntityClass; +import org.opendaylight.controller.hosttracker.SwitchPort; +import org.opendaylight.controller.hosttracker.internal.AttachmentPoint; +import org.opendaylight.controller.hosttracker.internal.Device; +import org.opendaylight.controller.hosttracker.internal.DeviceManagerImpl; + +/** + * This mock device removes the dependency on topology and a parent device + * manager and simply assumes all its entities are current and correct + */ +public class MockDevice extends Device { + + public MockDevice(DeviceManagerImpl deviceManager, Long deviceKey, + Entity entity, IEntityClass entityClass) { + super(deviceManager, deviceKey, entity, entityClass); + } + + public MockDevice(Device device, Entity newEntity, int insertionpoint) { + super(device, newEntity, insertionpoint); + } + + public MockDevice(DeviceManagerImpl deviceManager, Long deviceKey, + List aps, List trueAPs, + Collection entities, IEntityClass entityClass) { + super(deviceManager, deviceKey, null, aps, trueAPs, entities, + entityClass); + } + + @Override + public Integer[] getIPv4Addresses() { + TreeSet vals = new TreeSet(); + for (Entity e : entities) { + if (e.getIpv4Address() == null) + continue; + vals.add(e.getIpv4Address()); + } + + return vals.toArray(new Integer[vals.size()]); + } + + @Override + public SwitchPort[] getAttachmentPoints() { + ArrayList vals = new ArrayList(entities.length); + for (Entity e : entities) { + if (e.getPort() != null + && deviceManager.isValidAttachmentPoint(e.getPort())) { + SwitchPort sp = new SwitchPort(e.getPort()); + vals.add(sp); + } + } + return vals.toArray(new SwitchPort[vals.size()]); + } + + @Override + public String toString() { + return "MockDevice [getEntityClass()=" + getEntityClass() + + ", getEntities()=" + Arrays.toString(getEntities()) + "]"; + } + +} diff --git a/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/test/MockDeviceManager.java b/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/test/MockDeviceManager.java new file mode 100644 index 0000000000..af2feb14b1 --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/test/MockDeviceManager.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2013 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker.test; + +import java.util.Collection; +import java.util.Date; +import java.util.List; + +import org.opendaylight.controller.hosttracker.Entity; +import org.opendaylight.controller.hosttracker.IDevice; +import org.opendaylight.controller.hosttracker.IDeviceListener; +import org.opendaylight.controller.hosttracker.IEntityClass; +import org.opendaylight.controller.hosttracker.IEntityClassifierService; +import org.opendaylight.controller.hosttracker.internal.AttachmentPoint; +import org.opendaylight.controller.hosttracker.internal.Device; +import org.opendaylight.controller.hosttracker.internal.DeviceManagerImpl; +import org.opendaylight.controller.sal.core.NodeConnector; + +/** + * Mock device manager useful for unit tests + * + * @author readams + */ +public class MockDeviceManager extends DeviceManagerImpl { + /** + * Set a new IEntityClassifier Use this as a quick way to use a particular + * entity classifier in a single test without having to setup the full + * FloodlightModuleContext again. + * + * @param ecs + */ + public void setEntityClassifier(IEntityClassifierService ecs) { + this.entityClassifier = ecs; + // setSyncServiceIfNotSet(new MockSyncService()); + this.start(); + } + + /** + * Learn a device using the given characteristics. + * + * @param macAddress + * the MAC + * @param vlan + * the VLAN (can be null) + * @param ipv4Address + * the IP (can be null) + * @param switchDPID + * the attachment point switch DPID (can be null) + * @param switchPort + * the attachment point switch port (can be null) + * @param processUpdates + * if false, will not send updates. Note that this method is not + * thread safe if this is false + * @return the device, either new or not + */ + public IDevice learnEntity(long macAddress, Short vlan, + Integer ipv4Address, NodeConnector port, boolean processUpdates) { + List listeners = deviceListeners.getOrderedListeners(); + if (!processUpdates) { + deviceListeners.clearListeners(); + } + + if (vlan != null && vlan.shortValue() <= 0) + vlan = null; + if (ipv4Address != null && ipv4Address == 0) + ipv4Address = null; + IDevice res = learnDeviceByEntity(new Entity(macAddress, vlan, + ipv4Address, port, new Date())); + // Restore listeners + if (listeners != null) { + for (IDeviceListener listener : listeners) { + deviceListeners.addListener("device", listener); + } + } + return res; + } + + @Override + public void deleteDevice(Device device) { + super.deleteDevice(device); + } + + /** + * Learn a device using the given characteristics. + * + * @param macAddress + * the MAC + * @param vlan + * the VLAN (can be null) + * @param ipv4Address + * the IP (can be null) + * @param switchDPID + * the attachment point switch DPID (can be null) + * @param switchPort + * the attachment point switch port (can be null) + * @return the device, either new or not + */ + public IDevice learnEntity(long macAddress, Short vlan, + Integer ipv4Address, NodeConnector port) { + return learnEntity(macAddress, vlan, ipv4Address, port, true); + } + + @Override + protected Device allocateDevice(Long deviceKey, Entity entity, + IEntityClass entityClass) { + return new MockDevice(this, deviceKey, entity, entityClass); + } + + @Override + protected Device allocateDevice(Long deviceKey, String dhcpClientName, + List aps, List trueAPs, + Collection entities, IEntityClass entityClass) { + return new MockDevice(this, deviceKey, aps, trueAPs, entities, + entityClass); + } + + @Override + protected Device allocateDevice(Device device, Entity entity, + int insertionpoint) { + return new MockDevice(device, entity, insertionpoint); + } +} diff --git a/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/test/MockEntityClassifier.java b/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/test/MockEntityClassifier.java new file mode 100644 index 0000000000..e9f919e7f2 --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/test/MockEntityClassifier.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker.test; + +import static org.opendaylight.controller.hosttracker.IDeviceService.DeviceField.MAC; +import static org.opendaylight.controller.hosttracker.IDeviceService.DeviceField.SWITCHPORT; +import static org.opendaylight.controller.hosttracker.IDeviceService.DeviceField.VLAN; + +import java.util.EnumSet; + +import org.opendaylight.controller.hosttracker.Entity; +import org.opendaylight.controller.hosttracker.IDeviceService; +import org.opendaylight.controller.hosttracker.IDeviceService.DeviceField; +import org.opendaylight.controller.hosttracker.IEntityClass; +import org.opendaylight.controller.hosttracker.internal.DefaultEntityClassifier; + +/** + * A simple IEntityClassifier. Useful for tests that need IEntityClassifiers and + * IEntityClass'es with switch and/or port key fields + */ +public class MockEntityClassifier extends DefaultEntityClassifier { + public static class TestEntityClass implements IEntityClass { + @Override + public EnumSet getKeyFields() { + return EnumSet.of(MAC, VLAN, SWITCHPORT); + } + + @Override + public String getName() { + return "TestEntityClass"; + } + } + + public static IEntityClass testEC = new MockEntityClassifier.TestEntityClass(); + + @Override + public IEntityClass classifyEntity(Entity entity) { + if (((Long) entity.getPort().getNode().getID()) >= 10L) { + return testEC; + } + return DefaultEntityClassifier.entityClass; + } + + @Override + public EnumSet getKeyFields() { + return EnumSet.of(MAC, VLAN, SWITCHPORT); + } + +} \ No newline at end of file diff --git a/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/test/MockEntityClassifierMac.java b/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/test/MockEntityClassifierMac.java new file mode 100644 index 0000000000..436e6fa30e --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/test/MockEntityClassifierMac.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker.test; + +import static org.opendaylight.controller.hosttracker.IDeviceService.DeviceField.MAC; +import static org.opendaylight.controller.hosttracker.IDeviceService.DeviceField.SWITCHPORT; +import static org.opendaylight.controller.hosttracker.IDeviceService.DeviceField.VLAN; + +import java.util.EnumSet; + +import org.opendaylight.controller.hosttracker.Entity; +import org.opendaylight.controller.hosttracker.IDeviceService; +import org.opendaylight.controller.hosttracker.IDeviceService.DeviceField; +import org.opendaylight.controller.hosttracker.IEntityClass; +import org.opendaylight.controller.hosttracker.internal.DefaultEntityClassifier; + +/** + * A simple IEntityClassifier. Useful for tests that need an IEntityClassifier + * with switch/port as key fields. + */ +public class MockEntityClassifierMac extends DefaultEntityClassifier { + public static class TestEntityClassMac implements IEntityClass { + protected String name; + + public TestEntityClassMac(String name) { + this.name = name; + } + + @Override + public EnumSet getKeyFields() { + return EnumSet.of(MAC, VLAN); + } + + @Override + public String getName() { + return name; + } + } + + public static IEntityClass testECMac1 = new MockEntityClassifierMac.TestEntityClassMac( + "testECMac1"); + public static IEntityClass testECMac2 = new MockEntityClassifierMac.TestEntityClassMac( + "testECMac2"); + + @Override + public IEntityClass classifyEntity(Entity entity) { + if (((Long) entity.getPort().getNode().getID()) == null) { + throw new IllegalArgumentException("Not all key fields specified." + + " Required fields: " + getKeyFields()); + } else if (((Long) entity.getPort().getNode().getID()) == 1L) { + return testECMac1; + } else if (((Long) entity.getPort().getNode().getID()) == 2L) { + return testECMac2; + } else if (((Long) entity.getPort().getNode().getID()) == -1L) { + return null; + } + return DefaultEntityClassifier.entityClass; + } + + @Override + public EnumSet getKeyFields() { + return EnumSet.of(MAC, VLAN, SWITCHPORT); + } +} \ No newline at end of file diff --git a/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/test/MockFlexEntityClassifier.java b/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/test/MockFlexEntityClassifier.java new file mode 100644 index 0000000000..fe2dd300d3 --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/test/java/org/opendaylight/controller/hosttracker/test/MockFlexEntityClassifier.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2013 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.opendaylight.controller.hosttracker.test; + +import static org.opendaylight.controller.hosttracker.IDeviceService.DeviceField.MAC; +import static org.opendaylight.controller.hosttracker.IDeviceService.DeviceField.SWITCHPORT; +import static org.opendaylight.controller.hosttracker.IDeviceService.DeviceField.VLAN; + +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +import org.opendaylight.controller.hosttracker.Entity; +import org.opendaylight.controller.hosttracker.IDeviceService; +import org.opendaylight.controller.hosttracker.IDeviceService.DeviceField; +import org.opendaylight.controller.hosttracker.IEntityClass; +import org.opendaylight.controller.hosttracker.internal.DefaultEntityClassifier; + +/** + * Extension to simple entity classifier to help in unit tests to provide table + * based multiple entity classification mock for reclassification tests + * + */ +public class MockFlexEntityClassifier extends DefaultEntityClassifier { + Map switchEntities; + Map vlanEntities; + + public static class TestEntityClass implements IEntityClass { + String name; + + public TestEntityClass(String name) { + this.name = name; + } + + @Override + public EnumSet getKeyFields() { + return EnumSet.of(MAC); + } + + @Override + public String getName() { + return name; + } + } + + public static IEntityClass defaultClass = new TestEntityClass("default"); + + public MockFlexEntityClassifier() { + switchEntities = new HashMap(); + vlanEntities = new HashMap(); + } + + public IEntityClass createTestEntityClass(String name) { + return new TestEntityClass(name); + } + + public void addSwitchEntity(Long dpid, IEntityClass entityClass) { + switchEntities.put(dpid, entityClass); + } + + public void removeSwitchEntity(Long dpid) { + switchEntities.remove(dpid); + } + + public void addVlanEntities(Short vlan, IEntityClass entityClass) { + vlanEntities.put(vlan, entityClass); + } + + public void removeVlanEntities(Short vlan) { + vlanEntities.remove(vlan); + } + + @Override + public IEntityClass classifyEntity(Entity entity) { + if (switchEntities.containsKey((Long) entity.getPort().getNode() + .getID())) + return switchEntities + .get((Long) entity.getPort().getNode().getID()); + if (vlanEntities.containsKey(entity.getVlan())) + return vlanEntities.get(entity.getVlan()); + return defaultClass; + } + + @Override + public EnumSet getKeyFields() { + return EnumSet.of(MAC, VLAN, SWITCHPORT); + } +} diff --git a/opendaylight/hosttracker_new/implementation/src/test/resources/logback.xml b/opendaylight/hosttracker_new/implementation/src/test/resources/logback.xml new file mode 100644 index 0000000000..5fa21fecfc --- /dev/null +++ b/opendaylight/hosttracker_new/implementation/src/test/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + diff --git a/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java b/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java index 6bafee0b2c..7061954e80 100644 --- a/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java +++ b/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java @@ -56,7 +56,7 @@ public class Activator implements BundleActivator { this.listener.logged(entry); } } - + /* * Install the default exception handler so that the uncaught * exceptions are handled by our customized handler. This new @@ -65,13 +65,13 @@ public class Activator implements BundleActivator { */ Thread.setDefaultUncaughtExceptionHandler(new org.opendaylight. controller.logging.bridge.internal.UncaughtExceptionHandler()); - + /* * Install the Shutdown handler. This will intercept SIGTERM signal and * close the system bundle. This allows for a graceful closing of OSGI * framework. */ - + Runtime.getRuntime().addShutdownHook(new shutdownHandler(context)); } else { this.log.error("Cannot register the LogListener because " @@ -95,13 +95,13 @@ public class Activator implements BundleActivator { this.listener = null; this.log = null; } - + private class shutdownHandler extends Thread { BundleContext bundlecontext; public shutdownHandler(BundleContext ctxt) { this.bundlecontext = ctxt; } - + public void run () { try { this.bundlecontext.getBundle(0).stop(); @@ -109,7 +109,7 @@ public class Activator implements BundleActivator { } catch (BundleException e) { log.debug("Bundle couldn't be stopped"); } - } + } } } diff --git a/opendaylight/northbound/commons/pom.xml b/opendaylight/northbound/commons/pom.xml index 7c0835a903..56da363d3e 100644 --- a/opendaylight/northbound/commons/pom.xml +++ b/opendaylight/northbound/commons/pom.xml @@ -33,7 +33,7 @@ org.opendaylight.controller.sal.authorization, org.opendaylight.controller.containermanager, org.opendaylight.controller.usermanager, - javax.servlet.http, + javax.servlet.http, org.slf4j diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/package-info.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/package-info.java index db2a13379b..d1f182b7dd 100644 --- a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/package-info.java +++ b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/package-info.java @@ -12,4 +12,3 @@ * */ package org.opendaylight.controller.northbound.commons.exception; - diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/utils/NorthboundUtils.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/utils/NorthboundUtils.java index 7069ff041f..3fedd0c9f8 100644 --- a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/utils/NorthboundUtils.java +++ b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/utils/NorthboundUtils.java @@ -9,11 +9,11 @@ import org.opendaylight.controller.usermanager.IUserManager; public class NorthboundUtils { - + /** * Returns whether the current user has the required privilege on the * specified container - * + * * @param userName * The user name * @param containerName @@ -21,21 +21,21 @@ public class NorthboundUtils { * @param required * Operation to be performed - READ/WRITE * @param bundle - * Class from where the function is invoked + * Class from where the function is invoked * @return The Status of the request, either Success or Unauthorized */ public static boolean isAuthorized(String userName, String containerName, Privilege required,Object bundle) { - + if (containerName.equals(GlobalConstants.DEFAULT.toString())) { IUserManager auth = (IUserManager) ServiceHelper.getGlobalInstance( IUserManager.class, bundle); - + switch (required) { case WRITE: return (auth.getUserLevel(userName).ordinal() <= UserLevel.NETWORKADMIN.ordinal()); case READ: - return (auth.getUserLevel(userName).ordinal() <= UserLevel.NETWORKOPERATOR.ordinal()); + return (auth.getUserLevel(userName).ordinal() <= UserLevel.NETWORKOPERATOR.ordinal()); default: return false; } @@ -56,5 +56,5 @@ public class NorthboundUtils { } return true; } - + } diff --git a/opendaylight/northbound/flowprogrammer/enunciate.xml b/opendaylight/northbound/flowprogrammer/enunciate.xml index a49d9f8265..90bf6de1d6 100644 --- a/opendaylight/northbound/flowprogrammer/enunciate.xml +++ b/opendaylight/northbound/flowprogrammer/enunciate.xml @@ -1,7 +1,7 @@ - + diff --git a/opendaylight/northbound/flowprogrammer/pom.xml b/opendaylight/northbound/flowprogrammer/pom.xml index 0a873ca065..c7e9a771c1 100644 --- a/opendaylight/northbound/flowprogrammer/pom.xml +++ b/opendaylight/northbound/flowprogrammer/pom.xml @@ -24,7 +24,7 @@ 0.5.0-SNAPSHOT - + org.apache.felix maven-bundle-plugin @@ -43,7 +43,7 @@ org.opendaylight.controller.northbound.commons.utils, org.opendaylight.controller.sal.authorization, org.opendaylight.controller.usermanager, - com.sun.jersey.spi.container.servlet, + com.sun.jersey.spi.container.servlet, javax.ws.rs, javax.ws.rs.core, javax.xml.bind.annotation, @@ -70,7 +70,7 @@ org.opendaylight.controller switchmanager 0.4.0-SNAPSHOT - + org.opendaylight.controller forwardingrulesmanager @@ -87,10 +87,10 @@ ${enunciate.version} - org.opendaylight.controller - commons.northbound - 0.4.0-SNAPSHOT - + org.opendaylight.controller + commons.northbound + 0.4.0-SNAPSHOT + org.opendaylight.controller.thirdparty com.sun.jersey.jersey-servlet diff --git a/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowConfigs.java b/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowConfigs.java index f6a757ec29..4b3761219f 100644 --- a/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowConfigs.java +++ b/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowConfigs.java @@ -21,22 +21,22 @@ import org.opendaylight.controller.forwardingrulesmanager.FlowConfig; @XmlAccessorType(XmlAccessType.NONE) public class FlowConfigs { - @XmlElement - List flowConfig; - //To satisfy JAXB - private FlowConfigs() { - - } - - public FlowConfigs(List flowConfig) { - this.flowConfig = flowConfig; - } - - public List getFlowConfig() { - return flowConfig; - } - - public void setFlowConfig(List flowConfig) { - this.flowConfig = flowConfig; - } + @XmlElement + List flowConfig; + //To satisfy JAXB + private FlowConfigs() { + + } + + public FlowConfigs(List flowConfig) { + this.flowConfig = flowConfig; + } + + public List getFlowConfig() { + return flowConfig; + } + + public void setFlowConfig(List flowConfig) { + this.flowConfig = flowConfig; + } } diff --git a/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java b/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java index 99452b4b21..b419a9b29d 100644 --- a/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java +++ b/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java @@ -48,7 +48,7 @@ import org.opendaylight.controller.switchmanager.ISwitchManager; /** * Flow Configuration Northbound API - * + * *
*
* Authentication scheme : HTTP Basic
@@ -60,7 +60,7 @@ import org.opendaylight.controller.switchmanager.ISwitchManager; * trusted authority.
* More info : * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration - * + * */ @Path("/") public class FlowProgrammerNorthbound { @@ -147,7 +147,7 @@ public class FlowProgrammerNorthbound { /** * Returns a list of Flows configured on the given container - * + * * @param containerName * Name of the Container. The Container name for the base * controller is "default". @@ -177,7 +177,7 @@ public class FlowProgrammerNorthbound { /** * Returns a list of Flows configured on a Node in a given container - * + * * @param containerName * Name of the Container. The Container name for the base * controller is "default". @@ -217,7 +217,7 @@ public class FlowProgrammerNorthbound { /** * Returns the flow configuration matching a human-readable name and nodeId * on a given Container. - * + * * @param containerName * Name of the Container. The Container name for the base * controller is "default". @@ -266,7 +266,7 @@ public class FlowProgrammerNorthbound { /** * Add a flow configuration - * + * * @param containerName * Name of the Container. The Container name for the base * controller is "default". @@ -330,9 +330,9 @@ public class FlowProgrammerNorthbound { /** * Delete a Flow configuration - * + * * DELETE /flows/{containerName}/{nodeType}/{nodeId}/{name} - * + * * @param containerName * Name of the Container. The Container name for the base * controller is "default". @@ -392,7 +392,7 @@ public class FlowProgrammerNorthbound { /** * Toggle a Flow configuration - * + * * @param containerName * Name of the Container. The Container name for the base * controller is "default". diff --git a/opendaylight/northbound/flowprogrammer/src/main/resources/WEB-INF/web.xml b/opendaylight/northbound/flowprogrammer/src/main/resources/WEB-INF/web.xml index 83f7e4b35d..4cedf2df89 100644 --- a/opendaylight/northbound/flowprogrammer/src/main/resources/WEB-INF/web.xml +++ b/opendaylight/northbound/flowprogrammer/src/main/resources/WEB-INF/web.xml @@ -1,51 +1,51 @@ - - - JAXRSFlowProgrammer - com.sun.jersey.spi.container.servlet.ServletContainer - - javax.ws.rs.Application - org.opendaylight.controller.flowprogrammer.northbound.FlowProgrammerNorthboundRSApplication - - 1 - - - - JAXRSFlowProgrammer - /* - + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" + version="3.0"> + + + JAXRSFlowProgrammer + com.sun.jersey.spi.container.servlet.ServletContainer + + javax.ws.rs.Application + org.opendaylight.controller.flowprogrammer.northbound.FlowProgrammerNorthboundRSApplication + + 1 + + + + JAXRSFlowProgrammer + /* + + + + + NB api + /* + + + System-Admin + Network-Admin + Network-Operator + Container-User + + - - - NB api - /* - - - System-Admin - Network-Admin - Network-Operator - Container-User - - - - System-Admin - - - Network-Admin - - - Network-Operator - - - Container-User - - - - BASIC - opendaylight - + System-Admin + + + Network-Admin + + + Network-Operator + + + Container-User + + + + BASIC + opendaylight + \ No newline at end of file diff --git a/opendaylight/northbound/hosttracker/enunciate.xml b/opendaylight/northbound/hosttracker/enunciate.xml index 8f0d7e6ab8..e0c7dcd2ac 100644 --- a/opendaylight/northbound/hosttracker/enunciate.xml +++ b/opendaylight/northbound/hosttracker/enunciate.xml @@ -1,7 +1,7 @@ - + diff --git a/opendaylight/northbound/hosttracker/pom.xml b/opendaylight/northbound/hosttracker/pom.xml index 853c54ec2c..f0caa52d63 100644 --- a/opendaylight/northbound/hosttracker/pom.xml +++ b/opendaylight/northbound/hosttracker/pom.xml @@ -24,7 +24,7 @@ 0.5.0-SNAPSHOT
-
+ org.apache.felix maven-bundle-plugin diff --git a/opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/HostTrackerNorthbound.java b/opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/HostTrackerNorthbound.java index a9f210e0ec..dbc99d06e4 100644 --- a/opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/HostTrackerNorthbound.java +++ b/opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/HostTrackerNorthbound.java @@ -56,7 +56,7 @@ import org.opendaylight.controller.sal.authorization.Privilege; * Location is represented by Host node connector which is essentially a logical * entity that represents a Switch/Port. A host is represented by it's * IP-address and mac-address. - * + * *
*
* Authentication scheme : HTTP Basic
@@ -68,7 +68,7 @@ import org.opendaylight.controller.sal.authorization.Privilege; * trusted authority.
* More info : * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration - * + * */ @Path("/") @@ -120,7 +120,7 @@ public class HostTrackerNorthbound { /** * Returns a list of all Hosts : both configured via PUT API and dynamically * learnt on the network. - * + * * @param containerName * Name of the Container. The Container name for the base * controller is "default". @@ -135,7 +135,7 @@ public class HostTrackerNorthbound { @ResponseCode(code = 404, condition = "The containerName is not found"), @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) public Hosts getActiveHosts(@PathParam("containerName") String containerName) { - + if (!NorthboundUtils.isAuthorized( getUserName(), containerName, Privilege.READ, this)) { throw new UnauthorizedException( @@ -154,7 +154,7 @@ public class HostTrackerNorthbound { /** * Returns a list of Hosts that are statically configured and are connected * to a NodeConnector that is down. - * + * * @param containerName * Name of the Container. The Container name for the base * controller is "default". @@ -187,7 +187,7 @@ public class HostTrackerNorthbound { /** * Returns a host that matches the IP Address value passed as parameter. - * + * * @param containerName * Name of the Container. The Container name for the base * controller is "default". @@ -236,7 +236,7 @@ public class HostTrackerNorthbound { /** * Add a Static Host configuration - * + * * @param containerName * Name of the Container. The Container name for the base * controller is "default". @@ -320,7 +320,7 @@ public class HostTrackerNorthbound { /** * Delete a Static Host configuration - * + * * @param containerName * Name of the Container. The Container name for the base * controller is "default". @@ -342,7 +342,7 @@ public class HostTrackerNorthbound { public Response deleteFlow( @PathParam(value = "containerName") String containerName, @PathParam(value = "networkAddress") String networkAddress) { - + if (!NorthboundUtils.isAuthorized( getUserName(), containerName, Privilege.WRITE, this)) { throw new UnauthorizedException( diff --git a/opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/Hosts.java b/opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/Hosts.java index 463b493536..c9ada2aeed 100644 --- a/opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/Hosts.java +++ b/opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/Hosts.java @@ -21,18 +21,18 @@ import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; @XmlAccessorType(XmlAccessType.NONE) public class Hosts { - @XmlElement (name="host") - Set hostNodeConnector; - - public Hosts() { - } - public Hosts (Set hostNodeConnector) { - this.hostNodeConnector = hostNodeConnector; - } - public Set getHostNodeConnector() { - return hostNodeConnector; - } - public void setHostNodeConnector(Set hostNodeConnector) { - this.hostNodeConnector = hostNodeConnector; - } + @XmlElement (name="host") + Set hostNodeConnector; + + public Hosts() { + } + public Hosts (Set hostNodeConnector) { + this.hostNodeConnector = hostNodeConnector; + } + public Set getHostNodeConnector() { + return hostNodeConnector; + } + public void setHostNodeConnector(Set hostNodeConnector) { + this.hostNodeConnector = hostNodeConnector; + } } diff --git a/opendaylight/northbound/hosttracker/src/main/resources/WEB-INF/web.xml b/opendaylight/northbound/hosttracker/src/main/resources/WEB-INF/web.xml index 7eb940875a..0fa8b95dd0 100644 --- a/opendaylight/northbound/hosttracker/src/main/resources/WEB-INF/web.xml +++ b/opendaylight/northbound/hosttracker/src/main/resources/WEB-INF/web.xml @@ -1,7 +1,7 @@ + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" + version="3.0"> JAXRSHostTracker com.sun.jersey.spi.container.servlet.ServletContainer @@ -17,34 +17,34 @@ /* - - - NB api - /* - - - System-Admin - Network-Admin - Network-Operator - Container-User - - + + + NB api + /* + + + System-Admin + Network-Admin + Network-Operator + Container-User + + - - System-Admin - - - Network-Admin - - - Network-Operator - - - Container-User - + + System-Admin + + + Network-Admin + + + Network-Operator + + + Container-User + - - BASIC - opendaylight - + + BASIC + opendaylight + \ No newline at end of file diff --git a/opendaylight/northbound/integrationtest/pom.xml b/opendaylight/northbound/integrationtest/pom.xml index aa4469e452..90acc8c59f 100644 --- a/opendaylight/northbound/integrationtest/pom.xml +++ b/opendaylight/northbound/integrationtest/pom.xml @@ -607,7 +607,7 @@ jersey-core ${jersey.version} - com.sun.jersey @@ -627,4 +627,3 @@ - diff --git a/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java b/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java index 24eb3d7a4c..103a515607 100644 --- a/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java +++ b/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java @@ -41,11 +41,9 @@ import org.opendaylight.controller.sal.core.UpdateType; import org.opendaylight.controller.switchmanager.IInventoryListener; import org.opendaylight.controller.usermanager.IUserManager; - @RunWith(PaxExam.class) public class NorthboundIT { - private Logger log = LoggerFactory - .getLogger(NorthboundIT.class); + private Logger log = LoggerFactory.getLogger(NorthboundIT.class); // get the OSGI bundle context @Inject private BundleContext bc; @@ -167,8 +165,429 @@ public class NorthboundIT { } } + private void testNodeProperties(JSONObject node, Integer nodeId, + String nodeType, Integer timestamp, String timestampName, + Integer actionsValue, Integer capabilitiesValue, + Integer tablesValue, Integer buffersValue) throws JSONException { + + JSONObject nodeInfo = node.getJSONObject("node"); + Assert.assertEquals(nodeId, (Integer) nodeInfo.getInt("@id")); + Assert.assertEquals(nodeType, nodeInfo.getString("@type")); + + JSONObject properties = node.getJSONObject("properties"); + + if (timestamp == null || timestampName == null) { + Assert.assertFalse(properties.has("timeStamp")); + } else { + Assert.assertEquals( + timestamp, + (Integer) properties.getJSONObject("timeStamp").getInt( + "timestamp")); + Assert.assertEquals( + timestampName, + properties.getJSONObject("timeStamp").getString( + "timestampName")); + } + if (actionsValue == null) { + Assert.assertFalse(properties.has("actions")); + } else { + Assert.assertEquals(actionsValue, (Integer) properties + .getJSONObject("actions").getInt("actionsValue")); + } + if (capabilitiesValue == null) { + Assert.assertFalse(properties.has("capabilities")); + } else { + Assert.assertEquals(capabilitiesValue, (Integer) properties + .getJSONObject("capabilities").getInt("capabilitiesValue")); + } + if (tablesValue == null) { + Assert.assertFalse(properties.has("tables")); + } else { + Assert.assertEquals(tablesValue, (Integer) properties + .getJSONObject("tables").getInt("tablesValue")); + } + if (buffersValue == null) { + Assert.assertFalse(properties.has("buffers")); + } else { + Assert.assertEquals(buffersValue, (Integer) properties + .getJSONObject("buffers").getInt("buffersValue")); + } + } + + private void testNodeConnectorProperties( + JSONObject nodeConnectorProperties, Integer ncId, String ncType, + Integer nodeId, String nodeType, Integer state, + Integer capabilities, Integer bandwidth) throws JSONException { + + JSONObject nodeConnector = nodeConnectorProperties + .getJSONObject("nodeconnector"); + JSONObject node = nodeConnector.getJSONObject("node"); + JSONObject properties = nodeConnectorProperties + .getJSONObject("properties"); + + Assert.assertEquals(ncId, (Integer) nodeConnector.getInt("@id")); + Assert.assertEquals(ncType, nodeConnector.getString("@type")); + Assert.assertEquals(nodeId, (Integer) node.getInt("@id")); + Assert.assertEquals(nodeType, node.getString("@type")); + if (state == null) { + Assert.assertFalse(properties.has("state")); + } else { + Assert.assertEquals( + state, + (Integer) properties.getJSONObject("state").getInt( + "stateValue")); + } + if (capabilities == null) { + Assert.assertFalse(properties.has("capabilities")); + } else { + Assert.assertEquals(capabilities, (Integer) properties + .getJSONObject("capabilities").getInt("capabilitiesValue")); + } + if (bandwidth == null) { + Assert.assertFalse(properties.has("bandwidth")); + } else { + Assert.assertEquals( + bandwidth, + (Integer) properties.getJSONObject("bandwidth").getInt( + "bandwidthValue")); + } + + } + + @Test + public void testSubnetsNorthbound() throws JSONException { + String baseURL = "http://127.0.0.1:8080/controller/nb/v2/subnet/"; + + String name1 = "testSubnet1"; + String subnet1 = "1.1.1.1/24"; + String name2 = "testSubnet2"; + String subnet2 = "2.2.2.2/24"; + + // Test GET subnets in default container + String result = getJsonResult(baseURL + "default"); + JSONTokener jt = new JSONTokener(result); + JSONObject json = new JSONObject(jt); + Assert.assertEquals("{}", result); + + // Test GET subnet1 expecting 404 + result = getJsonResult(baseURL + "default/" + name1); + Assert.assertEquals(404, httpResponseCode.intValue()); + + // Test POST subnet1 + String queryParameter = new QueryParameter("subnetName", name1).add( + "subnet", subnet1).getString(); + result = getJsonResult(baseURL + "default/" + name1 + queryParameter, + "POST"); + Assert.assertEquals(201, httpResponseCode.intValue()); + + // Test GET subnet1 + result = getJsonResult(baseURL + "default/" + name1); + jt = new JSONTokener(result); + json = new JSONObject(jt); + Assert.assertEquals(200, httpResponseCode.intValue()); + Assert.assertEquals(name1, json.getString("@name")); + Assert.assertEquals(subnet1, json.getString("@subnet")); + + // Test POST subnet2 + queryParameter = new QueryParameter("subnetName", name2).add("subnet", + subnet2).getString(); + result = getJsonResult(baseURL + "default/" + name2 + queryParameter, + "POST"); + Assert.assertEquals(201, httpResponseCode.intValue()); + + // Test GET all subnets in default container + result = getJsonResult(baseURL + "default"); + jt = new JSONTokener(result); + json = new JSONObject(jt); + JSONArray subnetConfigArray = json.getJSONArray("subnetConfig"); + JSONObject subnetConfig; + Assert.assertEquals(2, subnetConfigArray.length()); + for (int i = 0; i < subnetConfigArray.length(); i++) { + subnetConfig = subnetConfigArray.getJSONObject(i); + if (subnetConfig.getString("@name").equals(name1)) { + Assert.assertEquals(subnet1, subnetConfig.getString("@subnet")); + } else if (subnetConfig.getString("@name").equals(name2)) { + Assert.assertEquals(subnet2, subnetConfig.getString("@subnet")); + } else { + // Unexpected config name + Assert.assertTrue(false); + } + } + + // Test DELETE subnet1 + result = getJsonResult(baseURL + "default/" + name1, "DELETE"); + Assert.assertEquals(200, httpResponseCode.intValue()); + + // Test GET deleted subnet1 + result = getJsonResult(baseURL + "default/" + name1); + Assert.assertEquals(404, httpResponseCode.intValue()); + + } + + @Test + public void testStaticRoutingNorthbound() throws JSONException { + String baseURL = "http://127.0.0.1:8080/controller/nb/v2/staticroute/"; + + String name1 = "testRoute1"; + String prefix1 = "192.168.1.1/24"; + String nextHop1 = "0.0.0.0"; + String name2 = "testRoute2"; + String prefix2 = "192.168.1.1/16"; + String nextHop2 = "1.1.1.1"; + + // Test GET static routes in default container, expecting no results + String result = getJsonResult(baseURL + "default"); + JSONTokener jt = new JSONTokener(result); + JSONObject json = new JSONObject(jt); + Assert.assertEquals("{}", result); + + // Test insert static route + String requestBody = "{\"name\":\"" + name1 + "\", \"prefix\":\"" + + prefix1 + "\", \"nextHop\":\"" + nextHop1 + "\"}"; + result = getJsonResult(baseURL + "default/" + name1, "POST", + requestBody); + Assert.assertEquals(201, httpResponseCode.intValue()); + + requestBody = "{\"name\":\"" + name2 + "\", \"prefix\":\"" + prefix2 + + "\", \"nextHop\":\"" + nextHop2 + "\"}"; + result = getJsonResult(baseURL + "default/" + name2, "POST", + requestBody); + Assert.assertEquals(201, httpResponseCode.intValue()); + + // Test Get all static routes + result = getJsonResult(baseURL + "default"); + jt = new JSONTokener(result); + json = new JSONObject(jt); + JSONArray staticRoutes = json.getJSONArray("staticRoute"); + Assert.assertEquals(2, staticRoutes.length()); + JSONObject route; + for (int i = 0; i < staticRoutes.length(); i++) { + route = staticRoutes.getJSONObject(i); + if (route.getString("name").equals(name1)) { + Assert.assertEquals(prefix1, route.getString("prefix")); + Assert.assertEquals(nextHop1, route.getString("nextHop")); + } else if (route.getString("name").equals(name2)) { + Assert.assertEquals(prefix2, route.getString("prefix")); + Assert.assertEquals(nextHop2, route.getString("nextHop")); + } else { + // static route has unknown name + Assert.assertTrue(false); + } + } + + // Test get specific static route + result = getJsonResult(baseURL + "default/" + name1); + jt = new JSONTokener(result); + json = new JSONObject(jt); + + Assert.assertEquals(name1, json.getString("name")); + Assert.assertEquals(prefix1, json.getString("prefix")); + Assert.assertEquals(nextHop1, json.getString("nextHop")); + + result = getJsonResult(baseURL + "default/" + name2); + jt = new JSONTokener(result); + json = new JSONObject(jt); + + Assert.assertEquals(name2, json.getString("name")); + Assert.assertEquals(prefix2, json.getString("prefix")); + Assert.assertEquals(nextHop2, json.getString("nextHop")); + + // Test delete static route + result = getJsonResult(baseURL + "default/" + name1, "DELETE"); + Assert.assertEquals(200, httpResponseCode.intValue()); + + result = getJsonResult(baseURL + "default"); + jt = new JSONTokener(result); + json = new JSONObject(jt); + JSONObject singleStaticRoute = json.getJSONObject("staticRoute"); + Assert.assertEquals(name2, singleStaticRoute.getString("name")); + + } + + @Test + public void testSwitchManager() throws JSONException { + String baseURL = "http://127.0.0.1:8080/controller/nb/v2/switch/default/"; + + // define Node/NodeConnector attributes for test + int nodeId_1 = 51966; + int nodeId_2 = 3366; + int nodeId_3 = 4477; + int nodeConnectorId_1 = 51966; + int nodeConnectorId_2 = 12; + int nodeConnectorId_3 = 34; + String nodeType = "STUB"; + String ncType = "STUB"; + int timestamp_1 = 100000; + String timestampName_1 = "connectedSince"; + int actionsValue_1 = 2; + int capabilitiesValue_1 = 3; + int tablesValue_1 = 1; + int buffersValue_1 = 1; + int ncState = 1; + int ncCapabilities = 1; + int ncBandwidth = 1000000000; + + // Test GET all nodes + + String result = getJsonResult(baseURL + "nodes"); + JSONTokener jt = new JSONTokener(result); + JSONObject json = new JSONObject(jt); + + // Test for first node + JSONObject node = getJsonInstance(json, "nodeProperties", nodeId_1); + Assert.assertNotNull(node); + testNodeProperties(node, nodeId_1, nodeType, timestamp_1, + timestampName_1, actionsValue_1, capabilitiesValue_1, + tablesValue_1, buffersValue_1); + + // Test 2nd node, properties of 2nd node same as first node + node = getJsonInstance(json, "nodeProperties", nodeId_2); + Assert.assertNotNull(node); + testNodeProperties(node, nodeId_2, nodeType, timestamp_1, + timestampName_1, actionsValue_1, capabilitiesValue_1, + tablesValue_1, buffersValue_1); + + // Test 3rd node, properties of 3rd node same as first node + node = getJsonInstance(json, "nodeProperties", nodeId_3); + Assert.assertNotNull(node); + testNodeProperties(node, nodeId_3, nodeType, timestamp_1, + timestampName_1, actionsValue_1, capabilitiesValue_1, + tablesValue_1, buffersValue_1); + + // Test GET nodeConnectors of a node + // Test first node + result = getJsonResult(baseURL + "node/STUB/" + nodeId_1); + jt = new JSONTokener(result); + json = new JSONObject(jt); + JSONObject nodeConnectorProperties = json + .getJSONObject("nodeConnectorProperties"); + + testNodeConnectorProperties(nodeConnectorProperties, nodeConnectorId_1, + ncType, nodeId_1, nodeType, ncState, ncCapabilities, + ncBandwidth); + + // Test second node + result = getJsonResult(baseURL + "node/STUB/" + nodeId_2); + jt = new JSONTokener(result); + json = new JSONObject(jt); + nodeConnectorProperties = json.getJSONObject("nodeConnectorProperties"); + + testNodeConnectorProperties(nodeConnectorProperties, nodeConnectorId_2, + ncType, nodeId_2, nodeType, ncState, ncCapabilities, + ncBandwidth); + + // Test third node + result = getJsonResult(baseURL + "node/STUB/" + nodeId_3); + jt = new JSONTokener(result); + json = new JSONObject(jt); + + nodeConnectorProperties = json.getJSONObject("nodeConnectorProperties"); + testNodeConnectorProperties(nodeConnectorProperties, nodeConnectorId_3, + ncType, nodeId_3, nodeType, ncState, ncCapabilities, + ncBandwidth); + + // Test delete node property + // Delete timestamp property from node1 + result = getJsonResult(baseURL + "node/STUB/" + nodeId_1 + + "/property/timeStamp", "DELETE"); + Assert.assertEquals(200, httpResponseCode.intValue()); + + // Check node1 + result = getJsonResult(baseURL + "nodes"); + jt = new JSONTokener(result); + json = new JSONObject(jt); + node = getJsonInstance(json, "nodeProperties", nodeId_1); + Assert.assertNotNull(node); + testNodeProperties(node, nodeId_1, nodeType, null, null, + actionsValue_1, capabilitiesValue_1, tablesValue_1, + buffersValue_1); + + // Delete actions property from node2 + result = getJsonResult(baseURL + "node/STUB/" + nodeId_2 + + "/property/actions", "DELETE"); + Assert.assertEquals(200, httpResponseCode.intValue()); + + // Check node2 + result = getJsonResult(baseURL + "nodes"); + jt = new JSONTokener(result); + json = new JSONObject(jt); + node = getJsonInstance(json, "nodeProperties", nodeId_2); + Assert.assertNotNull(node); + testNodeProperties(node, nodeId_2, nodeType, timestamp_1, + timestampName_1, null, capabilitiesValue_1, tablesValue_1, + buffersValue_1); + + // Test add property to node + // Add Tier and Bandwidth property to node1 + result = getJsonResult(baseURL + "node/STUB/" + nodeId_1 + + "/property/tier/1001", "PUT"); + Assert.assertEquals(201, httpResponseCode.intValue()); + result = getJsonResult(baseURL + "node/STUB/" + nodeId_1 + + "/property/bandwidth/1002", "PUT"); + Assert.assertEquals(201, httpResponseCode.intValue()); + + // Test for first node + result = getJsonResult(baseURL + "nodes"); + jt = new JSONTokener(result); + json = new JSONObject(jt); + node = getJsonInstance(json, "nodeProperties", nodeId_1); + Assert.assertNotNull(node); + Assert.assertEquals(1001, node.getJSONObject("properties") + .getJSONObject("tier").getInt("tierValue")); + Assert.assertEquals(1002, node.getJSONObject("properties") + .getJSONObject("bandwidth").getInt("bandwidthValue")); + + // Test delete nodeConnector property + // Delete state property of nodeconnector1 + result = getJsonResult(baseURL + "nodeconnector/STUB/" + nodeId_1 + + "/STUB/" + nodeConnectorId_1 + "/property/state", "DELETE"); + Assert.assertEquals(200, httpResponseCode.intValue()); + + result = getJsonResult(baseURL + "node/STUB/" + nodeId_1); + jt = new JSONTokener(result); + json = new JSONObject(jt); + nodeConnectorProperties = json.getJSONObject("nodeConnectorProperties"); + + testNodeConnectorProperties(nodeConnectorProperties, nodeConnectorId_1, + ncType, nodeId_1, nodeType, null, ncCapabilities, ncBandwidth); + + // Delete capabilities property of nodeconnector2 + result = getJsonResult(baseURL + "nodeconnector/STUB/" + nodeId_2 + + "/STUB/" + nodeConnectorId_2 + "/property/capabilities", + "DELETE"); + Assert.assertEquals(200, httpResponseCode.intValue()); + + result = getJsonResult(baseURL + "node/STUB/" + nodeId_2); + jt = new JSONTokener(result); + json = new JSONObject(jt); + nodeConnectorProperties = json.getJSONObject("nodeConnectorProperties"); + + testNodeConnectorProperties(nodeConnectorProperties, nodeConnectorId_2, + ncType, nodeId_2, nodeType, ncState, null, ncBandwidth); + + // Test PUT nodeConnector property + int newBandwidth = 1001; + + // Add Name/Bandwidth property to nodeConnector1 + result = getJsonResult(baseURL + "nodeconnector/STUB/" + nodeId_1 + + "/STUB/" + nodeConnectorId_1 + "/property/bandwidth/" + + newBandwidth, "PUT"); + Assert.assertEquals(201, httpResponseCode.intValue()); + + result = getJsonResult(baseURL + "node/STUB/" + nodeId_1); + jt = new JSONTokener(result); + json = new JSONObject(jt); + nodeConnectorProperties = json.getJSONObject("nodeConnectorProperties"); + + // Check for new bandwidth value, state value removed from previous + // test + testNodeConnectorProperties(nodeConnectorProperties, nodeConnectorId_1, + ncType, nodeId_1, nodeType, null, ncCapabilities, newBandwidth); + + } + @Test - public void testStatistics() { + public void testStatistics() throws JSONException { String actionTypes[] = { "drop", "loopback", "flood", "floodAll", "controller", "swPath", "hwPath", "output", "setDlSrc", "setDlDst", "setDlType", "setVlanId", "setVlanPcp", @@ -177,262 +596,247 @@ public class NorthboundIT { System.out.println("Starting Statistics JAXB client."); String baseURL = "http://127.0.0.1:8080/controller/nb/v2/statistics/default/"; - try { - String result = getJsonResult(baseURL + "flowstats"); - JSONTokener jt = new JSONTokener(result); - JSONObject json = new JSONObject(jt); - JSONObject flowStatistics = getJsonInstance(json, "flowStatistics", - 0xCAFE); - JSONObject node = flowStatistics.getJSONObject("node"); - // test that node was returned properly - Assert.assertTrue(node.getInt("@id") == 0xCAFE); - Assert.assertTrue(node.getString("@type").equals("STUB")); - - // test that flow statistics results are correct - JSONArray flowStats = flowStatistics.getJSONArray("flowStat"); - for (int i = 0; i < flowStats.length(); i++) { - - JSONObject flowStat = flowStats.getJSONObject(i); - testFlowStat(flowStat, actionTypes[i]); - } + String result = getJsonResult(baseURL + "flowstats"); + JSONTokener jt = new JSONTokener(result); + JSONObject json = new JSONObject(jt); + JSONObject flowStatistics = getJsonInstance(json, "flowStatistics", + 0xCAFE); + JSONObject node = flowStatistics.getJSONObject("node"); + // test that node was returned properly + Assert.assertTrue(node.getInt("@id") == 0xCAFE); + Assert.assertTrue(node.getString("@type").equals("STUB")); - // for /controller/nb/v2/statistics/default/portstats - result = getJsonResult(baseURL + "portstats"); - jt = new JSONTokener(result); - json = new JSONObject(jt); - JSONObject portStatistics = getJsonInstance(json, "portStatistics", - 0xCAFE); - JSONObject node2 = portStatistics.getJSONObject("node"); - // test that node was returned properly - Assert.assertTrue(node2.getInt("@id") == 0xCAFE); - Assert.assertTrue(node2.getString("@type").equals("STUB")); - - // test that port statistic results are correct - JSONObject portStat = portStatistics.getJSONObject("portStat"); - Assert.assertTrue(portStat.getInt("receivePackets") == 250); - Assert.assertTrue(portStat.getInt("transmitPackets") == 500); - Assert.assertTrue(portStat.getInt("receiveBytes") == 1000); - Assert.assertTrue(portStat.getInt("transmitBytes") == 5000); - Assert.assertTrue(portStat.getInt("receiveDrops") == 2); - Assert.assertTrue(portStat.getInt("transmitDrops") == 50); - Assert.assertTrue(portStat.getInt("receiveErrors") == 3); - Assert.assertTrue(portStat.getInt("transmitErrors") == 10); - Assert.assertTrue(portStat.getInt("receiveFrameError") == 5); - Assert.assertTrue(portStat.getInt("receiveOverRunError") == 6); - Assert.assertTrue(portStat.getInt("receiveCrcError") == 1); - Assert.assertTrue(portStat.getInt("collisionCount") == 4); - - // test for getting one specific node's stats - result = getJsonResult(baseURL + "flowstats/STUB/51966"); - jt = new JSONTokener(result); - json = new JSONObject(jt); - node = json.getJSONObject("node"); - // test that node was returned properly - Assert.assertTrue(node.getInt("@id") == 0xCAFE); - Assert.assertTrue(node.getString("@type").equals("STUB")); - - // test that flow statistics results are correct - flowStats = json.getJSONArray("flowStat"); - for (int i = 0; i < flowStats.length(); i++) { - JSONObject flowStat = flowStats.getJSONObject(i); - testFlowStat(flowStat, actionTypes[i]); - } + // test that flow statistics results are correct + JSONArray flowStats = flowStatistics.getJSONArray("flowStat"); + for (int i = 0; i < flowStats.length(); i++) { - result = getJsonResult(baseURL + "portstats/STUB/51966"); - jt = new JSONTokener(result); - json = new JSONObject(jt); - node2 = json.getJSONObject("node"); - // test that node was returned properly - Assert.assertTrue(node2.getInt("@id") == 0xCAFE); - Assert.assertTrue(node2.getString("@type").equals("STUB")); - - // test that port statistic results are correct - portStat = json.getJSONObject("portStat"); - Assert.assertTrue(portStat.getInt("receivePackets") == 250); - Assert.assertTrue(portStat.getInt("transmitPackets") == 500); - Assert.assertTrue(portStat.getInt("receiveBytes") == 1000); - Assert.assertTrue(portStat.getInt("transmitBytes") == 5000); - Assert.assertTrue(portStat.getInt("receiveDrops") == 2); - Assert.assertTrue(portStat.getInt("transmitDrops") == 50); - Assert.assertTrue(portStat.getInt("receiveErrors") == 3); - Assert.assertTrue(portStat.getInt("transmitErrors") == 10); - Assert.assertTrue(portStat.getInt("receiveFrameError") == 5); - Assert.assertTrue(portStat.getInt("receiveOverRunError") == 6); - Assert.assertTrue(portStat.getInt("receiveCrcError") == 1); - Assert.assertTrue(portStat.getInt("collisionCount") == 4); + JSONObject flowStat = flowStats.getJSONObject(i); + testFlowStat(flowStat, actionTypes[i]); - } catch (Exception e) { - // Got an unexpected exception - Assert.assertTrue(false); + } + // for /controller/nb/v2/statistics/default/portstats + result = getJsonResult(baseURL + "portstats"); + jt = new JSONTokener(result); + json = new JSONObject(jt); + JSONObject portStatistics = getJsonInstance(json, "portStatistics", + 0xCAFE); + JSONObject node2 = portStatistics.getJSONObject("node"); + // test that node was returned properly + Assert.assertTrue(node2.getInt("@id") == 0xCAFE); + Assert.assertTrue(node2.getString("@type").equals("STUB")); + + // test that port statistic results are correct + JSONObject portStat = portStatistics.getJSONObject("portStat"); + Assert.assertTrue(portStat.getInt("receivePackets") == 250); + Assert.assertTrue(portStat.getInt("transmitPackets") == 500); + Assert.assertTrue(portStat.getInt("receiveBytes") == 1000); + Assert.assertTrue(portStat.getInt("transmitBytes") == 5000); + Assert.assertTrue(portStat.getInt("receiveDrops") == 2); + Assert.assertTrue(portStat.getInt("transmitDrops") == 50); + Assert.assertTrue(portStat.getInt("receiveErrors") == 3); + Assert.assertTrue(portStat.getInt("transmitErrors") == 10); + Assert.assertTrue(portStat.getInt("receiveFrameError") == 5); + Assert.assertTrue(portStat.getInt("receiveOverRunError") == 6); + Assert.assertTrue(portStat.getInt("receiveCrcError") == 1); + Assert.assertTrue(portStat.getInt("collisionCount") == 4); + + // test for getting one specific node's stats + result = getJsonResult(baseURL + "flowstats/STUB/51966"); + jt = new JSONTokener(result); + json = new JSONObject(jt); + node = json.getJSONObject("node"); + // test that node was returned properly + Assert.assertTrue(node.getInt("@id") == 0xCAFE); + Assert.assertTrue(node.getString("@type").equals("STUB")); + + // test that flow statistics results are correct + flowStats = json.getJSONArray("flowStat"); + for (int i = 0; i < flowStats.length(); i++) { + JSONObject flowStat = flowStats.getJSONObject(i); + testFlowStat(flowStat, actionTypes[i]); } + + result = getJsonResult(baseURL + "portstats/STUB/51966"); + jt = new JSONTokener(result); + json = new JSONObject(jt); + node2 = json.getJSONObject("node"); + // test that node was returned properly + Assert.assertTrue(node2.getInt("@id") == 0xCAFE); + Assert.assertTrue(node2.getString("@type").equals("STUB")); + + // test that port statistic results are correct + portStat = json.getJSONObject("portStat"); + Assert.assertTrue(portStat.getInt("receivePackets") == 250); + Assert.assertTrue(portStat.getInt("transmitPackets") == 500); + Assert.assertTrue(portStat.getInt("receiveBytes") == 1000); + Assert.assertTrue(portStat.getInt("transmitBytes") == 5000); + Assert.assertTrue(portStat.getInt("receiveDrops") == 2); + Assert.assertTrue(portStat.getInt("transmitDrops") == 50); + Assert.assertTrue(portStat.getInt("receiveErrors") == 3); + Assert.assertTrue(portStat.getInt("transmitErrors") == 10); + Assert.assertTrue(portStat.getInt("receiveFrameError") == 5); + Assert.assertTrue(portStat.getInt("receiveOverRunError") == 6); + Assert.assertTrue(portStat.getInt("receiveCrcError") == 1); + Assert.assertTrue(portStat.getInt("collisionCount") == 4); } - private void testFlowStat(JSONObject flowStat, String actionType) { - try { - Assert.assertTrue(flowStat.getInt("tableId") == 1); - Assert.assertTrue(flowStat.getInt("durationSeconds") == 40); - Assert.assertTrue(flowStat.getInt("durationNanoseconds") == 400); - Assert.assertTrue(flowStat.getInt("packetCount") == 200); - Assert.assertTrue(flowStat.getInt("byteCount") == 100); - - // test that flow information is correct - JSONObject flow = flowStat.getJSONObject("flow"); - Assert.assertTrue(flow.getInt("priority") == 3500); - Assert.assertTrue(flow.getInt("idleTimeout") == 1000); - Assert.assertTrue(flow.getInt("hardTimeout") == 2000); - Assert.assertTrue(flow.getInt("id") == 12345); - - JSONObject match = (flow.getJSONObject("match") - .getJSONObject("matchField")); - Assert.assertTrue(match.getString("type").equals("NW_DST")); - Assert.assertTrue(match.getString("value").equals("1.1.1.1")); - - JSONObject act = flow.getJSONObject("actions"); - Assert.assertTrue(act.getString("@type").equals(actionType)); - - if (act.getString("@type").equals("output")) { - JSONObject port = act.getJSONObject("port"); - JSONObject port_node = port.getJSONObject("node"); - Assert.assertTrue(port.getInt("@id") == 51966); - Assert.assertTrue(port.getString("@type").equals("STUB")); - Assert.assertTrue(port_node.getInt("@id") == 51966); - Assert.assertTrue(port_node.getString("@type").equals("STUB")); - } + private void testFlowStat(JSONObject flowStat, String actionType) + throws JSONException { + Assert.assertTrue(flowStat.getInt("tableId") == 1); + Assert.assertTrue(flowStat.getInt("durationSeconds") == 40); + Assert.assertTrue(flowStat.getInt("durationNanoseconds") == 400); + Assert.assertTrue(flowStat.getInt("packetCount") == 200); + Assert.assertTrue(flowStat.getInt("byteCount") == 100); + + // test that flow information is correct + JSONObject flow = flowStat.getJSONObject("flow"); + Assert.assertTrue(flow.getInt("priority") == 3500); + Assert.assertTrue(flow.getInt("idleTimeout") == 1000); + Assert.assertTrue(flow.getInt("hardTimeout") == 2000); + Assert.assertTrue(flow.getInt("id") == 12345); + + JSONObject match = (flow.getJSONObject("match") + .getJSONObject("matchField")); + Assert.assertTrue(match.getString("type").equals("NW_DST")); + Assert.assertTrue(match.getString("value").equals("1.1.1.1")); + + JSONObject act = flow.getJSONObject("actions"); + Assert.assertTrue(act.getString("@type").equals(actionType)); + + if (act.getString("@type").equals("output")) { + JSONObject port = act.getJSONObject("port"); + JSONObject port_node = port.getJSONObject("node"); + Assert.assertTrue(port.getInt("@id") == 51966); + Assert.assertTrue(port.getString("@type").equals("STUB")); + Assert.assertTrue(port_node.getInt("@id") == 51966); + Assert.assertTrue(port_node.getString("@type").equals("STUB")); + } - if (act.getString("@type").equals("setDlSrc")) { - byte srcMatch[] = { (byte) 5, (byte) 4, (byte) 3, (byte) 2, - (byte) 1 }; - String src = act.getString("address"); - byte srcBytes[] = new byte[5]; - srcBytes[0] = Byte.parseByte(src.substring(0, 2)); - srcBytes[1] = Byte.parseByte(src.substring(2, 4)); - srcBytes[2] = Byte.parseByte(src.substring(4, 6)); - srcBytes[3] = Byte.parseByte(src.substring(6, 8)); - srcBytes[4] = Byte.parseByte(src.substring(8, 10)); - Assert.assertTrue(Arrays.equals(srcBytes, srcMatch)); - } + if (act.getString("@type").equals("setDlSrc")) { + byte srcMatch[] = { (byte) 5, (byte) 4, (byte) 3, (byte) 2, + (byte) 1 }; + String src = act.getString("address"); + byte srcBytes[] = new byte[5]; + srcBytes[0] = Byte.parseByte(src.substring(0, 2)); + srcBytes[1] = Byte.parseByte(src.substring(2, 4)); + srcBytes[2] = Byte.parseByte(src.substring(4, 6)); + srcBytes[3] = Byte.parseByte(src.substring(6, 8)); + srcBytes[4] = Byte.parseByte(src.substring(8, 10)); + Assert.assertTrue(Arrays.equals(srcBytes, srcMatch)); + } - if (act.getString("@type").equals("setDlDst")) { - byte dstMatch[] = { (byte) 1, (byte) 2, (byte) 3, (byte) 4, - (byte) 5 }; - String dst = act.getString("address"); - byte dstBytes[] = new byte[5]; - dstBytes[0] = Byte.parseByte(dst.substring(0, 2)); - dstBytes[1] = Byte.parseByte(dst.substring(2, 4)); - dstBytes[2] = Byte.parseByte(dst.substring(4, 6)); - dstBytes[3] = Byte.parseByte(dst.substring(6, 8)); - dstBytes[4] = Byte.parseByte(dst.substring(8, 10)); - Assert.assertTrue(Arrays.equals(dstBytes, dstMatch)); - } - if (act.getString("@type").equals("setDlType")) - Assert.assertTrue(act.getInt("dlType") == 10); - if (act.getString("@type").equals("setVlanId")) - Assert.assertTrue(act.getInt("vlanId") == 2); - if (act.getString("@type").equals("setVlanPcp")) - Assert.assertTrue(act.getInt("pcp") == 3); - if (act.getString("@type").equals("setVlanCfi")) - Assert.assertTrue(act.getInt("cfi") == 1); - - if (act.getString("@type").equals("setNwSrc")) - Assert.assertTrue(act.getString("address").equals("2.2.2.2")); - if (act.getString("@type").equals("setNwDst")) - Assert.assertTrue(act.getString("address").equals("1.1.1.1")); - - if (act.getString("@type").equals("pushVlan")) { - int head = act.getInt("VlanHeader"); - // parsing vlan header - int id = head & 0xfff; - int cfi = (head >> 12) & 0x1; - int pcp = (head >> 13) & 0x7; - int tag = (head >> 16) & 0xffff; - Assert.assertTrue(id == 1234); - Assert.assertTrue(cfi == 1); - Assert.assertTrue(pcp == 1); - Assert.assertTrue(tag == 0x8100); - } - if (act.getString("@type").equals("setNwTos")) - Assert.assertTrue(act.getInt("tos") == 16); - if (act.getString("@type").equals("setTpSrc")) - Assert.assertTrue(act.getInt("port") == 4201); - if (act.getString("@type").equals("setTpDst")) - Assert.assertTrue(act.getInt("port") == 8080); - } catch (Exception e) { - Assert.assertTrue(false); + if (act.getString("@type").equals("setDlDst")) { + byte dstMatch[] = { (byte) 1, (byte) 2, (byte) 3, (byte) 4, + (byte) 5 }; + String dst = act.getString("address"); + byte dstBytes[] = new byte[5]; + dstBytes[0] = Byte.parseByte(dst.substring(0, 2)); + dstBytes[1] = Byte.parseByte(dst.substring(2, 4)); + dstBytes[2] = Byte.parseByte(dst.substring(4, 6)); + dstBytes[3] = Byte.parseByte(dst.substring(6, 8)); + dstBytes[4] = Byte.parseByte(dst.substring(8, 10)); + Assert.assertTrue(Arrays.equals(dstBytes, dstMatch)); + } + if (act.getString("@type").equals("setDlType")) + Assert.assertTrue(act.getInt("dlType") == 10); + if (act.getString("@type").equals("setVlanId")) + Assert.assertTrue(act.getInt("vlanId") == 2); + if (act.getString("@type").equals("setVlanPcp")) + Assert.assertTrue(act.getInt("pcp") == 3); + if (act.getString("@type").equals("setVlanCfi")) + Assert.assertTrue(act.getInt("cfi") == 1); + + if (act.getString("@type").equals("setNwSrc")) + Assert.assertTrue(act.getString("address").equals("2.2.2.2")); + if (act.getString("@type").equals("setNwDst")) + Assert.assertTrue(act.getString("address").equals("1.1.1.1")); + + if (act.getString("@type").equals("pushVlan")) { + int head = act.getInt("VlanHeader"); + // parsing vlan header + int id = head & 0xfff; + int cfi = (head >> 12) & 0x1; + int pcp = (head >> 13) & 0x7; + int tag = (head >> 16) & 0xffff; + Assert.assertTrue(id == 1234); + Assert.assertTrue(cfi == 1); + Assert.assertTrue(pcp == 1); + Assert.assertTrue(tag == 0x8100); } + if (act.getString("@type").equals("setNwTos")) + Assert.assertTrue(act.getInt("tos") == 16); + if (act.getString("@type").equals("setTpSrc")) + Assert.assertTrue(act.getInt("port") == 4201); + if (act.getString("@type").equals("setTpDst")) + Assert.assertTrue(act.getInt("port") == 8080); } @Test - public void testFlowProgrammer() { - try { - String baseURL = "http://127.0.0.1:8080/controller/nb/v2/flow/default/"; - // Attempt to get a flow that doesn't exit. Should return 404 - // status. - String result = getJsonResult(baseURL + "STUB/51966/test1", "GET"); - Assert.assertTrue(result.equals("404")); - - // test add flow1 - String fc = "{\"dynamic\":\"false\", \"name\":\"test1\", \"node\":{\"@id\":\"51966\",\"@type\":\"STUB\"}, \"actions\":[\"DROP\"]}"; - result = getJsonResult(baseURL + "STUB/51966/test1", "POST", fc); - Assert.assertTrue(httpResponseCode == 201); - - // test get returns flow that was added. - result = getJsonResult(baseURL + "STUB/51966/test1", "GET"); - // check that result came out fine. - Assert.assertTrue(httpResponseCode == 200); - JSONTokener jt = new JSONTokener(result); - JSONObject json = new JSONObject(jt); - Assert.assertTrue(json.getString("name").equals("test1")); - Assert.assertTrue(json.getString("actions").equals("DROP")); - Assert.assertTrue(json.getString("installInHw").equals("true")); - JSONObject node = json.getJSONObject("node"); - Assert.assertTrue(node.getString("@type").equals("STUB")); - Assert.assertTrue(node.getString("@id").equals("51966")); - // test adding same flow again fails due to repeat name..return 409 - // code - result = getJsonResult(baseURL + "STUB/51966/test1", "POST", fc); - Assert.assertTrue(result.equals("409")); - - fc = "{\"dynamic\":\"false\", \"name\":\"test2\", \"node\":{\"@id\":\"51966\",\"@type\":\"STUB\"}, \"actions\":[\"DROP\"]}"; - result = getJsonResult(baseURL + "STUB/51966/test2", "POST", fc); - // test should return 500 for error due to same flow being added. - Assert.assertTrue(result.equals("500")); - - // add second flow that's different - fc = "{\"dynamic\":\"false\", \"name\":\"test2\", \"nwSrc\":\"1.1.1.1\", \"node\":{\"@id\":\"51966\",\"@type\":\"STUB\"}, \"actions\":[\"DROP\"]}"; - result = getJsonResult(baseURL + "STUB/51966/test2", "POST", fc); - Assert.assertTrue(httpResponseCode == 201); - - // check that request returns both flows given node. - result = getJsonResult(baseURL + "STUB/51966/", "GET"); - jt = new JSONTokener(result); - json = new JSONObject(jt); - Assert.assertTrue(json.get("flowConfig") instanceof JSONArray); - JSONArray ja = json.getJSONArray("flowConfig"); - Integer count = ja.length(); - Assert.assertTrue(count == 2); - - // check that request returns both flows given just container. - result = getJsonResult(baseURL); - jt = new JSONTokener(result); - json = new JSONObject(jt); - Assert.assertTrue(json.get("flowConfig") instanceof JSONArray); - ja = json.getJSONArray("flowConfig"); - count = ja.length(); - Assert.assertTrue(count == 2); - - // delete a flow, check that it's no longer in list. - result = getJsonResult(baseURL + "STUB/51966/test2", "DELETE"); - Assert.assertTrue(httpResponseCode == 200); - - result = getJsonResult(baseURL + "STUB/51966/test2", "GET"); - Assert.assertTrue(result.equals("404")); - - } catch (Exception e) { - Assert.assertTrue(false); - } - + public void testFlowProgrammer() throws JSONException { + String baseURL = "http://127.0.0.1:8080/controller/nb/v2/flow/default/"; + // Attempt to get a flow that doesn't exit. Should return 404 + // status. + String result = getJsonResult(baseURL + "STUB/51966/test1", "GET"); + Assert.assertTrue(result.equals("404")); + + // test add flow1 + String fc = "{\"dynamic\":\"false\", \"name\":\"test1\", \"node\":{\"@id\":\"51966\",\"@type\":\"STUB\"}, \"actions\":[\"DROP\"]}"; + result = getJsonResult(baseURL + "STUB/51966/test1", "POST", fc); + Assert.assertTrue(httpResponseCode == 201); + + // test get returns flow that was added. + result = getJsonResult(baseURL + "STUB/51966/test1", "GET"); + // check that result came out fine. + Assert.assertTrue(httpResponseCode == 200); + JSONTokener jt = new JSONTokener(result); + JSONObject json = new JSONObject(jt); + Assert.assertTrue(json.getString("name").equals("test1")); + Assert.assertTrue(json.getString("actions").equals("DROP")); + Assert.assertTrue(json.getString("installInHw").equals("true")); + JSONObject node = json.getJSONObject("node"); + Assert.assertTrue(node.getString("@type").equals("STUB")); + Assert.assertTrue(node.getString("@id").equals("51966")); + // test adding same flow again fails due to repeat name..return 409 + // code + result = getJsonResult(baseURL + "STUB/51966/test1", "POST", fc); + Assert.assertTrue(result.equals("409")); + + fc = "{\"dynamic\":\"false\", \"name\":\"test2\", \"node\":{\"@id\":\"51966\",\"@type\":\"STUB\"}, \"actions\":[\"DROP\"]}"; + result = getJsonResult(baseURL + "STUB/51966/test2", "POST", fc); + // test should return 500 for error due to same flow being added. + Assert.assertTrue(result.equals("500")); + + // add second flow that's different + fc = "{\"dynamic\":\"false\", \"name\":\"test2\", \"nwSrc\":\"1.1.1.1\", \"node\":{\"@id\":\"51966\",\"@type\":\"STUB\"}, \"actions\":[\"DROP\"]}"; + result = getJsonResult(baseURL + "STUB/51966/test2", "POST", fc); + Assert.assertTrue(httpResponseCode == 201); + + // check that request returns both flows given node. + result = getJsonResult(baseURL + "STUB/51966/", "GET"); + jt = new JSONTokener(result); + json = new JSONObject(jt); + Assert.assertTrue(json.get("flowConfig") instanceof JSONArray); + JSONArray ja = json.getJSONArray("flowConfig"); + Integer count = ja.length(); + Assert.assertTrue(count == 2); + + // check that request returns both flows given just container. + result = getJsonResult(baseURL); + jt = new JSONTokener(result); + json = new JSONObject(jt); + Assert.assertTrue(json.get("flowConfig") instanceof JSONArray); + ja = json.getJSONArray("flowConfig"); + count = ja.length(); + Assert.assertTrue(count == 2); + + // delete a flow, check that it's no longer in list. + result = getJsonResult(baseURL + "STUB/51966/test2", "DELETE"); + Assert.assertTrue(httpResponseCode == 200); + + result = getJsonResult(baseURL + "STUB/51966/test2", "GET"); + Assert.assertTrue(result.equals("404")); } // method to extract a JSONObject with specified node ID from a JSONObject @@ -484,7 +888,7 @@ public class NorthboundIT { } @Test - public void testHostTracker() { + public void testHostTracker() throws JSONException { System.out.println("Starting HostTracker JAXB client."); @@ -510,34 +914,29 @@ public class NorthboundIT { String baseURL = "http://127.0.0.1:8080/controller/nb/v2/host/default"; // test POST method: addHost() - try { - String queryParameter = new QueryParameter("dataLayerAddress", - dataLayerAddress_1).add("nodeType", nodeType_1) - .add("nodeId", nodeId_1.toString()) - .add("nodeConnectorType", nodeConnectorType_1) - .add("nodeConnectorId", nodeConnectorId_1.toString()) - .add("vlan", vlan_1).getString(); - - String result = getJsonResult(baseURL + "/" + networkAddress_1 - + queryParameter, "POST"); - Assert.assertTrue(httpResponseCode.intValue() == (Integer) 201); - - // vlan is not passed through query parameter but should be - // defaulted to "0" - queryParameter = new QueryParameter("dataLayerAddress", - dataLayerAddress_2).add("nodeType", nodeType_2) - .add("nodeId", nodeId_2.toString()) - .add("nodeConnectorType", nodeConnectorType_2) - .add("nodeConnectorId", nodeConnectorId_2.toString()) - .getString(); - - result = getJsonResult(baseURL + "/" + networkAddress_2 - + queryParameter, "POST"); - Assert.assertTrue(httpResponseCode.intValue() == (Integer) 201); - } catch (Exception e) { - // Got an unexpected exception - Assert.assertTrue(false); - } + String queryParameter = new QueryParameter("dataLayerAddress", + dataLayerAddress_1).add("nodeType", nodeType_1) + .add("nodeId", nodeId_1.toString()) + .add("nodeConnectorType", nodeConnectorType_1) + .add("nodeConnectorId", nodeConnectorId_1.toString()) + .add("vlan", vlan_1).getString(); + + String result = getJsonResult(baseURL + "/" + networkAddress_1 + + queryParameter, "POST"); + Assert.assertTrue(httpResponseCode.intValue() == (Integer) 201); + + // vlan is not passed through query parameter but should be + // defaulted to "0" + queryParameter = new QueryParameter("dataLayerAddress", + dataLayerAddress_2).add("nodeType", nodeType_2) + .add("nodeId", nodeId_2.toString()) + .add("nodeConnectorType", nodeConnectorType_2) + .add("nodeConnectorId", nodeConnectorId_2.toString()) + .getString(); + + result = getJsonResult(baseURL + "/" + networkAddress_2 + + queryParameter, "POST"); + Assert.assertTrue(httpResponseCode.intValue() == (Integer) 201); // define variables for decoding returned strings String networkAddress; @@ -545,69 +944,59 @@ public class NorthboundIT { // the two hosts should be in inactive host DB // test GET method: getInactiveHosts() - try { - String result = getJsonResult(baseURL + "/inactive", "GET"); - Assert.assertTrue(httpResponseCode.intValue() == (Integer) 200); + result = getJsonResult(baseURL + "/inactive", "GET"); + Assert.assertTrue(httpResponseCode.intValue() == (Integer) 200); + + JSONTokener jt = new JSONTokener(result); + JSONObject json = new JSONObject(jt); + // there should be at least two hosts in the DB + Assert.assertTrue(json.get("host") instanceof JSONArray); + JSONArray ja = json.getJSONArray("host"); + Integer count = ja.length(); + Assert.assertTrue(count == 2); + + for (int i = 0; i < count; i++) { + host_jo = ja.getJSONObject(i); + dl_jo = host_jo.getJSONObject("dataLayerAddress"); + nc_jo = host_jo.getJSONObject("nodeConnector"); + node_jo = nc_jo.getJSONObject("node"); - JSONTokener jt = new JSONTokener(result); - JSONObject json = new JSONObject(jt); - // there should be at least two hosts in the DB - Assert.assertTrue(json.get("host") instanceof JSONArray); - JSONArray ja = json.getJSONArray("host"); - Integer count = ja.length(); - Assert.assertTrue(count == 2); - - for (int i = 0; i < count; i++) { - host_jo = ja.getJSONObject(i); - dl_jo = host_jo.getJSONObject("dataLayerAddress"); - nc_jo = host_jo.getJSONObject("nodeConnector"); - node_jo = nc_jo.getJSONObject("node"); - - networkAddress = host_jo.getString("networkAddress"); - if (networkAddress.equalsIgnoreCase(networkAddress_1)) { - Assert.assertTrue(dl_jo.getString("macAddress") - .equalsIgnoreCase(dataLayerAddress_1)); - Assert.assertTrue(nc_jo.getString("@type") - .equalsIgnoreCase(nodeConnectorType_1)); - Assert.assertTrue(Integer.parseInt(nc_jo.getString("@id")) == nodeConnectorId_1); - Assert.assertTrue(node_jo.getString("@type") - .equalsIgnoreCase(nodeType_1)); - Assert.assertTrue(Integer.parseInt(node_jo.getString("@id")) == nodeId_1); - Assert.assertTrue(host_jo.getString("vlan") - .equalsIgnoreCase(vlan_1)); - } else if (networkAddress.equalsIgnoreCase(networkAddress_2)) { - Assert.assertTrue(dl_jo.getString("macAddress") - .equalsIgnoreCase(dataLayerAddress_2)); - Assert.assertTrue(nc_jo.getString("@type") - .equalsIgnoreCase(nodeConnectorType_2)); - Assert.assertTrue(Integer.parseInt(nc_jo.getString("@id")) == nodeConnectorId_2); - Assert.assertTrue(node_jo.getString("@type") - .equalsIgnoreCase(nodeType_2)); - Assert.assertTrue(Integer.parseInt(node_jo.getString("@id")) == nodeId_2); - Assert.assertTrue(host_jo.getString("vlan") - .equalsIgnoreCase(vlan_2)); - } else { - Assert.assertTrue(false); - } + networkAddress = host_jo.getString("networkAddress"); + if (networkAddress.equalsIgnoreCase(networkAddress_1)) { + Assert.assertTrue(dl_jo.getString("macAddress") + .equalsIgnoreCase(dataLayerAddress_1)); + Assert.assertTrue(nc_jo.getString("@type").equalsIgnoreCase( + nodeConnectorType_1)); + Assert.assertTrue(Integer.parseInt(nc_jo.getString("@id")) == nodeConnectorId_1); + Assert.assertTrue(node_jo.getString("@type").equalsIgnoreCase( + nodeType_1)); + Assert.assertTrue(Integer.parseInt(node_jo.getString("@id")) == nodeId_1); + Assert.assertTrue(host_jo.getString("vlan").equalsIgnoreCase( + vlan_1)); + } else if (networkAddress.equalsIgnoreCase(networkAddress_2)) { + Assert.assertTrue(dl_jo.getString("macAddress") + .equalsIgnoreCase(dataLayerAddress_2)); + Assert.assertTrue(nc_jo.getString("@type").equalsIgnoreCase( + nodeConnectorType_2)); + Assert.assertTrue(Integer.parseInt(nc_jo.getString("@id")) == nodeConnectorId_2); + Assert.assertTrue(node_jo.getString("@type").equalsIgnoreCase( + nodeType_2)); + Assert.assertTrue(Integer.parseInt(node_jo.getString("@id")) == nodeId_2); + Assert.assertTrue(host_jo.getString("vlan").equalsIgnoreCase( + vlan_2)); + } else { + Assert.assertTrue(false); } - } catch (Exception e) { - // Got an unexpected exception - Assert.assertTrue(false); } // test GET method: getActiveHosts() - no host expected - try { - String result = getJsonResult(baseURL, "GET"); - Assert.assertTrue(httpResponseCode.intValue() == (Integer) 200); + result = getJsonResult(baseURL, "GET"); + Assert.assertTrue(httpResponseCode.intValue() == (Integer) 200); - JSONTokener jt = new JSONTokener(result); - JSONObject json = new JSONObject(jt); - Assert.assertFalse(hostInJson(json, networkAddress_1)); - Assert.assertFalse(hostInJson(json, networkAddress_2)); - } catch (Exception e) { - // Got an unexpected exception - Assert.assertTrue(false); - } + jt = new JSONTokener(result); + json = new JSONObject(jt); + Assert.assertFalse(hostInJson(json, networkAddress_1)); + Assert.assertFalse(hostInJson(json, networkAddress_2)); // put the 1st host into active host DB Node nd; @@ -623,75 +1012,57 @@ public class NorthboundIT { } // verify the host shows up in active host DB - try { - String result = getJsonResult(baseURL, "GET"); - Assert.assertTrue(httpResponseCode.intValue() == (Integer) 200); - JSONTokener jt = new JSONTokener(result); - JSONObject json = new JSONObject(jt); + result = getJsonResult(baseURL, "GET"); + Assert.assertTrue(httpResponseCode.intValue() == (Integer) 200); - Assert.assertTrue(hostInJson(json, networkAddress_1)); - } catch (Exception e) { - // Got an unexpected exception - Assert.assertTrue(false); - } + jt = new JSONTokener(result); + json = new JSONObject(jt); + + Assert.assertTrue(hostInJson(json, networkAddress_1)); // test GET method for getHostDetails() - try { - String result = getJsonResult(baseURL + "/" + networkAddress_1, - "GET"); - Assert.assertTrue(httpResponseCode.intValue() == (Integer) 200); - JSONTokener jt = new JSONTokener(result); - JSONObject json = new JSONObject(jt); + result = getJsonResult(baseURL + "/" + networkAddress_1, "GET"); + Assert.assertTrue(httpResponseCode.intValue() == (Integer) 200); - Assert.assertFalse(json.length() == 0); + jt = new JSONTokener(result); + json = new JSONObject(jt); - dl_jo = json.getJSONObject("dataLayerAddress"); - nc_jo = json.getJSONObject("nodeConnector"); - node_jo = nc_jo.getJSONObject("node"); + Assert.assertFalse(json.length() == 0); - Assert.assertTrue(json.getString("networkAddress") - .equalsIgnoreCase(networkAddress_1)); - Assert.assertTrue(dl_jo.getString("macAddress").equalsIgnoreCase( - dataLayerAddress_1)); - Assert.assertTrue(nc_jo.getString("@type").equalsIgnoreCase( - nodeConnectorType_1)); - Assert.assertTrue(Integer.parseInt(nc_jo.getString("@id")) == nodeConnectorId_1); - Assert.assertTrue(node_jo.getString("@type").equalsIgnoreCase( - nodeType_1)); - Assert.assertTrue(Integer.parseInt(node_jo.getString("@id")) == nodeId_1); - Assert.assertTrue(json.getString("vlan").equalsIgnoreCase(vlan_1)); - } catch (Exception e) { - // Got an unexpected exception - Assert.assertTrue(false); - } + dl_jo = json.getJSONObject("dataLayerAddress"); + nc_jo = json.getJSONObject("nodeConnector"); + node_jo = nc_jo.getJSONObject("node"); + + Assert.assertTrue(json.getString("networkAddress").equalsIgnoreCase( + networkAddress_1)); + Assert.assertTrue(dl_jo.getString("macAddress").equalsIgnoreCase( + dataLayerAddress_1)); + Assert.assertTrue(nc_jo.getString("@type").equalsIgnoreCase( + nodeConnectorType_1)); + Assert.assertTrue(Integer.parseInt(nc_jo.getString("@id")) == nodeConnectorId_1); + Assert.assertTrue(node_jo.getString("@type").equalsIgnoreCase( + nodeType_1)); + Assert.assertTrue(Integer.parseInt(node_jo.getString("@id")) == nodeId_1); + Assert.assertTrue(json.getString("vlan").equalsIgnoreCase(vlan_1)); // test DELETE method for deleteFlow() - try { - String result = getJsonResult(baseURL + "/" + networkAddress_1, - "DELETE"); - Assert.assertTrue(httpResponseCode.intValue() == (Integer) 200); - } catch (Exception e) { - // Got an unexpected exception - Assert.assertTrue(false); - } + result = getJsonResult(baseURL + "/" + networkAddress_1, "DELETE"); + Assert.assertTrue(httpResponseCode.intValue() == (Integer) 200); // verify host_1 removed from active host DB // test GET method: getActiveHosts() - no host expected - try { - String result = getJsonResult(baseURL, "GET"); - Assert.assertTrue(httpResponseCode.intValue() == (Integer) 200); - JSONTokener jt = new JSONTokener(result); - JSONObject json = new JSONObject(jt); + result = getJsonResult(baseURL, "GET"); + Assert.assertTrue(httpResponseCode.intValue() == (Integer) 200); + + jt = new JSONTokener(result); + json = new JSONObject(jt); + + Assert.assertFalse(hostInJson(json, networkAddress_1)); - Assert.assertFalse(hostInJson(json, networkAddress_1)); - } catch (Exception e) { - // Got an unexpected exception - Assert.assertTrue(false); - } } private Boolean hostInJson(JSONObject json, String hostIp) @@ -796,6 +1167,8 @@ public class NorthboundIT { mavenBundle("org.opendaylight.controller", "usermanager", "0.4.0-SNAPSHOT"), + mavenBundle("org.opendaylight.controller", + "usermanager.implementation", "0.4.0-SNAPSHOT"), mavenBundle("org.opendaylight.controller", "logging.bridge", "0.4.0-SNAPSHOT"), mavenBundle("org.opendaylight.controller", "clustering.test", @@ -982,4 +1355,4 @@ public class NorthboundIT { mavenBundle("com.sun.jersey", "jersey-json", "1.17") .startLevel(2), junitBundles()); } -} \ No newline at end of file +} diff --git a/opendaylight/northbound/integrationtest/src/test/resources/tomcat-server.xml b/opendaylight/northbound/integrationtest/src/test/resources/tomcat-server.xml index 4be075451e..56d469b599 100644 --- a/opendaylight/northbound/integrationtest/src/test/resources/tomcat-server.xml +++ b/opendaylight/northbound/integrationtest/src/test/resources/tomcat-server.xml @@ -30,13 +30,13 @@ connectionTimeout="20000" redirectPort="8443" /> - - - - 0.5.1-SNAPSHOT + 0.5.2-SNAPSHOT diff --git a/opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/controller-network.yang b/opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/controller-network.yang index 357e6bab0b..600e87d267 100644 --- a/opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/controller-network.yang +++ b/opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/controller-network.yang @@ -11,7 +11,6 @@ module controller-network { - typedef topology-id { type string; } diff --git a/opendaylight/sal/yang-prototype/code-generator/samples/modeling-sample/pom.xml b/opendaylight/sal/yang-prototype/code-generator/samples/modeling-sample/pom.xml new file mode 100644 index 0000000000..260303ef9e --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/samples/modeling-sample/pom.xml @@ -0,0 +1,116 @@ + + 4.0.0 + + binding-generator + org.opendaylight.controller + 0.5.1-SNAPSHOT + + modeling-sample + + + + + org.opendaylight.controller + yang-maven-plugin + 0.5.1-SNAPSHOT + + + + generate-sources + + + src/main/yang + + + + org.opendaylight.controller.maven.sal.api.gen.plugin.CodeGeneratorImpl + + + target/generated-sources/sal + + + + false + + + + + + + org.opendaylight.controller + maven-sal-api-gen-plugin + 0.5.1-SNAPSHOT + jar + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.7 + + + generate-sources + + add-source + + + + target/generated-sources/sal + + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + + org.opendaylight.controller + + + yang-maven-plugin + + + [0.5,) + + + + generate-sources + + + + + + + + + + + + + + + + + org.opendaylight.controller + yang-binding + + + org.opendaylight.controller + yang-common + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/samples/modeling-sample/src/main/yang/sample.yang b/opendaylight/sal/yang-prototype/code-generator/samples/modeling-sample/src/main/yang/sample.yang new file mode 100644 index 0000000000..3ecdc0a3ce --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/samples/modeling-sample/src/main/yang/sample.yang @@ -0,0 +1,62 @@ +module sample { + yang-version 1; + namespace "sample"; + prefix "s"; + + revision 2013-06-13 { + description "Initial demo"; + } + + + + // Simple Type definition + + typedef foo-name { + type string; + } + + // Storage / data structure + + container topologies { + list topology { + leaf foo-name { + type string; + } + } + } + + + // Notification / Event + + notification packet-in { + leaf node { + type string; + } + leaf port { + type uint16; + } + leaf content { + type binary; + } + } + + // RPC + + rpc packet-out { + input { + leaf node { + type string; + } + leaf port { + type uint16; + } + leaf content { + type binary; + } + } + output { + + } + } + +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-api/pom.xml b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-api/pom.xml index 547d83adc8..53ca931406 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-api/pom.xml +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-api/pom.xml @@ -3,7 +3,7 @@ org.opendaylight.controller yang - 0.5.1-SNAPSHOT + 0.5.2-SNAPSHOT ../../yang/pom.xml yang-model-parser-api diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/pom.xml b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/pom.xml index 16a746905e..b83d63f9b0 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/pom.xml +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/pom.xml @@ -4,7 +4,7 @@ org.opendaylight.controller yang - 0.5.1-SNAPSHOT + 0.5.2-SNAPSHOT ../../yang/pom.xml yang-model-parser-impl diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/DataNodeContainerBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/DataNodeContainerBuilder.java index 32c7a6d3f1..e64bb02c6d 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/DataNodeContainerBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/DataNodeContainerBuilder.java @@ -24,6 +24,8 @@ public interface DataNodeContainerBuilder extends Builder { void addChildNode(DataSchemaNodeBuilder childNode); + Set getGroupings(); + void addGrouping(GroupingBuilder groupingBuilder); void addUsesNode(UsesNodeBuilder usesBuilder); diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/UsesNodeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/UsesNodeBuilder.java index 1c4a4acde4..c295c0eafd 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/UsesNodeBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/api/UsesNodeBuilder.java @@ -19,9 +19,13 @@ import org.opendaylight.controller.yang.parser.util.RefineHolder; */ public interface UsesNodeBuilder extends Builder { - String getGroupingPathString(); + String getGroupingName(); - SchemaPath getGroupingPath(); + void setGroupingPath(SchemaPath groupingPath); + + SchemaPath getPath(); + + void setPath(SchemaPath path); Set getAugmentations(); diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/AugmentationSchemaBuilderImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/AugmentationSchemaBuilderImpl.java index e5ba8b17cc..775751a166 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/AugmentationSchemaBuilderImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/AugmentationSchemaBuilderImpl.java @@ -68,6 +68,11 @@ public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBu return childNodes; } + @Override + public Set getGroupings() { + return groupings; + } + @Override public void addGrouping(GroupingBuilder grouping) { groupings.add(grouping); diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/LeafSchemaNodeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/LeafSchemaNodeBuilder.java index ba9609b4db..ec9c35c1bd 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/LeafSchemaNodeBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/LeafSchemaNodeBuilder.java @@ -290,6 +290,7 @@ public final class LeafSchemaNodeBuilder extends AbstractTypeAwareBuilder } } + @Override public String getDefault() { return defaultStr; } @@ -298,6 +299,7 @@ public final class LeafSchemaNodeBuilder extends AbstractTypeAwareBuilder this.defaultStr = defaultStr; } + @Override public String getUnits() { return unitsStr; } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ModuleBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ModuleBuilder.java index 6940e91e38..fa307972d4 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ModuleBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ModuleBuilder.java @@ -71,7 +71,6 @@ public class ModuleBuilder implements Builder { private final Map, GroupingBuilder> addedGroupings = new HashMap, GroupingBuilder>(); private final List addedAugments = new ArrayList(); private final Map, UsesNodeBuilder> addedUsesNodes = new HashMap, UsesNodeBuilder>(); - //private final Map, RefineHolder> addedRefines = new HashMap, RefineHolder>(); private final Map, RpcDefinitionBuilder> addedRpcs = new HashMap, RpcDefinitionBuilder>(); private final Set addedNotifications = new HashSet(); private final Set addedIdentities = new HashSet(); @@ -177,6 +176,14 @@ public class ModuleBuilder implements Builder { actualPath.pop(); } + public Builder getActualNode() { + if (actualPath.isEmpty()) { + return null; + } else { + return actualPath.get(0); + } + } + public Builder getModuleNode(final List path) { return childNodes.get(path); } @@ -233,6 +240,17 @@ public class ModuleBuilder implements Builder { return typedefs; } + public Set getModuleGroupings() { + final Set groupings = new HashSet(); + for (Map.Entry, GroupingBuilder> entry : addedGroupings + .entrySet()) { + if (entry.getKey().size() == 2) { + groupings.add(entry.getValue()); + } + } + return groupings; + } + public String getName() { return name; } @@ -756,6 +774,11 @@ public class ModuleBuilder implements Builder { return builder; } + @Override + public String toString() { + return ModuleBuilder.class.getSimpleName() + "[" + name + "]"; + } + private final class ModuleImpl implements Module { private URI namespace; private final String name; @@ -1101,8 +1124,7 @@ public class ModuleBuilder implements Builder { if (parent instanceof AugmentationSchemaBuilder) { nodeBuilder.setAugmenting(true); } - ((DataNodeContainerBuilder) parent) - .addChildNode(nodeBuilder); + ((DataNodeContainerBuilder) parent).addChildNode(nodeBuilder); } else if (parent instanceof ChoiceBuilder) { ((ChoiceBuilder) parent).addChildNode(nodeBuilder); } else { diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/RpcDefinitionBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/RpcDefinitionBuilder.java index 5b9638eb63..6cbcec1054 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/RpcDefinitionBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/RpcDefinitionBuilder.java @@ -103,6 +103,10 @@ public final class RpcDefinitionBuilder implements SchemaNodeBuilder, addedTypedefs.add(type); } + public Set getGroupings() { + return addedGroupings; + } + public void addGrouping(GroupingBuilder grouping) { addedGroupings.add(grouping); } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/TypeDefinitionBuilderImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/TypeDefinitionBuilderImpl.java index d60dbbb615..a8628eae72 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/TypeDefinitionBuilderImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/TypeDefinitionBuilderImpl.java @@ -32,6 +32,7 @@ public final class TypeDefinitionBuilderImpl extends AbstractTypeAwareBuilder private SchemaPath schemaPath; private final List addedUnknownNodes = new ArrayList(); + private List unknownNodes; private List ranges = Collections.emptyList(); private List lengths = Collections.emptyList(); private List patterns = Collections.emptyList(); @@ -73,9 +74,11 @@ public final class TypeDefinitionBuilderImpl extends AbstractTypeAwareBuilder typeBuilder.fractionDigits(fractionDigits); // UNKNOWN NODES - final List unknownNodes = new ArrayList(); - for (UnknownSchemaNodeBuilder b : addedUnknownNodes) { - unknownNodes.add(b.build()); + if (unknownNodes == null) { + unknownNodes = new ArrayList(); + for (UnknownSchemaNodeBuilder b : addedUnknownNodes) { + unknownNodes.add(b.build()); + } } typeBuilder.unknownSchemaNodes(unknownNodes); result = typeBuilder.build(); @@ -164,6 +167,10 @@ public final class TypeDefinitionBuilderImpl extends AbstractTypeAwareBuilder addedUnknownNodes.add(unknownNode); } + public void setUnknownNodes(List unknownNodes) { + this.unknownNodes = unknownNodes; + } + @Override public List getRanges() { return ranges; diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/UsesNodeBuilderImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/UsesNodeBuilderImpl.java index dba747db1d..850938161b 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/UsesNodeBuilderImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/UsesNodeBuilderImpl.java @@ -15,7 +15,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.opendaylight.controller.yang.common.QName; import org.opendaylight.controller.yang.model.api.AugmentationSchema; import org.opendaylight.controller.yang.model.api.SchemaNode; import org.opendaylight.controller.yang.model.api.SchemaPath; @@ -27,25 +26,25 @@ import org.opendaylight.controller.yang.parser.util.RefineHolder; public final class UsesNodeBuilderImpl implements UsesNodeBuilder { private boolean isBuilt; - private final UsesNodeImpl instance; + private UsesNodeImpl instance; private final int line; - private final String groupingPathStr; - private final SchemaPath groupingPath; + private SchemaPath schemaPath; + private final String groupingName; + private SchemaPath groupingPath; private boolean augmenting; private final Set addedAugments = new HashSet(); private List refineBuilders = new ArrayList(); private List refines = new ArrayList(); - public UsesNodeBuilderImpl(final String groupingPathStr, final int line) { - this.groupingPathStr = groupingPathStr; - this.groupingPath = parseUsesPath(groupingPathStr); + public UsesNodeBuilderImpl(final String groupingName, final int line) { + this.groupingName = groupingName; this.line = line; - instance = new UsesNodeImpl(groupingPath); } @Override public UsesNode build() { if (!isBuilt) { + instance = new UsesNodeImpl(groupingPath); instance.setAugmenting(augmenting); // AUGMENTATIONS @@ -74,13 +73,23 @@ public final class UsesNodeBuilderImpl implements UsesNodeBuilder { } @Override - public String getGroupingPathString() { - return groupingPathStr; + public void setGroupingPath(SchemaPath groupingPath) { + this.groupingPath = groupingPath; } @Override - public SchemaPath getGroupingPath() { - return groupingPath; + public SchemaPath getPath() { + return schemaPath; + } + + @Override + public void setPath(SchemaPath path) { + this.schemaPath = path; + } + + @Override + public String getGroupingName() { + return groupingName; } @Override @@ -123,23 +132,6 @@ public final class UsesNodeBuilderImpl implements UsesNodeBuilder { refines.add(refine); } - private SchemaPath parseUsesPath(final String groupingPathStr) { - final String[] splittedPath = groupingPathStr.split("/"); - final List path = new ArrayList(); - QName name; - for (String pathElement : splittedPath) { - final String[] splittedElement = pathElement.split(":"); - if (splittedElement.length == 1) { - name = new QName(null, null, null, splittedElement[0]); - } else { - name = new QName(null, null, splittedElement[0], - splittedElement[1]); - } - path.add(name); - } - final boolean absolute = groupingPathStr.startsWith("/"); - return new SchemaPath(path, absolute); - } private final class UsesNodeImpl implements UsesNode { private final SchemaPath groupingPath; diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java index 401189b1d1..94437170f4 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserImpl.java @@ -41,15 +41,11 @@ import org.opendaylight.controller.yang.model.api.TypeDefinition; import org.opendaylight.controller.yang.model.api.type.BinaryTypeDefinition; import org.opendaylight.controller.yang.model.api.type.DecimalTypeDefinition; import org.opendaylight.controller.yang.model.api.type.IntegerTypeDefinition; -import org.opendaylight.controller.yang.model.api.type.LengthConstraint; -import org.opendaylight.controller.yang.model.api.type.PatternConstraint; -import org.opendaylight.controller.yang.model.api.type.RangeConstraint; import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition; import org.opendaylight.controller.yang.model.parser.api.YangModelParser; import org.opendaylight.controller.yang.model.util.ExtendedType; import org.opendaylight.controller.yang.model.util.IdentityrefType; import org.opendaylight.controller.yang.model.util.UnknownType; -import org.opendaylight.controller.yang.model.util.YangTypesConverter; import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder; import org.opendaylight.controller.yang.parser.builder.api.AugmentationTargetBuilder; import org.opendaylight.controller.yang.parser.builder.api.Builder; @@ -232,6 +228,7 @@ public final class YangParserImpl implements YangModelParser { final YangLexer lexer = new YangLexer(input); final CommonTokenStream tokens = new CommonTokenStream(lexer); final YangParser parser = new YangParser(tokens); + result = parser.yang(); } catch (IOException e) { logger.warn("Exception while reading yang file: " + yangStream, e); @@ -297,222 +294,116 @@ public final class YangParserImpl implements YangModelParser { if (!dirtyNodes.isEmpty()) { for (Map.Entry, TypeAwareBuilder> entry : dirtyNodes .entrySet()) { - final TypeAwareBuilder nodeToResolve = entry.getValue(); - // different handling for union types + if (nodeToResolve instanceof UnionTypeBuilder) { - final UnionTypeBuilder union = (UnionTypeBuilder) nodeToResolve; - final List> unionTypes = union.getTypes(); - final List toRemove = new ArrayList(); - for (TypeDefinition td : unionTypes) { - if (td instanceof UnknownType) { - final UnknownType unknownType = (UnknownType) td; - final TypeDefinitionBuilder resolvedType = resolveTypeUnion( - nodeToResolve, unknownType, modules, module); - union.setTypedef(resolvedType); - toRemove.add(unknownType); - } - } - unionTypes.removeAll(toRemove); + // special handling for union types + resolveTypeUnion((UnionTypeBuilder) nodeToResolve, modules, + module); } else if (nodeToResolve.getTypedef() instanceof IdentityrefTypeBuilder) { - // different handling for identityref types + // special handling for identityref types IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) nodeToResolve .getTypedef(); nodeToResolve.setType(new IdentityrefType(findFullQName( modules, module, idref), idref.getPath())); } else { - final TypeDefinitionBuilder resolvedType = resolveType( - nodeToResolve, modules, module); - nodeToResolve.setTypedef(resolvedType); + resolveType(nodeToResolve, modules, module); } } } } - private TypeDefinitionBuilder resolveType( - final TypeAwareBuilder nodeToResolve, - final Map> modules, - final ModuleBuilder builder) { - final TypeConstraints constraints = new TypeConstraints(); - - final TypeDefinitionBuilder targetTypeBuilder = getTypeDefinitionBuilderFromDirtyNode( - nodeToResolve, modules, builder); - final TypeConstraints tConstraints = findConstraints(nodeToResolve, - constraints, modules, builder); - targetTypeBuilder.setRanges(tConstraints.getRange()); - targetTypeBuilder.setLengths(tConstraints.getLength()); - targetTypeBuilder.setPatterns(tConstraints.getPatterns()); - targetTypeBuilder.setFractionDigits(tConstraints.getFractionDigits()); - - return targetTypeBuilder; - } - - private TypeDefinitionBuilder resolveTypeUnion( - final TypeAwareBuilder typeToResolve, - final UnknownType unknownType, + private void resolveType(final TypeAwareBuilder nodeToResolve, final Map> modules, final ModuleBuilder builder) { - final TypeConstraints constraints = new TypeConstraints(); - - final TypeDefinitionBuilder targetTypeBuilder = getUnionBuilder( - typeToResolve, unknownType, modules, builder); - final TypeConstraints tConstraints = findConstraints(typeToResolve, - constraints, modules, builder); - targetTypeBuilder.setRanges(tConstraints.getRange()); - targetTypeBuilder.setLengths(tConstraints.getLength()); - targetTypeBuilder.setPatterns(tConstraints.getPatterns()); - targetTypeBuilder.setFractionDigits(tConstraints.getFractionDigits()); - - return targetTypeBuilder; - } - - private TypeDefinitionBuilder getTypeDefinitionBuilderFromDirtyNode( - final TypeAwareBuilder nodeToResolve, - final Map> modules, - final ModuleBuilder module) { - - final UnknownType unknownType = (UnknownType) nodeToResolve.getType(); - final QName unknownTypeQName = unknownType.getQName(); - - // search for module which contains referenced typedef + TypeDefinitionBuilder resolvedType = null; + final int line = nodeToResolve.getLine(); + final TypeDefinition typedefType = nodeToResolve.getType(); + final QName unknownTypeQName = typedefType.getBaseType().getQName(); final ModuleBuilder dependentModule = findDependentModule(modules, - module, unknownTypeQName.getPrefix(), nodeToResolve.getLine()); + builder, unknownTypeQName.getPrefix(), line); - final TypeDefinitionBuilder lookedUpBuilder = findTypeDefinitionBuilder( + final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder( nodeToResolve.getPath(), dependentModule, - unknownTypeQName.getLocalName(), module.getName(), - nodeToResolve.getLine()); - - final TypeDefinitionBuilder lookedUpBuilderCopy = copyTypedefBuilder( - lookedUpBuilder, nodeToResolve instanceof TypeDefinitionBuilder); - final TypeDefinitionBuilder resolvedCopy = resolveCopiedBuilder( - lookedUpBuilderCopy, modules, dependentModule); - return resolvedCopy; - } + unknownTypeQName.getLocalName(), builder.getName(), line); - private TypeDefinitionBuilder getUnionBuilder( - final TypeAwareBuilder nodeToResolve, - final UnknownType unknownType, - final Map> modules, - final ModuleBuilder module) { - - final TypeDefinition baseTypeToResolve = nodeToResolve.getType(); - if (baseTypeToResolve != null - && !(baseTypeToResolve instanceof UnknownType)) { - return (TypeDefinitionBuilder) nodeToResolve; - } - - final QName unknownTypeQName = unknownType.getQName(); - // search for module which contains referenced typedef - final ModuleBuilder dependentModule = findDependentModule(modules, - module, unknownTypeQName.getPrefix(), nodeToResolve.getLine()); - final TypeDefinitionBuilder lookedUpBuilder = findTypeDefinitionBuilder( - nodeToResolve.getPath(), dependentModule, - unknownTypeQName.getLocalName(), module.getName(), - nodeToResolve.getLine()); - - final TypeDefinitionBuilder lookedUpBuilderCopy = copyTypedefBuilder( - lookedUpBuilder, nodeToResolve instanceof TypeDefinitionBuilder); - final TypeDefinitionBuilder resolvedCopy = resolveCopiedBuilder( - lookedUpBuilderCopy, modules, dependentModule); - return resolvedCopy; - } - - private TypeDefinitionBuilder copyTypedefBuilder( - final TypeDefinitionBuilder old, final boolean seekByTypedefBuilder) { - if (old instanceof UnionTypeBuilder) { - final UnionTypeBuilder oldUnion = (UnionTypeBuilder) old; - final UnionTypeBuilder newUnion = new UnionTypeBuilder( - old.getLine()); - for (TypeDefinition td : oldUnion.getTypes()) { - newUnion.setType(td); - } - for (TypeDefinitionBuilder tdb : oldUnion.getTypedefs()) { - newUnion.setTypedef(copyTypedefBuilder(tdb, true)); - } - newUnion.setPath(old.getPath()); - return newUnion; - } - - final QName oldName = old.getQName(); - final QName newName = new QName(oldName.getNamespace(), - oldName.getRevision(), oldName.getPrefix(), - oldName.getLocalName()); - final TypeDefinitionBuilder tdb = new TypeDefinitionBuilderImpl( - newName, old.getLine()); - - tdb.setRanges(old.getRanges()); - tdb.setLengths(old.getLengths()); - tdb.setPatterns(old.getPatterns()); - tdb.setFractionDigits(old.getFractionDigits()); - tdb.setPath(old.getPath()); - - final TypeDefinition oldType = old.getType(); - if (oldType == null) { - tdb.setTypedef(old.getTypedef()); + if (typedefType instanceof ExtendedType) { + final ExtendedType extType = (ExtendedType) typedefType; + final TypeDefinitionBuilder newType = extendedTypeWithNewBaseType( + nodeToResolve, targetTypeBuilder, extType, modules, builder); + resolvedType = newType; } else { - tdb.setType(oldType); - } - - if (!seekByTypedefBuilder) { - tdb.setDescription(old.getDescription()); - tdb.setReference(old.getReference()); - tdb.setStatus(old.getStatus()); - tdb.setDefaultValue(old.getDefaultValue()); - tdb.setUnits(old.getUnits()); + resolvedType = targetTypeBuilder; } - return tdb; + nodeToResolve.setTypedef(resolvedType); } - private TypeDefinitionBuilder resolveCopiedBuilder( - final TypeDefinitionBuilder copy, + private void resolveTypeUnion(final UnionTypeBuilder union, final Map> modules, final ModuleBuilder builder) { - if (copy instanceof UnionTypeBuilder) { - final UnionTypeBuilder union = (UnionTypeBuilder) copy; - final List> unionTypes = union.getTypes(); - final List toRemove = new ArrayList(); - for (TypeDefinition td : unionTypes) { - if (td instanceof UnknownType) { - final UnknownType unknownType = (UnknownType) td; - final TypeDefinitionBuilder resolvedType = resolveTypeUnion( - union, unknownType, modules, builder); - union.setTypedef(resolvedType); - toRemove.add(unknownType); + final List> unionTypes = union.getTypes(); + final List> toRemove = new ArrayList>(); + for (TypeDefinition unionType : unionTypes) { + if (unionType instanceof UnknownType) { + final UnknownType ut = (UnknownType) unionType; + final ModuleBuilder dependentModule = findDependentModule( + modules, builder, ut.getQName().getPrefix(), + union.getLine()); + final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder( + union.getPath(), dependentModule, ut.getQName() + .getLocalName(), builder.getName(), + union.getLine()); + union.setTypedef(resolvedType); + toRemove.add(ut); + } else if (unionType instanceof ExtendedType) { + final ExtendedType extType = (ExtendedType) unionType; + TypeDefinition extTypeBase = extType.getBaseType(); + if (extTypeBase instanceof UnknownType) { + final UnknownType ut = (UnknownType) extTypeBase; + final ModuleBuilder dependentModule = findDependentModule( + modules, builder, ut.getQName().getPrefix(), + union.getLine()); + final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder( + union.getPath(), dependentModule, ut.getQName() + .getLocalName(), builder.getName(), + union.getLine()); + + final TypeDefinitionBuilder newType = extendedTypeWithNewBaseType( + targetTypeBuilder, targetTypeBuilder, extType, + modules, builder); + + union.setTypedef(newType); + toRemove.add(extType); } } - unionTypes.removeAll(toRemove); - - return union; } + unionTypes.removeAll(toRemove); + } - final TypeDefinition base = copy.getType(); - final TypeDefinitionBuilder baseTdb = copy.getTypedef(); - if (base != null && !(base instanceof UnknownType)) { - return copy; - } else if (base instanceof UnknownType) { - final UnknownType unknownType = (UnknownType) base; - final QName unknownTypeQName = unknownType.getQName(); - final String unknownTypePrefix = unknownTypeQName.getPrefix(); - final ModuleBuilder dependentModule = findDependentModule(modules, - builder, unknownTypePrefix, copy.getLine()); - final TypeDefinitionBuilder utBuilder = getTypeDefinitionBuilderFromDirtyNode( - copy, modules, dependentModule); - copy.setTypedef(utBuilder); - return copy; - } else if (base == null && baseTdb != null) { - // make a copy of baseTypeDef and call again - final TypeDefinitionBuilder baseTdbCopy = copyTypedefBuilder( - baseTdb, true); - final TypeDefinitionBuilder baseTdbCopyResolved = resolveCopiedBuilder( - baseTdbCopy, modules, builder); - copy.setTypedef(baseTdbCopyResolved); - return copy; - } else { - throw new YangParseException(copy.getLine(), - "Failed to resolve type " + copy.getQName().getLocalName()); - } + private TypeDefinitionBuilder extendedTypeWithNewBaseType( + final TypeAwareBuilder nodeToResolve, + final TypeDefinitionBuilder newBaseType, + final ExtendedType oldExtendedType, + final Map> modules, + final ModuleBuilder builder) { + final TypeConstraints constraints = findConstraints(nodeToResolve, + new TypeConstraints(), modules, builder); + final TypeDefinitionBuilderImpl newType = new TypeDefinitionBuilderImpl( + oldExtendedType.getQName(), nodeToResolve.getLine()); + newType.setTypedef(newBaseType); + newType.setPath(oldExtendedType.getPath()); + newType.setDescription(oldExtendedType.getDescription()); + newType.setReference(oldExtendedType.getReference()); + newType.setStatus(oldExtendedType.getStatus()); + newType.setLengths(constraints.getLength()); + newType.setPatterns(constraints.getPatterns()); + newType.setRanges(constraints.getRange()); + newType.setFractionDigits(constraints.getFractionDigits()); + newType.setUnits(oldExtendedType.getUnits()); + newType.setDefaultValue(oldExtendedType.getDefaultValue()); + newType.setUnknownNodes(oldExtendedType.getUnknownSchemaNodes()); + return newType; } private TypeConstraints findConstraints( @@ -520,77 +411,63 @@ public final class YangParserImpl implements YangModelParser { final TypeConstraints constraints, final Map> modules, final ModuleBuilder builder) { + // union type cannot be restricted if (nodeToResolve instanceof UnionTypeBuilder) { return constraints; } - // if referenced type is UnknownType again, search recursively with - // current constraints - final TypeDefinition referencedType = nodeToResolve.getType(); - List ranges = Collections.emptyList(); - List lengths = Collections.emptyList(); - List patterns = Collections.emptyList(); - Integer fractionDigits = null; - if (referencedType == null) { - final TypeDefinitionBuilder tdb = nodeToResolve.getTypedef(); - ranges = tdb.getRanges(); - constraints.addRanges(ranges); - lengths = tdb.getLengths(); - constraints.addLengths(lengths); - patterns = tdb.getPatterns(); - constraints.addPatterns(patterns); - fractionDigits = tdb.getFractionDigits(); - constraints.setFractionDigits(fractionDigits); - return constraints; - } else if (referencedType instanceof ExtendedType) { - final ExtendedType ext = (ExtendedType) referencedType; - ranges = ext.getRanges(); - constraints.addRanges(ranges); - lengths = ext.getLengths(); - constraints.addLengths(lengths); - patterns = ext.getPatterns(); - constraints.addPatterns(patterns); - fractionDigits = ext.getFractionDigits(); - constraints.setFractionDigits(fractionDigits); - if(YangTypesConverter.isBaseYangType(ext.getBaseType().getQName().getLocalName())) { - mergeConstraints(ext.getBaseType(), constraints); - return constraints; + if (nodeToResolve instanceof TypeDefinitionBuilder) { + TypeDefinitionBuilder typedefToResolve = (TypeDefinitionBuilder) nodeToResolve; + constraints.addFractionDigits(typedefToResolve.getFractionDigits()); + constraints.addLengths(typedefToResolve.getLengths()); + constraints.addPatterns(typedefToResolve.getPatterns()); + constraints.addRanges(typedefToResolve.getRanges()); + } + + TypeDefinition type = nodeToResolve.getType(); + if (type == null) { + return findConstraints(nodeToResolve.getTypedef(), constraints, + modules, builder); + } else { + if (type instanceof UnknownType) { + ModuleBuilder dependentModule = findDependentModule(modules, + builder, type.getQName().getPrefix(), + nodeToResolve.getLine()); + TypeDefinitionBuilder tdb = findTypeDefinitionBuilder( + nodeToResolve.getPath(), dependentModule, type + .getQName().getLocalName(), builder.getName(), + nodeToResolve.getLine()); + return findConstraints(tdb, constraints, modules, + dependentModule); + } else if (type instanceof ExtendedType) { + ExtendedType extType = (ExtendedType) type; + constraints.addFractionDigits(extType.getFractionDigits()); + constraints.addLengths(extType.getLengths()); + constraints.addPatterns(extType.getPatterns()); + constraints.addRanges(extType.getRanges()); + + TypeDefinition base = extType.getBaseType(); + if (base instanceof UnknownType) { + ModuleBuilder dependentModule = findDependentModule( + modules, builder, base.getQName().getPrefix(), + nodeToResolve.getLine()); + TypeDefinitionBuilder tdb = findTypeDefinitionBuilder( + nodeToResolve.getPath(), dependentModule, base + .getQName().getLocalName(), + builder.getName(), nodeToResolve.getLine()); + return findConstraints(tdb, constraints, modules, + dependentModule); + } else { + // it has to be base yang type + mergeConstraints(type, constraints); + return constraints; + } } else { - return findConstraints( - findTypeDefinitionBuilder(nodeToResolve.getPath(), builder, - ext.getQName().getLocalName(), builder.getName(), - nodeToResolve.getLine()), constraints, modules, - builder); - } - } else if (referencedType instanceof UnknownType) { - final UnknownType unknown = (UnknownType) referencedType; - ranges = unknown.getRangeStatements(); - constraints.addRanges(ranges); - lengths = unknown.getLengthStatements(); - constraints.addLengths(lengths); - patterns = unknown.getPatterns(); - constraints.addPatterns(patterns); - fractionDigits = unknown.getFractionDigits(); - constraints.setFractionDigits(fractionDigits); - - String unknownTypePrefix = unknown.getQName().getPrefix(); - if (unknownTypePrefix == null || "".equals(unknownTypePrefix)) { - unknownTypePrefix = builder.getPrefix(); + // it is base yang type + mergeConstraints(type, constraints); + return constraints; } - final ModuleBuilder dependentModule = findDependentModule(modules, - builder, unknown.getQName().getPrefix(), - nodeToResolve.getLine()); - final TypeDefinitionBuilder utBuilder = findTypeDefinitionBuilder( - nodeToResolve.getPath(), dependentModule, unknown - .getQName().getLocalName(), builder.getName(), - nodeToResolve.getLine()); - return findConstraints(utBuilder, constraints, modules, - dependentModule); - } else { - // HANDLE BASE YANG TYPE - mergeConstraints(referencedType, constraints); - return constraints; } } @@ -677,7 +554,7 @@ public final class YangParserImpl implements YangModelParser { constraints.addRanges(((DecimalTypeDefinition) referencedType) .getRangeStatements()); constraints - .setFractionDigits(((DecimalTypeDefinition) referencedType) + .addFractionDigits(((DecimalTypeDefinition) referencedType) .getFractionDigits()); } else if (referencedType instanceof IntegerTypeDefinition) { constraints.addRanges(((IntegerTypeDefinition) referencedType) @@ -884,15 +761,15 @@ public final class YangParserImpl implements YangModelParser { .getUsesNodes(); for (Map.Entry, UsesNodeBuilder> entry : moduleUses .entrySet()) { - final List key = entry.getKey(); final UsesNodeBuilder usesNode = entry.getValue(); final int line = usesNode.getLine(); - final String groupingName = key.get(key.size() - 1); + GroupingBuilder targetGrouping = getTargetGrouping(usesNode, modules, module); + usesNode.setGroupingPath(targetGrouping.getPath()); for (RefineHolder refine : usesNode.getRefines()) { SchemaNodeBuilder refineTarget = getRefineNodeBuilderCopy( - groupingName, refine, modules, module); + targetGrouping, refine, modules, module); ParserUtils.checkRefine(refineTarget, refine); ParserUtils.refineDefault(refineTarget, refine, line); if (refineTarget instanceof LeafSchemaNodeBuilder) { @@ -928,6 +805,82 @@ public final class YangParserImpl implements YangModelParser { } } + private GroupingBuilder getTargetGrouping( + final UsesNodeBuilder usesBuilder, + final Map> modules, + final ModuleBuilder module) { + final int line = usesBuilder.getLine(); + String groupingString = usesBuilder.getGroupingName(); + String groupingPrefix; + String groupingName; + + if(groupingString.contains(":")) { + String[] splitted = groupingString.split(":"); + if(splitted.length != 2 || groupingString.contains("/")) { + throw new YangParseException(module.getName(), line, "Invalid name of target grouping"); + } + groupingPrefix = splitted[0]; + groupingName = splitted[1]; + } else { + groupingPrefix = module.getPrefix(); + groupingName = groupingString; + } + + ModuleBuilder dependentModule = null; + if(groupingPrefix.equals(module.getPrefix())) { + dependentModule = module; + } else { + dependentModule = findDependentModule(modules, module, groupingPrefix, line); + } + + + List path = usesBuilder.getPath().getPath(); + GroupingBuilder result = null; + Set groupings = dependentModule.getModuleGroupings(); + result = findGrouping(groupings, groupingName); + + if (result == null) { + Builder currentNode = null; + final List currentPath = new ArrayList(); + currentPath.add(dependentModule.getName()); + + for (int i = 0; i < path.size(); i++) { + QName qname = path.get(i); + currentPath.add(qname.getLocalName()); + currentNode = dependentModule.getModuleNode(currentPath); + + if (currentNode instanceof RpcDefinitionBuilder) { + groupings = ((RpcDefinitionBuilder) currentNode).getGroupings(); + } else if (currentNode instanceof DataNodeContainerBuilder) { + groupings = ((DataNodeContainerBuilder) currentNode).getGroupings(); + } else { + groupings = Collections.emptySet(); + } + + result = findGrouping(groupings, groupingName); + if (result != null) { + break; + } + } + } + + if (result != null) { + return result; + } + throw new YangParseException(module.getName(), line, + "Referenced grouping '" + groupingName + "' not found."); + } + + private GroupingBuilder findGrouping(Set groupings, + String name) { + for (GroupingBuilder grouping : groupings) { + if (grouping.getQName().getLocalName().equals(name)) { + return grouping; + } + } + return null; + } + /** * Find original builder of node to refine and return copy of this builder. *

@@ -948,11 +901,11 @@ public final class YangParserImpl implements YangModelParser { * otherwise */ private SchemaNodeBuilder getRefineNodeBuilderCopy( - final String groupingPath, final RefineHolder refine, + final GroupingBuilder targetGrouping, final RefineHolder refine, final Map> modules, final ModuleBuilder module) { Builder result = null; - final Builder lookedUpBuilder = findRefineTargetBuilder(groupingPath, + final Builder lookedUpBuilder = findRefineTargetBuilder(targetGrouping, refine, modules, module); if (lookedUpBuilder instanceof LeafSchemaNodeBuilder) { result = ParserUtils @@ -999,28 +952,11 @@ public final class YangParserImpl implements YangModelParser { * @return Builder object of refine node if it is present in grouping, null * otherwise */ - private Builder findRefineTargetBuilder(final String groupingPath, + private Builder findRefineTargetBuilder(final GroupingBuilder builder, final RefineHolder refine, final Map> modules, final ModuleBuilder module) { final String refineNodeName = refine.getName(); - final SchemaPath path = ParserUtils.parseUsesPath(groupingPath); - final List builderPath = new ArrayList(); - String prefix = null; - for (QName qname : path.getPath()) { - builderPath.add(qname.getLocalName()); - prefix = qname.getPrefix(); - } - if (prefix == null) { - prefix = module.getPrefix(); - } - - final ModuleBuilder dependentModule = findDependentModule(modules, - module, prefix, refine.getLine()); - builderPath.add(0, dependentModule.getName()); - final GroupingBuilder builder = dependentModule - .getGrouping(builderPath); - Builder result = builder.getChildNode(refineNodeName); if (result == null) { Set grps = builder.getGroupings(); diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserListenerImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserListenerImpl.java index d7394e6229..1c01cd4a82 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserListenerImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/impl/YangParserListenerImpl.java @@ -342,7 +342,6 @@ public final class YangParserListenerImpl extends YangParserBaseListener { if ("union".equals(typeName)) { List typePath = new ArrayList(actualPath); typePath.add(typeName); - SchemaPath p = createActualSchemaPath(typePath, namespace, revision, yangModelPrefix); UnionTypeBuilder unionBuilder = moduleBuilder.addUnionType( @@ -357,12 +356,15 @@ public final class YangParserListenerImpl extends YangParserBaseListener { line); } else { type = parseTypeBody(typeName, typeBody, actualPath, - namespace, revision, yangModelPrefix); + namespace, revision, yangModelPrefix, + moduleBuilder.getActualNode()); moduleBuilder.setType(type, actualPath); } } } else { - type = parseUnknownTypeBody(typeQName, typeBody); + type = parseUnknownTypeBody(typeQName, typeBody, actualPath, + namespace, revision, yangModelPrefix, + moduleBuilder.getActualNode(), moduleBuilder); // mark parent node of this type statement as dirty moduleBuilder.addDirtyNode(actualPath); moduleBuilder.setType(type, actualPath); @@ -408,15 +410,15 @@ public final class YangParserListenerImpl extends YangParserBaseListener { GroupingBuilder builder = moduleBuilder.addGrouping(groupQName, actualPath, ctx.getStart().getLine()); moduleBuilder.enterNode(builder); - updatePath("grouping"); updatePath(groupName); + builder.setPath(createActualSchemaPath(actualPath, namespace, revision, + yangModelPrefix)); parseSchemaNodeArgs(ctx, builder); } @Override public void exitGrouping_stmt(YangParser.Grouping_stmtContext ctx) { String actContainer = actualPath.pop(); - actContainer += "-" + actualPath.pop(); logger.debug("exiting " + actContainer); moduleBuilder.exitNode(); } @@ -493,8 +495,11 @@ public final class YangParserListenerImpl extends YangParserBaseListener { final String groupingPathStr = stringFromNode(ctx); UsesNodeBuilder builder = moduleBuilder.addUsesNode(groupingPathStr, actualPath, ctx.getStart().getLine()); + moduleBuilder.enterNode(builder); updatePath(groupingPathStr); + builder.setPath(createActualSchemaPath(actualPath, namespace, revision, + yangModelPrefix)); } @Override diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/ParserUtils.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/ParserUtils.java index e95a162de7..d38bc5e7ad 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/ParserUtils.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/ParserUtils.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.yang.parser.util; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; +import java.util.Set; import org.opendaylight.controller.yang.common.QName; import org.opendaylight.controller.yang.model.api.ModuleImport; @@ -27,6 +28,9 @@ import org.opendaylight.controller.yang.model.api.type.IdentityrefTypeDefinition import org.opendaylight.controller.yang.model.api.type.InstanceIdentifierTypeDefinition; import org.opendaylight.controller.yang.model.api.type.IntegerTypeDefinition; import org.opendaylight.controller.yang.model.api.type.LeafrefTypeDefinition; +import org.opendaylight.controller.yang.model.api.type.LengthConstraint; +import org.opendaylight.controller.yang.model.api.type.PatternConstraint; +import org.opendaylight.controller.yang.model.api.type.RangeConstraint; import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition; import org.opendaylight.controller.yang.model.api.type.UnionTypeDefinition; import org.opendaylight.controller.yang.model.api.type.UnsignedIntegerTypeDefinition; @@ -36,6 +40,7 @@ import org.opendaylight.controller.yang.model.util.BooleanType; import org.opendaylight.controller.yang.model.util.Decimal64; import org.opendaylight.controller.yang.model.util.EmptyType; import org.opendaylight.controller.yang.model.util.EnumerationType; +import org.opendaylight.controller.yang.model.util.ExtendedType; import org.opendaylight.controller.yang.model.util.IdentityrefType; import org.opendaylight.controller.yang.model.util.InstanceIdentifier; import org.opendaylight.controller.yang.model.util.Int16; @@ -75,7 +80,7 @@ public final class ParserUtils { /** * Get module import referenced by given prefix. - * + * * @param builder * module to search * @param prefix @@ -96,7 +101,7 @@ public final class ParserUtils { /** * Parse uses path. - * + * * @param usesPath * as String * @return SchemaPath from given String @@ -123,7 +128,7 @@ public final class ParserUtils { /** * Add all augment's child nodes to given target. - * + * * @param augment * @param target */ @@ -132,54 +137,139 @@ public final class ParserUtils { final DataNodeContainerBuilder target) { for (DataSchemaNodeBuilder builder : augment.getChildNodes()) { builder.setAugmenting(true); - correctAugmentChildPath(augment, target.getPath()); + correctAugmentChildPath(builder, target.getPath()); target.addChildNode(builder); } } public static void fillAugmentTarget( - final AugmentationSchemaBuilder augment, - final ChoiceBuilder target) { + final AugmentationSchemaBuilder augment, final ChoiceBuilder target) { for (DataSchemaNodeBuilder builder : augment.getChildNodes()) { builder.setAugmenting(true); - correctAugmentChildPath(augment, target.getPath()); + correctAugmentChildPath(builder, target.getPath()); target.addChildNode(builder); } } - private static void correctAugmentChildPath(final DataNodeContainerBuilder node, + private static void correctAugmentChildPath( + final DataSchemaNodeBuilder childNode, final SchemaPath parentSchemaPath) { - for (DataSchemaNodeBuilder builder : node.getChildNodes()) { - - // add correct path - List targetNodePath = new ArrayList( - parentSchemaPath.getPath()); - targetNodePath.add(builder.getQName()); - builder.setPath(new SchemaPath(targetNodePath, true)); - if (builder instanceof DataNodeContainerBuilder) { - DataNodeContainerBuilder cnb = (DataNodeContainerBuilder) builder; - correctAugmentChildPath(cnb, builder.getPath()); + // set correct path + List targetNodePath = new ArrayList( + parentSchemaPath.getPath()); + targetNodePath.add(childNode.getQName()); + childNode.setPath(new SchemaPath(targetNodePath, true)); + + // set correct path for all child nodes + if (childNode instanceof DataNodeContainerBuilder) { + DataNodeContainerBuilder dataNodeContainer = (DataNodeContainerBuilder) childNode; + for (DataSchemaNodeBuilder child : dataNodeContainer + .getChildNodes()) { + correctAugmentChildPath(child, childNode.getPath()); } + } - // if child can contains type, correct path for this type too - if (builder instanceof TypeAwareBuilder) { - TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) builder; - QName nodeBuilderQName = nodeBuilder.getQName(); - TypeDefinition nodeBuilderType = nodeBuilder.getType(); - if (nodeBuilderType != null) { - TypeDefinition newType = createCorrectTypeDefinition( - parentSchemaPath, nodeBuilderQName, nodeBuilderType); - nodeBuilder.setType(newType); - } else { - TypeDefinitionBuilder nodeBuilderTypedef = nodeBuilder - .getTypedef(); - SchemaPath newSchemaPath = createNewSchemaPath( - nodeBuilderTypedef.getPath(), nodeBuilderQName, - nodeBuilderTypedef.getQName()); - nodeBuilderTypedef.setPath(newSchemaPath); + // if node can contains type, correct path for this type too + if (childNode instanceof TypeAwareBuilder) { + TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) childNode; + correctTypeAwareNodePath(nodeBuilder, parentSchemaPath); + } + } + + /** + * Repair schema path of node type. + * + * @param node + * node which contains type statement + * @param parentSchemaPath + * schema path of parent node + */ + private static void correctTypeAwareNodePath( + TypeAwareBuilder node, SchemaPath parentSchemaPath) { + final QName nodeBuilderQName = node.getQName(); + final TypeDefinition nodeType = node.getType(); + + Integer fd = null; + List lengths = null; + List patterns = null; + List ranges = null; + + if (nodeType != null) { + if (nodeType instanceof ExtendedType) { + ExtendedType et = (ExtendedType) nodeType; + if (nodeType + .getQName() + .getLocalName() + .equals(nodeType.getBaseType().getQName() + .getLocalName())) { + fd = et.getFractionDigits(); + lengths = et.getLengths(); + patterns = et.getPatterns(); + ranges = et.getRanges(); + if (!hasConstraints(fd, lengths, patterns, ranges)) { + return; + } } } + TypeDefinition newType = createCorrectTypeDefinition( + parentSchemaPath, nodeBuilderQName, nodeType); + node.setType(newType); + } else { + TypeDefinitionBuilder nodeBuilderTypedef = node.getTypedef(); + + fd = nodeBuilderTypedef.getFractionDigits(); + lengths = nodeBuilderTypedef.getLengths(); + patterns = nodeBuilderTypedef.getPatterns(); + ranges = nodeBuilderTypedef.getRanges(); + + String tdbTypeName = nodeBuilderTypedef.getQName().getLocalName(); + String baseTypeName = null; + if (nodeBuilderTypedef.getType() == null) { + baseTypeName = nodeBuilderTypedef.getTypedef().getQName() + .getLocalName(); + } else { + baseTypeName = nodeBuilderTypedef.getType().getQName() + .getLocalName(); + } + if (!(tdbTypeName.equals(baseTypeName))) { + return; + } + + if (!hasConstraints(fd, lengths, patterns, ranges)) { + return; + } + + SchemaPath newSchemaPath = createNewSchemaPath( + nodeBuilderTypedef.getPath(), nodeBuilderQName, + nodeBuilderTypedef.getQName()); + nodeBuilderTypedef.setPath(newSchemaPath); + } + } + + /** + * Check if there are some constraints. + * + * @param fd + * fraction digits + * @param lengths + * length constraints + * @param patterns + * pattern constraints + * @param ranges + * range constraints + * @return true, if any of constraints are present, false otherwise + */ + private static boolean hasConstraints(final Integer fd, + final List lengths, + final List patterns, + final List ranges) { + if (fd == null && (lengths == null || lengths.isEmpty()) + && (patterns == null || patterns.isEmpty()) + && (ranges == null || ranges.isEmpty())) { + return false; + } else { + return true; } } @@ -209,7 +299,8 @@ public final class ParserUtils { DecimalTypeDefinition decimalType = (DecimalTypeDefinition) nodeType; newSchemaPath = createNewSchemaPath(parentSchemaPath, nodeQName, decimalType.getQName()); - result = new Decimal64(newSchemaPath, decimalType.getFractionDigits()); + result = new Decimal64(newSchemaPath, + decimalType.getFractionDigits()); } else if (nodeType instanceof EmptyTypeDefinition) { newSchemaPath = createNewSchemaPath(parentSchemaPath, nodeQName, nodeType.getQName()); @@ -253,11 +344,33 @@ public final class ParserUtils { newSchemaPath = createNewSchemaPath(parentSchemaPath, nodeQName, unionType.getQName()); return new UnionType(newSchemaPath, unionType.getTypes()); + } else if (nodeType instanceof ExtendedType) { + ExtendedType extType = (ExtendedType) nodeType; + newSchemaPath = createNewSchemaPath(parentSchemaPath, + nodeQName, extType.getQName()); + result = createNewExtendedType(newSchemaPath, extType); } } return result; } + private static TypeDefinition createNewExtendedType( + SchemaPath newSchemaPath, ExtendedType oldExtendedType) { + QName qname = oldExtendedType.getQName(); + TypeDefinition baseType = oldExtendedType.getBaseType(); + String desc = oldExtendedType.getDescription(); + String ref = oldExtendedType.getReference(); + ExtendedType.Builder builder = new ExtendedType.Builder(qname, + baseType, desc, ref, newSchemaPath); + builder.status(oldExtendedType.getStatus()); + builder.lengths(oldExtendedType.getLengths()); + builder.patterns(oldExtendedType.getPatterns()); + builder.ranges(oldExtendedType.getRanges()); + builder.fractionDigits(oldExtendedType.getFractionDigits()); + builder.unknownSchemaNodes(oldExtendedType.getUnknownSchemaNodes()); + return builder.build(); + } + private static TypeDefinition createNewStringType(SchemaPath schemaPath, QName nodeQName, StringTypeDefinition nodeType) { List path = schemaPath.getPath(); @@ -537,9 +650,9 @@ public final class ParserUtils { *

  • reference
  • *
  • config
  • * - * + * * These parameters may be refined for any node. - * + * * @param node * node to refine * @param refine @@ -794,7 +907,7 @@ public final class ParserUtils { public static UsesNodeBuilder copyUsesNodeBuilder(UsesNodeBuilder old) { final UsesNodeBuilder copy = new UsesNodeBuilderImpl( - old.getGroupingPathString(), old.getLine()); + old.getGroupingName(), old.getLine()); for (AugmentationSchemaBuilder augment : old.getAugmentations()) { copy.addAugment(augment); } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/TypeConstraints.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/TypeConstraints.java index 18e4c31ab9..670c1d573c 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/TypeConstraints.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/TypeConstraints.java @@ -23,14 +23,14 @@ public final class TypeConstraints { private final List> ranges = new ArrayList>(); private final List> lengths = new ArrayList>(); private final List patterns = new ArrayList(); - private Integer fractionDigits; + private final List fractionDigits = new ArrayList(); List> getAllRanges() { return ranges; } public List getRange() { - if(ranges.isEmpty()) { + if (ranges.isEmpty()) { return Collections.emptyList(); } @@ -108,7 +108,7 @@ public final class TypeConstraints { } public List getLength() { - if(lengths.isEmpty()) { + if (lengths.isEmpty()) { return Collections.emptyList(); } @@ -190,13 +190,14 @@ public final class TypeConstraints { } public Integer getFractionDigits() { - return fractionDigits; + if (fractionDigits.isEmpty()) { + return null; + } + return fractionDigits.get(0); } - public void setFractionDigits(final Integer fractionDigits) { - if (this.fractionDigits == null) { - this.fractionDigits = fractionDigits; - } + public void addFractionDigits(final Integer fractionDigits) { + this.fractionDigits.add(fractionDigits); } } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/YangModelBuilderUtil.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/YangModelBuilderUtil.java index f58ee740cf..1e55b24449 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/YangModelBuilderUtil.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/util/YangModelBuilderUtil.java @@ -76,13 +76,17 @@ import org.opendaylight.controller.yang.model.api.SchemaPath; import org.opendaylight.controller.yang.model.api.Status; import org.opendaylight.controller.yang.model.api.TypeDefinition; import org.opendaylight.controller.yang.model.api.UnknownSchemaNode; +import org.opendaylight.controller.yang.model.api.type.BinaryTypeDefinition; import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition; import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit; import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition; import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition.EnumPair; +import org.opendaylight.controller.yang.model.api.type.IntegerTypeDefinition; import org.opendaylight.controller.yang.model.api.type.LengthConstraint; import org.opendaylight.controller.yang.model.api.type.PatternConstraint; import org.opendaylight.controller.yang.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition; +import org.opendaylight.controller.yang.model.api.type.UnsignedIntegerTypeDefinition; import org.opendaylight.controller.yang.model.util.BaseConstraints; import org.opendaylight.controller.yang.model.util.BaseTypes; import org.opendaylight.controller.yang.model.util.BinaryType; @@ -103,8 +107,12 @@ import org.opendaylight.controller.yang.model.util.Uint32; import org.opendaylight.controller.yang.model.util.Uint64; import org.opendaylight.controller.yang.model.util.Uint8; import org.opendaylight.controller.yang.model.util.UnknownType; +import org.opendaylight.controller.yang.parser.builder.api.Builder; import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder; +import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder; import org.opendaylight.controller.yang.parser.builder.impl.ConstraintsBuilder; +import org.opendaylight.controller.yang.parser.builder.impl.ModuleBuilder; +import org.opendaylight.controller.yang.parser.builder.impl.UnionTypeBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -964,19 +972,48 @@ public final class YangModelBuilderUtil { * @return UnknownType object with constraints from parsed type body */ public static TypeDefinition parseUnknownTypeBody(QName typedefQName, - Type_body_stmtsContext ctx) { + Type_body_stmtsContext ctx, final List actualPath, + final URI namespace, final Date revision, final String prefix, + Builder parent, ModuleBuilder moduleBuilder) { + String typeName = typedefQName.getLocalName(); + UnknownType.Builder unknownType = new UnknownType.Builder(typedefQName); + if (ctx != null) { List rangeStatements = getRangeConstraints(ctx); List lengthStatements = getLengthConstraints(ctx); List patternStatements = getPatternConstraint(ctx); Integer fractionDigits = getFractionDigits(ctx); - unknownType.rangeStatements(rangeStatements); - unknownType.lengthStatements(lengthStatements); - unknownType.patterns(patternStatements); - unknownType.fractionDigits(fractionDigits); + if (parent instanceof TypeDefinitionBuilder) { + TypeDefinitionBuilder typedef = (TypeDefinitionBuilder) parent; + typedef.setRanges(rangeStatements); + typedef.setLengths(lengthStatements); + typedef.setPatterns(patternStatements); + typedef.setFractionDigits(fractionDigits); + return unknownType.build(); + } else { + TypeDefinition baseType = unknownType.build(); + TypeDefinition result = null; + QName qname = new QName(namespace, revision, prefix, typeName); + ExtendedType.Builder typeBuilder = null; + + SchemaPath schemaPath = createTypeSchemaPath(actualPath, + namespace, revision, prefix, typeName, false, false); + typeBuilder = new ExtendedType.Builder(qname, baseType, "", "", + schemaPath); + + typeBuilder.ranges(rangeStatements); + typeBuilder.lengths(lengthStatements); + typeBuilder.patterns(patternStatements); + typeBuilder.fractionDigits(fractionDigits); + + result = typeBuilder.build(); + + return result; + } } + return unknownType.build(); } @@ -1000,7 +1037,7 @@ public final class YangModelBuilderUtil { public static TypeDefinition parseTypeBody(final String typeName, final Type_body_stmtsContext typeBody, final List actualPath, final URI namespace, - final Date revision, final String prefix) { + final Date revision, final String prefix, Builder parent) { TypeDefinition baseType = null; List rangeStatements = getRangeConstraints(typeBody); @@ -1010,40 +1047,56 @@ public final class YangModelBuilderUtil { List enumConstants = getEnumConstants( typeBody, actualPath, namespace, revision, prefix); + TypeConstraints constraints = new TypeConstraints(); + constraints.addFractionDigits(fractionDigits); + constraints.addLengths(lengthStatements); + constraints.addPatterns(patternStatements); + constraints.addRanges(rangeStatements); + SchemaPath baseTypePathFinal = createTypeSchemaPath(actualPath, namespace, revision, prefix, typeName, true, true); - SchemaPath baseTypePath = createTypeSchemaPath(actualPath, - namespace, revision, prefix, typeName, true, false); + SchemaPath baseTypePath = createTypeSchemaPath(actualPath, namespace, + revision, prefix, typeName, true, false); if ("decimal64".equals(typeName)) { if (rangeStatements.isEmpty()) { return new Decimal64(baseTypePathFinal, fractionDigits); } - baseType = new Decimal64(baseTypePath, fractionDigits); + Decimal64 decimalType = new Decimal64(baseTypePath, fractionDigits); + constraints.addRanges(decimalType.getRangeStatements()); + baseType = decimalType; } else if (typeName.startsWith("int")) { + IntegerTypeDefinition intType = null; if ("int8".equals(typeName)) { - baseType = new Int8(baseTypePath); + intType = new Int8(baseTypePath); } else if ("int16".equals(typeName)) { - baseType = new Int16(baseTypePath); + intType = new Int16(baseTypePath); } else if ("int32".equals(typeName)) { - baseType = new Int32(baseTypePath); + intType = new Int32(baseTypePath); } else if ("int64".equals(typeName)) { - baseType = new Int64(baseTypePath); + intType = new Int64(baseTypePath); } + constraints.addRanges(intType.getRangeStatements()); + baseType = intType; } else if (typeName.startsWith("uint")) { + UnsignedIntegerTypeDefinition uintType = null; if ("uint8".equals(typeName)) { - baseType = new Uint8(baseTypePath); + uintType = new Uint8(baseTypePath); } else if ("uint16".equals(typeName)) { - baseType = new Uint16(baseTypePath); + uintType = new Uint16(baseTypePath); } else if ("uint32".equals(typeName)) { - baseType = new Uint32(baseTypePath); + uintType = new Uint32(baseTypePath); } else if ("uint64".equals(typeName)) { - baseType = new Uint64(baseTypePath); + uintType = new Uint64(baseTypePath); } + constraints.addRanges(uintType.getRangeStatements()); + baseType = uintType; } else if ("enumeration".equals(typeName)) { return new EnumerationType(baseTypePathFinal, enumConstants); } else if ("string".equals(typeName)) { - baseType = new StringType(baseTypePath); + StringTypeDefinition stringType = new StringType(baseTypePath); + constraints.addLengths(stringType.getLengthStatements()); + baseType = stringType; } else if ("bits".equals(typeName)) { return new BitsType(baseTypePathFinal, getBits(typeBody, actualPath, namespace, revision, prefix)); @@ -1054,13 +1107,25 @@ public final class YangModelBuilderUtil { absolute); return new Leafref(baseTypePathFinal, xpath); } else if ("binary".equals(typeName)) { - baseType = new BinaryType(baseTypePath); + BinaryTypeDefinition binaryType = new BinaryType(baseTypePath); + constraints.addLengths(binaryType.getLengthConstraints()); + baseType = binaryType; } else if ("instance-identifier".equals(typeName)) { boolean requireInstance = isRequireInstance(typeBody); baseType = new InstanceIdentifier(baseTypePath, null, requireInstance); } + if (parent instanceof TypeDefinitionBuilder + && !(parent instanceof UnionTypeBuilder)) { + TypeDefinitionBuilder typedef = (TypeDefinitionBuilder) parent; + typedef.setRanges(constraints.getRange()); + typedef.setLengths(constraints.getLength()); + typedef.setPatterns(constraints.getPatterns()); + typedef.setFractionDigits(constraints.getFractionDigits()); + return baseType; + } + TypeDefinition result = null; QName qname = new QName(namespace, revision, prefix, typeName); ExtendedType.Builder typeBuilder = null; @@ -1070,10 +1135,10 @@ public final class YangModelBuilderUtil { typeBuilder = new ExtendedType.Builder(qname, baseType, "", "", schemaPath); - typeBuilder.ranges(rangeStatements); - typeBuilder.lengths(lengthStatements); - typeBuilder.patterns(patternStatements); - typeBuilder.fractionDigits(fractionDigits); + typeBuilder.ranges(constraints.getRange()); + typeBuilder.lengths(constraints.getLength()); + typeBuilder.patterns(constraints.getPatterns()); + typeBuilder.fractionDigits(constraints.getFractionDigits()); result = typeBuilder.build(); return result; diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/TestUtils.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/TestUtils.java index d14c54219e..26c2c61b98 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/TestUtils.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/TestUtils.java @@ -49,13 +49,9 @@ final class TestUtils { return parser.parseYangModels(testFiles); } - public static Set loadModules(String... pathToYangFile) throws IOException { - YangModelParser parser = new YangParserImpl(); - List input = new ArrayList(); - for(String path : pathToYangFile) { - input.add(TestUtils.class.getResourceAsStream(path)); - } - Set modules = new HashSet( + public static Set loadModules(List input) throws IOException { + final YangModelParser parser = new YangParserImpl(); + final Set modules = new HashSet( parser.parseYangModelsFromStreams(input)); for(InputStream stream : input) { stream.close(); @@ -63,11 +59,11 @@ final class TestUtils { return modules; } - public static Module loadModule(String pathToYangFile) throws IOException { - YangModelParser parser = new YangParserImpl(); - InputStream stream = TestUtils.class.getResourceAsStream(pathToYangFile); - List input = Collections.singletonList(stream); - Set modules = new HashSet( + public static Module loadModule(final InputStream stream) throws + IOException { + final YangModelParser parser = new YangParserImpl(); + final List input = Collections.singletonList(stream); + final Set modules = new HashSet( parser.parseYangModelsFromStreams(input)); stream.close(); return modules.iterator().next(); diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/TypesResolutionTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/TypesResolutionTest.java index 461cc4b5c2..2c910ce3f6 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/TypesResolutionTest.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/TypesResolutionTest.java @@ -26,6 +26,7 @@ import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit; import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition.EnumPair; import org.opendaylight.controller.yang.model.api.type.LengthConstraint; import org.opendaylight.controller.yang.model.api.type.PatternConstraint; +import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition; import org.opendaylight.controller.yang.model.util.BitsType; import org.opendaylight.controller.yang.model.util.EnumerationType; import org.opendaylight.controller.yang.model.util.ExtendedType; @@ -38,7 +39,8 @@ public class TypesResolutionTest { @Before public void init() throws FileNotFoundException { - testedModules = TestUtils.loadModules("src/test/resources/types"); + testedModules = TestUtils.loadModules(getClass().getResource + ("/types").getPath()); } @Test @@ -122,16 +124,19 @@ public class TypesResolutionTest { List> unionTypes = baseType.getTypes(); ExtendedType ipv4 = (ExtendedType) unionTypes.get(0); - ExtendedType ipv4Base = (ExtendedType) ipv4.getBaseType(); + assertTrue(ipv4.getBaseType() instanceof StringTypeDefinition); String expectedPattern = "(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}" + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])" + "(%[\\p{N}\\p{L}]+)?"; - assertEquals(expectedPattern, ipv4Base.getPatterns().get(0) + assertEquals(expectedPattern, ipv4.getPatterns().get(0) .getRegularExpression()); + TypeDefinition ipv4Address = TestUtils.findTypedef(typedefs, "ipv4-address"); + assertEquals(ipv4Address, ipv4); + ExtendedType ipv6 = (ExtendedType) unionTypes.get(1); - ExtendedType ipv6Base = (ExtendedType) ipv6.getBaseType(); - List ipv6Patterns = ipv6Base.getPatterns(); + assertTrue(ipv6.getBaseType() instanceof StringTypeDefinition); + List ipv6Patterns = ipv6.getPatterns(); expectedPattern = "((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}" + "((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|" + "(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}" @@ -140,6 +145,9 @@ public class TypesResolutionTest { assertEquals(expectedPattern, ipv6Patterns.get(0) .getRegularExpression()); + TypeDefinition ipv6Address = TestUtils.findTypedef(typedefs, "ipv6-address"); + assertEquals(ipv6Address, ipv6); + expectedPattern = "(([^:]+:){6}(([^:]+:[^:]+)|(.*\\..*)))|" + "((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)" + "(%.+)?"; assertEquals(expectedPattern, ipv6Patterns.get(1) @@ -150,18 +158,18 @@ public class TypesResolutionTest { public void testDomainName() { Module tested = TestUtils.findModule(testedModules, "ietf-inet-types"); Set> typedefs = tested.getTypeDefinitions(); - TypeDefinition type = TestUtils.findTypedef(typedefs, "domain-name"); - ExtendedType baseType = (ExtendedType) type.getBaseType(); - List patterns = baseType.getPatterns(); + ExtendedType type = (ExtendedType)TestUtils.findTypedef(typedefs, "domain-name"); + assertTrue(type.getBaseType() instanceof StringTypeDefinition); + List patterns = type.getPatterns(); assertEquals(1, patterns.size()); String expectedPattern = "((([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.)*" + "([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.?)" + "|\\."; assertEquals(expectedPattern, patterns.get(0).getRegularExpression()); - List lengths = baseType.getLengths(); + List lengths = type.getLengths(); assertEquals(1, lengths.size()); - LengthConstraint length = baseType.getLengths().get(0); + LengthConstraint length = type.getLengths().get(0); assertEquals(1L, length.getMin()); assertEquals(253L, length.getMax()); } @@ -173,7 +181,8 @@ public class TypesResolutionTest { LeafSchemaNode leaf = (LeafSchemaNode) tested .getDataChildByName("inst-id-leaf1"); ExtendedType leafType = (ExtendedType) leaf.getType(); - InstanceIdentifier leafTypeBase = (InstanceIdentifier)leafType.getBaseType(); + InstanceIdentifier leafTypeBase = (InstanceIdentifier) leafType + .getBaseType(); assertFalse(leafTypeBase.requireInstance()); } @@ -300,6 +309,11 @@ public class TypesResolutionTest { ExtendedType testedType = (ExtendedType) TestUtils.findTypedef( typedefs, "object-identifier-128"); + List patterns = testedType.getPatterns(); + assertEquals(1, patterns.size()); + PatternConstraint pattern = patterns.get(0); + assertEquals("\\d*(\\.\\d*){1,127}", pattern.getRegularExpression()); + QName testedTypeQName = testedType.getQName(); assertEquals(URI.create("urn:ietf:params:xml:ns:yang:ietf-yang-types"), testedTypeQName.getNamespace()); @@ -309,15 +323,13 @@ public class TypesResolutionTest { assertEquals("object-identifier-128", testedTypeQName.getLocalName()); ExtendedType testedTypeBase = (ExtendedType) testedType.getBaseType(); + patterns = testedTypeBase.getPatterns(); + assertEquals(1, patterns.size()); - List patterns = testedTypeBase.getPatterns(); - assertEquals(2, patterns.size()); - PatternConstraint pattern1 = patterns.get(0); - assertEquals("\\d*(\\.\\d*){1,127}", pattern1.getRegularExpression()); - PatternConstraint pattern2 = patterns.get(1); + pattern = patterns.get(0); assertEquals( "(([0-1](\\.[1-3]?[0-9]))|(2\\.(0|([1-9]\\d*))))(\\.(0|([1-9]\\d*)))*", - pattern2.getRegularExpression()); + pattern.getRegularExpression()); QName testedTypeBaseQName = testedTypeBase.getQName(); assertEquals(URI.create("urn:ietf:params:xml:ns:yang:ietf-yang-types"), diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/YangParserNegativeTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/YangParserNegativeTest.java index be44c6ff98..35bfb1bebf 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/YangParserNegativeTest.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/YangParserNegativeTest.java @@ -9,7 +9,11 @@ package org.opendaylight.controller.yang.parser.impl; import static org.junit.Assert.*; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; import org.junit.Test; import org.opendaylight.controller.yang.parser.util.YangParseException; @@ -20,8 +24,11 @@ public class YangParserNegativeTest { @Test public void testInvalidImport() throws IOException { try { - TestUtils.loadModule("/negative-scenario/testfile1.yang"); - fail("ValidationException should by thrown"); + try (InputStream stream = new FileInputStream(getClass().getResource + ("/negative-scenario/testfile1.yang").getPath())) { + TestUtils.loadModule(stream); + fail("ValidationException should by thrown"); + } } catch(YangValidationException e) { assertTrue(e.getMessage().contains("Not existing module imported")); } @@ -30,8 +37,11 @@ public class YangParserNegativeTest { @Test public void testTypeNotFound() throws IOException { try { - TestUtils.loadModule("/negative-scenario/testfile2.yang"); - fail("YangParseException should by thrown"); + try (InputStream stream = new FileInputStream(getClass().getResource + ("/negative-scenario/testfile2.yang").getPath())) { + TestUtils.loadModule(stream); + fail("YangParseException should by thrown"); + } } catch(YangParseException e) { assertTrue(e.getMessage().contains("Error in module 'test2' on line 24: Referenced type 'int-ext' not found.")); } @@ -40,8 +50,19 @@ public class YangParserNegativeTest { @Test public void testInvalidAugmentTarget() throws IOException { try { - TestUtils.loadModules("/negative-scenario/testfile0.yang", "/negative-scenario/testfile3.yang"); - fail("YangParseException should by thrown"); + final List streams = new ArrayList<>(2); + try (InputStream testFile0 = new FileInputStream(getClass().getResource + ("/negative-scenario/testfile0.yang").getPath())) { + streams.add(testFile0); + try (InputStream testFile3 = new FileInputStream(getClass().getResource + ("/negative-scenario/testfile3.yang").getPath())) { + streams.add(testFile3); + assertEquals("Expected loaded files count is 2", 2, + streams.size()); + TestUtils.loadModules(streams); + fail("YangParseException should by thrown"); + } + } } catch(YangParseException e) { assertTrue(e.getMessage().contains("Failed to resolve augments in module 'test3'.")); } @@ -50,8 +71,11 @@ public class YangParserNegativeTest { @Test public void testInvalidRefine() throws IOException { try { - TestUtils.loadModule("/negative-scenario/testfile4.yang"); - fail("YangParseException should by thrown"); + try (InputStream stream = new FileInputStream(getClass().getResource + ("/negative-scenario/testfile4.yang").getPath())) { + TestUtils.loadModule(stream); + fail("YangParseException should by thrown"); + } } catch(YangParseException e) { assertTrue(e.getMessage().contains("Can not refine 'presence' for 'node'.")); } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/YangParserTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/YangParserTest.java index 23bb4a41d2..ba31e51922 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/YangParserTest.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/parser/impl/YangParserTest.java @@ -16,7 +16,6 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -64,13 +63,14 @@ import org.opendaylight.controller.yang.model.util.Uint32; import org.opendaylight.controller.yang.model.util.UnionType; public class YangParserTest { - private final DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + private final DateFormat simpleDateFormat = new SimpleDateFormat( + "yyyy-MM-dd"); private Set modules; @Before public void init() throws FileNotFoundException { - modules = TestUtils.loadModules("src/test/resources/model"); + modules = TestUtils.loadModules(getClass().getResource("/model").getPath()); assertEquals(3, modules.size()); } @@ -209,7 +209,7 @@ public class YangParserTest { // leaf if-name LeafSchemaNode ifName = (LeafSchemaNode) test .getDataChildByName("if-name"); - Leafref ifNameType = (Leafref)ifName.getType(); + Leafref ifNameType = (Leafref) ifName.getType(); QName qname = ifNameType.getQName(); URI baseYangTypeNS = URI.create("urn:ietf:params:xml:ns:yang:1"); @@ -219,9 +219,8 @@ public class YangParserTest { assertEquals("leafref", qname.getLocalName()); // leaf name - LeafSchemaNode name = (LeafSchemaNode) test - .getDataChildByName("name"); - StringType nameType = (StringType)name.getType(); + LeafSchemaNode name = (LeafSchemaNode) test.getDataChildByName("name"); + StringType nameType = (StringType) name.getType(); QName nameQName = nameType.getQName(); assertEquals(baseYangTypeNS, nameQName.getNamespace()); @@ -232,7 +231,7 @@ public class YangParserTest { // leaf count LeafSchemaNode count = (LeafSchemaNode) test .getDataChildByName("count"); - ExtendedType countType = (ExtendedType)count.getType(); + ExtendedType countType = (ExtendedType) count.getType(); QName countTypeQName = countType.getQName(); URI expectedNS = URI.create("urn:simple.types.data.demo"); @@ -242,7 +241,7 @@ public class YangParserTest { assertEquals("t2", countTypeQName.getPrefix()); assertEquals("int8", countTypeQName.getLocalName()); - Int8 countTypeBase = (Int8)countType.getBaseType(); + Int8 countTypeBase = (Int8) countType.getBaseType(); QName countTypeBaseQName = countTypeBase.getQName(); assertEquals(baseYangTypeNS, countTypeBaseQName.getNamespace()); @@ -341,17 +340,29 @@ public class YangParserTest { } @Test - public void testTypedefRangesResolving() { + public void testTypedefRangesResolving() throws ParseException { Module testModule = TestUtils.findModule(modules, "types1"); LeafSchemaNode testleaf = (LeafSchemaNode) testModule .getDataChildByName("testleaf"); ExtendedType leafType = (ExtendedType) testleaf.getType(); - assertEquals("my-type1", leafType.getQName().getLocalName()); - assertEquals("t2", leafType.getQName().getPrefix()); + QName leafTypeQName = leafType.getQName(); + assertEquals("my-type1", leafTypeQName.getLocalName()); + assertEquals("t1", leafTypeQName.getPrefix()); + assertEquals(URI.create("urn:simple.container.demo"), + leafTypeQName.getNamespace()); + Date expectedDate = simpleDateFormat.parse("2013-02-27"); + assertEquals(expectedDate, leafTypeQName.getRevision()); + assertEquals(1, leafType.getRanges().size()); + ExtendedType baseType = (ExtendedType) leafType.getBaseType(); - assertEquals("my-base-int32-type", baseType.getQName().getLocalName()); - assertEquals("t2", baseType.getQName().getPrefix()); + QName baseTypeQName = baseType.getQName(); + assertEquals("my-type1", baseTypeQName.getLocalName()); + assertEquals("t2", baseTypeQName.getPrefix()); + assertEquals(URI.create("urn:simple.types.data.demo"), + baseTypeQName.getNamespace()); + assertEquals(expectedDate, baseTypeQName.getRevision()); + assertEquals(2, baseType.getRanges().size()); List ranges = leafType.getRanges(); assertEquals(1, ranges.size()); @@ -371,28 +382,21 @@ public class YangParserTest { assertEquals("my-string-type-ext", testleafTypeQName.getLocalName()); assertEquals("t2", testleafTypeQName.getPrefix()); - Set expectedRegex = new HashSet(); - expectedRegex.add("[a-k]*"); - expectedRegex.add("[b-u]*"); - expectedRegex.add("[e-z]*"); - - Set actualRegex = new HashSet(); List patterns = testleafType.getPatterns(); - assertEquals(3, patterns.size()); - for (PatternConstraint pc : patterns) { - actualRegex.add(pc.getRegularExpression()); - } - assertEquals(expectedRegex, actualRegex); + assertEquals(1, patterns.size()); + PatternConstraint pattern = patterns.iterator().next(); + assertEquals("[e-z]*", pattern.getRegularExpression()); - TypeDefinition baseType = testleafType.getBaseType(); + ExtendedType baseType = (ExtendedType) testleafType.getBaseType(); assertEquals("my-string-type2", baseType.getQName().getLocalName()); - List lengths = testleafType.getLengths(); - assertEquals(1, lengths.size()); + patterns = baseType.getPatterns(); + assertEquals(1, patterns.size()); + pattern = patterns.iterator().next(); + assertEquals("[b-u]*", pattern.getRegularExpression()); - LengthConstraint length = lengths.get(0); - assertEquals(5L, length.getMin()); - assertEquals(10L, length.getMax()); + List lengths = testleafType.getLengths(); + assertTrue(lengths.isEmpty()); } @Test @@ -424,14 +428,14 @@ public class YangParserTest { ExtendedType baseType = (ExtendedType) testleafType.getBaseType(); assertEquals("my-base-int32-type", baseType.getQName().getLocalName()); - ExtendedType int32Type = (ExtendedType) baseType.getBaseType(); - Int32 int32TypeBase = (Int32)int32Type.getBaseType(); - QName qname = int32TypeBase.getQName(); - assertEquals(URI.create("urn:ietf:params:xml:ns:yang:1"), qname.getNamespace()); + Int32 int32Type = (Int32) baseType.getBaseType(); + QName qname = int32Type.getQName(); + assertEquals(URI.create("urn:ietf:params:xml:ns:yang:1"), + qname.getNamespace()); assertNull(qname.getRevision()); assertEquals("", qname.getPrefix()); assertEquals("int32", qname.getLocalName()); - List ranges = int32Type.getRanges(); + List ranges = baseType.getRanges(); assertEquals(1, ranges.size()); RangeConstraint range = ranges.get(0); assertEquals(2L, range.getMin()); @@ -447,8 +451,12 @@ public class YangParserTest { ExtendedType type = (ExtendedType) testleaf.getType(); assertEquals(4, (int) type.getFractionDigits()); - Decimal64 baseType = (Decimal64) type.getBaseType(); - assertEquals(6, (int) baseType.getFractionDigits()); + ExtendedType typeBase = (ExtendedType) type.getBaseType(); + assertEquals("my-decimal-type", typeBase.getQName().getLocalName()); + assertNull(typeBase.getFractionDigits()); + + Decimal64 decimal = (Decimal64) typeBase.getBaseType(); + assertEquals(6, (int) decimal.getFractionDigits()); } @Test @@ -840,14 +848,20 @@ public class YangParserTest { Leafref ifcIdType = (Leafref) ifcId.getType(); SchemaPath ifcIdTypeSchemaPath = ifcIdType.getPath(); List ifcIdTypePath = ifcIdTypeSchemaPath.getPath(); - QName q0 = new QName(new URI("urn:simple.types.data.demo"), - simpleDateFormat.parse("2013-02-27"), "data", "interfaces"); - QName q1 = new QName(new URI("urn:simple.types.data.demo"), - simpleDateFormat.parse("2013-02-27"), "data", "ifEntry"); - QName q2 = new QName(new URI("urn:simple.container.demo.test"), - simpleDateFormat.parse("2013-02-27"), "data", "augment-holder"); - QName q3 = new QName(new URI("urn:simple.container.demo"), - simpleDateFormat.parse("2013-02-27"), "data", "interface-id"); + + URI types1URI = URI.create("urn:simple.container.demo"); + URI types2URI = URI.create("urn:simple.types.data.demo"); + URI types3URI = URI.create("urn:simple.container.demo.test"); + Date expectedDate = simpleDateFormat.parse("2013-02-27"); + + QName q0 = new QName(types2URI, + expectedDate, "data", "interfaces"); + QName q1 = new QName(types2URI, + expectedDate, "data", "ifEntry"); + QName q2 = new QName(types3URI, + expectedDate, "data", "augment-holder"); + QName q3 = new QName(types1URI, + expectedDate, "data", "interface-id"); assertEquals(q0, ifcIdTypePath.get(0)); assertEquals(q1, ifcIdTypePath.get(1)); assertEquals(q2, ifcIdTypePath.get(2)); @@ -861,9 +875,18 @@ public class YangParserTest { assertEquals(q0, higherLayerTypePath.get(0)); assertEquals(q1, higherLayerTypePath.get(1)); assertEquals(q2, higherLayerTypePath.get(2)); - q3 = new QName(new URI("urn:simple.container.demo"), - simpleDateFormat.parse("2013-02-27"), "data", "higher-layer-if"); + q3 = new QName(types1URI, + expectedDate, "data", "higher-layer-if"); assertEquals(q3, higherLayerTypePath.get(3)); + + LeafSchemaNode myType = (LeafSchemaNode) augment + .getDataChildByName("my-type"); + ExtendedType leafType = (ExtendedType)myType.getType(); + + testModule = TestUtils.findModule(modules, "types2"); + TypeDefinition typedef = TestUtils.findTypedef(testModule.getTypeDefinitions(), "my-type1"); + + assertEquals(typedef, leafType); } @Test @@ -872,7 +895,8 @@ public class YangParserTest { Set> types = test.getTypeDefinitions(); // my-base-int32-type - ExtendedType int32Typedef = (ExtendedType)TestUtils.findTypedef(types, "my-base-int32-type"); + ExtendedType int32Typedef = (ExtendedType) TestUtils.findTypedef(types, + "my-base-int32-type"); QName int32TypedefQName = int32Typedef.getQName(); URI expectedNS = URI.create("urn:simple.types.data.demo"); @@ -888,24 +912,10 @@ public class YangParserTest { assertEquals(int32TypedefQName, typePath.get(0)); // my-base-int32-type/int32 - ExtendedType int32Ext = (ExtendedType)int32Typedef.getBaseType(); - QName int32ExtQName = int32Ext.getQName(); - - assertEquals(expectedNS, int32ExtQName.getNamespace()); - assertEquals(expectedDate, int32ExtQName.getRevision()); - assertEquals("t2", int32ExtQName.getPrefix()); - assertEquals("int32", int32ExtQName.getLocalName()); - - SchemaPath int32ExtSchemaPath = int32Ext.getPath(); - List int32ExtPath = int32ExtSchemaPath.getPath(); - assertEquals(2, int32ExtPath.size()); - assertEquals(int32TypedefQName, int32ExtPath.get(0)); - assertEquals(int32ExtQName, int32ExtPath.get(1)); - - // my-base-int32-type/int32/int32 - Int32 int32 = (Int32)int32Ext.getBaseType(); + Int32 int32 = (Int32) int32Typedef.getBaseType(); QName int32QName = int32.getQName(); - assertEquals(URI.create("urn:ietf:params:xml:ns:yang:1"), int32QName.getNamespace()); + assertEquals(URI.create("urn:ietf:params:xml:ns:yang:1"), + int32QName.getNamespace()); assertNull(int32QName.getRevision()); assertEquals("", int32QName.getPrefix()); assertEquals("int32", int32QName.getLocalName()); @@ -914,7 +924,6 @@ public class YangParserTest { List int32Path = int32SchemaPath.getPath(); assertEquals(3, int32Path.size()); assertEquals(int32TypedefQName, int32Path.get(0)); - assertEquals(int32ExtQName, int32Path.get(1)); assertEquals(int32QName, int32Path.get(2)); } @@ -924,7 +933,8 @@ public class YangParserTest { Set> types = test.getTypeDefinitions(); // my-base-int32-type - ExtendedType myDecType = (ExtendedType)TestUtils.findTypedef(types, "my-decimal-type"); + ExtendedType myDecType = (ExtendedType) TestUtils.findTypedef(types, + "my-decimal-type"); QName myDecTypeQName = myDecType.getQName(); URI expectedNS = URI.create("urn:simple.types.data.demo"); @@ -940,10 +950,11 @@ public class YangParserTest { assertEquals(myDecTypeQName, typePath.get(0)); // my-base-int32-type/int32 - Decimal64 dec64 = (Decimal64)myDecType.getBaseType(); + Decimal64 dec64 = (Decimal64) myDecType.getBaseType(); QName dec64QName = dec64.getQName(); - assertEquals(URI.create("urn:ietf:params:xml:ns:yang:1"), dec64QName.getNamespace()); + assertEquals(URI.create("urn:ietf:params:xml:ns:yang:1"), + dec64QName.getNamespace()); assertNull(dec64QName.getRevision()); assertEquals("", dec64QName.getPrefix()); assertEquals("decimal64", dec64QName.getLocalName()); diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile1.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile1.yang index 4ec69c18b2..3dbfa780a3 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile1.yang +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile1.yang @@ -123,6 +123,9 @@ module types1 { path "/if:interfaces/if:interface/if:higher-layer-if"; } } + leaf my-type { + type data:my-type1; + } } container mycont { diff --git a/opendaylight/sal/yang-prototype/yang/pom.xml b/opendaylight/sal/yang-prototype/yang/pom.xml index e79e70028b..4e15f8d47c 100644 --- a/opendaylight/sal/yang-prototype/yang/pom.xml +++ b/opendaylight/sal/yang-prototype/yang/pom.xml @@ -6,7 +6,7 @@ yang-prototype 0.5-SNAPSHOT - 0.5.1-SNAPSHOT + 0.5.2-SNAPSHOT yang pom diff --git a/opendaylight/sal/yang-prototype/yang/yang-binding/pom.xml b/opendaylight/sal/yang-prototype/yang/yang-binding/pom.xml index f7df24f53f..6362eb9acc 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-binding/pom.xml +++ b/opendaylight/sal/yang-prototype/yang/yang-binding/pom.xml @@ -3,7 +3,7 @@ org.opendaylight.controller yang - 0.5.1-SNAPSHOT + 0.5.2-SNAPSHOT yang-binding \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/BaseIdentity.java b/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/BaseIdentity.java new file mode 100644 index 0000000000..004287aebc --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/BaseIdentity.java @@ -0,0 +1,15 @@ +/* + * 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.yang.binding; + +public abstract class BaseIdentity { + + protected BaseIdentity() { + } + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-common/pom.xml b/opendaylight/sal/yang-prototype/yang/yang-common/pom.xml index 987b9b11a1..7f55386925 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-common/pom.xml +++ b/opendaylight/sal/yang-prototype/yang/yang-common/pom.xml @@ -3,7 +3,7 @@ org.opendaylight.controller yang - 0.5.1-SNAPSHOT + 0.5.2-SNAPSHOT yang-common diff --git a/opendaylight/sal/yang-prototype/yang/yang-common/src/main/java/org/opendaylight/controller/yang/common/QName.java b/opendaylight/sal/yang-prototype/yang/yang-common/src/main/java/org/opendaylight/controller/yang/common/QName.java index cdf8674893..004a2a4952 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-common/src/main/java/org/opendaylight/controller/yang/common/QName.java +++ b/opendaylight/sal/yang-prototype/yang/yang-common/src/main/java/org/opendaylight/controller/yang/common/QName.java @@ -36,7 +36,7 @@ import org.slf4j.LoggerFactory; * * */ -public class QName { +public final class QName { protected static final Logger logger = LoggerFactory .getLogger(QName.class); diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/pom.xml b/opendaylight/sal/yang-prototype/yang/yang-data-api/pom.xml index 749c9c66f4..02562172e8 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-data-api/pom.xml +++ b/opendaylight/sal/yang-prototype/yang/yang-data-api/pom.xml @@ -3,7 +3,7 @@ org.opendaylight.controller yang - 0.5.1-SNAPSHOT + 0.5.2-SNAPSHOT yang-data-api diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-util/pom.xml b/opendaylight/sal/yang-prototype/yang/yang-data-util/pom.xml index 15b391f5b8..bce9e91346 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-data-util/pom.xml +++ b/opendaylight/sal/yang-prototype/yang/yang-data-util/pom.xml @@ -3,7 +3,7 @@ org.opendaylight.controller yang - 0.5.1-SNAPSHOT + 0.5.2-SNAPSHOT yang-data-util diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/pom.xml b/opendaylight/sal/yang-prototype/yang/yang-model-api/pom.xml index 3eabd7ff9f..fc601e32b4 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-api/pom.xml +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/pom.xml @@ -3,7 +3,7 @@ org.opendaylight.controller yang - 0.5.1-SNAPSHOT + 0.5.2-SNAPSHOT yang-model-api diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/LeafSchemaNode.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/LeafSchemaNode.java index 9325cb8f0c..e3dd0ecd22 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/LeafSchemaNode.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/LeafSchemaNode.java @@ -20,4 +20,8 @@ public interface LeafSchemaNode extends DataSchemaNode { */ TypeDefinition getType(); + String getDefault(); + + String getUnits(); + } diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/pom.xml b/opendaylight/sal/yang-prototype/yang/yang-model-util/pom.xml index 3390837be9..d95b23957b 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/pom.xml +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/pom.xml @@ -3,7 +3,7 @@ org.opendaylight.controller yang - 0.5.1-SNAPSHOT + 0.5.2-SNAPSHOT yang-model-util diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/DataNodeIterator.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/DataNodeIterator.java index df111acf08..7c26531f37 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/DataNodeIterator.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/DataNodeIterator.java @@ -8,29 +8,30 @@ import java.util.Set; import org.opendaylight.controller.yang.model.api.ContainerSchemaNode; import org.opendaylight.controller.yang.model.api.DataNodeContainer; import org.opendaylight.controller.yang.model.api.DataSchemaNode; +import org.opendaylight.controller.yang.model.api.GroupingDefinition; import org.opendaylight.controller.yang.model.api.LeafListSchemaNode; import org.opendaylight.controller.yang.model.api.LeafSchemaNode; import org.opendaylight.controller.yang.model.api.ListSchemaNode; public class DataNodeIterator implements Iterator { - + private final DataNodeContainer container; private List allLists; private List allContainers; private List allLeafs; private List allLeafLists; private List allChilds; - + public DataNodeIterator(final DataNodeContainer container) { if (container == null) { throw new IllegalArgumentException("Data Node Container MUST be specified and cannot be NULL!"); } - + init(); this.container = container; traverse(this.container); } - + private void init() { this.allContainers = new ArrayList(); this.allLists = new ArrayList(); @@ -38,28 +39,28 @@ public class DataNodeIterator implements Iterator { this.allLeafLists = new ArrayList(); this.allChilds = new ArrayList(); } - + public List allContainers() { return allContainers; } - + public List allLists() { return allLists; } - + public List allLeafs() { return allLeafs; } - + public List allLeafLists() { return allLeafLists; } - + private void traverse(final DataNodeContainer dataNode) { if (dataNode == null) { return; } - + final Set childs = dataNode.getChildNodes(); if (childs != null) { for (DataSchemaNode childNode : childs) { @@ -83,15 +84,21 @@ public class DataNodeIterator implements Iterator { allLeafLists.add(leafList); } } - return; + } + + final Set groupings = dataNode.getGroupings(); + if(groupings != null) { + for(GroupingDefinition grouping : groupings) { + traverse(grouping); + } } } - + @Override public boolean hasNext() { if (container.getChildNodes() != null) { Set childs = container.getChildNodes(); - + if ((childs != null) && !childs.isEmpty()) { return childs.iterator().hasNext(); } diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/ExtendedType.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/ExtendedType.java index 86bde24d62..e5ef2026f1 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/ExtendedType.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/ExtendedType.java @@ -194,126 +194,54 @@ public class ExtendedType implements TypeDefinition> { } @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((baseType == null) ? 0 : baseType.hashCode()); - result = prime * result - + ((defaultValue == null) ? 0 : defaultValue.hashCode()); - result = prime * result - + ((description == null) ? 0 : description.hashCode()); - result = prime - * result - + ((unknownSchemaNodes == null) ? 0 : unknownSchemaNodes - .hashCode()); - result = prime * result + ((path == null) ? 0 : path.hashCode()); - result = prime * result - + ((reference == null) ? 0 : reference.hashCode()); - result = prime * result + ((status == null) ? 0 : status.hashCode()); - result = prime * result - + ((typeName == null) ? 0 : typeName.hashCode()); - result = prime * result + ((units == null) ? 0 : units.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { + public boolean equals(Object o) { + if (this == o) { return true; } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ExtendedType other = (ExtendedType) obj; - if (baseType == null) { - if (other.baseType != null) { - return false; - } - } else if (!baseType.equals(other.baseType)) { - return false; - } - if (defaultValue == null) { - if (other.defaultValue != null) { - return false; - } - } else if (!defaultValue.equals(other.defaultValue)) { - return false; - } - if (description == null) { - if (other.description != null) { - return false; - } - } else if (!description.equals(other.description)) { - return false; - } - if (unknownSchemaNodes == null) { - if (other.unknownSchemaNodes != null) { - return false; - } - } else if (!unknownSchemaNodes.equals(other.unknownSchemaNodes)) { + if (!(o instanceof ExtendedType)) { return false; } - if (path == null) { - if (other.path != null) { - return false; - } - } else if (!path.equals(other.path)) { - return false; - } - if (reference == null) { - if (other.reference != null) { - return false; - } - } else if (!reference.equals(other.reference)) { - return false; - } - if (status != other.status) { - return false; - } - if (typeName == null) { - if (other.typeName != null) { - return false; - } - } else if (!typeName.equals(other.typeName)) { + + ExtendedType that = (ExtendedType) o; + if (path != null ? !path.equals(that.path) : that.path != null) { return false; } - if (units == null) { - if (other.units != null) { - return false; - } - } else if (!units.equals(other.units)) { + if (typeName != null ? !typeName.equals(that.typeName) : that.typeName != null) return false; - } + return true; } + @Override + public int hashCode() { + int result = typeName != null ? typeName.hashCode() : 0; + result = 31 * result + (path != null ? path.hashCode() : 0); + return result; + } + @Override public String toString() { - StringBuilder builder2 = new StringBuilder(); - builder2.append("ExtendedType [typeName="); - builder2.append(typeName); - builder2.append(", baseType="); - builder2.append(baseType); - builder2.append(", path="); - builder2.append(path); - builder2.append(", description="); - builder2.append(description); - builder2.append(", reference="); - builder2.append(reference); - builder2.append(", unknownSchemaNodes="); - builder2.append(unknownSchemaNodes); - builder2.append(", status="); - builder2.append(status); - builder2.append(", units="); - builder2.append(units); - builder2.append(", defaultValue="); - builder2.append(defaultValue); - builder2.append("]"); - return builder2.toString(); + StringBuilder builder = new StringBuilder(); + builder.append("ExtendedType [typeName="); + builder.append(typeName); + builder.append(", baseType="); + builder.append(baseType); + builder.append(", path="); + builder.append(path); + builder.append(", description="); + builder.append(description); + builder.append(", reference="); + builder.append(reference); + builder.append(", unknownSchemaNodes="); + builder.append(unknownSchemaNodes); + builder.append(", status="); + builder.append(status); + builder.append(", units="); + builder.append(units); + builder.append(", defaultValue="); + builder.append(defaultValue); + builder.append("]"); + return builder.toString(); } public List getRanges() { diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java index 2d6a789887..13c2ba7cb5 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java @@ -33,7 +33,7 @@ public final class SchemaContextUtil { public static DataSchemaNode findDataSchemaNode(final SchemaContext context, final SchemaPath schemaPath) { if (schemaPath != null) { final Module module = resolveModuleFromSchemaPath(context, schemaPath); - final Queue prefixedPath = new LinkedList(schemaPath.getPath()); + final Queue prefixedPath = new LinkedList<>(schemaPath.getPath()); if ((module != null) && (prefixedPath != null)) { return findSchemaNodeForGivenPath(context, module, prefixedPath); @@ -87,32 +87,35 @@ public final class SchemaContextUtil { return null; } - public static Module resolveModuleFromSchemaPath(final SchemaContext context, final SchemaPath schemaPath) { + private static Module resolveModuleFromSchemaPath(final SchemaContext + context, final SchemaPath schemaPath) { if ((schemaPath != null) && (schemaPath.getPath() != null)) { - List path = schemaPath.getPath(); - final QName qname = path.get(path.size()-1); + final List path = schemaPath.getPath(); + if (!path.isEmpty()) { + final QName qname = path.get(path.size() - 1); - if ((qname != null) && (qname.getNamespace() != null)) { - return context.findModuleByNamespace(qname.getNamespace()); + if ((qname != null) && (qname.getNamespace() != null)) { + return context.findModuleByNamespace(qname.getNamespace()); + } } } return null; } - public static Module resolveModuleFromTypePath(final SchemaContext context, final TypeDefinition type) { + public static Module findParentModuleForTypeDefinition( + final SchemaContext context, final TypeDefinition type) { final SchemaPath schemaPath = type.getPath(); if ((schemaPath != null) && (schemaPath.getPath() != null)) { if(type instanceof ExtendedType) { List path = schemaPath.getPath(); - final QName qname = path.get(path.size()-1); + final QName qname = path.get(path.size() - 1); if ((qname != null) && (qname.getNamespace() != null)) { return context.findModuleByNamespace(qname.getNamespace()); } } else { - LinkedList path = new LinkedList(schemaPath.getPath()); - path.removeLast(); - final QName qname = path.get(path.size()-1); + List path = schemaPath.getPath(); + final QName qname = path.get(path.size() - 2); if ((qname != null) && (qname.getNamespace() != null)) { return context.findModuleByNamespace(qname.getNamespace()); @@ -142,7 +145,7 @@ public final class SchemaContextUtil { "The Schema Path MUST contain at least ONE QName which defines namespace and Local name" + "of path."); } - final QName qname = qnamedPath.get(0); + final QName qname = qnamedPath.get(qnamedPath.size() - 1); return context.findModuleByNamespace(qname.getNamespace()); } @@ -186,7 +189,7 @@ public final class SchemaContextUtil { private static Queue xpathToQNamePath(final SchemaContext context, final Module parentModule, final String xpath) { - final Queue path = new LinkedList(); + final Queue path = new LinkedList<>(); if (xpath != null) { final String[] prefixedPath = xpath.split("/"); @@ -240,7 +243,7 @@ public final class SchemaContextUtil { private static Queue resolveRelativeXPath(final SchemaContext context, final Module module, final RevisionAwareXPath relativeXPath, final SchemaPath leafrefSchemaPath) { - final Queue absolutePath = new LinkedList(); + final Queue absolutePath = new LinkedList<>(); if ((module != null) && (relativeXPath != null) && !relativeXPath.isAbsolute() && (leafrefSchemaPath != null)) { diff --git a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/ConfigManager.java b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/ConfigManager.java index 3cacab7846..ff91e93f58 100644 --- a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/ConfigManager.java +++ b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/ConfigManager.java @@ -19,36 +19,36 @@ import org.slf4j.LoggerFactory; /** * This class represents a configuration manager for the Load Balancer service. - * This class is responsible for managing(store/update/delete) the load balancer + * This class is responsible for managing(store/update/delete) the load balancer * configuration that it receives through REST APIs or from any other applications * present in the controller. * */ public class ConfigManager implements IConfigManager{ - + /* * Logger instance */ private static final Logger cmLogger = LoggerFactory.getLogger(ConfigManager.class); - + /* - * All the available VIPs + * All the available VIPs */ private HashMap vips = new HashMap(); - + /* * All the available Pools */ private HashMap pools = new HashMap(); - + public ConfigManager(){ } - + @Override public boolean vipExists(String name) { return this.vips.containsKey(name); } - + @Override public boolean vipExists(VIP vip){ if(vip.getName()==null){ @@ -64,80 +64,80 @@ public class ConfigManager implements IConfigManager{ } return true; } - + @Override public boolean vipExists(String name,String ip,String protocol,short protocolPort,String poolName){ - + VIP vip = new VIP(name,ip,protocol,protocolPort,poolName); - + //Check VIP with the same name - + if(!vips.containsKey(name)){ //Check VIP with the same ip, protocol and protocolPort if(!vips.containsValue(vip)){ - + //if you reach here, means this VIP don't exist return false; } } - + //Yeah, i have it. - return true; + return true; } - + @Override public Set getAllVIPs(){ return new HashSet(this.vips.values()); } - + public VIP getVIPWithPoolName(VIP vip){ cmLogger.info("Search a VIP with name:{}",vip); for(VIP vipTemp: this.vips.values()){ if(vipTemp.equals(vip)){ - + cmLogger.info("Found VIP with pool detail : {}",vipTemp); return vipTemp; } } - + cmLogger.info("VIP with pool detail not found "); return null; } - + @Override public VIP createVIP(String name,String ip,String protocol,short protocolPort,String poolName){ - + cmLogger.info("Create VIP with the following details :[ name : "+name +" ip : "+ip +" protocol : "+protocol +" protocol_port : "+protocolPort +" pool name : "+poolName); - + VIP vip = new VIP(name,ip,protocol,protocolPort,poolName); - + if(poolName !=null && !poolName.isEmpty()){ if(pools.containsKey(poolName)){ pools.get(poolName).addVIP(vip); } } - + vip.setStatus(LBConst.STATUS_ACTIVE); this.vips.put(name, vip); - + cmLogger.info("New VIP created : "+vip.toString()); return vip; } - + @Override public String getVIPAttachedPool(String name) { return this.vips.get(name).getPoolName(); } - + @Override public VIP updateVIP(String name, String poolName){ - + cmLogger.info("Updating VIP : "+name+" pool name to "+poolName); - + if(vips.containsKey(name)){ VIP vip = vips.get(name); if(vip.getPoolName() == null){ @@ -150,30 +150,30 @@ public class ConfigManager implements IConfigManager{ cmLogger.error("VIP with name: "+name+" does not exist"); return null; } - + @Override public VIP deleteVIP(String name){ - + cmLogger.info("Deleting VIP : "+name); - + VIP vip = vips.get(name); - + String poolName = vip.getPoolName(); - + if(poolName != null){ if(pools.containsKey(poolName)){ Pool pool = pools.get(poolName); pool.removeVIP(vip.getName()); } } - + cmLogger.info("VIP removed : "+vip.toString()); - + vips.remove(vip.getName()); - + return vip; } - + @Override public boolean memberExists(String name, String poolName) { if(this.pools.containsKey(poolName)){ @@ -182,89 +182,89 @@ public class ConfigManager implements IConfigManager{ } return false; } - + @Override public boolean memberExists(String name, String memberIP,String poolName){ if(!this.pools.containsKey(poolName)) return false; - + return this.pools.get(poolName).poolMemberExists(new PoolMember(name, memberIP, poolName)); } - + @Override public PoolMember addPoolMember(String name, String memberIP, String poolName){ - + PoolMember pm = new PoolMember(name,memberIP,poolName); - + cmLogger.info("Adding pool member : "+pm.toString()); - + pools.get(poolName).addMember(pm); - + return pm; } - + @Override public PoolMember removePoolMember(String name, String poolName){ - + cmLogger.info("Removing pool member : {} from pool {}",name, poolName); - + Pool pool = pools.get(poolName); - + PoolMember pm = pool.getMember(name); - + pool.removeMember(name); - + cmLogger.info("Pool member {} removed from {} ",name,poolName); - + return pm; } - + @Override public Set getAllPools(){ return new HashSet(this.pools.values()); } - + @Override public boolean poolExists(String name) { return this.pools.containsKey(name); } - + @Override public boolean poolExists(String name, String lbMethod){ - + return pools.containsValue(new Pool(name,lbMethod)); } - + @Override public Pool createPool(String name, String lbMethod){ - + Pool newPool = new Pool(name,lbMethod); - + cmLogger.info("New pool created : " + newPool.toString()); - + pools.put(name, newPool); - + return newPool; } - + @Override public Pool deletePool(String poolName){ - + Pool pool = pools.get(poolName); - + for(VIP vip:pool.getAllVip()){ - + vip.setPoolName(null); - + } - + cmLogger.info("Pool removed : "+pool.toString()); - + pools.remove(poolName); - + return pool; } - + @Override public Pool getPool( String poolName){ if(pools.containsKey(poolName)){ @@ -272,16 +272,16 @@ public class ConfigManager implements IConfigManager{ } return null; } - + @Override public Set getAllPoolMembers(String poolName) { - + if(pools.containsKey(poolName)){ return new HashSet(pools.get(poolName).getAllMembers()); } return null; } - + /* (non-Javadoc) * @see java.lang.Object#toString() */ diff --git a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/IConfigManager.java b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/IConfigManager.java index df35b0ae1f..5e55b2a3dd 100644 --- a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/IConfigManager.java +++ b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/IConfigManager.java @@ -18,164 +18,164 @@ import org.opendaylight.controller.samples.loadbalancer.entities.VIP; * */ public interface IConfigManager { - + /** * Return all existing VIPs * @return Set of VIP's * if there is no VIP, it will return empty set. */ public Set getAllVIPs(); - + /** * Check if VIP with the 'name' exists - * @param name Name of the VIP - * @return true if exists - * false else + * @param name Name of the VIP + * @return true if exists + * false else */ public boolean vipExists(String name); /** - * Check if VIP exists with the details 'VIP' - * @param vip Search for this VIP - * @return true if exists - * false else + * Check if VIP exists with the details 'VIP' + * @param vip Search for this VIP + * @return true if exists + * false else */ public boolean vipExists(VIP vip); /** * Check if VIP with the provided details exists - * @param name Name of the VIP - * @param ip IP of the VIP - * @param protocol IP Protocol of the VIP (TCP/UDP) - * @param protocolPort Transport port of the VIP (e.g 5550) - * @param poolName Name of the pool attached with the VIP - * @return true if exists - * false else + * @param name Name of the VIP + * @param ip IP of the VIP + * @param protocol IP Protocol of the VIP (TCP/UDP) + * @param protocolPort Transport port of the VIP (e.g 5550) + * @param poolName Name of the pool attached with the VIP + * @return true if exists + * false else */ public boolean vipExists(String name,String ip,String protocol,short protocolPort,String poolName); - + /** * Add VIP to the configuration - * @param name Name of the VIP - * @param ip IP of the VIP - * @param protocol IP Protocol of the VIP (TCP/UDP) - * @param protocolPort Transport port of the VIP - * @param poolName Name of the pool that VIP will use for load balancing its traffic - * @return Newly created VIP + * @param name Name of the VIP + * @param ip IP of the VIP + * @param protocol IP Protocol of the VIP (TCP/UDP) + * @param protocolPort Transport port of the VIP + * @param poolName Name of the pool that VIP will use for load balancing its traffic + * @return Newly created VIP */ public VIP createVIP(String name,String ip,String protocol,short protocolPort,String poolName); - + /** * Return pool attached to VIP * @param name Name of the VIP - * @return Name of the pool attached to VIP - * else null + * @return Name of the pool attached to VIP + * else null */ public String getVIPAttachedPool(String name); /** * Update pool name of the VIP. - * @param name Name of the VIP - * @param poolName Attach this pool to VIP - * @return Updated VIP If successful - * null If this VIP is already attached to any existing pool. - */ + * @param name Name of the VIP + * @param poolName Attach this pool to VIP + * @return Updated VIP If successful + * null If this VIP is already attached to any existing pool. + */ public VIP updateVIP(String name, String poolName); - + /** * Delete the VIP - * @param name Delete VIP with this name - * @return Details of the deleted VIP + * @param name Delete VIP with this name + * @return Details of the deleted VIP */ public VIP deleteVIP(String name); /** - * Check if pool member with the 'name' present in the pool with name 'poolName' - * @param name Name of the pool member - * @param poolName Name of the pool, you want to search for pool member - * @return true If exist - * false else + * Check if pool member with the 'name' present in the pool with name 'poolName' + * @param name Name of the pool member + * @param poolName Name of the pool, you want to search for pool member + * @return true If exist + * false else */ public boolean memberExists(String name, String poolName); /** * Check if pool member with name 'name' and IP 'memberIP' exist in the pool 'poolName' - * @param name Name of the pool member - * @param memberIP IP of the pool member - * @param poolName Name of the pool member you want to search - * @return true If Exist - * false else + * @param name Name of the pool member + * @param memberIP IP of the pool member + * @param poolName Name of the pool member you want to search + * @return true If Exist + * false else */ public boolean memberExists(String name, String memberIP,String poolName); - + /** * Return all pool members of the pool 'poolName' - * @param poolName Name of the pool - * @return Set of all the pool members if pool with the name present in the configuration - * null else - * + * @param poolName Name of the pool + * @return Set of all the pool members if pool with the name present in the configuration + * null else + * */ public Set getAllPoolMembers(String poolName); - + /** * Add new pool member to the configuration - * @param name Name of the pool - * @param memberIP IP of the pool - * @param poolName Attach pool member to this pool - * @return Newly created pool member + * @param name Name of the pool + * @param memberIP IP of the pool + * @param poolName Attach pool member to this pool + * @return Newly created pool member */ public PoolMember addPoolMember(String name, String memberIP, String poolName); - + /** * Remove pool member from the pool - * @param name Name of the pool member - * @param poolName Name of the pool - * @return Details of the removed pool member + * @param name Name of the pool member + * @param poolName Name of the pool + * @return Details of the removed pool member */ public PoolMember removePoolMember(String name, String poolName); /** * Return all the existing pools - * @return Set of Pools + * @return Set of Pools */ public Set getAllPools(); - + /** * Return pool with input name - * @param poolName Name of the pool - * @return Details of the pool if pool exist - * null else + * @param poolName Name of the pool + * @return Details of the pool if pool exist + * null else */ public Pool getPool(String poolName); - + /** - * Check if pool exists with the input name - * @param name Name of the pool - * @return true If exists - * false else + * Check if pool exists with the input name + * @param name Name of the pool + * @return true If exists + * false else */ public boolean poolExists(String name); /** * Check if pool exists with the input name and loadbalancing method. - * @param name Name of the pool - * @param lbMethod Load balancing method name - * @return true If exists - * false else + * @param name Name of the pool + * @param lbMethod Load balancing method name + * @return true If exists + * false else */ public boolean poolExists(String name, String lbMethod); - + /** * Create new pool with the provided details - * @param name Name of the pool - * @param lbMethod Load balancing method this pool will use - * @return Details of the newly created pool + * @param name Name of the pool + * @param lbMethod Load balancing method this pool will use + * @return Details of the newly created pool */ public Pool createPool(String name, String lbMethod); - + /** * Delete pool with the provided name - * @param poolName Name of the pool - * @return Details of the deleted pool + * @param poolName Name of the pool + * @return Details of the deleted pool */ public Pool deletePool(String poolName); diff --git a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/LBConst.java b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/LBConst.java index 7e93304de1..bd6fb473c1 100644 --- a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/LBConst.java +++ b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/LBConst.java @@ -12,22 +12,21 @@ package org.opendaylight.controller.samples.loadbalancer; * */ public class LBConst { - + public static final int FORWARD_DIRECTION_LB_FLOW = 0; - + public static final int REVERSE_DIRECTION_LB_FLOW = 1; - + public static final String ROUND_ROBIN_LB_METHOD = "roundrobin"; - + public static final String RANDOM_LB_METHOD = "random"; - + public static final String STATUS_ACTIVE="active"; - + public static final String STATUS_INACTIVE="inactive"; - + public static final String STATUS_PENDING="pending"; - + public static final String STATUS_ERROR="error"; - -} +} diff --git a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/LBUtil.java b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/LBUtil.java index c320250084..aa195a34e9 100644 --- a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/LBUtil.java +++ b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/LBUtil.java @@ -19,36 +19,36 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Class defines utilty methods that will be used by different components - * of the load balancer service + * Class defines utilty methods that will be used by different components + * of the load balancer service * */ public class LBUtil { - + private static final Logger lbuLogger = LoggerFactory.getLogger(LBUtil.class); - + public LBUtil(){} - + /** - * Extract the details of the source machine that sent this packet 'inPkt' - * @param inPkt Packet that is received by the controller - * @return Details of the source machine in Client object. + * Extract the details of the source machine that sent this packet 'inPkt' + * @param inPkt Packet that is received by the controller + * @return Details of the source machine in Client object. */ public Client getClientFromPacket(IPv4 inPkt){ lbuLogger.info("Find client information from packet : {}",inPkt.toString()); - + String ip = NetUtils.getInetAddress(inPkt.getSourceAddress()).getHostAddress(); - + String protocol = IPProtocols.getProtocolName(inPkt.getProtocol()); - + lbuLogger.info("client ip {} and protocl {}",ip,protocol); - + Packet tpFrame= inPkt.getPayload(); - + lbuLogger.info("Get protocol layer {}",tpFrame.toString()); - + short port = 0; - + if(protocol.equals(IPProtocols.TCP.toString())){ TCP tcpFrame = (TCP)tpFrame; port = tcpFrame.getSourcePort(); @@ -56,47 +56,47 @@ public class LBUtil { UDP udpFrame = (UDP)tpFrame; port = udpFrame.getSourcePort(); } - + lbuLogger.info("Found port {}",port); - + Client source = new Client(ip, protocol,port); - + lbuLogger.info("Client information : {}",source.toString()); - + return source; } - + /** * Extract the details of the destination machine where this packet 'inPkt' need * to be delivered * @param inPkt Packet that is received by controller for forwarding - * @return Details of the destination machine packet in VIP + * @return Details of the destination machine packet in VIP */ public VIP getVIPFromPacket(IPv4 inPkt){ - + lbuLogger.info("Find VIP information from packet : {}",inPkt.toString()); - + String ip = NetUtils.getInetAddress(inPkt.getDestinationAddress()).getHostAddress(); - + String protocol = IPProtocols.getProtocolName(inPkt.getProtocol()); - + Packet tpFrame= inPkt.getPayload(); - + short port = 0; - + if(protocol.equals(IPProtocols.TCP.toString())){ TCP tcpFrame = (TCP)tpFrame; port = tcpFrame.getDestinationPort(); }else{ - + UDP udpFrame = (UDP)tpFrame; port = udpFrame.getDestinationPort(); } - + VIP dest = new VIP(null,ip, protocol,port,null); - + lbuLogger.info("VIP information : {}",dest.toString()); - + return dest; } } \ No newline at end of file diff --git a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/Client.java b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/Client.java index 4d7cf4928a..a16582d532 100644 --- a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/Client.java +++ b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/Client.java @@ -17,73 +17,73 @@ package org.opendaylight.controller.samples.loadbalancer.entities; * e.g TCP traffic from two different ports from the same host to a given VIP will be considered * as two different clients by this service. Similarly, traffic using two different protocols * (TCP, UDP) from the same host will be considered as two different clients. - * + * */ public class Client { - + /* * IP address of the client (source address) */ private String ip; - + /* * Network protocol of the traffic sent by client */ private String protocol; - + /* * Port used to send network traffic (source port) */ private short port; - + public Client(String ip, String protocol, short port){ this.ip = ip; this.protocol = protocol; this.port = port; } - + /** * @return the client IP */ public String getIp() { return ip; } - + /** * @param ip the IP to set */ public void setIp(String ip) { this.ip = ip; } - + /** * @return the client network protocol */ public String getProtocol() { return protocol; } - + /** * @param protocol the protocol to set */ public void setProtocol(String protocol) { this.protocol = protocol; } - + /** * @return the client port */ public short getPort() { return port; } - + /** * @param port the port to set */ public void setPort(short port) { this.port = port; } - + /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @@ -96,7 +96,7 @@ public class Client { result = prime * result+ ((protocol == null) ? 0 : protocol.hashCode()); return result; } - + /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @@ -131,7 +131,7 @@ public class Client { } return true; } - + /* (non-Javadoc) * @see java.lang.Object#toString() */ diff --git a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/Pool.java b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/Pool.java index bbf31162aa..ae48a3a451 100644 --- a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/Pool.java +++ b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/Pool.java @@ -16,12 +16,12 @@ import javax.xml.bind.annotation.XmlRootElement; /** * This class represents the pool of hosts among which incoming traffic - * will be load balanced. Each pool will load balance the traffic among its pool members - * based on the loadbalancing policy set for the pool. + * will be load balanced. Each pool will load balance the traffic among its pool members + * based on the loadbalancing policy set for the pool. * Currently, the pool supports two load balancing policies: * 1. Round Robin Policy{@link org.opendaylight.controller.samples.loadbalancer.policies.RoundRobinLBPolicy} * 2. Random Policy {@link org.opendaylight.controller.samples.loadbalancer.policies.RandomLBPolicy} - * + * * NOTE: After creation of the pool, user can't update (change) its load balancing policy. * NOTE: Each Pool should have a unique name. */ @@ -29,124 +29,124 @@ import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name="pool") @XmlAccessorType(XmlAccessType.NONE) public class Pool { - + /* * Unique name of the pool */ @XmlElement private String name; - + /* * Associated load balancing policy */ @XmlElement(name="lbmethod") private String lbMethod; - + /* * Status of the pool (active/inactive) */ @XmlElement private String status; - + /* * List of all the VIPs using this pool for load balancing their traffic - more than * one VIP can be mapped to each pool. */ @XmlElement private ArrayList vips = new ArrayList(); - + /* * List of all the pool members used for load balancing the traffic */ @XmlElement private ArrayList members = new ArrayList(); - + /* * Private constructor used for JAXB mapping */ @SuppressWarnings("unused") private Pool() {} - + /** * Getter/ Setter methods */ - + public Pool(String name, String lbMethod) { this.name = name; this.lbMethod = lbMethod; } - + /** * @return the name */ public String getName() { return name; } - + /** * @param name the name to set */ public void setName(String name) { this.name = name; } - + /** * @return the lbMethod */ public String getLbMethod() { return lbMethod; } - + /** * @param lbMethod the lbMethod to set */ public void setLbMethod(String lbMethod) { this.lbMethod = lbMethod; } - + /** * @return the status */ public String getStatus() { return status; } - + /** * @param status the status to set */ public void setStatus(String status) { this.status = status; } - + /** * @return the vip */ public ArrayList getAllVip() { return vips; } - + /** * @param vip the vip to set */ public void setVips(ArrayList vips) { this.vips = vips; } - + /** * @return the members */ public ArrayList getAllMembers() { return members; } - + /** * @param members the members to set */ public void setMembers(ArrayList members) { this.members = members; } - + /** * Add new VIP to the VIP list * @param vip new VIP to add @@ -154,11 +154,11 @@ public class Pool { public void addVIP(VIP vip){ this.vips.add(vip); } - + /** * Remove VIP with given name from the VIP list of the pool * @param name Name of the VIP - * @return true If VIP was using this pool and removed + * @return true If VIP was using this pool and removed * false IF VIP is not using this pool */ public boolean removeVIP(String name){ @@ -170,25 +170,25 @@ public class Pool { } return false; } - + /** * Check if the given pool member is part of this pool * @param pm Search for this pool member - * @return true If pool member is attached to this pool + * @return true If pool member is attached to this pool * false else */ public boolean poolMemberExists(PoolMember pm){ return this.members.contains(pm); } - + /** * Returns the pool member with the given name * @param name Search for this pool member - * @return PoolMember If pool member is attached to this pool + * @return PoolMember If pool member is attached to this pool * null else */ public PoolMember getMember(String name){ - + for(PoolMember pm: this.members){ if(pm.getName().equals(name)){ return pm; @@ -196,7 +196,7 @@ public class Pool { } return null; } - + /** * Add new pool member to the pool * @param pm Add this new pool @@ -204,12 +204,12 @@ public class Pool { public void addMember(PoolMember pm){ this.members.add(pm); } - + /** * Remove pool member from the pool list * @param name Remove this pool member - * @return true If pool member was attached to this pool and successfully removed - * false If pool member is not attached to this pool + * @return true If pool member was attached to this pool and successfully removed + * false If pool member is not attached to this pool */ public boolean removeMember(String name){ for(PoolMember pm: this.members){ @@ -220,7 +220,7 @@ public class Pool { } return false; } - + /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @@ -232,7 +232,7 @@ public class Pool { result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } - + /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @@ -264,7 +264,7 @@ public class Pool { } return true; } - + /* (non-Javadoc) * @see java.lang.Object#toString() */ diff --git a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/PoolMember.java b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/PoolMember.java index 31297ebcce..31949b43d4 100644 --- a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/PoolMember.java +++ b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/PoolMember.java @@ -17,111 +17,111 @@ import javax.xml.bind.annotation.XmlRootElement; * This class represents the host where load balancing service will * redirect VIP traffic for load balancing. All these hosts have to * register with a pool to be a part of traffic load balancing. - * This entity is referred to as a 'PoolMember'. - * Load balancer service differentiates each pool member based on its + * This entity is referred to as a 'PoolMember'. + * Load balancer service differentiates each pool member based on its * two properties { ip address, attached pool }. * A host (IP) can be attached to two different pools through creation of two * different pool member objects. - * + * * NOTE: Each pool member should have a unique name. * */ @XmlRootElement(name="poolmember") @XmlAccessorType(XmlAccessType.NONE) public class PoolMember { - + /* * Unique name of the pool member */ @XmlElement private String name; - + /* * IP address of the pool member */ @XmlElement private String ip; - + /* * Name of the pool this member is attached to. */ @XmlElement(name="poolname") private String poolName; - + /* * Status (active/inactive) */ @XmlElement private String status; - + /** * Private constructor used for JAXB mapping */ @SuppressWarnings("unused") private PoolMember() {} - + public PoolMember(String name, String memberIP, String poolName){ this.name = name; this.ip = memberIP; this.poolName = poolName; } - + /** * @return the name */ public String getName() { return name; } - + /** * @param name the name to set */ public void setName(String name) { this.name = name; } - + /** * @return the ip */ public String getIp() { return ip; } - + /** * @param ip the ip to set */ public void setIp(String ip) { this.ip = ip; } - + /** * @return the poolName */ public String getPoolName() { return poolName; } - + /** * @param poolName the poolName to set */ public void setPoolName(String poolName) { this.poolName = poolName; } - + /** * @return the status */ public String getStatus() { return status; } - + /** * @param status the status to set */ public void setStatus(String status) { this.status = status; } - + /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @@ -134,7 +134,7 @@ public class PoolMember { + ((poolName == null) ? 0 : poolName.hashCode()); return result; } - + /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ diff --git a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/VIP.java b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/VIP.java index 6f866fe23f..22a7109f59 100644 --- a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/VIP.java +++ b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/entities/VIP.java @@ -18,47 +18,47 @@ import javax.xml.bind.annotation.XmlRootElement; * 1. IP address of the VIP exposed by the application * 2. Protocol of the network traffic (TCP/UDP) * 3. Port to which incoming traffic is destined - * - * User is allowed to create mutliple VIPs with the same IP, but all such VIPs (with the same IP) + * + * User is allowed to create mutliple VIPs with the same IP, but all such VIPs (with the same IP) * should differ at least in the protocol or port or both. - * + * * NOTE: Each VIP should have a unique name. */ @XmlRootElement(name="vip") @XmlAccessorType(XmlAccessType.NONE) public class VIP { - + /* * Unique name of the VIP */ @XmlElement private String name; - + /* - * Virtual IP address of the VIP + * Virtual IP address of the VIP */ @XmlElement private String ip; - + /* - * Network traffic protocol + * Network traffic protocol */ @XmlElement private String protocol; - + /* * Port where network traffic is destined (destination port) */ @XmlElement private short port; - + /* * Name of the pool attached to the VIP for load balancing its traffic */ @XmlElement(name="poolname") private String poolName; - + /* * Status (Active/inactive) */ @@ -70,7 +70,7 @@ public class VIP { */ @SuppressWarnings("unused") private VIP() {} - + public VIP(String name, String ip, String protocol, @@ -82,61 +82,61 @@ public class VIP { this.port = port; this.poolName = poolName; } - + public String getName() { return name; } - + public void setName(String name) { this.name = name; } - + public String getIp() { return ip; } - + public void setIp(String ip) { this.ip = ip; } - + public String getProtocol() { return protocol; } - + public void setProtocol(String protocol) { this.protocol = protocol; } - + public short getPort() { return port; } - + public void setPort(short port) { this.port = port; } - + public String getPoolName() { return poolName; } - + public void setPoolName(String poolName) { this.poolName = poolName; } - + /** * @return the status */ public String getStatus() { return status; } - + /** * @param status the status to set */ public void setStatus(String status) { this.status = status; } - + /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @@ -150,7 +150,7 @@ public class VIP { + ((protocol == null) ? 0 : protocol.hashCode()); return result; } - + /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @@ -158,7 +158,7 @@ public class VIP { public boolean equals(Object obj) { if (this == obj) { return true; - + } if (obj == null) { return false; @@ -166,7 +166,7 @@ public class VIP { if (!(obj instanceof VIP)) { return false; } - + VIP other = (VIP) obj; if (ip == null) { if (other.ip != null) { @@ -187,7 +187,7 @@ public class VIP { } return true; } - + /* (non-Javadoc) * @see java.lang.Object#toString() */ diff --git a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/internal/Activator.java b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/internal/Activator.java index 0568fced6e..fc78a72eaf 100644 --- a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/internal/Activator.java +++ b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/internal/Activator.java @@ -23,13 +23,13 @@ import org.opendaylight.controller.sal.routing.IRouting; import org.opendaylight.controller.samples.loadbalancer.IConfigManager; /** - * Main application activator class for registering the dependencies and + * Main application activator class for registering the dependencies and * initialising the load balancer application. * */ public class Activator extends ComponentActivatorAbstractBase { - + /* * Logger instance */ @@ -86,13 +86,13 @@ public class Activator extends ComponentActivatorAbstractBase { props.put("salListenerName", "loadbalancer"); c.setInterface(new String[] { IListenDataPacket.class.getName(), - IConfigManager.class.getName()}, props); + IConfigManager.class.getName()}, props); c.add(createContainerServiceDependency(containerName).setService( IDataPacketService.class).setCallbacks( "setDataPacketService", "unsetDataPacketService") .setRequired(true)); - + c.add(createContainerServiceDependency(containerName).setService( IRouting.class).setCallbacks("setRouting", "unsetRouting") .setRequired(false)); diff --git a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/internal/LoadBalancerService.java b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/internal/LoadBalancerService.java index ddfde38931..7eaa8b4ec0 100644 --- a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/internal/LoadBalancerService.java +++ b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/internal/LoadBalancerService.java @@ -56,78 +56,78 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * This class is the main class that represents the load balancer service. - * This is a sample load balancer application that balances traffic to backend servers - * based on the source address and source port on each incoming packet. The service + * This class is the main class that represents the load balancer service. + * This is a sample load balancer application that balances traffic to backend servers + * based on the source address and source port on each incoming packet. The service * reactively installs OpenFlow rules to direct all packets with a specific source address - * and source port to one of the appropriate backend servers. The servers may be chosen - * using a round robin policy or a random policy. This service can be configured via a + * and source port to one of the appropriate backend servers. The servers may be chosen + * using a round robin policy or a random policy. This service can be configured via a * REST APIs which are similar to the OpenStack Quantum LBaaS (Load-balancer-as-a-Service) * v1.0 API proposal (http://wiki.openstack.org/Quantum/LBaaS) - * + * * To use this service, a virtual IP (or VIP) should be exposed to the clients of this service * and used as the destination address. A VIP is a entity that comprises of a virtual IP, port * and protocol (TCP or UDP). * Assumptions: * 1. One or more VIPs may be mapped to the same server pool. All VIPs that share the same * pool must also share the same load balancing policy (random or round robin). - * + * * 2. Only one server pool can be be assigned to a VIP. - * + * * 3. All flow rules are installed with an idle timeout of 5 seconds. - * + * * 4. Packets to a VIP must leave the OpenFlow cluster from the same switch from where * it entered it. - * + * * 5. When you delete a VIP or a server pool or a server from a pool, the service does not * delete the flow rules it has already installed. The flow rules should automatically - * time out after the idle timeout of 5 seconds. + * time out after the idle timeout of 5 seconds. * */ public class LoadBalancerService implements IListenDataPacket, IConfigManager{ - + /* * Logger instance */ private static Logger lbsLogger = LoggerFactory.getLogger(LoadBalancerService.class); - + /* * Single instance of the configuration manager. Application passes this reference to all * the new policies implemented for load balancing. */ private static ConfigManager configManager = new ConfigManager(); - + /* * Round robing policy instance. Need to implement factory patterns to get * policy instance. */ private static RoundRobinLBPolicy rrLBMethod= new RoundRobinLBPolicy(configManager); - + /* * Random policy instance. */ private static RandomLBPolicy ranLBMethod= new RandomLBPolicy(configManager); - + /* * Reference to the data packet service */ private IDataPacketService dataPacketService = null; - + /* * Reference to the host tracker service */ private IfIptoHost hostTracker; - + /* * Reference to the forwarding manager */ private IForwardingRulesManager ruleManager; - + /* * Reference to the routing service */ private IRouting routing; - + /* * Load balancer application installs all flows with priority 2. */ @@ -139,7 +139,7 @@ public class LoadBalancerService implements IListenDataPacket, IConfigManager{ private String containerName = null; /* - * Set/unset methods for the service instance that load balancer + * Set/unset methods for the service instance that load balancer * service requires */ public String getContainerName() { @@ -147,7 +147,7 @@ public class LoadBalancerService implements IListenDataPacket, IConfigManager{ return GlobalConstants.DEFAULT.toString(); return containerName; } - + void setDataPacketService(IDataPacketService s) { this.dataPacketService = s; } @@ -157,7 +157,7 @@ public class LoadBalancerService implements IListenDataPacket, IConfigManager{ this.dataPacketService = null; } } - + public void setRouting(IRouting routing) { this.routing = routing; } @@ -169,7 +169,7 @@ public class LoadBalancerService implements IListenDataPacket, IConfigManager{ } public void setHostTracker(IfIptoHost hostTracker) { - lbsLogger.debug("Setting HostTracker"); + lbsLogger.debug("Setting HostTracker"); this.hostTracker = hostTracker; } @@ -181,7 +181,7 @@ public class LoadBalancerService implements IListenDataPacket, IConfigManager{ public void setForwardingRulesManager( IForwardingRulesManager forwardingRulesManager) { - lbsLogger.debug("Setting ForwardingRulesManager"); + lbsLogger.debug("Setting ForwardingRulesManager"); this.ruleManager = forwardingRulesManager; } @@ -194,68 +194,68 @@ public class LoadBalancerService implements IListenDataPacket, IConfigManager{ /** * This method receives first packet of flows for which there is no - * matching flow rule installed on the switch. IP addresses used for VIPs + * matching flow rule installed on the switch. IP addresses used for VIPs * are not supposed to be used by any real/virtual host in the network. * Hence, any forwarding/routing service will not install any flows rules matching * these VIPs. This ensures that all the flows destined for VIPs will not find a match * in the switch and will be forwarded to the load balancing service. - * Service will decide where to route this traffic based on the load balancing - * policy of the VIP's attached pool and will install appropriate flow rules - * in a reactive manner. + * Service will decide where to route this traffic based on the load balancing + * policy of the VIP's attached pool and will install appropriate flow rules + * in a reactive manner. */ @Override public PacketResult receiveDataPacket(RawPacket inPkt){ - + if (inPkt == null) { return PacketResult.IGNORED; } - + Packet formattedPak = this.dataPacketService.decodeDataPacket(inPkt); - + if (formattedPak instanceof Ethernet) { byte[] vipMacAddr = ((Ethernet) formattedPak).getDestinationMACAddress(); Object ipPkt = formattedPak.getPayload(); - + if (ipPkt instanceof IPv4) { - + lbsLogger.debug("Packet recieved from switch : {}",inPkt.getIncomingNodeConnector().getNode().toString()); IPv4 ipv4Pkt = (IPv4)ipPkt; if(IPProtocols.getProtocolName(ipv4Pkt.getProtocol()).equals(IPProtocols.TCP.toString()) || IPProtocols.getProtocolName(ipv4Pkt.getProtocol()).equals(IPProtocols.UDP.toString())){ - + lbsLogger.debug("Packet protocol : {}",IPProtocols.getProtocolName(ipv4Pkt.getProtocol())); Client client = new LBUtil().getClientFromPacket(ipv4Pkt); VIP vip = new LBUtil().getVIPFromPacket(ipv4Pkt); - + if(configManager.vipExists(vip)){ VIP vipWithPoolName = configManager.getVIPWithPoolName(vip); String poolMemberIp = null; if(configManager.getPool(vipWithPoolName.getPoolName()).getLbMethod().equalsIgnoreCase(LBConst.ROUND_ROBIN_LB_METHOD)){ - + poolMemberIp = rrLBMethod.getPoolMemberForClient(client,vipWithPoolName); } - + if(configManager.getPool(vipWithPoolName.getPoolName()).getLbMethod().equalsIgnoreCase(LBConst.RANDOM_LB_METHOD)){ poolMemberIp = ranLBMethod.getPoolMemberForClient(client,vipWithPoolName); } - + try { - + Node clientNode = inPkt.getIncomingNodeConnector().getNode(); HostNodeConnector hnConnector = this.hostTracker.hostFind(InetAddress.getByName(poolMemberIp)); - + Node destNode = hnConnector.getnodeconnectorNode(); - + lbsLogger.debug("Client is connected to switch : {}",clientNode.toString()); lbsLogger.debug("Destination pool machine is connected to switch : {}",destNode.toString()); - + //Get path between both the nodes Path route = this.routing.getRoute(clientNode, destNode); - + lbsLogger.info("Path between source (client) and destination switch nodes : {}",route.toString()); - + NodeConnector forwardPort = route.getEdges().get(0).getTailNodeConnector(); - + if(installLoadBalancerFlow(client, vip, clientNode, @@ -268,7 +268,7 @@ public class LoadBalancerService implements IListenDataPacket, IConfigManager{ }else{ lbsLogger.error("Not able to route traffic from client : {}",client ); } - + if(installLoadBalancerFlow(client, vip, clientNode, @@ -291,7 +291,7 @@ public class LoadBalancerService implements IListenDataPacket, IConfigManager{ } return PacketResult.IGNORED; } - + /* * This method installs the flow rule for routing the traffic between two hosts. * @param source Traffic is sent by this source @@ -301,21 +301,21 @@ public class LoadBalancerService implements IListenDataPacket, IConfigManager{ * @param destMachineMac MAC address of the pool member where traffic needs to be routed * @param outport Use this port to send out traffic * @param flowDirection FORWARD_DIRECTION_LB_FLOW or REVERSE_DIRECTION_LB_FLOW - * @return true If flow installation was successful - * false else + * @return true If flow installation was successful + * false else * @throws UnknownHostException */ private boolean installLoadBalancerFlow(Client source, VIP dest, Node sourceSwitch, String destMachineIp, - byte[] destMachineMac, + byte[] destMachineMac, NodeConnector outport, int flowDirection) throws UnknownHostException{ - + Match match = new Match(); List actions = new ArrayList(); - + if(flowDirection == LBConst.FORWARD_DIRECTION_LB_FLOW){ match.setField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue()); match.setField(MatchType.NW_SRC, InetAddress.getByName(source.getIp())); @@ -323,11 +323,11 @@ public class LoadBalancerService implements IListenDataPacket, IConfigManager{ match.setField(MatchType.NW_PROTO, IPProtocols.getProtocolNumberByte(dest.getProtocol())); match.setField(MatchType.TP_SRC, source.getPort()); match.setField(MatchType.TP_DST, dest.getPort()); - + actions.add(new SetNwDst(InetAddress.getByName(destMachineIp))); actions.add(new SetDlDst(destMachineMac)); } - + if(flowDirection == LBConst.REVERSE_DIRECTION_LB_FLOW){ match.setField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue()); match.setField(MatchType.NW_SRC, InetAddress.getByName(destMachineIp)); @@ -335,37 +335,37 @@ public class LoadBalancerService implements IListenDataPacket, IConfigManager{ match.setField(MatchType.NW_PROTO, IPProtocols.getProtocolNumberByte(source.getProtocol())); match.setField(MatchType.TP_SRC, dest.getPort()); match.setField(MatchType.TP_DST,source.getPort()); - + actions.add(new SetNwSrc(InetAddress.getByName(dest.getIp()))); actions.add(new SetDlSrc(destMachineMac)); } - + actions.add(new Output(outport)); - + // Make sure the priority for IP switch entries is // set to a level just above default drop entries - + Flow flow = new Flow(match, actions); flow.setIdleTimeout((short) 5); flow.setHardTimeout((short) 0); flow.setPriority(LB_IPSWITCH_PRIORITY); - + String policyName = source.getIp()+":"+source.getProtocol()+":"+source.getPort(); String flowName =null; - + if(flowDirection == LBConst.FORWARD_DIRECTION_LB_FLOW){ flowName = "["+policyName+":"+source.getIp() + ":"+dest.getIp()+"]"; } - + if(flowDirection == LBConst.REVERSE_DIRECTION_LB_FLOW){ - + flowName = "["+policyName+":"+dest.getIp() + ":"+source.getIp()+"]"; } - + FlowEntry fEntry = new FlowEntry(policyName, flowName, flow, sourceSwitch); - + lbsLogger.info("Install flow entry {} on node {}",fEntry.toString(),sourceSwitch.toString()); - + if(!this.ruleManager.checkFlowEntryConflict(fEntry)){ if(this.ruleManager.installFlowEntry(fEntry).isSuccess()){ return true; @@ -377,7 +377,7 @@ public class LoadBalancerService implements IListenDataPacket, IConfigManager{ } return false; } - + /** * Function called by the dependency manager when all the required * dependencies are satisfied @@ -387,16 +387,16 @@ public class LoadBalancerService implements IListenDataPacket, IConfigManager{ Dictionary props = c.getServiceProperties(); if (props != null) { this.containerName = (String) props.get("containerName"); - + lbsLogger.info("Running container name:" + this.containerName); }else { - + // In the Global instance case the containerName is empty this.containerName = ""; } lbsLogger.info(configManager.toString()); } - + /** * Function called by the dependency manager when at least one * dependency become unsatisfied or when the component is shutting @@ -426,106 +426,106 @@ public class LoadBalancerService implements IListenDataPacket, IConfigManager{ /* * All the methods below are just proxy methods to direct the REST API requests to configuration - * manager. We need this redirection as currently, opendaylight supports only one - * implementation of the service. + * manager. We need this redirection as currently, opendaylight supports only one + * implementation of the service. */ @Override public Set getAllVIPs() { return configManager.getAllVIPs(); } - + @Override public boolean vipExists(String name, String ip, String protocol, short protocolPort, String poolName) { return configManager.vipExists(name, ip, protocol, protocolPort, poolName); } - + @Override public boolean vipExists(VIP vip) { return configManager.vipExists(vip); } - + @Override public VIP createVIP(String name, String ip, String protocol, short protocolPort, String poolName) { return configManager.createVIP(name, ip, protocol, protocolPort, poolName); } - + @Override public VIP updateVIP(String name, String poolName) { return configManager.updateVIP(name, poolName); } - + @Override public VIP deleteVIP(String name) { return configManager.deleteVIP(name); } - + @Override public boolean memberExists(String name, String memberIP, String poolName) { return configManager.memberExists(name, memberIP, poolName); } - + @Override public Set getAllPoolMembers(String poolName) { - + return configManager.getAllPoolMembers(poolName); } - + @Override - public PoolMember addPoolMember(String name, + public PoolMember addPoolMember(String name, String memberIP, String poolName) { return configManager.addPoolMember(name, memberIP, poolName); } - + @Override public PoolMember removePoolMember(String name, String poolName) { - + return configManager.removePoolMember(name, poolName); } - + @Override public Set getAllPools() { - + return configManager.getAllPools(); } - + @Override public Pool getPool(String poolName) { return configManager.getPool(poolName); } - + @Override public boolean poolExists(String name, String lbMethod) { return configManager.poolExists(name, lbMethod); } - + @Override public Pool createPool(String name, String lbMethod) { return configManager.createPool(name, lbMethod); } - + @Override public Pool deletePool(String poolName) { return configManager.deletePool(poolName); } - + @Override public boolean vipExists(String name) { return configManager.vipExists(name); } - + @Override public boolean memberExists(String name, String poolName) { return configManager.memberExists(name, poolName); } - + @Override public boolean poolExists(String name) { return configManager.poolExists(name); } - + @Override public String getVIPAttachedPool(String name) { return configManager.getVIPAttachedPool(name); diff --git a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/policies/ILoadBalancingPolicy.java b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/policies/ILoadBalancingPolicy.java index d69c63c200..f9562d6c52 100644 --- a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/policies/ILoadBalancingPolicy.java +++ b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/policies/ILoadBalancingPolicy.java @@ -14,16 +14,16 @@ import org.opendaylight.controller.samples.loadbalancer.entities.VIP; * All new load balancer policies must implement this interface. */ public interface ILoadBalancingPolicy { - + /** * Returns IP address of the next pool member from the pool * to which the load balancer service can direct incoming packets. * @param source source on the packet * @param dest virtual IP (VIP) that is used as destination on the packet - * @return IP address of the next pool member which will serve + * @return IP address of the next pool member which will serve * all incoming traffic destined for the given VIP and with the given source * information */ public String getPoolMemberForClient(Client source, VIP dest); - + } \ No newline at end of file diff --git a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/policies/RandomLBPolicy.java b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/policies/RandomLBPolicy.java index b4b616f3a8..ba5d5babb6 100644 --- a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/policies/RandomLBPolicy.java +++ b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/policies/RandomLBPolicy.java @@ -24,31 +24,31 @@ import org.slf4j.LoggerFactory; * */ public class RandomLBPolicy implements ILoadBalancingPolicy { - + /* * Instance logger */ private static final Logger rLogger = LoggerFactory.getLogger(RandomLBPolicy.class); - + /* - * Reference to the configuration manager. This reference is passed from load balancer + * Reference to the configuration manager. This reference is passed from load balancer * class. */ private ConfigManager cmgr; - + /* * Mapping between the client and the pool member that serves all traffic for that client. */ private HashMap clientMemberMap; - + /* * Random generator */ Random randomGenerator = null; - + @SuppressWarnings("unused") private RandomLBPolicy(){} - + public RandomLBPolicy(ConfigManager cmgr){ this.cmgr = cmgr; this.clientMemberMap = new HashMap(); @@ -56,13 +56,13 @@ public class RandomLBPolicy implements ILoadBalancingPolicy { } @Override public String getPoolMemberForClient(Client source, VIP dest){ - + rLogger.info("Received traffic from client : {} for VIP : {} ",source, dest); - + syncWithLoadBalancerData(); - + PoolMember pm= null; - + if(this.clientMemberMap.containsKey(source)){ pm= this.clientMemberMap.get(source); rLogger.info("Client {} had sent traffic before,new traffic will be routed to the same pool member {}",source,pm); @@ -76,7 +76,7 @@ public class RandomLBPolicy implements ILoadBalancingPolicy { } return pm.getIp(); } - + /* * This method does the clean up. Whenever a new client packet arrives with a given VIP, * this method checks the current configuration to see if any pool members have been deleted and @@ -84,25 +84,25 @@ public class RandomLBPolicy implements ILoadBalancingPolicy { */ private void syncWithLoadBalancerData(){ rLogger.debug("[Client - PoolMember] table before cleanup : {}",this.clientMemberMap.toString()); - + ArrayList removeClient = new ArrayList(); - + if(this.clientMemberMap.size() != 0){ for(Client client : this.clientMemberMap.keySet()){ - + if(!this.cmgr.memberExists(this.clientMemberMap.get(client).getName(), this.clientMemberMap.get(client).getPoolName())){ removeClient.add(client); } } } - + for(Client client : removeClient){ this.clientMemberMap.remove(client); - + rLogger.debug("Removed client : {} ",client); } rLogger.debug("[Client - PoolMember] table after cleanup : {}",this.clientMemberMap.toString()); } - + } diff --git a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/policies/RoundRobinLBPolicy.java b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/policies/RoundRobinLBPolicy.java index f1011dddc5..c8687883e7 100644 --- a/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/policies/RoundRobinLBPolicy.java +++ b/opendaylight/samples/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/policies/RoundRobinLBPolicy.java @@ -23,23 +23,23 @@ import org.slf4j.LoggerFactory; * */ public class RoundRobinLBPolicy implements ILoadBalancingPolicy{ - + /* * Logger instance */ private static final Logger rrLogger = LoggerFactory.getLogger(RoundRobinLBPolicy.class); - + /* - * Reference to the configuration manager. This reference is passed from load balancer + * Reference to the configuration manager. This reference is passed from load balancer * class. */ private ConfigManager cmgr; - + /* * Mapping between the client and the pool member that serves all traffic for that client. */ private HashMap clientMemberMap; - + /* * Maintains the next pool member counter for the VIPs. * More than one VIP can be attached to one pool, so each VIP @@ -47,34 +47,34 @@ public class RoundRobinLBPolicy implements ILoadBalancingPolicy{ * the same pool. */ private HashMap nextItemFromPool; - + @SuppressWarnings("unused") private RoundRobinLBPolicy(){} - + public RoundRobinLBPolicy(ConfigManager cmgr){ this.cmgr = cmgr; this.clientMemberMap = new HashMap(); this.nextItemFromPool = new HashMap(); } - + @Override public String getPoolMemberForClient(Client source, VIP dest){ - + rrLogger.info("Received traffic from client : {} for VIP : {} ",source, dest); - + syncWithLoadBalancerData(); - + PoolMember pm= null; - + if(this.clientMemberMap.containsKey(source)){ - + pm= this.clientMemberMap.get(source); rrLogger.info("Client {} had sent traffic before,new traffic will be routed to the same pool member {}",source,pm); }else{ - + Pool pool = null; if(nextItemFromPool.containsKey(dest)){ - + int memberNum = nextItemFromPool.get(dest).intValue(); rrLogger.debug("Packet is from new client for VIP {}",dest); pool = this.cmgr.getPool(dest.getPoolName()); @@ -82,19 +82,19 @@ public class RoundRobinLBPolicy implements ILoadBalancingPolicy{ this.clientMemberMap.put(source, pm ); rrLogger.info("New client's packet will be directed to pool member {}",pm); memberNum++; - + if(memberNum > pool.getAllMembers().size()-1){ memberNum = 0; } rrLogger.debug("Next pool member for new client of VIP is set to {}",pool.getAllMembers().get(memberNum)); - + this.nextItemFromPool.put(dest, new Integer(memberNum)); }else{ rrLogger.debug("Network traffic for VIP : {} has appeared first time from client {}",dest,source); pool = this.cmgr.getPool(dest.getPoolName()); pm = pool.getAllMembers().get(0); this.clientMemberMap.put(source, pm); - + rrLogger.info("Network traffic from client {} will be directed to pool member {}",pm); this.nextItemFromPool.put(dest, new Integer(1)); rrLogger.debug("Next pool member for new client of VIP is set to {}",pool.getAllMembers().get(1)); @@ -102,7 +102,7 @@ public class RoundRobinLBPolicy implements ILoadBalancingPolicy{ } return pm.getIp(); } - + /* * This method does the clean up. Whenever a new client packet arrives with a given VIP, * this method checks the current configuration to see if any pool members have been deleted and @@ -111,43 +111,43 @@ public class RoundRobinLBPolicy implements ILoadBalancingPolicy{ private void syncWithLoadBalancerData(){ rrLogger.debug("[Client - PoolMember] table before cleanup : {}",this.clientMemberMap.toString()); ArrayList removeClient = new ArrayList(); - + if(this.clientMemberMap.size() != 0){ for(Client client : this.clientMemberMap.keySet()){ if(!this.cmgr.memberExists(this.clientMemberMap.get(client).getName(), this.clientMemberMap.get(client).getPoolName())){ - + removeClient.add(client); } } } - + for(Client client : removeClient){ this.clientMemberMap.remove(client); - + rrLogger.debug("Removed client : {} ",client); } rrLogger.debug("[Client - PoolMember] table after cleanup : {}",this.clientMemberMap.toString()); - + rrLogger.debug("[VIP- NextMember] table before cleanup : {}",this.nextItemFromPool.toString()); - + ArrayList resetVIPPoolMemberCount= new ArrayList(); - + if(this.nextItemFromPool.size() != 0){ - + for(VIP vip:this.nextItemFromPool.keySet()){ if(this.nextItemFromPool.get(vip).intValue() > this.cmgr.getPool(vip.getPoolName()).getAllMembers().size()-1){ - + resetVIPPoolMemberCount.add(vip); } } } - + for(VIP vip:resetVIPPoolMemberCount){ rrLogger.debug("VIP next pool member counter reset to 0"); this.nextItemFromPool.put(vip, new Integer(0)); } - + rrLogger.debug("[VIP- NextMember] table after cleanup : {}",this.nextItemFromPool.toString()); } } diff --git a/opendaylight/samples/loadbalancer/src/test/java/org/opendaylight/controller/samples/loadbalancer/internal/LoadBalancerTest.java b/opendaylight/samples/loadbalancer/src/test/java/org/opendaylight/controller/samples/loadbalancer/internal/LoadBalancerTest.java index f8633b9ef8..45d041c3e1 100644 --- a/opendaylight/samples/loadbalancer/src/test/java/org/opendaylight/controller/samples/loadbalancer/internal/LoadBalancerTest.java +++ b/opendaylight/samples/loadbalancer/src/test/java/org/opendaylight/controller/samples/loadbalancer/internal/LoadBalancerTest.java @@ -20,7 +20,7 @@ import org.opendaylight.controller.samples.loadbalancer.policies.RoundRobinLBPol import junit.framework.TestCase; /** - * + * * Class to unit test the load balancing policies. * */ @@ -30,7 +30,7 @@ public class LoadBalancerTest extends TestCase { ConfigManager cm = null; cm = new ConfigManager(); Assert.assertFalse(cm== null); - + Pool pool = cm.createPool("TestPool","roundrobin"); VIP vip = cm.createVIP("TestVIP","10.0.0.9","TCP",(short)5550,"TestPool"); PoolMember host1 = new PoolMember("host1","10.0.0.1","TestPool"); @@ -40,7 +40,7 @@ public class LoadBalancerTest extends TestCase { PoolMember host5 = new PoolMember("host5","10.0.0.5","TestPool"); PoolMember host6 = new PoolMember("host6","10.0.0.6","TestPool"); PoolMember host7 = new PoolMember("host7","10.0.0.7","TestPool"); - + pool.addMember(host1); pool.addMember(host2); pool.addMember(host3); @@ -49,20 +49,20 @@ public class LoadBalancerTest extends TestCase { pool.addMember(host6); pool.addMember(host7); pool.addVIP(vip); - + Assert.assertTrue(cm.getAllPoolMembers("TestPool").size() == pool.getAllMembers().size()); - + RoundRobinLBPolicy rrp = new RoundRobinLBPolicy(cm); - + Client c1 = new Client("10.0.0.1","TCP",(short)5000); Assert.assertTrue(rrp.getPoolMemberForClient(c1, vip).equals(host1.getIp())); - + c1 = new Client("10.0.0.1","TCP",(short)5001); Assert.assertTrue(rrp.getPoolMemberForClient(c1, vip).equals(host2.getIp())); - + c1 = new Client("10.0.0.1","TCP",(short)5002); Assert.assertTrue(rrp.getPoolMemberForClient(c1, vip).equals(host3.getIp())); - + c1 = new Client("10.0.0.1","TCP",(short)5003); Assert.assertTrue(rrp.getPoolMemberForClient(c1, vip).equals(host4.getIp())); } diff --git a/opendaylight/samples/northbound/loadbalancer/enunciate.xml b/opendaylight/samples/northbound/loadbalancer/enunciate.xml index e666af7e51..13ec7ca5ec 100644 --- a/opendaylight/samples/northbound/loadbalancer/enunciate.xml +++ b/opendaylight/samples/northbound/loadbalancer/enunciate.xml @@ -1,7 +1,7 @@ - + diff --git a/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/LoadBalancerNorthbound.java b/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/LoadBalancerNorthbound.java index 4ec567c95b..8ea0d78360 100644 --- a/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/LoadBalancerNorthbound.java +++ b/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/LoadBalancerNorthbound.java @@ -41,38 +41,38 @@ import org.opendaylight.controller.samples.loadbalancer.IConfigManager; /** * This class exposes North bound REST APIs for the Load Balancer Service. * Following APIs are exposed by the Load Balancer Service: - * + * * Data retrieval REST APIs:: - * 1. Get details of all existing pools - * Type : GET - * URI : /one/nb/v2/lb/{container-name}/ - * NOTE: Current implementation of the opendaylight usage 'default' as a container-name - * e.g : http://localhost:8080/one/nb/v2/lb/default will give you list of all the pools - * - * 2. Get details of all the existing VIPs - * Type : GET - * URI: /one/nb/v2/lb/{container-name}/vips - * + * 1. Get details of all existing pools + * Type : GET + * URI : /one/nb/v2/lb/{container-name}/ + * NOTE: Current implementation of the opendaylight usage 'default' as a container-name + * e.g : http://localhost:8080/one/nb/v2/lb/default will give you list of all the pools + * + * 2. Get details of all the existing VIPs + * Type : GET + * URI: /one/nb/v2/lb/{container-name}/vips + * * Pool related REST APIs:: - * 1. Create Pool : - * Type : POST - * URI : /one/nb/v2/lb/{container-name}/create/pool - * Request body : + * 1. Create Pool : + * Type : POST + * URI : /one/nb/v2/lb/{container-name}/create/pool + * Request body : * { * "name":"", * "lbmethod":"" * } - * Currently, two load balancing policies are allowed {"roundrobin" and "random" } - * - * 2. Delete Pool : - * Type : DELETE - * URI : /one/nb/v2/lb/{container-name}/delete/pool/{pool-name} - * + * Currently, two load balancing policies are allowed {"roundrobin" and "random" } + * + * 2. Delete Pool : + * Type : DELETE + * URI : /one/nb/v2/lb/{container-name}/delete/pool/{pool-name} + * * VIP related REST APIs:: - * 1. Create VIP: - * Type : POST - * URI : /one/nb/v2/lb/{container-name}/create/vip - * Request body : + * 1. Create VIP: + * Type : POST + * URI : /one/nb/v2/lb/{container-name}/create/vip + * Request body : * { * "name":"", * "ip":"ip in (xxx.xxx.xxx.xxx) format", @@ -80,12 +80,12 @@ import org.opendaylight.controller.samples.loadbalancer.IConfigManager; * "port":"any valid port number", * "poolname":"" (optional) * } - * The pool name is optional and can be set up at a later stage (using the REST API given below). - * - * 2. Update VIP: Update pool name of the VIP - * Type : PUT - * URI : /one/nb/v2/lb/{container-name}/update/vip - * Request body : + * The pool name is optional and can be set up at a later stage (using the REST API given below). + * + * 2. Update VIP: Update pool name of the VIP + * Type : PUT + * URI : /one/nb/v2/lb/{container-name}/update/vip + * Request body : * { * "name":"", * "poolname":"" @@ -94,34 +94,34 @@ import org.opendaylight.controller.samples.loadbalancer.IConfigManager; * and not of the VIP name itself. * The specified pool name must already exist. If the specified VIP is already attached to a pool, the update * will fail. - * - * 3. Delete VIP : - * Type : DELETE - * URI : /one/nb/v2/lb/{container-name}/delete/vip/{vip-name} - * + * + * 3. Delete VIP : + * Type : DELETE + * URI : /one/nb/v2/lb/{container-name}/delete/vip/{vip-name} + * * Pool member related REST APIs:: - * 1. Create pool member: - * Type : POST - * URI : /one/nb/v2/lb/default/create/poolmember - * Request body : + * 1. Create pool member: + * Type : POST + * URI : /one/nb/v2/lb/default/create/poolmember + * Request body : * { * "name":"", * "ip":"ip in (xxx.xxx.xxx.xxx) format", * "poolname":"existing pool name" * } - * - * 2. Delete pool member: - * Type : DELETE - * URI : /one/nb/v2/lb/{container-name}/delete/poolmember/{pool-member-name}/{pool-name} - * - * NOTE: Property "name" of each individual entity must be unique. - * All the above REST APIs throw appropriate response codes in case of error/success. - * Please consult the respective methods to get details of various response codes. + * + * 2. Delete pool member: + * Type : DELETE + * URI : /one/nb/v2/lb/{container-name}/delete/poolmember/{pool-member-name}/{pool-name} + * + * NOTE: Property "name" of each individual entity must be unique. + * All the above REST APIs throw appropriate response codes in case of error/success. + * Please consult the respective methods to get details of various response codes. */ @Path("/") public class LoadBalancerNorthbound { - + /* * Method returns the Load balancer service instance running within * 'default' container. @@ -148,7 +148,7 @@ public class LoadBalancerNorthbound { } IConfigManager configManager = (IConfigManager) ServiceHelper.getInstance( - IConfigManager.class, containerName, this); + IConfigManager.class, containerName, this); if (configManager == null) { throw new ServiceUnavailableException("Load Balancer" @@ -168,13 +168,13 @@ public class LoadBalancerNorthbound { @ResponseCode(code = 503, condition = "Load balancer service is unavailable") }) public Pools getAllPools( @PathParam("containerName") String containerName) { - + IConfigManager configManager = getConfigManagerService(containerName); if (configManager == null) { throw new ServiceUnavailableException("Load Balancer " + RestMessages.SERVICEUNAVAILABLE.toString()); } - + return new Pools(configManager.getAllPools()); } @@ -188,7 +188,7 @@ public class LoadBalancerNorthbound { @ResponseCode(code = 503, condition = "Load balancer service is unavailable") }) public VIPs getAllVIPs( @PathParam("containerName") String containerName) { - + IConfigManager configManager = getConfigManagerService(containerName); if (configManager == null) { throw new ServiceUnavailableException("Load Balancer " @@ -209,7 +209,7 @@ public class LoadBalancerNorthbound { @ResponseCode(code = 415, condition = "Invalid input data")}) public Response addVIP(@PathParam("containerName") String containerName, @TypeHint(VIP.class) JAXBElement inVIP){ - + VIP vipInput = inVIP.getValue(); String name = vipInput.getName(); String ip = vipInput.getIp(); @@ -222,16 +222,16 @@ public class LoadBalancerNorthbound { protocolPort < 0 ){ throw new UnsupportedMediaTypeException(RestMessages.INVALIDDATA.toString()); } - + IConfigManager configManager = getConfigManagerService(containerName); - + if (configManager == null) { throw new ServiceUnavailableException("Load Balancer " + RestMessages.SERVICEUNAVAILABLE.toString()); } - + if(!configManager.vipExists(name, ip, protocol, protocolPort, poolName)){ - + VIP vip = configManager.createVIP(name, ip, protocol, protocolPort, poolName); if ( vip != null){ return Response.status(Response.Status.CREATED).build(); @@ -254,7 +254,7 @@ public class LoadBalancerNorthbound { @ResponseCode(code = 415, condition = "Invalid input name")}) public Response updateVIP(@PathParam("containerName") String containerName, @TypeHint(VIP.class) JAXBElement inVIP) { - + VIP vipInput = inVIP.getValue(); String name = vipInput.getName(); String poolName = vipInput.getPoolName(); @@ -262,25 +262,25 @@ public class LoadBalancerNorthbound { poolName.isEmpty()){ throw new UnsupportedMediaTypeException(RestMessages.INVALIDDATA.toString()); } - + IConfigManager configManager = getConfigManagerService(containerName); if (configManager == null) { throw new ServiceUnavailableException("Load Balancer " + RestMessages.SERVICEUNAVAILABLE.toString()); } - + if(!configManager.poolExists(poolName)) throw new ResourceNotFoundException(NBConst.RES_POOL_NOT_FOUND); - + if(configManager.getVIPAttachedPool(name)!=null) throw new MethodNotAllowedException(NBConst.RES_VIP_POOL_EXIST); - + if(configManager.updateVIP(name, poolName)!= null) return Response.status(Response.Status.ACCEPTED).build(); - + throw new InternalServerErrorException(NBConst.RES_VIP_UPDATE_FAILED); } - + @Path("/{containerName}/delete/vip/{vipName}") @DELETE @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @@ -293,19 +293,19 @@ public class LoadBalancerNorthbound { public Response deleteVIP( @PathParam(value = "containerName") String containerName, @PathParam(value = "vipName") String vipName) { - + if(vipName.isEmpty()) throw new UnsupportedMediaTypeException(RestMessages.INVALIDDATA.toString()); - + IConfigManager configManager = getConfigManagerService(containerName); if (configManager == null) { throw new ServiceUnavailableException("Load Balancer" + RestMessages.SERVICEUNAVAILABLE.toString()); } - + if(!configManager.vipExists(vipName)) throw new ResourceNotFoundException(NBConst.RES_VIP_NOT_FOUND); - + for(VIP vip : configManager.getAllVIPs()){ if(vip.getName().equals(vipName)){ configManager.deleteVIP(vipName); @@ -326,7 +326,7 @@ public class LoadBalancerNorthbound { @ResponseCode(code = 415, condition = "Invalid input data")}) public Response addPool(@PathParam("containerName") String containerName, @TypeHint(Pool.class) JAXBElement inPool) { - + Pool poolInput = inPool.getValue(); String name = poolInput.getName(); String lbMethod =poolInput.getLbMethod(); @@ -334,15 +334,15 @@ public class LoadBalancerNorthbound { lbMethod.isEmpty()){ throw new UnsupportedMediaTypeException(RestMessages.INVALIDDATA.toString()); } - + IConfigManager configManager = getConfigManagerService(containerName); if (configManager == null) { throw new ServiceUnavailableException("Load Balancer " + RestMessages.SERVICEUNAVAILABLE.toString()); } - + if(!configManager.poolExists(name)){ - + Pool pool = configManager.createPool(name, lbMethod); if ( pool != null){ return Response.status(Response.Status.CREATED).build(); @@ -365,19 +365,19 @@ public class LoadBalancerNorthbound { public Response deletePool( @PathParam(value = "containerName") String containerName, @PathParam(value = "poolName") String poolName) { - + if(poolName.isEmpty()) throw new UnsupportedMediaTypeException(RestMessages.INVALIDDATA.toString()); - + IConfigManager configManager = getConfigManagerService(containerName); if (configManager == null) { throw new ServiceUnavailableException("Load Balancer" + RestMessages.SERVICEUNAVAILABLE.toString()); } - + if(!configManager.poolExists(poolName)) throw new ResourceNotFoundException(NBConst.RES_POOL_NOT_FOUND); - + for(Pool pool:configManager.getAllPools()){ if(pool.getName().equals(poolName)){ configManager.deletePool(poolName); @@ -399,37 +399,37 @@ public class LoadBalancerNorthbound { @ResponseCode(code = 415, condition = "Invalid input data")}) public Response addPoolMember(@PathParam("containerName") String containerName, @TypeHint(PoolMember.class) JAXBElement inPoolMember){ - + PoolMember pmInput = inPoolMember.getValue(); - String name = pmInput.getName(); - String memberIP = pmInput.getIp(); - String poolName = pmInput.getPoolName(); - - if(name.isEmpty() || - memberIP.isEmpty()|| - poolName.isEmpty()){ - throw new UnsupportedMediaTypeException(RestMessages.INVALIDDATA.toString()); - } - - IConfigManager configManager = getConfigManagerService(containerName); - if (configManager == null) { - throw new ServiceUnavailableException("Load Balancer " - + RestMessages.SERVICEUNAVAILABLE.toString()); - } - - if(!configManager.poolExists(poolName)) - throw new ResourceNotFoundException(NBConst.RES_POOL_NOT_FOUND); - - if(!configManager.memberExists(name, memberIP, poolName)){ - - PoolMember poolMember = configManager.addPoolMember(name, memberIP, poolName); - if ( poolMember != null){ - return Response.status(Response.Status.CREATED).build(); - } - }else{ - throw new ResourceConflictException(NBConst.RES_POOLMEMBER_ALREADY_EXIST); - } - throw new InternalServerErrorException(NBConst.RES_POOLMEMBER_CREATION_FAILED); + String name = pmInput.getName(); + String memberIP = pmInput.getIp(); + String poolName = pmInput.getPoolName(); + + if(name.isEmpty() || + memberIP.isEmpty()|| + poolName.isEmpty()){ + throw new UnsupportedMediaTypeException(RestMessages.INVALIDDATA.toString()); + } + + IConfigManager configManager = getConfigManagerService(containerName); + if (configManager == null) { + throw new ServiceUnavailableException("Load Balancer " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + if(!configManager.poolExists(poolName)) + throw new ResourceNotFoundException(NBConst.RES_POOL_NOT_FOUND); + + if(!configManager.memberExists(name, memberIP, poolName)){ + + PoolMember poolMember = configManager.addPoolMember(name, memberIP, poolName); + if ( poolMember != null){ + return Response.status(Response.Status.CREATED).build(); + } + }else{ + throw new ResourceConflictException(NBConst.RES_POOLMEMBER_ALREADY_EXIST); + } + throw new InternalServerErrorException(NBConst.RES_POOLMEMBER_CREATION_FAILED); } @Path("/{containerName}/delete/poolmember/{poolMemberName}/{poolName}") @@ -445,25 +445,25 @@ public class LoadBalancerNorthbound { @PathParam(value = "containerName") String containerName, @PathParam(value = "poolMemberName") String poolMemberName, @PathParam(value = "poolName") String poolName) { - + if(poolMemberName.isEmpty()|| poolName.isEmpty()) throw new UnsupportedMediaTypeException(RestMessages.INVALIDDATA.toString()); - + IConfigManager configManager = getConfigManagerService(containerName); - + if (configManager == null) { throw new ServiceUnavailableException("Load Balancer" + RestMessages.SERVICEUNAVAILABLE.toString()); } - + if(!configManager.poolExists(poolName)) throw new ResourceNotFoundException(NBConst.RES_POOL_NOT_FOUND); - + if(configManager.memberExists(poolMemberName, poolName)){ - + configManager.removePoolMember(poolMemberName, poolName); - + return Response.ok().build(); } throw new ResourceNotFoundException(NBConst.RES_POOLMEMBER_NOT_FOUND); diff --git a/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/NBConst.java b/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/NBConst.java index 4aa4705a53..a5d2091470 100644 --- a/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/NBConst.java +++ b/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/NBConst.java @@ -12,32 +12,32 @@ package org.opendaylight.controller.samples.loadbalancer.northbound; * */ public class NBConst { - + public static final String RES_VIP_ALREADY_EXIST= " VIP already exists"; - + public static final String RES_VIP_NOT_FOUND= " VIP not found"; - + public static final String RES_VIP_CREATION_FAILED = " Creation of VIP failed"; - + public static final String RES_VIP_DELETION_FAILED = " Deletion of VIP failed"; - + public static final String RES_VIP_UPDATE_FAILED = " Update of VIP failed"; - + public static final String RES_POOL_ALREADY_EXIST= " Pool already exists"; - + public static final String RES_POOL_NOT_FOUND= " Pool not found"; - + public static final String RES_POOL_CREATION_FAILED = " Creation of pool failed"; - + public static final String RES_POOL_DELETION_FAILED = " Deletion of pool failed"; - + public static final String RES_POOLMEMBER_ALREADY_EXIST= " Pool member already exists"; - + public static final String RES_POOLMEMBER_NOT_FOUND= " Pool member not found"; - + public static final String RES_POOLMEMBER_CREATION_FAILED = " Creation of pool member failed"; - + public static final String RES_POOLMEMBER_DELETION_FAILED = " Deletion of pool member failed"; - + public static final String RES_VIP_POOL_EXIST = "Pool already attached to a VIP"; } diff --git a/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/Pools.java b/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/Pools.java index abb5495cbf..74be568018 100644 --- a/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/Pools.java +++ b/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/Pools.java @@ -19,29 +19,29 @@ import org.opendaylight.controller.samples.loadbalancer.entities.Pool; @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) /** - * JAX-RS resource for handling details of all the available pools + * JAX-RS resource for handling details of all the available pools * in response to respective REST API requests. */ public class Pools { - + @XmlElement (name="pool") Set loadBalancerPools; - + public Pools() { } - + public Pools (Set loadBalancerPools) { this.loadBalancerPools = loadBalancerPools; } - + /** * @return the loadBalancerPools */ public Set getLoadBalancerPools() { return loadBalancerPools; } - + /** * @param loadBalancerPools the loadBalancerPools to set */ diff --git a/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/VIPs.java b/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/VIPs.java index f0af929b39..66a20338ab 100644 --- a/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/VIPs.java +++ b/opendaylight/samples/northbound/loadbalancer/src/main/java/org/opendaylight/controller/samples/loadbalancer/northbound/VIPs.java @@ -25,28 +25,28 @@ import org.opendaylight.controller.samples.loadbalancer.entities.VIP; @XmlAccessorType(XmlAccessType.NONE) public class VIPs { - + @XmlElement (name="vip") Set loadBalancerVIPs; - + public VIPs() {} - - + + public VIPs (Set loadBalancerVIPs) { this.loadBalancerVIPs = loadBalancerVIPs; } - + /** * @return the loadBalancerVIPs */ public Set getLoadBalancerVIPs() { return loadBalancerVIPs; } - + /** * @param loadBalancerVIPs the loadBalancerVIPs to set */ - + public void setLoadBalancerVIPs(Set loadBalancerVIPs) { this.loadBalancerVIPs = loadBalancerVIPs; } diff --git a/opendaylight/samples/northbound/loadbalancer/src/main/resources/WEB-INF/web.xml b/opendaylight/samples/northbound/loadbalancer/src/main/resources/WEB-INF/web.xml index 365e4b22d6..aac4647de6 100644 --- a/opendaylight/samples/northbound/loadbalancer/src/main/resources/WEB-INF/web.xml +++ b/opendaylight/samples/northbound/loadbalancer/src/main/resources/WEB-INF/web.xml @@ -1,7 +1,7 @@ + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" + version="3.0"> JAXRSLoadBalancer com.sun.jersey.spi.container.servlet.ServletContainer @@ -17,34 +17,34 @@ /* - - - NB api - /* - - - System-Admin - Network-Admin - Network-Operator - Container-User - - + + + NB api + /* + + + System-Admin + Network-Admin + Network-Operator + Container-User + + - - System-Admin - - - Network-Admin - - - Network-Operator - - - Container-User - + + System-Admin + + + Network-Admin + + + Network-Operator + + + Container-User + - - BASIC - opendaylight - + + BASIC + opendaylight + diff --git a/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleForwardingImpl.java b/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleForwardingImpl.java index c2fee970ac..11056478db 100644 --- a/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleForwardingImpl.java +++ b/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleForwardingImpl.java @@ -147,7 +147,7 @@ public class SimpleForwardingImpl implements IfNewHostNotify, } @SuppressWarnings("deprecation") - private void allocateCaches() { + private void allocateCaches() { if (this.clusterContainerService == null) { log.info("un-initialized clusterContainerService, can't create cache"); return; @@ -178,7 +178,7 @@ public class SimpleForwardingImpl implements IfNewHostNotify, } @SuppressWarnings("deprecation") - private void destroyCaches() { + private void destroyCaches() { if (this.clusterContainerService == null) { log.info("un-initialized clusterContainerService, can't destroy cache"); return; @@ -367,7 +367,7 @@ public class SimpleForwardingImpl implements IfNewHostNotify, } } else { - log.debug("Adding policyMatch(DIP = {}) Action(outPort= {}) " + + log.debug("Adding policyMatch(DIP = {}) Action(outPort= {}) " + "to node {}", new Object[] { host.getNetworkAddress().getHostAddress(), outPort, currNode}); @@ -482,7 +482,7 @@ public class SimpleForwardingImpl implements IfNewHostNotify, updatePerHostRuleInSW(host, rootNode, rootNode, null, new HostNodePair( host, rootNode), ports); - // log.debug("Getting out at the end!"); + // log.debug("Getting out at the end!"); return switchesToProgram; } @@ -575,10 +575,10 @@ public class SimpleForwardingImpl implements IfNewHostNotify, // rest of the world // switchesToProgram.add(rootNode); //updatePerHostRuleInSW(host, rootNode, - // rootNode, null, - // new HostNodePair(host, rootNode),ports); + // rootNode, null, + // new HostNodePair(host, rootNode),ports); - // log.debug("Getting out at the end!"); + // log.debug("Getting out at the end!"); return switchesToProgram; } @@ -617,7 +617,7 @@ public class SimpleForwardingImpl implements IfNewHostNotify, Status poStatus = this.frm.installFlowEntry(po); if (!poStatus.isSuccess()) { log.error("Failed to install policy: " - + po.getGroupName() + " (" + + po.getGroupName() + " (" + poStatus.getDescription() + ")"); retCode = RulesProgrammingReturnCode.FAILED_FEW_SWITCHES; @@ -632,8 +632,8 @@ public class SimpleForwardingImpl implements IfNewHostNotify, swId, host); /* // Now dump every single rule */ /* for (HostNodePair dumpkey : this.rulesDB.keySet()) { */ - /* po = this.rulesDB.get(dumpkey); */ - /* log.debug("Dumping entry H{" + dumpkey.getHost() + "} S{" + dumpkey.getSwitchId() + "} = {" + (po == null ? "null policy" : po)); */ + /* po = this.rulesDB.get(dumpkey); */ + /* log.debug("Dumping entry H{" + dumpkey.getHost() + "} S{" + dumpkey.getSwitchId() + "} = {" + (po == null ? "null policy" : po)); */ /* } */ } } diff --git a/opendaylight/statisticsmanager/api/pom.xml b/opendaylight/statisticsmanager/api/pom.xml index 7ee475ed2b..1bf1c7ca74 100644 --- a/opendaylight/statisticsmanager/api/pom.xml +++ b/opendaylight/statisticsmanager/api/pom.xml @@ -29,7 +29,7 @@ org.apache.felix.dm - org.opendaylight.controller.statisticsmanager + org.opendaylight.controller.statisticsmanager ${project.basedir}/META-INF diff --git a/opendaylight/statisticsmanager/api/src/main/java/org/opendaylight/controller/statisticsmanager/IStatisticsManager.java b/opendaylight/statisticsmanager/api/src/main/java/org/opendaylight/controller/statisticsmanager/IStatisticsManager.java index 98977f6e91..a2ab07ac7b 100644 --- a/opendaylight/statisticsmanager/api/src/main/java/org/opendaylight/controller/statisticsmanager/IStatisticsManager.java +++ b/opendaylight/statisticsmanager/api/src/main/java/org/opendaylight/controller/statisticsmanager/IStatisticsManager.java @@ -31,7 +31,7 @@ public interface IStatisticsManager { * If the context is the default container, the returned statistics are for all the flows installed on the node, * regardless of the container they belong to * - * @param node the network node + * @param node the network node * @return the list of flows installed on the network node */ List getFlows(Node node); @@ -40,7 +40,7 @@ public interface IStatisticsManager { * Returns the statistics for the flows specified in the list * * @param flows - * @return the list of flows installed on the network node + * @return the list of flows installed on the network node */ Map> getFlowStatisticsForFlowList( List flows); diff --git a/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/IInventoryListener.java b/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/IInventoryListener.java index e7b8c59dff..29d0a42f85 100644 --- a/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/IInventoryListener.java +++ b/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/IInventoryListener.java @@ -23,11 +23,11 @@ public interface IInventoryListener { /** * This method is called when some properties of a node are added/deleted/changed. * - * @param node {@link org.opendaylight.controller.sal.core.Node} being updated - * @param type {@link org.opendaylight.controller.sal.core.UpdateType} - * @param propMap map of {@link org.opendaylight.controller.sal.core.Property} such as - * {@link org.opendaylight.controller.sal.core.Description} and/or - * {@link org.opendaylight.controller.sal.core.Tier} etc. + * @param node {@link org.opendaylight.controller.sal.core.Node} being updated + * @param type {@link org.opendaylight.controller.sal.core.UpdateType} + * @param propMap map of {@link org.opendaylight.controller.sal.core.Property} such as + * {@link org.opendaylight.controller.sal.core.Description} and/or + * {@link org.opendaylight.controller.sal.core.Tier} etc. */ public void notifyNode(Node node, UpdateType type, Map propMap); @@ -35,11 +35,11 @@ public interface IInventoryListener { /** * This method is called when some properties of a node connector are added/deleted/changed. * - * @param nodeConnector {@link org.opendaylight.controller.sal.core.NodeConnector} being updated - * @param type {@link org.opendaylight.controller.sal.core.UpdateType} - * @param propMap map of {@link org.opendaylight.controller.sal.core.Property} such as - * {@link org.opendaylight.controller.sal.core.Description} and/or - * {@link org.opendaylight.controller.sal.core.State} etc. + * @param nodeConnector {@link org.opendaylight.controller.sal.core.NodeConnector} being updated + * @param type {@link org.opendaylight.controller.sal.core.UpdateType} + * @param propMap map of {@link org.opendaylight.controller.sal.core.Property} such as + * {@link org.opendaylight.controller.sal.core.Description} and/or + * {@link org.opendaylight.controller.sal.core.State} etc. */ public void notifyNodeConnector(NodeConnector nodeConnector, UpdateType type, Map propMap); diff --git a/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/ISpanAware.java b/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/ISpanAware.java index af1ab1cc7b..1e4a79fcc0 100644 --- a/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/ISpanAware.java +++ b/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/ISpanAware.java @@ -22,9 +22,9 @@ public interface ISpanAware { /** * This method is called when list of ports in a node are added/deleted as span ports. * - * @param node {@link org.opendaylight.controller.sal.core.Node} being updated - * @param portList list of span {@link org.opendaylight.controller.sal.core.NodeConnector} - * @param add true if add; false if delete. + * @param node {@link org.opendaylight.controller.sal.core.Node} being updated + * @param portList list of span {@link org.opendaylight.controller.sal.core.NodeConnector} + * @param add true if add; false if delete. */ public void spanUpdate(Node node, List portList, boolean add); } \ No newline at end of file diff --git a/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/ISwitchManager.java b/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/ISwitchManager.java index ddc5f8ffee..48f5aa48f6 100644 --- a/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/ISwitchManager.java +++ b/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/ISwitchManager.java @@ -44,7 +44,7 @@ public interface ISwitchManager { /** * Remove a subnet configuration * - * @param configObject refer to {@link Open Declaration org.opendaylight.controller.switchmanager.SubnetConfig} + * @param configObject refer to {@link Open Declaration org.opendaylight.controller.switchmanager.SubnetConfig} * @return "Success" or failure reason */ public Status removeSubnet(SubnetConfig configObject); @@ -53,14 +53,14 @@ public interface ISwitchManager { * Remove a subnet configuration given the name * * @param name subnet name - * @return "Success" or failure reason + * @return "Success" or failure reason */ public Status removeSubnet(String name); /** * Return a list of all known devices in the system * - * @return returns a list of {@link org.opendaylight.controller.switchmanager.Switch} + * @return returns a list of {@link org.opendaylight.controller.switchmanager.Switch} */ public List getNetworkDevices(); @@ -82,8 +82,8 @@ public interface ISwitchManager { /** * Return a subnet configuration given the network address * - * @param networkAddress the ip address in long format - * @return the {@link org.opendaylight.controller.switchmanager.Subnet} + * @param networkAddress the ip address in long format + * @return the {@link org.opendaylight.controller.switchmanager.Subnet} */ public Subnet getSubnetByNetworkAddress(InetAddress networkAddress); @@ -98,7 +98,7 @@ public interface ISwitchManager { * Add a span port configuration * * @param SpanConfig refer to {@link Open Declaration org.opendaylight.controller.switchmanager.SpanConfig} - * @return status code + * @return status code */ public Status addSpanConfig(SpanConfig configObject); @@ -106,7 +106,7 @@ public interface ISwitchManager { * Remove a span port configuration * * @param SpanConfig refer to {@link Open Declaration org.opendaylight.controller.switchmanager.SpanConfig} - * @return status code + * @return status code */ public Status removeSpanConfig(SpanConfig cfgObject); @@ -152,8 +152,8 @@ public interface ISwitchManager { /** * Remove node connectors from a subnet * - * @param name the subnet config name - * @param nodeConnectors nodePorts string specified by {@link Open Declaration org.opendaylight.controller.switchmanager.SubnetConfig} + * @param name the subnet config name + * @param nodeConnectors nodePorts string specified by {@link Open Declaration org.opendaylight.controller.switchmanager.SubnetConfig} * @return "Success" or failure reason */ public Status removePortsFromSubnet(String name, String nodeConnectors); @@ -170,16 +170,16 @@ public interface ISwitchManager { * * @param node {@link org.opendaylight.controller.sal.core.Node} * @return map of {@link org.opendaylight.controller.sal.core.Property} such as - * {@link org.opendaylight.controller.sal.core.Description} and/or - * {@link org.opendaylight.controller.sal.core.Tier} etc. + * {@link org.opendaylight.controller.sal.core.Description} and/or + * {@link org.opendaylight.controller.sal.core.Tier} etc. */ public Map getNodeProps(Node node); /** * Return a specific property of a node given the property name * - * @param node {@link org.opendaylight.controller.sal.core.Node} - * @param propName the property name specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes + * @param node {@link org.opendaylight.controller.sal.core.Node} + * @param propName the property name specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes * @return {@link org.opendaylight.controller.sal.core.Property} */ public Property getNodeProp(Node node, String propName); @@ -187,23 +187,23 @@ public interface ISwitchManager { /** * Set a specific property of a node * - * @param node {@link org.opendaylight.controller.sal.core.Node} - * @param prop {@link org.opendaylight.controller.sal.core.Property} + * @param node {@link org.opendaylight.controller.sal.core.Node} + * @param prop {@link org.opendaylight.controller.sal.core.Property} */ public void setNodeProp(Node node, Property prop); /** * Remove a property of a node - * - * @param nc {@link org.opendaylight.controller.sal.core.Node} - * @param propName the property name specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes + * + * @param nc {@link org.opendaylight.controller.sal.core.Node} + * @param propName the property name specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes * @return success or failed reason */ public Status removeNodeProp(Node node, String propName); /** * Remove all the properties of a node - * + * * @param node {@link org.opendaylight.controller.sal.core.Node} * @return success or failed reason */ @@ -238,8 +238,8 @@ public interface ISwitchManager { * * @param nodeConnector {@link org.opendaylight.controller.sal.core.NodeConnector} * @return map of {@link org.opendaylight.controller.sal.core.Property} such as - * {@link org.opendaylight.controller.sal.core.Description} and/or - * {@link org.opendaylight.controller.sal.core.State} etc. + * {@link org.opendaylight.controller.sal.core.Description} and/or + * {@link org.opendaylight.controller.sal.core.State} etc. */ public Map getNodeConnectorProps( NodeConnector nodeConnector); @@ -266,7 +266,7 @@ public interface ISwitchManager { /** * Remove a property of a node connector - * + * * @param nc {@link org.opendaylight.controller.sal.core.NodeConnector} * @param propName property name specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes * @return success or failed reason @@ -275,7 +275,7 @@ public interface ISwitchManager { /** * Remove all the properties of a node connector - * + * * @param nodeConnector {@link org.opendaylight.controller.sal.core.NodeConnector} * @return success or failed reason */ @@ -284,7 +284,7 @@ public interface ISwitchManager { /** * Return the node connector given its name * - * @param node {@link org.opendaylight.controller.sal.core.Node} + * @param node {@link org.opendaylight.controller.sal.core.Node} * @param nodeConnectorName node connector identifier specified by {@link org.opendaylight.controller.sal.core.NodeConnector} * @return {@link org.opendaylight.controller.sal.core.NodeConnector} */ @@ -309,7 +309,7 @@ public interface ISwitchManager { /** * Return controller MAC address - * + * * @return MAC address in byte array */ public byte[] getControllerMAC(); @@ -317,7 +317,7 @@ public interface ISwitchManager { /** * Return MAC address for a given node * - * @param node {@link org.opendaylight.controller.sal.core.Node} + * @param node {@link org.opendaylight.controller.sal.core.Node} * @return MAC address in byte array */ public byte[] getNodeMAC(Node node); @@ -338,22 +338,22 @@ public interface ISwitchManager { */ public int getHostRetryCount(); - /** - * Create a Name/Tier/Bandwidth Property object based on given property - * name and value. Other property types are not supported yet. - * + /** + * Create a Name/Tier/Bandwidth Property object based on given property + * name and value. Other property types are not supported yet. + * * @param propName Name of the Property specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes * @param propValue Value of the Property specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes - * @return {@link org.opendaylight.controller.sal.core.Property} - */ + * @return {@link org.opendaylight.controller.sal.core.Property} + */ public Property createProperty(String propName, String propValue); - + /** - * Returns the description for the specified node. It is either the one + * Returns the description for the specified node. It is either the one * configured by user or the description advertised by the node. - * + * * @param node the network node identifier - * @return the description of the specified node. If no description is + * @return the description of the specified node. If no description is * configured and the network node does not provide its description, * an empty string is returned. */ diff --git a/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/Switch.java b/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/Switch.java index eae01a6487..a665096e8b 100644 --- a/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/Switch.java +++ b/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/Switch.java @@ -16,9 +16,9 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.utils.HexEncode; /** * The class describes switch related information including L2 address, ports, @@ -164,6 +164,8 @@ public class Switch implements Serializable { @Override public String toString() { - return "Switch[" + ReflectionToStringBuilder.toString(this) + "]"; + return "Switch [dataLayerAddress=" + HexEncode.bytesToHexStringFormat(dataLayerAddress) + + ", nodeConnectors=" + nodeConnectors + ", spanPorts=" + + spanPorts + ", node=" + node + "]"; } } diff --git a/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SwitchConfig.java b/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SwitchConfig.java index 778310e07f..253096edc3 100644 --- a/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SwitchConfig.java +++ b/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SwitchConfig.java @@ -47,9 +47,9 @@ public class SwitchConfig implements Serializable { } public boolean isProactive() { - return Integer.parseInt(mode) != 0; + return Integer.parseInt(mode) != 0; } - + public static long getSerialversionuid() { return serialVersionUID; } diff --git a/opendaylight/switchmanager/api/src/test/java/org/opendaylight/controller/switchmanager/SwitchTest.java b/opendaylight/switchmanager/api/src/test/java/org/opendaylight/controller/switchmanager/SwitchTest.java index 1499f9e2ef..18b3195372 100644 --- a/opendaylight/switchmanager/api/src/test/java/org/opendaylight/controller/switchmanager/SwitchTest.java +++ b/opendaylight/switchmanager/api/src/test/java/org/opendaylight/controller/switchmanager/SwitchTest.java @@ -119,23 +119,23 @@ public class SwitchTest { Assert.assertTrue(sw.getSpanPorts().isEmpty()); } - + @Test public void testSwitchConfig(){ SwitchConfig sc = new SwitchConfig(null, null, null, null); SwitchConfig sc2 = new SwitchConfig(null, null, null, null); Assert.assertTrue(sc.equals(sc2)); - + Assert.assertNull(sc.getMode()); Assert.assertNull(sc.getNodeId()); Assert.assertNull(sc.getTier()); Assert.assertNull(sc.getNodeDescription()); - + SwitchConfig sc3 = new SwitchConfig("123", "name", "tier", "mode"); SwitchConfig sc4 = new SwitchConfig("123", "name", "tier", "mode"); Assert.assertFalse(sc.equals(sc3)); Assert.assertTrue(sc3.equals(sc4)); - + Assert.assertTrue(sc3.getNodeId().equals("123")); Assert.assertTrue(sc3.getNodeDescription().equals("name")); Assert.assertTrue(sc3.getTier().equals("tier")); diff --git a/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImpl.java b/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImpl.java index 971213e483..443c7a42ab 100644 --- a/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImpl.java +++ b/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImpl.java @@ -820,6 +820,8 @@ CommandProvider { @Override public void updateNode(Node node, UpdateType type, Set props) { + log.debug("updateNode: {} type {} props {} for container {}", + new Object[] { node, type, props, containerName }); switch (type) { case ADDED: addNode(node, props); @@ -841,7 +843,8 @@ CommandProvider { Node node = nodeConnector.getNode(); Map propMap = new HashMap(); - log.trace("{} {}", nodeConnector, type); + log.debug("updateNodeConnector: {} type {} props {} for container {}", + new Object[] { nodeConnector, type, props, containerName }); if (nodeConnectorProps == null) { return; @@ -1335,6 +1338,8 @@ CommandProvider { Set nodeSet = nodeProps.keySet(); if (nodeSet != null) { for (Node node : nodeSet) { + log.debug("getInventories: {} added for container {}", + new Object[] { node, containerName }); addNode(node, null); } } @@ -1384,17 +1389,17 @@ CommandProvider { } private void bulkUpdateService(IInventoryListener service) { + Map propMap; + UpdateType type = UpdateType.ADDED; + for (Node node : getNodes()) { - service.notifyNode(node, UpdateType.ADDED, null); + propMap = nodeProps.get(node); + service.notifyNode(node, type, propMap); } - Map propMap = new HashMap(); - propMap.put(State.StatePropName, new State(State.EDGE_UP)); for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) { - if (isNodeConnectorEnabled(nodeConnector)) { - service.notifyNodeConnector(nodeConnector, UpdateType.ADDED, - propMap); - } + propMap = nodeConnectorProps.get(nodeConnector); + service.notifyNodeConnector(nodeConnector, type, propMap); } } diff --git a/opendaylight/switchmanager/integrationtest/pom.xml b/opendaylight/switchmanager/integrationtest/pom.xml index 44ad73c496..e774dae115 100644 --- a/opendaylight/switchmanager/integrationtest/pom.xml +++ b/opendaylight/switchmanager/integrationtest/pom.xml @@ -21,7 +21,7 @@ org.opendaylight.controller switchmanager.implementation - 0.4.0-SNAPSHOT + 0.4.0-SNAPSHOT org.opendaylight.controller diff --git a/opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/TopologyUserLinkConfig.java b/opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/TopologyUserLinkConfig.java index 872fb17129..f485fdd0db 100644 --- a/opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/TopologyUserLinkConfig.java +++ b/opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/TopologyUserLinkConfig.java @@ -127,7 +127,7 @@ public class TopologyUserLinkConfig implements Serializable { return false; } - if (!isValidNodeConnector(srcNodeConnector) || + if (!isValidNodeConnector(srcNodeConnector) || !isValidNodeConnector(dstNodeConnector)) { logger.warn("Invalid NodeConnector"); return false; @@ -178,4 +178,4 @@ public class TopologyUserLinkConfig implements Serializable { + ", srcNodeConnector=" + srcNodeConnector + ", dstNodeConnector=" + dstNodeConnector + "]"; } -} \ No newline at end of file +} diff --git a/opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImpl.java b/opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImpl.java index 277465813b..f9574b993c 100644 --- a/opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImpl.java +++ b/opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImpl.java @@ -608,7 +608,7 @@ CommandProvider { if (srcNodeConnector == null || dstNodeConnector == null) return null; try { linkTuple = new Edge(srcNodeConnector, dstNodeConnector); - } catch (Exception e) { + } catch (Exception e) { } return linkTuple; } diff --git a/opendaylight/topologymanager/src/test/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImplTest.java b/opendaylight/topologymanager/src/test/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImplTest.java index b4dfba9277..65487a614a 100644 --- a/opendaylight/topologymanager/src/test/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImplTest.java +++ b/opendaylight/topologymanager/src/test/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImplTest.java @@ -45,9 +45,9 @@ public class TopologyManagerImplTest { * NodeConnectorId> : <1:1>--><11:11>; <1:2>--><11:12>; <3:3>--><13:13>; * <3:4>--><13:14>; <5:5>--><15:15>; <5:6>--><15:16>; Method used by two * tests: testGetNodeEdges and testGetEdges - * + * * @param topoManagerImpl - * + * * @throws ConstructionException */ public void setNodeEdges(TopologyManagerImpl topoManagerImpl) @@ -73,16 +73,16 @@ public class TopologyManagerImplTest { NodeConnector tailnc1 = NodeConnectorCreator .createOFNodeConnector((short) (i + 10), NodeCreator.createOFNode((long) (i + 10))); - Edge e1 = new Edge(headnc1, tailnc1); + Edge e1 = new Edge(tailnc1, headnc1); TopoEdgeUpdate teu1 = new TopoEdgeUpdate(e1, props, UpdateType.ADDED); topoedgeupdateList.add(teu1); - NodeConnector headnc2 = NodeConnectorCreator.createOFNodeConnector( - (short) (i + 1), headnc1.getNode()); NodeConnector tailnc2 = NodeConnectorCreator.createOFNodeConnector( + (short) (i + 1), headnc1.getNode()); + NodeConnector headnc2 = NodeConnectorCreator.createOFNodeConnector( (short) (i + 11), tailnc1.getNode()); - Edge e2 = new Edge(headnc2, tailnc2); + Edge e2 = new Edge(tailnc2, headnc2); TopoEdgeUpdate teu2 = new TopoEdgeUpdate(e2, props, UpdateType.ADDED); topoedgeupdateList.add(teu2); @@ -111,25 +111,12 @@ public class TopologyManagerImplTest { .longValue(); Long tailNcId = ((Short) edge.getTailNodeConnector().getID()) .longValue(); - if (nodeId == 1 || nodeId == 3 || nodeId == 5) { - Assert.assertTrue((headNcId.equals(nodeId) && tailNcId - .equals(nodeId + 10)) - || (headNcId.equals(nodeId + 10) && tailNcId - .equals(nodeId)) - || (headNcId.equals(nodeId + 1) && tailNcId - .equals(nodeId + 11)) - || (headNcId.equals(nodeId + 11) && tailNcId - .equals(nodeId + 1))); - } else if (nodeId == 11 || nodeId == 13 || nodeId == 15) { - Assert.assertTrue((headNcId.equals(nodeId) && tailNcId - .equals(nodeId - 10)) - || (headNcId.equals(nodeId) && tailNcId - .equals(nodeId - 10)) - || (headNcId.equals(nodeId - 9) && tailNcId - .equals(nodeId + 1)) - || (headNcId.equals(nodeId + 1) && tailNcId - .equals(nodeId - 9))); - } + Assert.assertTrue( + (headNcId.equals(nodeId) && tailNcId.equals(nodeId + 10)) + || (headNcId.equals(nodeId + 11) && tailNcId.equals(nodeId + 1)) + || (headNcId.equals(nodeId + 1) && tailNcId.equals(nodeId - 9)) + || (headNcId.equals(nodeId - 10) && tailNcId.equals(nodeId)) + ); } i.remove(); } diff --git a/opendaylight/usermanager/pom.xml b/opendaylight/usermanager/api/pom.xml similarity index 95% rename from opendaylight/usermanager/pom.xml rename to opendaylight/usermanager/api/pom.xml index 1859e8ed4c..877461daaa 100644 --- a/opendaylight/usermanager/pom.xml +++ b/opendaylight/usermanager/api/pom.xml @@ -6,7 +6,7 @@ org.opendaylight.controller commons.opendaylight 1.4.0-SNAPSHOT - ../commons/opendaylight + ../../commons/opendaylight usermanager @@ -48,11 +48,15 @@ org.opendaylight.controller.usermanager, + + + + ${project.basedir}/META-INF diff --git a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/AuthResponse.java b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/AuthResponse.java similarity index 100% rename from opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/AuthResponse.java rename to opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/AuthResponse.java diff --git a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/AuthorizationConfig.java b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/AuthorizationConfig.java similarity index 89% rename from opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/AuthorizationConfig.java rename to opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/AuthorizationConfig.java index 038ccca2fc..bad8fa511f 100644 --- a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/AuthorizationConfig.java +++ b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/AuthorizationConfig.java @@ -6,9 +6,10 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.usermanager.internal; +package org.opendaylight.controller.usermanager; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import org.opendaylight.controller.sal.utils.Status; @@ -44,4 +45,9 @@ public class AuthorizationConfig extends UserConfig { public String toString() { return "AuthorizationConfig=[user: " + user + ", roles: " + roles + "]"; } + + public String getRolesString() { + return super.getRolesString(); + } + } diff --git a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/IAAAProvider.java b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/IAAAProvider.java similarity index 98% rename from opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/IAAAProvider.java rename to opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/IAAAProvider.java index 0fb26a1a62..36a2c06bf6 100644 --- a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/IAAAProvider.java +++ b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/IAAAProvider.java @@ -18,7 +18,7 @@ public interface IAAAProvider { /** * Authenticate user with AAA server and return authentication and * authorization info using the Provider's mechanism - * + * * @param userName * the username * @param password @@ -35,7 +35,7 @@ public interface IAAAProvider { /** * Returns the Name of the Provider - * + * * @return Name of the AAA provider */ public String getName(); diff --git a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/ISessionManager.java b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/ISessionManager.java similarity index 98% rename from opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/ISessionManager.java rename to opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/ISessionManager.java index 8149d7a5a2..372462eaae 100644 --- a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/ISessionManager.java +++ b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/ISessionManager.java @@ -11,14 +11,14 @@ package org.opendaylight.controller.usermanager; import javax.servlet.http.HttpSessionListener; /** - * + * * This interface defines method(s) to invalidate a session. */ public interface ISessionManager extends HttpSessionListener { /** * Invalidates the session for a given user and a session Id - * + * * @param username * the username * @param sessionId diff --git a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/IUserManager.java b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/IUserManager.java similarity index 92% rename from opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/IUserManager.java rename to opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/IUserManager.java index ed23b5f067..cd86ed73fe 100644 --- a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/IUserManager.java +++ b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/IUserManager.java @@ -15,9 +15,9 @@ import java.util.Set; import org.opendaylight.controller.sal.authorization.AuthResultEnum; import org.opendaylight.controller.sal.authorization.UserLevel; import org.opendaylight.controller.sal.utils.Status; -import org.opendaylight.controller.usermanager.internal.AuthorizationConfig; -import org.opendaylight.controller.usermanager.internal.ServerConfig; -import org.opendaylight.controller.usermanager.internal.UserConfig; +import org.opendaylight.controller.usermanager.AuthorizationConfig; +import org.opendaylight.controller.usermanager.ServerConfig; +import org.opendaylight.controller.usermanager.UserConfig; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.web.context.SecurityContextRepository; @@ -267,6 +267,18 @@ public interface IUserManager extends UserDetailsService { */ public ISessionManager getSessionManager(); + /** + * Checks if the specified role belongs to any application. Usually an + * application will call this function when configuring a role, to check if + * that role is already being used by another application. + * + * @param role + * The role to check + * @return true if the specified role belongs to any application or if the + * role is a well-known controller role, false otherwise. + */ + public boolean isRoleInUse(String role); + /* non-Javadoc * Returns the password for a given user * diff --git a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/ODLUserLevel.java b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/ODLUserLevel.java similarity index 89% rename from opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/ODLUserLevel.java rename to opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/ODLUserLevel.java index 9766fd475a..ca6000a9f5 100644 --- a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/ODLUserLevel.java +++ b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/ODLUserLevel.java @@ -13,8 +13,8 @@ import org.opendaylight.controller.sal.authorization.UserLevel; import org.springframework.security.core.GrantedAuthority; public class ODLUserLevel implements GrantedAuthority { - private static final long serialVersionUID = 1L; - UserLevel userLevel; + private static final long serialVersionUID = 1L; + UserLevel userLevel; public ODLUserLevel(UserLevel userLevel) { this.userLevel = userLevel; diff --git a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/ServerConfig.java b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/ServerConfig.java similarity index 94% rename from opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/ServerConfig.java rename to opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/ServerConfig.java index 2ad98aba68..f50f9e71c9 100644 --- a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/ServerConfig.java +++ b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/ServerConfig.java @@ -7,7 +7,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.usermanager.internal; +package org.opendaylight.controller.usermanager; import java.io.Serializable; @@ -27,11 +27,11 @@ public class ServerConfig implements Serializable { } public ServerConfig(String ip, String secret, String protocol) { - this.ip = ip; - this.secret = secret; - this.protocol = protocol; + this.ip = ip; + this.secret = secret; + this.protocol = protocol; } - + public String getAddress() { return ip; } diff --git a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/UserConfig.java b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/UserConfig.java similarity index 98% rename from opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/UserConfig.java rename to opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/UserConfig.java index 176af3a3e4..0e6a48ab52 100644 --- a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/UserConfig.java +++ b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/UserConfig.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.usermanager.internal; +package org.opendaylight.controller.usermanager; import java.io.Serializable; import java.util.ArrayList; @@ -49,7 +49,7 @@ public class UserConfig implements Serializable { this.roles = (roles == null) ? new ArrayList() : new ArrayList(roles); } - + public String getUser() { return user; } @@ -161,24 +161,24 @@ public class UserConfig implements Serializable { return new Status(StatusCode.BADREQUEST, "Current password is incorrect"); } - + // Create a new object with the proposed modifications UserConfig proposed = new UserConfig(); proposed.user = this.user; proposed.password = (newPassword != null)? newPassword : this.password; proposed.roles = (newRoles != null)? newRoles : this.roles; - + // Validate it Status status = proposed.validate(); if (!status.isSuccess()) { return status; } - + // Accept the modifications this.user = proposed.user; this.password = proposed.password; this.roles = new ArrayList(proposed.roles); - + return status; } @@ -192,7 +192,7 @@ public class UserConfig implements Serializable { } return locResponse; } - + protected String getRolesString() { StringBuffer buffer = new StringBuffer(); if (!roles.isEmpty()) { diff --git a/opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/AuthResponseTest.java b/opendaylight/usermanager/api/src/test/java/org/opendaylight/controller/usermanager/AuthResponseTest.java similarity index 99% rename from opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/AuthResponseTest.java rename to opendaylight/usermanager/api/src/test/java/org/opendaylight/controller/usermanager/AuthResponseTest.java index cb4c75fecc..af68be6cef 100644 --- a/opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/AuthResponseTest.java +++ b/opendaylight/usermanager/api/src/test/java/org/opendaylight/controller/usermanager/AuthResponseTest.java @@ -10,5 +10,5 @@ package org.opendaylight.controller.usermanager; public class AuthResponseTest{ - + } \ No newline at end of file diff --git a/opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/AuthorizationUserConfigTest.java b/opendaylight/usermanager/api/src/test/java/org/opendaylight/controller/usermanager/AuthorizationUserConfigTest.java similarity index 96% rename from opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/AuthorizationUserConfigTest.java rename to opendaylight/usermanager/api/src/test/java/org/opendaylight/controller/usermanager/AuthorizationUserConfigTest.java index 7d28d23075..cccbe24734 100644 --- a/opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/AuthorizationUserConfigTest.java +++ b/opendaylight/usermanager/api/src/test/java/org/opendaylight/controller/usermanager/AuthorizationUserConfigTest.java @@ -5,7 +5,7 @@ * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.usermanager.internal; +package org.opendaylight.controller.usermanager; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -18,6 +18,8 @@ import org.junit.Test; import org.opendaylight.controller.sal.authorization.AuthResultEnum; import org.opendaylight.controller.sal.authorization.UserLevel; import org.opendaylight.controller.usermanager.AuthResponse; +import org.opendaylight.controller.usermanager.AuthorizationConfig; +import org.opendaylight.controller.usermanager.UserConfig; /* * This test case includes tests for UserConfig and the extending class AuthorizationConfig @@ -65,13 +67,13 @@ public class AuthorizationUserConfigTest { roles.clear(); roles.add(UserLevel.NETWORKADMIN.toString()); assertTrue(userConfig.update("ciscocisco", null, roles).isSuccess()); - + // Role change and same new password roles.clear(); roles.add(UserLevel.NETWORKOPERATOR.toString()); assertTrue(userConfig.update("ciscocisco", "ciscocisco", roles) .isSuccess()); - + // New Password = null, No change in password assertTrue(userConfig.getPassword().equals("ciscocisco")); diff --git a/opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/ServerConfigTest.java b/opendaylight/usermanager/api/src/test/java/org/opendaylight/controller/usermanager/ServerConfigTest.java similarity index 82% rename from opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/ServerConfigTest.java rename to opendaylight/usermanager/api/src/test/java/org/opendaylight/controller/usermanager/ServerConfigTest.java index 33c11de0ba..eaeca73003 100644 --- a/opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/ServerConfigTest.java +++ b/opendaylight/usermanager/api/src/test/java/org/opendaylight/controller/usermanager/ServerConfigTest.java @@ -1,12 +1,12 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * 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.usermanager.internal; +package org.opendaylight.controller.usermanager; public class ServerConfigTest { } diff --git a/opendaylight/usermanager/implementation/pom.xml b/opendaylight/usermanager/implementation/pom.xml new file mode 100644 index 0000000000..a558fa2048 --- /dev/null +++ b/opendaylight/usermanager/implementation/pom.xml @@ -0,0 +1,97 @@ + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../commons/opendaylight + + + usermanager.implementation + 0.4.0-SNAPSHOT + bundle + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + + org.opendaylight.controller.clustering.services, + org.opendaylight.controller.configuration, + org.opendaylight.controller.sal.authorization, + org.opendaylight.controller.sal.core, + org.opendaylight.controller.sal.packet, + org.opendaylight.controller.sal.utils, + org.opendaylight.controller.switchmanager, + org.opendaylight.controller.containermanager, + org.slf4j, + org.eclipse.osgi.framework.console, + org.osgi.framework, + org.apache.felix.dm, + org.apache.commons.lang3.builder, + org.apache.commons.logging, + javax.servlet, + javax.servlet.http, + org.springframework.security.web.context, + org.springframework.security.core, + org.springframework.security.core.context, + org.apache.commons.lang3, + org.springframework.security.authentication, + org.springframework.security.core.authority, + org.springframework.security.core.userdetails, + org.opendaylight.controller.usermanager + + + + + + org.opendaylight.controller.usermanager.internal.Activator + + + ${project.basedir}/META-INF + + + + + + + org.opendaylight.controller + usermanager + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + switchmanager + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + containermanager + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + clustering.services + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + configuration + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + sal + 0.5.0-SNAPSHOT + + + diff --git a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/Activator.java b/opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/internal/Activator.java similarity index 100% rename from opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/Activator.java rename to opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/internal/Activator.java diff --git a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/AuthenticatedUser.java b/opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/internal/AuthenticatedUser.java similarity index 100% rename from opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/AuthenticatedUser.java rename to opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/internal/AuthenticatedUser.java diff --git a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/UserManagerImpl.java b/opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/internal/UserManagerImpl.java similarity index 92% rename from opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/UserManagerImpl.java rename to opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/internal/UserManagerImpl.java index 5ddf6be6c5..faa6e3b96f 100644 --- a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/UserManagerImpl.java +++ b/opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/internal/UserManagerImpl.java @@ -43,11 +43,16 @@ import org.opendaylight.controller.sal.utils.ObjectReader; import org.opendaylight.controller.sal.utils.ObjectWriter; import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.usermanager.AuthResponse; +import org.opendaylight.controller.usermanager.AuthorizationConfig; import org.opendaylight.controller.usermanager.IAAAProvider; import org.opendaylight.controller.usermanager.ISessionManager; import org.opendaylight.controller.usermanager.IUserManager; +import org.opendaylight.controller.usermanager.ServerConfig; +import org.opendaylight.controller.usermanager.UserConfig; import org.opendaylight.controller.usermanager.security.SessionManager; import org.opendaylight.controller.usermanager.security.UserSecurityContextRepository; +import org.opendaylight.controller.usermanager.internal.AuthenticatedUser; + import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.slf4j.Logger; @@ -156,9 +161,9 @@ public class UserManagerImpl implements IUserManager, IObjectReader, "usermanager.authorizationSaveConfigEvent", EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); } catch (CacheConfigException cce) { - logger.error("\nCache configuration invalid - check cache mode"); + logger.error("Cache configuration invalid - check cache mode"); } catch (CacheExistException ce) { - logger.error("\nCache already exits - destroy and recreate if needed"); + logger.debug("Skipping cache creation as already present"); } } @@ -172,43 +177,43 @@ public class UserManagerImpl implements IUserManager, IObjectReader, activeUsers = (ConcurrentMap) clusterGlobalService .getCache("usermanager.activeUsers"); if (activeUsers == null) { - logger.error("\nFailed to get cache for activeUsers"); + logger.error("Failed to get cache for activeUsers"); } localUserConfigList = (ConcurrentMap) clusterGlobalService .getCache("usermanager.localUserConfigList"); if (localUserConfigList == null) { - logger.error("\nFailed to get cache for localUserConfigList"); + logger.error("Failed to get cache for localUserConfigList"); } remoteServerConfigList = (ConcurrentMap) clusterGlobalService .getCache("usermanager.remoteServerConfigList"); if (remoteServerConfigList == null) { - logger.error("\nFailed to get cache for remoteServerConfigList"); + logger.error("Failed to get cache for remoteServerConfigList"); } authorizationConfList = (ConcurrentMap) clusterGlobalService .getCache("usermanager.authorizationConfList"); if (authorizationConfList == null) { - logger.error("\nFailed to get cache for authorizationConfList"); + logger.error("Failed to get cache for authorizationConfList"); } localUserListSaveConfigEvent = (ConcurrentMap) clusterGlobalService .getCache("usermanager.localUserSaveConfigEvent"); if (localUserListSaveConfigEvent == null) { - logger.error("\nFailed to get cache for localUserSaveConfigEvent"); + logger.error("Failed to get cache for localUserSaveConfigEvent"); } remoteServerSaveConfigEvent = (ConcurrentMap) clusterGlobalService .getCache("usermanager.remoteServerSaveConfigEvent"); if (remoteServerSaveConfigEvent == null) { - logger.error("\nFailed to get cache for remoteServerSaveConfigEvent"); + logger.error("Failed to get cache for remoteServerSaveConfigEvent"); } authorizationSaveConfigEvent = (ConcurrentMap) clusterGlobalService .getCache("usermanager.authorizationSaveConfigEvent"); if (authorizationSaveConfigEvent == null) { - logger.error("\nFailed to get cache for authorizationSaveConfigEvent"); + logger.error("Failed to get cache for authorizationSaveConfigEvent"); } } @@ -866,29 +871,29 @@ public class UserManagerImpl implements IUserManager, IObjectReader, @Override public List getUserRoles(String userName) { - if (userName == null) { - return new ArrayList(0); + List roles = null; + if (userName != null) { + /* + * First look in active users then in local configured users, + * finally in local authorized users + */ + if (activeUsers.containsKey(userName)) { + roles = activeUsers.get(userName).getUserRoles(); + } else if (localUserConfigList.containsKey(userName)) { + roles = localUserConfigList.get(userName).getRoles(); + } else if (authorizationConfList.containsKey(userName)) { + roles = authorizationConfList.get(userName).getRoles(); + } } - AuthenticatedUser locatedUser = activeUsers.get(userName); - return (locatedUser == null) ? new ArrayList(0) : locatedUser - .getUserRoles(); + return (roles == null) ? new ArrayList(0) : roles; } @Override public UserLevel getUserLevel(String username) { - // Returns the controller well-know user level for the passed user - List rolesNames = null; - - // First check in active users then in local configured users - if (activeUsers.containsKey(username)) { - List roles = activeUsers.get(username).getUserRoles(); - rolesNames = (roles == null || roles.isEmpty()) ? null : roles; - } else if (localUserConfigList.containsKey(username)) { - UserConfig config = localUserConfigList.get(username); - rolesNames = (config == null) ? null : config.getRoles(); - } + // Returns the highest controller user level for the passed user + List rolesNames = getUserRoles(username); - if (rolesNames == null) { + if (rolesNames.isEmpty()) { return UserLevel.NOUSER; } @@ -926,19 +931,11 @@ public class UserManagerImpl implements IUserManager, IObjectReader, @Override public List getUserLevels(String username) { - // Returns the controller well-know user levels for the passed user - List rolesNames = null; + // Returns the controller user levels for the passed user + List rolesNames = getUserRoles(username); List levels = new ArrayList(); - if (activeUsers.containsKey(username)) { - List roles = activeUsers.get(username).getUserRoles(); - rolesNames = (roles == null || roles.isEmpty()) ? null : roles; - } else if (localUserConfigList.containsKey(username)) { - UserConfig config = localUserConfigList.get(username); - rolesNames = (config == null) ? null : config.getRoles(); - } - - if (rolesNames == null) { + if (rolesNames.isEmpty()) { return levels; } @@ -1075,7 +1072,7 @@ public class UserManagerImpl implements IUserManager, IObjectReader, } - // following are setters for use in unit testing + // Following are setters for use in unit testing void setLocalUserConfigList(ConcurrentMap ucl) { if (ucl != null) { this.localUserConfigList = ucl; @@ -1119,4 +1116,32 @@ public class UserManagerImpl implements IUserManager, IObjectReader, public String getPassword(String username) { return localUserConfigList.get(username).getPassword(); } + + @Override + public boolean isRoleInUse(String role) { + if (role == null || role.isEmpty()) { + return false; + } + // Check against controller roles + if (role.equals(UserLevel.SYSTEMADMIN.toString()) + || role.equals(UserLevel.NETWORKADMIN.toString()) + || role.equals(UserLevel.NETWORKOPERATOR.toString())) { + return true; + } + // Check if container roles + if (containerAuthorizationClient != null) { + if (containerAuthorizationClient.isApplicationRole(role)) { + return true; + } + } + // Finally if application role + if (applicationAuthorizationClients != null) { + for (IResourceAuthorization client : this.applicationAuthorizationClients) { + if (client.isApplicationRole(role)) { + return true; + } + } + } + return false; + } } diff --git a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/security/SessionManager.java b/opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/security/SessionManager.java similarity index 97% rename from opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/security/SessionManager.java rename to opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/security/SessionManager.java index 21d0137849..5201a6dc6d 100644 --- a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/security/SessionManager.java +++ b/opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/security/SessionManager.java @@ -83,7 +83,7 @@ public class SessionManager implements ISessionManager { while (sessIterator.hasNext()) { HttpSession session = sessIterator.next(); if (session != null && sessionId != null && session.getId() != null && !session.getId().equals(sessionId)) { - sessionsList.add(session); + sessionsList.add(session); sessIterator.remove(); } else { diff --git a/opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/security/UserSecurityContextRepository.java b/opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/security/UserSecurityContextRepository.java similarity index 100% rename from opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/security/UserSecurityContextRepository.java rename to opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/security/UserSecurityContextRepository.java diff --git a/opendaylight/usermanager/implementation/src/test/java/org/opendaylight/controller/usermanager/internal/AuthenticatedUserTest.java b/opendaylight/usermanager/implementation/src/test/java/org/opendaylight/controller/usermanager/internal/AuthenticatedUserTest.java new file mode 100644 index 0000000000..f4810c978f --- /dev/null +++ b/opendaylight/usermanager/implementation/src/test/java/org/opendaylight/controller/usermanager/internal/AuthenticatedUserTest.java @@ -0,0 +1,72 @@ +/* + * 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.usermanager.internal; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import org.opendaylight.controller.sal.authorization.UserLevel; +import org.springframework.security.core.GrantedAuthority; + +public class AuthenticatedUserTest { + + static String[] roleArray; + static AuthenticatedUser user; + + @BeforeClass + public static void testSetup() { + roleArray = new String[] { UserLevel.NETWORKOPERATOR.toString(), + UserLevel.APPUSER.toString() }; + } + + @Test + public void testAuthenticatedUser() { + user = new AuthenticatedUser("auser"); + + Assert.assertFalse(user.getAccessDate().isEmpty()); + Assert.assertNull(user.getUserRoles()); + } + + @Test + public void testSetUserRoleList() { + List retrievedRoleList = null; + List roleList = Arrays.asList(roleArray); + + // list arg + user = new AuthenticatedUser("auser"); + user.setRoleList(roleList); + retrievedRoleList = user.getUserRoles(); + Assert.assertTrue(roleList.equals(retrievedRoleList)); + + // array arg + user = new AuthenticatedUser("auser"); + user.setRoleList(roleArray); + retrievedRoleList = user.getUserRoles(); + for (int i = 0; i < roleArray.length; i++) + Assert.assertTrue(roleArray[i].equals(retrievedRoleList.get(i))); + + // test addUserRole + user.addUserRole("AnotherRole"); + Assert.assertTrue(user.getUserRoles().lastIndexOf("AnotherRole") != -1); + + } + + @Test + public void testGetGrantedAuthorities() { + List gaList = user + .getGrantedAuthorities(UserLevel.NETWORKOPERATOR); + Assert.assertTrue(gaList.get(0).getAuthority() + .equals("ROLE_NETWORK-OPERATOR")); + } + +} diff --git a/opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/UserManagerImplTest.java b/opendaylight/usermanager/implementation/src/test/java/org/opendaylight/controller/usermanager/internal/UserManagerImplTest.java similarity index 88% rename from opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/UserManagerImplTest.java rename to opendaylight/usermanager/implementation/src/test/java/org/opendaylight/controller/usermanager/internal/UserManagerImplTest.java index 626011bd69..e8748d8200 100644 --- a/opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/UserManagerImplTest.java +++ b/opendaylight/usermanager/implementation/src/test/java/org/opendaylight/controller/usermanager/internal/UserManagerImplTest.java @@ -25,6 +25,9 @@ import org.opendaylight.controller.sal.utils.ServiceHelper; import org.opendaylight.controller.usermanager.AuthResponse; import org.opendaylight.controller.usermanager.IAAAProvider; import org.opendaylight.controller.usermanager.IUserManager; +import org.opendaylight.controller.usermanager.ServerConfig; +import org.opendaylight.controller.usermanager.UserConfig; +import org.opendaylight.controller.usermanager.AuthorizationConfig; /** * Unit Tests for UserManagerImpl @@ -55,14 +58,17 @@ public class UserManagerImplTest { // Server config can't be empty static final long serialVersionUID = 8645L; + @Override public String getAddress() { return "1.1.1.1"; } + @Override public String getSecret() { return "secret"; } + @Override public String getProtocol() { return "IPv4"; } @@ -80,11 +86,21 @@ public class UserManagerImplTest { "7029,7455,8165,7029,7881", roles)); } }); + + um.setAuthorizationConfList(new ConcurrentHashMap() { + static final long serialVersionUID = 2L; + { + List roles = new ArrayList(3); + roles.add(UserLevel.NETWORKOPERATOR.toString()); + roles.add("Container1-Admin"); + roles.add("Application2-User"); + + put("Andrew", new AuthorizationConfig("Andrew", roles)); + } + }); // instantiate an empty activeUser collection um.setActiveUsers(new ConcurrentHashMap()); - } - } /** @@ -97,11 +113,13 @@ public class UserManagerImplTest { // instantiate an anonymous AAAProvider IAAAProvider a3p = new IAAAProvider() { + @Override public AuthResponse authService(String userName, String password, String server, String secretKey) { return new AuthResponse(); }; + @Override public String getName() { return "dummyAAAProvider"; } @@ -142,7 +160,7 @@ public class UserManagerImplTest { /** * Test method for - * {@link org.opendaylight.controller.usermanager.internal.UserManagerImpl#addRemoveLocalUser(org.opendaylight.controller.usermanager.internal.UserConfig, boolean)} + * {@link org.opendaylight.controller.usermanager.internal.UserManagerImpl#addRemoveLocalUser(org.opendaylight.controller.usermanager.org.opendaylight.controller.usermanager.internal.UserConfig, boolean)} * . */ @Test @@ -254,6 +272,9 @@ public class UserManagerImplTest { Assert.assertTrue(um.getUserLevel("Jack") == UserLevel.SYSTEMADMIN); // Run the check on configured users Assert.assertTrue(um.getUserLevel("John") == UserLevel.NETWORKOPERATOR); - Assert.assertTrue(um.getUserLevel("Andrew") == UserLevel.NOUSER); + // Run the check on local authorized users + Assert.assertTrue(um.getUserLevel("Andrew") == UserLevel.NETWORKOPERATOR); + // Non locally known user + Assert.assertTrue(um.getUserLevel("Tom") == UserLevel.NOUSER); } } diff --git a/opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/AuthenticatedUserTest.java b/opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/AuthenticatedUserTest.java deleted file mode 100644 index 810500baa4..0000000000 --- a/opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/AuthenticatedUserTest.java +++ /dev/null @@ -1,72 +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.usermanager.internal; - -import java.util.Arrays; -import java.util.List; - -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import org.opendaylight.controller.sal.authorization.UserLevel; -import org.springframework.security.core.GrantedAuthority; - -public class AuthenticatedUserTest { - - static String[] roleArray; - static AuthenticatedUser user; - - @BeforeClass - public static void testSetup() { - roleArray = new String[] { UserLevel.NETWORKOPERATOR.toString(), - UserLevel.APPUSER.toString() }; - } - - @Test - public void testAuthenticatedUser() { - user = new AuthenticatedUser("auser"); - - Assert.assertFalse(user.getAccessDate().isEmpty()); - Assert.assertNull(user.getUserRoles()); - } - - @Test - public void testSetUserRoleList() { - List retrievedRoleList = null; - List roleList = Arrays.asList(roleArray); - - // list arg - user = new AuthenticatedUser("auser"); - user.setRoleList(roleList); - retrievedRoleList = user.getUserRoles(); - Assert.assertTrue(roleList.equals(retrievedRoleList)); - - // array arg - user = new AuthenticatedUser("auser"); - user.setRoleList(roleArray); - retrievedRoleList = user.getUserRoles(); - for (int i = 0; i < roleArray.length; i++) - Assert.assertTrue(roleArray[i].equals(retrievedRoleList.get(i))); - - // test addUserRole - user.addUserRole("AnotherRole"); - Assert.assertTrue(user.getUserRoles().lastIndexOf("AnotherRole") != -1); - - } - - @Test - public void testGetGrantedAuthorities() { - List gaList = user - .getGrantedAuthorities(UserLevel.NETWORKOPERATOR); - Assert.assertTrue(gaList.get(0).getAuthority() - .equals("ROLE_NETWORK-OPERATOR")); - } - -} diff --git a/opendaylight/web/devices/src/main/resources/WEB-INF/Devices-servlet.xml b/opendaylight/web/devices/src/main/resources/WEB-INF/Devices-servlet.xml index 6b0a731b99..af5cd8d456 100644 --- a/opendaylight/web/devices/src/main/resources/WEB-INF/Devices-servlet.xml +++ b/opendaylight/web/devices/src/main/resources/WEB-INF/Devices-servlet.xml @@ -3,19 +3,19 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" - xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - + - + - - + + diff --git a/opendaylight/web/devices/src/main/resources/WEB-INF/web.xml b/opendaylight/web/devices/src/main/resources/WEB-INF/web.xml index 0c7edce249..6294a9fb5b 100644 --- a/opendaylight/web/devices/src/main/resources/WEB-INF/web.xml +++ b/opendaylight/web/devices/src/main/resources/WEB-INF/web.xml @@ -1,75 +1,75 @@ - - - free access - /js/* - /images/* - /css/* - /favicon.ico - - + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" + version="3.0"> + + + free access + /js/* + /images/* + /css/* + /favicon.ico + + - - DevicesApp - - DevicesGUI - /* - - - System-Admin - Network-Admin - Network-Operator - Container-User - - + + DevicesApp + + DevicesGUI + /* + + + System-Admin + Network-Admin + Network-Operator + Container-User + + - - System-Admin - - - Network-Admin - - - Network-Operator - - - Container-User - + + System-Admin + + + Network-Admin + + + Network-Operator + + + Container-User + - - FORM - - /WEB-INF/jsp/login.jsp - /WEB-INF/jsp/error.jsp - - + + FORM + + /WEB-INF/jsp/login.jsp + /WEB-INF/jsp/error.jsp + + 403 /WEB-INF/jsp/autherror.jsp - - Devices - org.springframework.web.servlet.DispatcherServlet - 1 - + + Devices + org.springframework.web.servlet.DispatcherServlet + 1 + - - Devices - / - + + Devices + / + - - org.opendaylight.controller.web.ControllerUISessionManager - - - - / - - + + org.opendaylight.controller.web.ControllerUISessionManager + + + + / + + 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 7cb2b3a054..e1cfcc5708 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 @@ -76,7 +76,7 @@ public class Flows implements IDaylightWeb { @ResponseBody public Set> getFlows(HttpServletRequest request, @RequestParam(required = false) String container) { String containerName = DaylightWebUtil.getAuthorizedContainer(request, container, this); - + // fetch frm IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper .getInstance(IForwardingRulesManager.class, containerName, this); @@ -113,7 +113,7 @@ public class Flows implements IDaylightWeb { @ResponseBody public Map getNodePorts(HttpServletRequest request, @RequestParam(required = false) String container) { String containerName = DaylightWebUtil.getAuthorizedContainer(request, container, this); - + ISwitchManager switchManager = (ISwitchManager) ServiceHelper .getInstance(ISwitchManager.class, containerName, this); if (switchManager == null) { @@ -160,7 +160,7 @@ public class Flows implements IDaylightWeb { @ResponseBody public Map getNodeFlows(HttpServletRequest request, @RequestParam(required = false) String container) { String containerName = DaylightWebUtil.getAuthorizedContainer(request, container, this); - + ISwitchManager switchManager = (ISwitchManager) ServiceHelper .getInstance(ISwitchManager.class, containerName, this); if (switchManager == null) { @@ -201,7 +201,7 @@ public class Flows implements IDaylightWeb { if (!isUserAuthorized(UserLevel.NETWORKADMIN, request)) { return "Operation not authorized"; } - + String containerName = DaylightWebUtil.getAuthorizedContainer(request, container, this); IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper @@ -232,7 +232,7 @@ public class Flows implements IDaylightWeb { if (!isUserAuthorized(UserLevel.NETWORKADMIN, request)) { return "Operation not authorized"; } - + String containerName = DaylightWebUtil.getAuthorizedContainer(request, container, this); IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper @@ -261,7 +261,7 @@ public class Flows implements IDaylightWeb { /** * Returns whether the current user's level is same or above the required * authorization level. - * + * * @param requiredLevel * the authorization level required */ diff --git a/opendaylight/web/flows/src/main/resources/WEB-INF/Flows-servlet.xml b/opendaylight/web/flows/src/main/resources/WEB-INF/Flows-servlet.xml index fbe69795c2..293fa77ef1 100644 --- a/opendaylight/web/flows/src/main/resources/WEB-INF/Flows-servlet.xml +++ b/opendaylight/web/flows/src/main/resources/WEB-INF/Flows-servlet.xml @@ -3,19 +3,19 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" - xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - + - + - - + + diff --git a/opendaylight/web/flows/src/main/resources/WEB-INF/web.xml b/opendaylight/web/flows/src/main/resources/WEB-INF/web.xml index 5660a37a14..c5d2479f6b 100644 --- a/opendaylight/web/flows/src/main/resources/WEB-INF/web.xml +++ b/opendaylight/web/flows/src/main/resources/WEB-INF/web.xml @@ -1,79 +1,79 @@ + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" + version="3.0"> - - Flows - org.springframework.web.servlet.DispatcherServlet - 1 - + + Flows + org.springframework.web.servlet.DispatcherServlet + 1 + - - Flows - / - + + Flows + / + - - - free access - /js/* - /images/* - /css/* - /favicon.ico - - + + + free access + /js/* + /images/* + /css/* + /favicon.ico + + - - FlowApp - - FlowMgrGUI - /* - - - System-Admin - Network-Admin - Network-Operator - Container-User - - - - System-Admin - - - Network-Admin - - - Network-Operator - - - Container-User - + + FlowApp + + FlowMgrGUI + /* + + + System-Admin + Network-Admin + Network-Operator + Container-User + + + + System-Admin + + + Network-Admin + + + Network-Operator + + + Container-User + - - FORM - - /WEB-INF/jsp/login.jsp - /WEB-INF/jsp/error.jsp - - + + FORM + + /WEB-INF/jsp/login.jsp + /WEB-INF/jsp/error.jsp + + 403 /WEB-INF/jsp/autherror.jsp - - org.opendaylight.controller.web.ControllerUISessionManager - + + org.opendaylight.controller.web.ControllerUISessionManager + - - - / - - + + + / + + 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 46b8d4e0fe..ba2075ddb6 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 @@ -17,7 +17,7 @@ import org.opendaylight.controller.sal.utils.ServiceHelper; import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.sal.utils.StatusCode; import org.opendaylight.controller.usermanager.IUserManager; -import org.opendaylight.controller.usermanager.internal.UserConfig; +import org.opendaylight.controller.usermanager.UserConfig; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -95,7 +95,7 @@ public class DaylightWebAdmin { return userManager.removeLocalUser(userName).getDescription(); } - + @RequestMapping(value = "/users/password/{username}", method = RequestMethod.POST) @ResponseBody public Status changePassword(@PathVariable("username") String username, HttpServletRequest request, @@ -105,23 +105,23 @@ public class DaylightWebAdmin { if (userManager == null) { return new Status(StatusCode.GONE, "User Manager not found"); } - + if (!authorize(userManager, UserLevel.NETWORKADMIN, request)) { return new Status(StatusCode.FORBIDDEN, "Operation not permitted"); } - + if (newPassword.isEmpty()) { return new Status(StatusCode.BADREQUEST, "Empty passwords not allowed"); } - + Status status = userManager.changeLocalUserPassword(username, currentPassword, newPassword); - + return status; } /** * Is the operation permitted for the given level - * + * * @param level */ private boolean authorize(IUserManager userManager, UserLevel level, diff --git a/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebUtil.java b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebUtil.java index ee8284e883..a7f7133cb2 100644 --- a/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebUtil.java +++ b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebUtil.java @@ -11,11 +11,11 @@ import org.opendaylight.controller.sal.utils.ServiceHelper; public class DaylightWebUtil { private static String defaultName = GlobalConstants.DEFAULT.toString(); - + /** * Returns the container that this user is authorized to access. If the user is not authorized to the requested * container, then this method will return the default container. - * + * * @param request - HttpServletRequest object to retrieve username * @param container - requested container * @param bundle - respective bundle @@ -25,7 +25,7 @@ public class DaylightWebUtil { if (container == null) { return defaultName; } - + String username = request.getUserPrincipal().getName(); IContainerAuthorization containerAuthorization = (IContainerAuthorization) ServiceHelper.getGlobalInstance(IContainerAuthorization.class, bundle); diff --git a/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/IDaylightWeb.java b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/IDaylightWeb.java index 55e3ee5110..7421759d98 100644 --- a/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/IDaylightWeb.java +++ b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/IDaylightWeb.java @@ -14,31 +14,31 @@ public interface IDaylightWeb { /** * Returns the name of the bundle. In the GUI, this name will be displayed * on the tab. - * + * * @return Name assigned to the bundle. */ public String getWebName(); /** * Returns the Id assigned to the web bundle. - * + * * @return Id assigned to the web bundle. */ public String getWebId(); /** * Returns the position where the bundle tab will be placed in the GUI. - * + * * @return Position number for the bundle tab. */ public short getWebOrder(); /** * This method checks if the user is authorized to access the bundle. - * + * * @param userLevel * user role level in the controller space. - * + * * @return true, if user is authorized to access the bundle, else false. */ public boolean isAuthorized(UserLevel userLevel); diff --git a/opendaylight/web/root/src/main/resources/WEB-INF/RootGUI-servlet.xml b/opendaylight/web/root/src/main/resources/WEB-INF/RootGUI-servlet.xml index a818c8e6c9..a8cb864367 100644 --- a/opendaylight/web/root/src/main/resources/WEB-INF/RootGUI-servlet.xml +++ b/opendaylight/web/root/src/main/resources/WEB-INF/RootGUI-servlet.xml @@ -3,19 +3,19 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" - xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - + - + - - + + \ No newline at end of file diff --git a/opendaylight/web/root/src/main/resources/WEB-INF/spring/servlet/security.xml b/opendaylight/web/root/src/main/resources/WEB-INF/spring/servlet/security.xml index 18ac6e7ecb..1e373fb56c 100644 --- a/opendaylight/web/root/src/main/resources/WEB-INF/spring/servlet/security.xml +++ b/opendaylight/web/root/src/main/resources/WEB-INF/spring/servlet/security.xml @@ -1,82 +1,82 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" /> + + @@ -88,33 +88,33 @@ - - + + + + + + + + - - - - - + + + + + + + - - - - - - - + - + + + - - - - diff --git a/opendaylight/web/root/src/main/resources/WEB-INF/web.xml b/opendaylight/web/root/src/main/resources/WEB-INF/web.xml index d96fb6eba2..557b9c74f5 100644 --- a/opendaylight/web/root/src/main/resources/WEB-INF/web.xml +++ b/opendaylight/web/root/src/main/resources/WEB-INF/web.xml @@ -1,84 +1,84 @@ - + + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" + version="3.0"> - - - free access - /js/* - /images/* - /css/* - /favicon.ico - - + + + free access + /js/* + /images/* + /css/* + /favicon.ico + + - - RootApp - - RootGUI - /* - - - System-Admin - Network-Admin - Network-Operator - Container-User - - + + RootApp + + RootGUI + /* + + + System-Admin + Network-Admin + Network-Operator + Container-User + + - - System-Admin - - - Network-Admin - - - Network-Operator - - - Container-User - + + System-Admin + + + Network-Admin + + + Network-Operator + + + Container-User + - - FORM - - /WEB-INF/jsp/login.jsp - /WEB-INF/jsp/error.jsp - - + + FORM + + /WEB-INF/jsp/login.jsp + /WEB-INF/jsp/error.jsp + + 403 /WEB-INF/jsp/autherror.jsp - - RootGUI - org.springframework.web.servlet.DispatcherServlet - 1 - + + RootGUI + org.springframework.web.servlet.DispatcherServlet + 1 + - - RootGUI - / - + + RootGUI + / + - OpenDaylight Controller - OpenDaylight Controller + OpenDaylight Controller + OpenDaylight Controller - - org.opendaylight.controller.web.ControllerUISessionManager - + + org.opendaylight.controller.web.ControllerUISessionManager + - - - / - - + + + / + + diff --git a/opendaylight/web/topology/src/main/java/org/opendaylight/controller/topology/web/Topology.java b/opendaylight/web/topology/src/main/java/org/opendaylight/controller/topology/web/Topology.java index b4695defdb..62b64a5184 100644 --- a/opendaylight/web/topology/src/main/java/org/opendaylight/controller/topology/web/Topology.java +++ b/opendaylight/web/topology/src/main/java/org/opendaylight/controller/topology/web/Topology.java @@ -70,77 +70,77 @@ public class Topology implements IObjectReader, IConfigurationAware { protected Map>> metaCache = new HashMap>>(); protected Map> stagedNodes; protected Map> newNodes; - + protected Map metaNodeHash = new HashMap(); protected Map metaHostHash = new HashMap(); protected Map metaNodeSingleHash = new HashMap(); protected Map metaNodeConfigurationHash = new HashMap(); - + public Topology() { - ServiceHelper.registerGlobalService(IConfigurationAware.class, this, null); - topologyWebFileName = ROOT + "topologyCache.sav"; - loadConfiguration(); + ServiceHelper.registerGlobalService(IConfigurationAware.class, this, null); + topologyWebFileName = ROOT + "topologyCache.sav"; + loadConfiguration(); } - + /** * Topology of nodes and hosts in the network in JSON format. - * + * * Mainly intended for consumption by the visual topology. - * + * * @return - JSON output for visual topology */ @RequestMapping(value = "/visual.json", method = RequestMethod.GET) @ResponseBody public Collection> getLinkData(@RequestParam(required = false) String container, HttpServletRequest request) { - String containerName = DaylightWebUtil.getAuthorizedContainer(request, container, this); - + String containerName = DaylightWebUtil.getAuthorizedContainer(request, container, this); + ITopologyManager topologyManager = (ITopologyManager) ServiceHelper .getInstance(ITopologyManager.class, containerName, this); if (topologyManager == null) { - return null; + return null; } ISwitchManager switchManager = (ISwitchManager) ServiceHelper .getInstance(ISwitchManager.class, containerName, this); if (switchManager == null) { - return null; + return null; } - + Map> nodeEdges = topologyManager.getNodeEdges(); Map> hostEdges = topologyManager .getNodesWithNodeConnectorHost(); List nodes = switchManager.getNetworkDevices(); - + List switchConfigurations = new ArrayList(); for(Switch sw : nodes) { - Node n = sw.getNode(); - SwitchConfig config = switchManager.getSwitchConfig(n.toString()); - switchConfigurations.add(config); + Node n = sw.getNode(); + SwitchConfig config = switchManager.getSwitchConfig(n.toString()); + switchConfigurations.add(config); } - + // initialize cache if needed if (!metaCache.containsKey(containerName)) { - metaCache.put(containerName, new HashMap>()); - // initialize hashes - metaNodeHash.put(containerName, null); - metaHostHash.put(containerName, null); - metaNodeSingleHash.put(containerName, null); - metaNodeConfigurationHash.put(containerName, null); + metaCache.put(containerName, new HashMap>()); + // initialize hashes + metaNodeHash.put(containerName, null); + metaHostHash.put(containerName, null); + metaNodeSingleHash.put(containerName, null); + metaNodeConfigurationHash.put(containerName, null); } - + // return cache if topology hasn't changed if ( - (metaNodeHash.get(containerName) != null && metaHostHash.get(containerName) != null && metaNodeSingleHash.get(containerName) != null && metaNodeConfigurationHash.get(containerName) != null) && - metaNodeHash.get(containerName).equals(nodeEdges.hashCode()) && metaHostHash.get(containerName).equals(hostEdges.hashCode()) && metaNodeSingleHash.get(containerName).equals(nodes.hashCode()) && metaNodeConfigurationHash.get(containerName).equals(switchConfigurations.hashCode()) + (metaNodeHash.get(containerName) != null && metaHostHash.get(containerName) != null && metaNodeSingleHash.get(containerName) != null && metaNodeConfigurationHash.get(containerName) != null) && + metaNodeHash.get(containerName).equals(nodeEdges.hashCode()) && metaHostHash.get(containerName).equals(hostEdges.hashCode()) && metaNodeSingleHash.get(containerName).equals(nodes.hashCode()) && metaNodeConfigurationHash.get(containerName).equals(switchConfigurations.hashCode()) ) { - return metaCache.get(containerName).values(); + return metaCache.get(containerName).values(); } - + // cache has changed, we must assign the new values metaNodeHash.put(containerName, nodeEdges.hashCode()); metaHostHash.put(containerName, hostEdges.hashCode()); metaNodeSingleHash.put(containerName, nodes.hashCode()); metaNodeConfigurationHash.put(containerName, switchConfigurations.hashCode()); - + stagedNodes = new HashMap>(); newNodes = new HashMap>(); @@ -149,12 +149,12 @@ public class Topology implements IObjectReader, IConfigurationAware { // single nodes addition addSingleNodes(nodes, switchManager, containerName); - + // hostNodes addition addHostNodes(hostEdges, topologyManager, containerName); - + repositionTopology(containerName); - + return metaCache.get(containerName).values(); } @@ -165,20 +165,20 @@ public class Topology implements IObjectReader, IConfigurationAware { * @param topology - the topology instance */ private void addNodes(Map> nodeEdges, - ITopologyManager topology, ISwitchManager switchManager, String containerName) { + ITopologyManager topology, ISwitchManager switchManager, String containerName) { Bandwidth bandwidth = new Bandwidth(0); Map> properties = topology.getEdges(); - + for (Map.Entry> e : nodeEdges.entrySet()) { Node n = e.getKey(); String description = switchManager.getNodeDescription(n); NodeBean node = createNodeBean(description, n); - + // skip production node if (nodeIgnore(n)) { continue; } - + List> adjacencies = new LinkedList>(); Set links = e.getValue(); for (Edge link : links) { @@ -187,53 +187,53 @@ public class Topology implements IObjectReader, IConfigurationAware { } for (Property p : properties.get(link)) { if (p instanceof Bandwidth) { - bandwidth = (Bandwidth) p; + bandwidth = (Bandwidth) p; break; } } EdgeBean edge = new EdgeBean(link, bandwidth); adjacencies.add(edge.out()); } - + node.setLinks(adjacencies); if (metaCache.get(containerName).containsKey(node.id())) { - // retrieve node from cache - Map nodeEntry = metaCache.get(containerName).get(node.id()); - - Map data = (Map) nodeEntry.get("data"); - data.put("$desc", description); - nodeEntry.put("data", data); - - // always update adjacencies - nodeEntry.put("adjacencies", adjacencies); - // stage this cached node (with position) - stagedNodes.put(node.id(), nodeEntry); + // retrieve node from cache + Map nodeEntry = metaCache.get(containerName).get(node.id()); + + Map data = (Map) nodeEntry.get("data"); + data.put("$desc", description); + nodeEntry.put("data", data); + + // always update adjacencies + nodeEntry.put("adjacencies", adjacencies); + // stage this cached node (with position) + stagedNodes.put(node.id(), nodeEntry); } else { - newNodes.put(node.id(), node.out()); + newNodes.put(node.id(), node.out()); } } } - + /** * Check if this node shouldn't appear in the visual topology - * + * * @param node * @return */ private boolean nodeIgnore(Node node) { String nodeType = node.getType(); - + // add other node types to ignore later if (nodeType.equals(NodeIDType.PRODUCTION)) { return true; } - + return false; } - + /** * Check if this edge shouldn't appear in the visual topology - * + * * @param edge * @return */ @@ -243,57 +243,57 @@ public class Topology implements IObjectReader, IConfigurationAware { if (nodeIgnore(headNode)) { return true; } - + NodeConnector tailNodeConnector = edge.getTailNodeConnector(); Node tailNode = tailNodeConnector.getNode(); if (nodeIgnore(tailNode)) { return true; } - + return false; } - + protected NodeBean createNodeBean(String description, Node node) { - String name = (description == null || - description.trim().isEmpty() || - description.equalsIgnoreCase("none"))? - node.toString() : description; - return new NodeBean(node.toString(), name, NodeType.NODE); + String name = (description == null || + description.trim().isEmpty() || + description.equalsIgnoreCase("none"))? + node.toString() : description; + return new NodeBean(node.toString(), name, NodeType.NODE); } - + @SuppressWarnings("unchecked") - private void addSingleNodes(List nodes, ISwitchManager switchManager, String containerName) { - if (nodes == null) { - return; - } - for (Switch sw : nodes) { - Node n = sw.getNode(); - - // skip production node - if (nodeIgnore(n)) { - continue; - } - - String description = switchManager.getNodeDescription(n); - - if ((stagedNodes.containsKey(n.toString()) && metaCache.get(containerName).containsKey(n.toString())) || newNodes.containsKey(n.toString())) { - continue; - } - NodeBean node = createNodeBean(description, n); - - // FIXME still doesn't display standalone node when last remaining link is removed - if (metaCache.get(containerName).containsKey(node.id()) && !stagedNodes.containsKey(node.id())) { - Map nodeEntry = metaCache.get(containerName).get(node.id()); - Map data = (Map) nodeEntry.get("data"); - data.put("$desc", description); - nodeEntry.put("data", data); - // clear adjacencies since this is now a single node - nodeEntry.put("adjacencies", new LinkedList>()); - stagedNodes.put(node.id(), nodeEntry); + private void addSingleNodes(List nodes, ISwitchManager switchManager, String containerName) { + if (nodes == null) { + return; + } + for (Switch sw : nodes) { + Node n = sw.getNode(); + + // skip production node + if (nodeIgnore(n)) { + continue; + } + + String description = switchManager.getNodeDescription(n); + + if ((stagedNodes.containsKey(n.toString()) && metaCache.get(containerName).containsKey(n.toString())) || newNodes.containsKey(n.toString())) { + continue; + } + NodeBean node = createNodeBean(description, n); + + // FIXME still doesn't display standalone node when last remaining link is removed + if (metaCache.get(containerName).containsKey(node.id()) && !stagedNodes.containsKey(node.id())) { + Map nodeEntry = metaCache.get(containerName).get(node.id()); + Map data = (Map) nodeEntry.get("data"); + data.put("$desc", description); + nodeEntry.put("data", data); + // clear adjacencies since this is now a single node + nodeEntry.put("adjacencies", new LinkedList>()); + stagedNodes.put(node.id(), nodeEntry); } else { - newNodes.put(node.id(), node.out()); + newNodes.put(node.id(), node.out()); } - } + } } /** @@ -313,22 +313,22 @@ public class Topology implements IObjectReader, IConfigurationAware { addressByteBuffer.putShort((short) 0); addressByteBuffer.put(dmac.getValue()); addressByteBuffer.rewind(); - + long hid = addressByteBuffer.getLong(); String hostId = String.valueOf(hid); - + NodeBean hostBean = new NodeBean(hostId, host.getNetworkAddressAsString(), NodeType.HOST); List> adjacencies = new LinkedList>(); EdgeBean edge = new EdgeBean(connector, hid); adjacencies.add(edge.out()); hostBean.setLinks(adjacencies); - + if (metaCache.get(containerName).containsKey(hostId)) { - Map hostEntry = metaCache.get(containerName).get(hostId); - hostEntry.put("adjacencies", adjacencies); - stagedNodes.put(hostId, hostEntry); + Map hostEntry = metaCache.get(containerName).get(hostId); + hostEntry.put("adjacencies", adjacencies); + stagedNodes.put(hostId, hostEntry); } else { - newNodes.put(String.valueOf(hid), hostBean.out()); + newNodes.put(String.valueOf(hid), hostBean.out()); } } } @@ -339,24 +339,24 @@ public class Topology implements IObjectReader, IConfigurationAware { */ private void repositionTopology(String containerName) { Graph graph = new SparseMultigraph(); - + metaCache.get(containerName).clear(); metaCache.get(containerName).putAll(stagedNodes); metaCache.get(containerName).putAll(newNodes); - + for (Map on : metaCache.get(containerName).values()) { graph.addVertex(on.toString()); List> adjacencies = (List>) on.get("adjacencies"); - + for (Map adj : adjacencies) { graph.addEdge( - adj.toString(), adj.get("nodeFrom").toString(), - adj.get("nodeTo").toString() + adj.toString(), adj.get("nodeFrom").toString(), + adj.get("nodeTo").toString() ); } } - + CircleLayout layout = new CircleLayout(graph); layout.setSize(new Dimension(1200, 365)); for (Map.Entry> v : newNodes.entrySet()) { @@ -373,7 +373,7 @@ public class Topology implements IObjectReader, IConfigurationAware { /** * Update node position - * + * * This method is mainly used by the visual topology * * @param nodeId - The node to update @@ -382,16 +382,16 @@ public class Topology implements IObjectReader, IConfigurationAware { @RequestMapping(value = "/node/{nodeId}", method = RequestMethod.POST) @ResponseBody public Map post(@PathVariable String nodeId, @RequestParam(required = true) String x, - @RequestParam(required = true) String y, @RequestParam(required = false) String container, - HttpServletRequest request) { - if (!authorize(UserLevel.NETWORKADMIN, request)) { - return new HashMap(); // silently disregard new node position - } - - String containerName = getAuthorizedContainer(request, container); - + @RequestParam(required = true) String y, @RequestParam(required = false) String container, + HttpServletRequest request) { + if (!authorize(UserLevel.NETWORKADMIN, request)) { + return new HashMap(); // silently disregard new node position + } + + String containerName = getAuthorizedContainer(request, container); + String id = new String(nodeId); - + if (!metaCache.get(containerName).containsKey(id)) { return null; } @@ -403,123 +403,123 @@ public class Topology implements IObjectReader, IConfigurationAware { data.put("$y", y); node.put("data", data); - + return node; } - + /** * Node object for visual topology */ protected class NodeBean { - protected String id; - protected String name; - protected Map data; - protected List> links; - - public NodeBean() { - data = new HashMap(); - links = new ArrayList>(); - } - - public NodeBean(String id, String name, String type) { - this(); - this.id = id; - this.name = name; - data.put("$desc", name); - data.put("$type", type); - } - - public void setLinks(List> links) { - this.links = links; - } - - public Map out() { - Map node = new HashMap(); - node.put("id", this.id); - node.put("name", this.name); - node.put("data", this.data); - node.put("adjacencies", this.links); - - return node; - } - - public String name() { - return this.name; - } - - public String id() { - return this.id; - } + protected String id; + protected String name; + protected Map data; + protected List> links; + + public NodeBean() { + data = new HashMap(); + links = new ArrayList>(); + } + + public NodeBean(String id, String name, String type) { + this(); + this.id = id; + this.name = name; + data.put("$desc", name); + data.put("$type", type); + } + + public void setLinks(List> links) { + this.links = links; + } + + public Map out() { + Map node = new HashMap(); + node.put("id", this.id); + node.put("name", this.name); + node.put("data", this.data); + node.put("adjacencies", this.links); + + return node; + } + + public String name() { + return this.name; + } + + public String id() { + return this.id; + } } - + /** * Edge object for visual topology */ protected class EdgeBean { - protected NodeConnector source; - protected NodeConnector destination; - protected Map data; - protected Long hostId; - - public EdgeBean() { - data = new HashMap(); - } - - public EdgeBean(Edge link, Bandwidth bandwidth) { - this(); - this.source = link.getHeadNodeConnector(); - this.destination = link.getTailNodeConnector(); - - // data - data.put("$bandwidth", bandwidth.toString()); - data.put("$color", bandwidthColor(bandwidth)); - data.put("$nodeToPort", destination.getID().toString()); - data.put("$nodeFromPort", source.getID().toString()); - data.put("$descFrom", source.getNode().toString()); - data.put("$descTo", destination.getNode().toString()); - data.put("$nodeFromPortName", source.toString()); - data.put("$nodeToPortName", destination.toString()); - } - - public EdgeBean(NodeConnector connector, Long hostId) { - this(); - this.source = null; - this.destination = connector; - this.hostId = hostId; - - data.put("$bandwidth", "N/A"); - data.put("$color", bandwidthColor(new Bandwidth(0))); - data.put("$nodeToPort", connector.getNodeConnectorIDString()); - data.put("$nodeFromPort", connector.getNodeConnectorIDString()); - data.put("$descTo", ""); - data.put("$descFrom", ""); - data.put("$nodeToPortName", ""); - data.put("$nodeFromPortName", ""); - } - - public Map out() { - Map edge = new HashMap(); - - edge.put("data", data); - if (source == null) { - edge.put("nodeFrom", String.valueOf(this.hostId)); - } else { - edge.put("nodeFrom", source.getNode().toString()); - } - edge.put("nodeTo", destination.getNode().toString()); - - - return edge; - } - - private String bandwidthColor(Bandwidth bandwidth) { - String color = null; - long bandwidthValue = bandwidth.getValue(); - - if (bandwidthValue == 0) { + protected NodeConnector source; + protected NodeConnector destination; + protected Map data; + protected Long hostId; + + public EdgeBean() { + data = new HashMap(); + } + + public EdgeBean(Edge link, Bandwidth bandwidth) { + this(); + this.source = link.getHeadNodeConnector(); + this.destination = link.getTailNodeConnector(); + + // data + data.put("$bandwidth", bandwidth.toString()); + data.put("$color", bandwidthColor(bandwidth)); + data.put("$nodeToPort", destination.getID().toString()); + data.put("$nodeFromPort", source.getID().toString()); + data.put("$descFrom", source.getNode().toString()); + data.put("$descTo", destination.getNode().toString()); + data.put("$nodeFromPortName", source.toString()); + data.put("$nodeToPortName", destination.toString()); + } + + public EdgeBean(NodeConnector connector, Long hostId) { + this(); + this.source = null; + this.destination = connector; + this.hostId = hostId; + + data.put("$bandwidth", "N/A"); + data.put("$color", bandwidthColor(new Bandwidth(0))); + data.put("$nodeToPort", connector.getNodeConnectorIDString()); + data.put("$nodeFromPort", connector.getNodeConnectorIDString()); + data.put("$descTo", ""); + data.put("$descFrom", ""); + data.put("$nodeToPortName", ""); + data.put("$nodeFromPortName", ""); + } + + public Map out() { + Map edge = new HashMap(); + + edge.put("data", data); + if (source == null) { + edge.put("nodeFrom", String.valueOf(this.hostId)); + } else { + edge.put("nodeFrom", source.getNode().toString()); + } + edge.put("nodeTo", destination.getNode().toString()); + + + return edge; + } + + private String bandwidthColor(Bandwidth bandwidth) { + String color = null; + long bandwidthValue = bandwidth.getValue(); + + if (bandwidthValue == 0) { color = "#000"; } else if (bandwidthValue < Bandwidth.BW1Kbps) { - color = "#148AC6"; + color = "#148AC6"; } else if (bandwidthValue < Bandwidth.BW1Mbps) { color = "#2858A0"; } else if (bandwidthValue < Bandwidth.BW1Gbps) { @@ -529,58 +529,58 @@ public class Topology implements IObjectReader, IConfigurationAware { } else if (bandwidthValue < Bandwidth.BW1Pbps) { color = "#F9F464"; } - - return color; + + return color; } } - + protected class NodeType { - public static final String NODE = "swtch"; - public static final String HOST = "host"; + public static final String NODE = "swtch"; + public static final String HOST = "host"; } - + private boolean authorize(UserLevel level, HttpServletRequest request) { - IUserManager userManager = (IUserManager) ServiceHelper + IUserManager userManager = (IUserManager) ServiceHelper .getGlobalInstance(IUserManager.class, this); if (userManager == null) { - return false; + return false; } - + String username = request.getUserPrincipal().getName(); UserLevel userLevel = userManager.getUserLevel(username); if (userLevel.toNumber() <= level.toNumber()) { - return true; + return true; } return false; } - + private String getAuthorizedContainer(HttpServletRequest request, String container) { - String username = request.getUserPrincipal().getName(); - IContainerAuthorization containerAuthorization = (IContainerAuthorization) ServiceHelper. - getGlobalInstance(IContainerAuthorization.class, this); - if (containerAuthorization != null) { - Set resources = containerAuthorization.getAllResourcesforUser(username); - if (authorizeContainer(container, resources)) { - return container; - } - } - - return GlobalConstants.DEFAULT.toString(); + String username = request.getUserPrincipal().getName(); + IContainerAuthorization containerAuthorization = (IContainerAuthorization) ServiceHelper. + getGlobalInstance(IContainerAuthorization.class, this); + if (containerAuthorization != null) { + Set resources = containerAuthorization.getAllResourcesforUser(username); + if (authorizeContainer(container, resources)) { + return container; + } + } + + return GlobalConstants.DEFAULT.toString(); } - + private boolean authorizeContainer(String container, Set resources) { - for(Resource resource : resources) { - String containerName = (String) resource.getResource(); - if (containerName.equals(container)) { - return true; - } - } - - return false; + for(Resource resource : resources) { + String containerName = (String) resource.getResource(); + if (containerName.equals(container)) { + return true; + } + } + + return false; } @SuppressWarnings("unchecked") - private void loadConfiguration() { + private void loadConfiguration() { ObjectReader objReader = new ObjectReader(); metaCache = (Map>>) objReader.read(this, topologyWebFileName); if (metaCache == null) metaCache = new HashMap>>(); diff --git a/opendaylight/web/topology/src/main/resources/WEB-INF/Topology-servlet.xml b/opendaylight/web/topology/src/main/resources/WEB-INF/Topology-servlet.xml index 1c05bbcd7e..cb6f2b6973 100644 --- a/opendaylight/web/topology/src/main/resources/WEB-INF/Topology-servlet.xml +++ b/opendaylight/web/topology/src/main/resources/WEB-INF/Topology-servlet.xml @@ -3,19 +3,19 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" - xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - + - + - - + + diff --git a/opendaylight/web/topology/src/main/resources/WEB-INF/web.xml b/opendaylight/web/topology/src/main/resources/WEB-INF/web.xml index 274908caec..c37fffe500 100644 --- a/opendaylight/web/topology/src/main/resources/WEB-INF/web.xml +++ b/opendaylight/web/topology/src/main/resources/WEB-INF/web.xml @@ -1,78 +1,78 @@ - - - free access - /js/* - /images/* - /css/* - /favicon.ico - - + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" + version="3.0"> + + + free access + /js/* + /images/* + /css/* + /favicon.ico + + - - TopologyApp - - TopoGUI - /* - - - System-Admin - Network-Admin - Network-Operator - Container-User - - - - System-Admin - - - Network-Admin - - - Network-Operator - - - Container-User - + + TopologyApp + + TopoGUI + /* + + + System-Admin + Network-Admin + Network-Operator + Container-User + + + + System-Admin + + + Network-Admin + + + Network-Operator + + + Container-User + - - FORM - - /WEB-INF/jsp/login.jsp - /WEB-INF/jsp/error.jsp - - + + FORM + + /WEB-INF/jsp/login.jsp + /WEB-INF/jsp/error.jsp + + 403 /WEB-INF/jsp/autherror.jsp - - Topology - org.springframework.web.servlet.DispatcherServlet - 1 - + + Topology + org.springframework.web.servlet.DispatcherServlet + 1 + - - Topology - / - + + Topology + / + - - org.opendaylight.controller.web.ControllerUISessionManager - + + org.opendaylight.controller.web.ControllerUISessionManager + - - - / - - + + + / + + diff --git a/opendaylight/web/topology/src/test/java/org/opendaylight/controller/topology/web/TopologyTest.java b/opendaylight/web/topology/src/test/java/org/opendaylight/controller/topology/web/TopologyTest.java index e26e7c666b..e33af082b6 100644 --- a/opendaylight/web/topology/src/test/java/org/opendaylight/controller/topology/web/TopologyTest.java +++ b/opendaylight/web/topology/src/test/java/org/opendaylight/controller/topology/web/TopologyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * 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, @@ -16,32 +16,32 @@ import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.utils.NodeCreator; import org.opendaylight.controller.switchmanager.SwitchConfig; import org.opendaylight.controller.topology.web.Topology.NodeBean; - + public class TopologyTest { - @Test - public void testCreateNodeBean() { - Topology topology = new Topology(); - Node node = NodeCreator.createOFNode(new Long(3)); - String description = "foo"; - - NodeBean bean = topology.createNodeBean(description, node); - - assertNotNull(bean); - assertEquals(bean.id, node.toString()); - assertEquals(bean.name, "foo"); - - bean = topology.createNodeBean(null, node); - - assertNotNull(bean); - assertEquals(bean.id, node.toString()); - assertEquals(bean.name, bean.id); - - bean = topology.createNodeBean(" ", node); - - assertNotNull(bean); - assertEquals(bean.id, node.toString()); - assertEquals(bean.name, bean.id); - } + @Test + public void testCreateNodeBean() { + Topology topology = new Topology(); + Node node = NodeCreator.createOFNode(new Long(3)); + String description = "foo"; + + NodeBean bean = topology.createNodeBean(description, node); + + assertNotNull(bean); + assertEquals(bean.id, node.toString()); + assertEquals(bean.name, "foo"); + + bean = topology.createNodeBean(null, node); + + assertNotNull(bean); + assertEquals(bean.id, node.toString()); + assertEquals(bean.name, bean.id); + + bean = topology.createNodeBean(" ", node); + + assertNotNull(bean); + assertEquals(bean.id, node.toString()); + assertEquals(bean.name, bean.id); + } } diff --git a/opendaylight/web/troubleshoot/src/main/java/org/opendaylight/controller/troubleshoot/web/Troubleshoot.java b/opendaylight/web/troubleshoot/src/main/java/org/opendaylight/controller/troubleshoot/web/Troubleshoot.java index f145c568b5..bde4152f5b 100644 --- a/opendaylight/web/troubleshoot/src/main/java/org/opendaylight/controller/troubleshoot/web/Troubleshoot.java +++ b/opendaylight/web/troubleshoot/src/main/java/org/opendaylight/controller/troubleshoot/web/Troubleshoot.java @@ -231,10 +231,10 @@ public class Troubleshoot implements IDaylightWeb { Match match = flow.getMatch(); ISwitchManager switchManager = (ISwitchManager) ServiceHelper .getInstance(ISwitchManager.class, containerName, this); - String desc = (switchManager == null)? - "" : switchManager.getNodeDescription(node); - desc = (desc.isEmpty() || desc.equalsIgnoreCase("none"))? - node.toString(): desc; + String desc = (switchManager == null)? + "" : switchManager.getNodeDescription(node); + desc = (desc.isEmpty() || desc.equalsIgnoreCase("none"))? + node.toString(): desc; row.put("nodeName", desc); if (match.isPresent(MatchType.IN_PORT)) { row.put(MatchType.IN_PORT.id(), ((NodeConnector) flow.getMatch() @@ -300,7 +300,7 @@ public class Troubleshoot implements IDaylightWeb { Short tpSrc = (Short) (flow.getMatch().getField(MatchType.TP_SRC) .getValue()); row.put(MatchType.TP_SRC.id(), - String.valueOf(NetUtils.getUnsignedShort(tpSrc))); + String.valueOf(NetUtils.getUnsignedShort(tpSrc))); } else { row.put(MatchType.TP_SRC.id(), "*"); } @@ -308,7 +308,7 @@ public class Troubleshoot implements IDaylightWeb { Short tpDst = (Short) (flow.getMatch().getField(MatchType.TP_DST) .getValue()); row.put(MatchType.TP_DST.id(), - String.valueOf(NetUtils.getUnsignedShort(tpDst))); + String.valueOf(NetUtils.getUnsignedShort(tpDst))); } else { row.put(MatchType.TP_DST.id(), "*"); } diff --git a/opendaylight/web/troubleshoot/src/main/resources/WEB-INF/Troubleshoot-servlet.xml b/opendaylight/web/troubleshoot/src/main/resources/WEB-INF/Troubleshoot-servlet.xml index 877617a975..91e22f6dad 100644 --- a/opendaylight/web/troubleshoot/src/main/resources/WEB-INF/Troubleshoot-servlet.xml +++ b/opendaylight/web/troubleshoot/src/main/resources/WEB-INF/Troubleshoot-servlet.xml @@ -3,19 +3,19 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" - xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - + - + - - + + diff --git a/opendaylight/web/troubleshoot/src/main/resources/WEB-INF/web.xml b/opendaylight/web/troubleshoot/src/main/resources/WEB-INF/web.xml index 47d38f9a53..2d89e9d975 100644 --- a/opendaylight/web/troubleshoot/src/main/resources/WEB-INF/web.xml +++ b/opendaylight/web/troubleshoot/src/main/resources/WEB-INF/web.xml @@ -1,81 +1,81 @@ + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" + version="3.0"> - - Troubleshoot - org.springframework.web.servlet.DispatcherServlet - 1 - + + Troubleshoot + org.springframework.web.servlet.DispatcherServlet + 1 + - - Troubleshoot - / - + + Troubleshoot + / + - - - free access - /js/* - /images/* - /css/* - /favicon.ico - - + + + free access + /js/* + /images/* + /css/* + /favicon.ico + + - - TroubleShootApp - - TroubleShootGUI - /* - - - System-Admin - Network-Admin - Network-Operator - Container-User - - + + TroubleShootApp + + TroubleShootGUI + /* + + + System-Admin + Network-Admin + Network-Operator + Container-User + + - - System-Admin - - - Network-Admin - - - Network-Operator - - - Container-User - + + System-Admin + + + Network-Admin + + + Network-Operator + + + Container-User + - - FORM - - /WEB-INF/jsp/login.jsp - /WEB-INF/jsp/error.jsp - - + + FORM + + /WEB-INF/jsp/login.jsp + /WEB-INF/jsp/error.jsp + + 403 /WEB-INF/jsp/autherror.jsp - - org.opendaylight.controller.web.ControllerUISessionManager - + + org.opendaylight.controller.web.ControllerUISessionManager + - - - / - - + + + / + +