From: Ed Warnicke Date: Thu, 5 Dec 2013 22:49:36 +0000 (+0000) Subject: Merge "Fixed Group and meter id bugs" X-Git-Tag: jenkins-controller-bulk-release-prepare-only-2-1~249 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=e640f23d9c37afac9ca51f48e155302bc65327ed;hp=18d8f268c059c3ec15672a3359ef667460c874dc Merge "Fixed Group and meter id bugs" --- diff --git a/opendaylight/clustering/integrationtest/pom.xml b/opendaylight/clustering/integrationtest/pom.xml index ca1e37e3be..1e317765c4 100644 --- a/opendaylight/clustering/integrationtest/pom.xml +++ b/opendaylight/clustering/integrationtest/pom.xml @@ -21,12 +21,12 @@ org.opendaylight.controller clustering.services - 0.4.1-SNAPSHOT + 0.5.0-SNAPSHOT org.opendaylight.controller sal - 0.5.1-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller diff --git a/opendaylight/clustering/services/pom.xml b/opendaylight/clustering/services/pom.xml index 7eede83638..ebaffc29df 100644 --- a/opendaylight/clustering/services/pom.xml +++ b/opendaylight/clustering/services/pom.xml @@ -16,7 +16,7 @@ clustering.services - 0.4.1-SNAPSHOT + 0.5.0-SNAPSHOT bundle diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServices.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServices.java index 77e300e95a..b3427c7fcc 100644 --- a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServices.java +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServices.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Properties; import java.util.Set; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; @@ -215,6 +216,16 @@ public interface IClusterServices { */ void tbegin() throws NotSupportedException, SystemException; + /** + * tbegin with a timeout + * @see IClusterServices#tbegin + * @param timeout the transaction timeout + * @param unit TimeUnit for the timeout + * @throws NotSupportedException + * @throws SystemException + */ + void tbegin(long timeout, TimeUnit unit) throws NotSupportedException, SystemException; + /** * Commit a transaction covering all the data structures/HW updates. */ diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServicesCommon.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServicesCommon.java index 6850c64a0e..7ea86c6db7 100644 --- a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServicesCommon.java +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServicesCommon.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Properties; import java.util.Set; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; @@ -118,6 +119,16 @@ public interface IClusterServicesCommon { */ void tbegin() throws NotSupportedException, SystemException; + /** + * tbegin with a timeout + * @see IClusterServicesCommon#tbegin + * @param timeout the transaction timeout + * @param unit TimeUnit for the timeout + * @throws NotSupportedException + * @throws SystemException + */ + void tbegin(long timeout, TimeUnit unit) throws NotSupportedException, SystemException; + /** * Commit a transaction covering all the data structures/HW updates. */ diff --git a/opendaylight/clustering/services_implementation/pom.xml b/opendaylight/clustering/services_implementation/pom.xml index ab75eb8dd1..90df7511e4 100644 --- a/opendaylight/clustering/services_implementation/pom.xml +++ b/opendaylight/clustering/services_implementation/pom.xml @@ -137,7 +137,7 @@ org.opendaylight.controller clustering.services - 0.4.1-SNAPSHOT + 0.5.0-SNAPSHOT org.opendaylight.controller diff --git a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManager.java b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManager.java index a9e6948a40..fcf71a90ac 100644 --- a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManager.java +++ b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManager.java @@ -22,6 +22,7 @@ import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; @@ -69,6 +70,9 @@ public class ClusterManager implements IClusterServices { private static String loopbackAddress = "127.0.0.1"; + // defaultTransactionTimeout is 60 seconds + private static int DEFAULT_TRANSACTION_TIMEOUT = 60; + /** * Start a JGroups GossipRouter if we are a supernode. The * GosispRouter is nothing more than a simple @@ -525,6 +529,12 @@ public class ClusterManager implements IClusterServices { @Override public void tbegin() throws NotSupportedException, SystemException { + // call tbegin with the default timeout + tbegin(DEFAULT_TRANSACTION_TIMEOUT, TimeUnit.SECONDS); + } + + @Override + public void tbegin(long timeout, TimeUnit unit) throws NotSupportedException, SystemException { EmbeddedCacheManager manager = this.cm; if (manager == null) { throw new IllegalStateException(); @@ -534,6 +544,15 @@ public class ClusterManager implements IClusterServices { if (tm == null) { throw new IllegalStateException(); } + long timeoutSec = unit.toSeconds(timeout); + if((timeoutSec > Integer.MAX_VALUE) || (timeoutSec <= 0)) { + // fall back to the default timeout + tm.setTransactionTimeout(DEFAULT_TRANSACTION_TIMEOUT); + } else { + // cast is ok here + // as here we are sure that timeoutSec < = Integer.MAX_VALUE. + tm.setTransactionTimeout((int) timeoutSec); + } tm.begin(); } diff --git a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManagerCommon.java b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManagerCommon.java index 9ee00484ce..97d9ded6c8 100644 --- a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManagerCommon.java +++ b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManagerCommon.java @@ -19,12 +19,15 @@ import java.util.Properties; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; + import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.NotSupportedException; import javax.transaction.RollbackException; import javax.transaction.SystemException; import javax.transaction.Transaction; + import org.apache.felix.dm.Component; import org.opendaylight.controller.clustering.services.CacheConfigException; import org.opendaylight.controller.clustering.services.CacheExistException; @@ -255,6 +258,15 @@ public abstract class ClusterManagerCommon implements IClusterServicesCommon { } } + @Override + public void tbegin(long timeout, TimeUnit unit) throws NotSupportedException, SystemException { + if (this.clusterService != null) { + this.clusterService.tbegin(timeout, unit); + } else { + throw new IllegalStateException(); + } + } + @Override public void tcommit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, java.lang.SecurityException, diff --git a/opendaylight/clustering/stub/pom.xml b/opendaylight/clustering/stub/pom.xml index 607b48b3aa..8fe1a99a0d 100644 --- a/opendaylight/clustering/stub/pom.xml +++ b/opendaylight/clustering/stub/pom.xml @@ -48,7 +48,7 @@ org.opendaylight.controller clustering.services - 0.4.1-SNAPSHOT + 0.5.0-SNAPSHOT org.opendaylight.controller diff --git a/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/ClusterManagerCommon.java b/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/ClusterManagerCommon.java index b6cb742d47..fe73e240f9 100644 --- a/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/ClusterManagerCommon.java +++ b/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/ClusterManagerCommon.java @@ -9,14 +9,16 @@ package org.opendaylight.controller.clustering.stub.internal; -import java.util.ArrayList; -import java.util.concurrent.ConcurrentHashMap; -import java.net.UnknownHostException; import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Dictionary; import java.util.List; import java.util.Properties; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; @@ -25,6 +27,7 @@ import javax.transaction.RollbackException; import javax.transaction.SystemException; import javax.transaction.Transaction; +import org.apache.felix.dm.Component; import org.opendaylight.controller.clustering.services.CacheConfigException; import org.opendaylight.controller.clustering.services.CacheExistException; import org.opendaylight.controller.clustering.services.IClusterServices; @@ -32,9 +35,6 @@ import org.opendaylight.controller.clustering.services.IClusterServicesCommon; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Dictionary; -import org.apache.felix.dm.Component; - public abstract class ClusterManagerCommon implements IClusterServicesCommon { protected String containerName = ""; protected static final Logger logger = LoggerFactory @@ -120,6 +120,11 @@ public abstract class ClusterManagerCommon implements IClusterServicesCommon { java.lang.IllegalStateException, SystemException { } + @Override + public void tbegin(long timeout, TimeUnit unit) throws NotSupportedException, SystemException { + + } + @Override public void trollback() throws java.lang.IllegalStateException, java.lang.SecurityException, SystemException { diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index a652845770..dd73815b34 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -59,8 +59,8 @@ 0.5.9-SNAPSHOT 14.0.1 5.0.0 - 2010.09.24.1 - 2010.09.24.1 + 2010.09.24.2-SNAPSHOT + 2010.09.24.2-SNAPSHOT 2013.08.27.1 2013.09.07.1 3.17.1-GA @@ -84,9 +84,9 @@ 0.2.3-SNAPSHOT 1.0-SNAPSHOT 0.5.1-SNAPSHOT - 0.6.1-SNAPSHOT + 0.7.0-SNAPSHOT 0.1.1-SNAPSHOT - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT 0.0.2-SNAPSHOT 0.1.1-SNAPSHOT 0.0.2-SNAPSHOT @@ -100,6 +100,7 @@ java 0.5.0-SNAPSHOT 0.5.0-SNAPSHOT + 0.5.0-SNAPSHOT 2.5.1 1.7 1.7 diff --git a/opendaylight/configuration/integrationtest/pom.xml b/opendaylight/configuration/integrationtest/pom.xml index 894f94bc46..e18fe8c1ed 100644 --- a/opendaylight/configuration/integrationtest/pom.xml +++ b/opendaylight/configuration/integrationtest/pom.xml @@ -25,7 +25,7 @@ org.opendaylight.controller sal - 0.5.1-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller @@ -40,7 +40,7 @@ org.opendaylight.controller clustering.services - 0.4.1-SNAPSHOT + 0.5.0-SNAPSHOT org.opendaylight.controller diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index 9ce668da85..35ebbbe0dd 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -509,7 +509,7 @@ org.opendaylight.controller clustering.services - ${controller.version} + ${clustering.services.version} org.opendaylight.controller diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini index b9b9c7337d..7d57e6005e 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini @@ -17,6 +17,9 @@ osgi.bundles=\ netconf.tcp.address=0.0.0.0 netconf.tcp.port=8383 +netconf.tcp.client.address=127.0.0.1 +netconf.tcp.client.port=8383 + netconf.ssh.address=0.0.0.0 netconf.ssh.port=1830 diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/00-netty.conf b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/00-netty.conf index ffee9c6da8..e83fdcc5c8 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/00-netty.conf +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/00-netty.conf @@ -31,7 +31,7 @@ netty:netty-event-executor global-event-executor - /config/modules/module[name='netty-global-eventexecutor']/instance[name='global-event-executor'] + /config/modules/module[name='netty-global-event-executor']/instance[name='global-event-executor'] diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.conf b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.conf index acae8866ce..07c21261bb 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.conf +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.conf @@ -43,16 +43,16 @@ ref_dom-broker - binding:binding-dom-mapping-service - ref_runtime-mapping-singleton + binding:binding-dom-mapping-service + ref_runtime-mapping-singleton //SERVICES START - dom:schema-service + dom:schema-service - ref_yang-schema-service - /config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service'] + ref_yang-schema-service + /config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service'] @@ -76,6 +76,13 @@ /config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl'] + + binding:binding-rpc-registry + + ref_binding-rpc-broker + /config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl'] + + binding-impl:binding-dom-mapping-service @@ -93,9 +100,9 @@ binding:binding-data-broker - ref_binding-data-broker - /config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker'] - + ref_binding-data-broker + /config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker'] + //CAPABILITIES START urn:opendaylight:l2:types?module=opendaylight-l2-types&revision=2013-08-27 diff --git a/opendaylight/forwardingrulesmanager/api/pom.xml b/opendaylight/forwardingrulesmanager/api/pom.xml index f25756cc11..499b98c28a 100644 --- a/opendaylight/forwardingrulesmanager/api/pom.xml +++ b/opendaylight/forwardingrulesmanager/api/pom.xml @@ -87,7 +87,7 @@ org.opendaylight.controller sal - 0.5.1-SNAPSHOT + 0.7.0-SNAPSHOT junit diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java index 43b0252df7..de7597730f 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java @@ -13,7 +13,6 @@ import java.net.Inet6Address; import java.net.InetAddress; import java.util.ArrayList; import java.util.List; -import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -26,6 +25,7 @@ import org.opendaylight.controller.sal.action.Action; import org.opendaylight.controller.sal.action.ActionType; import org.opendaylight.controller.sal.action.Controller; import org.opendaylight.controller.sal.action.Drop; +import org.opendaylight.controller.sal.action.Enqueue; import org.opendaylight.controller.sal.action.Flood; import org.opendaylight.controller.sal.action.HwPath; import org.opendaylight.controller.sal.action.Loopback; @@ -609,25 +609,13 @@ public class FlowConfig implements Serializable { return true; } - public boolean isPortValid(Switch sw, Short port) { - if (port < 1) { - log.debug("port {} is not valid", port); - return false; - } - + public boolean isPortValid(Switch sw, String port) { if (sw == null) { log.debug("switch info is not available. Skip checking if port is part of a switch or not."); return true; } - - Set nodeConnectorSet = sw.getNodeConnectors(); - for (NodeConnector nodeConnector : nodeConnectorSet) { - if (((Short) nodeConnector.getID()).equals(port)) { - return true; - } - } - log.debug("port {} is not a valid port of node {}", port, sw.getNode()); - return false; + NodeConnector nc = NodeConnectorCreator.createNodeConnector(port, sw.getNode()); + return sw.getNodeConnectors().contains(nc); } public boolean isVlanIdValid(String vlanId) { @@ -735,9 +723,8 @@ public class FlowConfig implements Serializable { } if (ingressPort != null) { - Short port = Short.decode(ingressPort); - if (isPortValid(sw, port) == false) { - String msg = String.format("Ingress port %d is not valid for the Switch", port); + if (!isPortValid(sw, ingressPort)) { + String msg = String.format("Ingress port %s is not valid for the Switch", ingressPort); if (!containerName.equals(GlobalConstants.DEFAULT.toString())) { msg += " in Container " + containerName; } @@ -850,10 +837,33 @@ public class FlowConfig implements Serializable { if (sstr.matches()) { for (String t : sstr.group(1).split(",")) { Matcher n = Pattern.compile("(?:(\\d+))").matcher(t); + if (n.matches()) { + String port = n.group(1); + if (port != null) { + if (!isPortValid(sw, port)) { + String msg = String.format("Output port %s is not valid for this switch", port); + if (!containerName.equals(GlobalConstants.DEFAULT.toString())) { + msg += " in Container " + containerName; + } + return new Status(StatusCode.BADREQUEST, msg); + } + } + } else { + String msg = String.format("Output port %s is not valid", t); + return new Status(StatusCode.BADREQUEST, msg); + } + } + continue; + } + // check enqueue + sstr = Pattern.compile("ENQUEUE=(.*)").matcher(actiongrp); + if (sstr.matches()) { + for (String t : sstr.group(1).split(",")) { + Matcher n = Pattern.compile("(?:(\\d+:\\d+))").matcher(t); if (n.matches()) { if (n.group(1) != null) { - Short port = Short.parseShort(n.group(1)); - if (isPortValid(sw, port) == false) { + String port = n.group(1).split(":")[0]; + if (!isPortValid(sw, port)) { String msg = String.format("Output port %d is not valid for this switch", port); if (!containerName.equals(GlobalConstants.DEFAULT.toString())) { msg += " in Container " + containerName; @@ -862,7 +872,7 @@ public class FlowConfig implements Serializable { } } } else { - String msg = String.format("Output port %s is not valid", t); + String msg = String.format("Enqueue port %s is not valid", t); return new Status(StatusCode.BADREQUEST, msg); } } @@ -990,7 +1000,7 @@ public class FlowConfig implements Serializable { if (this.ingressPort != null) { match.setField(MatchType.IN_PORT, - NodeConnectorCreator.createOFNodeConnector(Short.parseShort(ingressPort), getNode())); + NodeConnector.fromString(String.format("%s|%s@%s", node.getType(), ingressPort, node.toString()))); } if (this.dlSrc != null) { match.setField(MatchType.DL_SRC, HexEncode.bytesFromHexString(this.dlSrc)); @@ -1095,9 +1105,28 @@ public class FlowConfig implements Serializable { Matcher n = Pattern.compile("(?:(\\d+))").matcher(t); if (n.matches()) { if (n.group(1) != null) { - short ofPort = Short.parseShort(n.group(1)); - actionList.add(new Output(NodeConnectorCreator.createOFNodeConnector(ofPort, - this.getNode()))); + String nc = String.format("%s|%s@%s", node.getType(), n.group(1), node.toString()); + actionList.add(new Output(NodeConnector.fromString(nc))); + } + } + } + continue; + } + + sstr = Pattern.compile(ActionType.ENQUEUE + "=(.*)").matcher(actiongrp); + if (sstr.matches()) { + for (String t : sstr.group(1).split(",")) { + Matcher n = Pattern.compile("(?:(\\d+:\\d+))").matcher(t); + if (n.matches()) { + if (n.group(1) != null) { + String parts[] = n.group(1).split(":"); + String nc = String.format("%s|%s@%s", node.getType(), parts[0], node.toString()); + if (parts.length == 1) { + actionList.add(new Enqueue(NodeConnector.fromString(nc))); + } else { + actionList + .add(new Enqueue(NodeConnector.fromString(nc), Integer.parseInt(parts[1]))); + } } } } diff --git a/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java b/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java index 406970711c..48e1f07716 100644 --- a/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java +++ b/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java @@ -546,11 +546,6 @@ public class frmTest { fc.setCookie("100"); Assert.assertTrue(fc.validate(null).isSuccess()); - fc.setIngressPort("-1"); - status = fc.validate(null); - Assert.assertFalse(status.isSuccess()); - Assert.assertTrue(status.getDescription().contains("is not valid for the Switch")); - fc.setIngressPort("100"); Assert.assertTrue(fc.validate(null).isSuccess()); diff --git a/opendaylight/forwardingrulesmanager/implementation/pom.xml b/opendaylight/forwardingrulesmanager/implementation/pom.xml index 23c36a3752..6b3f5347ad 100644 --- a/opendaylight/forwardingrulesmanager/implementation/pom.xml +++ b/opendaylight/forwardingrulesmanager/implementation/pom.xml @@ -93,7 +93,7 @@ org.opendaylight.controller sal - 0.5.1-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller diff --git a/opendaylight/forwardingrulesmanager/integrationtest/pom.xml b/opendaylight/forwardingrulesmanager/integrationtest/pom.xml index 7904bd3a8f..1595f257d4 100644 --- a/opendaylight/forwardingrulesmanager/integrationtest/pom.xml +++ b/opendaylight/forwardingrulesmanager/integrationtest/pom.xml @@ -61,7 +61,7 @@ org.opendaylight.controller clustering.services - 0.4.1-SNAPSHOT + 0.5.0-SNAPSHOT org.opendaylight.controller @@ -71,7 +71,7 @@ org.opendaylight.controller switchmanager - 0.6.1-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller @@ -81,7 +81,7 @@ org.opendaylight.controller sal - 0.5.1-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller diff --git a/opendaylight/hosttracker/integrationtest/pom.xml b/opendaylight/hosttracker/integrationtest/pom.xml index 8f4163d686..03e70002d3 100644 --- a/opendaylight/hosttracker/integrationtest/pom.xml +++ b/opendaylight/hosttracker/integrationtest/pom.xml @@ -31,7 +31,7 @@ org.opendaylight.controller sal - 0.5.1-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller @@ -58,7 +58,7 @@ org.opendaylight.controller clustering.services - 0.4.1-SNAPSHOT + 0.5.0-SNAPSHOT @@ -70,7 +70,7 @@ org.opendaylight.controller switchmanager - 0.6.1-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller diff --git a/opendaylight/md-sal/clustered-data-store/integrationtest/pom.xml b/opendaylight/md-sal/clustered-data-store/integrationtest/pom.xml index 968f87a402..176ab6cbe0 100644 --- a/opendaylight/md-sal/clustered-data-store/integrationtest/pom.xml +++ b/opendaylight/md-sal/clustered-data-store/integrationtest/pom.xml @@ -17,8 +17,18 @@ clustered-datastore.integrationtest 0.4.0-SNAPSHOT - + + + + xml-apis + xml-apis + 1.4.01 + + + + + com.google.guava guava @@ -47,6 +57,16 @@ org.opendaylight.controller sal-binding-broker-impl 1.0-SNAPSHOT + + + xml-apis + xml-apis + + + reflections + org.reflections + + org.opendaylight.controller @@ -126,6 +146,12 @@ config-netconf-connector ${netconf.version} test + + + xml-apis + xml-apis + + org.opendaylight.controller diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/table-service.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/table-service.yang index 3a6f20f77d..02a63cb2b2 100644 --- a/opendaylight/md-sal/model/model-flow-service/src/main/yang/table-service.yang +++ b/opendaylight/md-sal/model/model-flow-service/src/main/yang/table-service.yang @@ -30,5 +30,14 @@ module sal-table { output { uses tr:transaction-aware; } - } + } + + notification table-updated { + uses "inv:node-context-ref"; + uses tr:transaction-aware; + leaf moreReplies { + type boolean; + } + uses table-type:table-features; + } } \ No newline at end of file diff --git a/opendaylight/md-sal/pom.xml b/opendaylight/md-sal/pom.xml index 94c31dd041..0e78598c11 100644 --- a/opendaylight/md-sal/pom.xml +++ b/opendaylight/md-sal/pom.xml @@ -29,6 +29,7 @@ sal-binding-broker sal-binding-util + sal-binding-dom-it samples @@ -193,9 +194,11 @@ - - - + + xml-apis + xml-apis + 1.4.01 + diff --git a/opendaylight/md-sal/sal-binding-broker/pom.xml b/opendaylight/md-sal/sal-binding-broker/pom.xml index 89bb1e8502..ac84aab977 100644 --- a/opendaylight/md-sal/sal-binding-broker/pom.xml +++ b/opendaylight/md-sal/sal-binding-broker/pom.xml @@ -131,6 +131,19 @@ + + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + @@ -168,6 +181,7 @@ org.reflections reflections 0.9.9-RC1 + compile org.javassist @@ -210,29 +224,11 @@ org.eclipse.xtend org.eclipse.xtend.lib - - org.eclipse.xtend - org.eclipse.xtend.standalone - 2.4.3 - runtime - org.opendaylight.controller sal-binding-config 1.0-SNAPSHOT - - org.opendaylight.controller.model - model-flow-service - 1.0-SNAPSHOT - test - - - org.opendaylight.controller.model - model-flow-management - 1.0-SNAPSHOT - test - org.opendaylight.yangtools yang-data-impl @@ -249,17 +245,5 @@ ${slf4j.version} test - - org.opendaylight.controller.model - model-flow-statistics - 1.0-SNAPSHOT - test - - - org.reflections - reflections - 0.9.9-RC1 - test - diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java index de6836489e..d33272d641 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java @@ -91,7 +91,7 @@ public class LazyGeneratedCodecRegistry implements // Map> typeToClass = new ConcurrentHashMap<>(); @SuppressWarnings("rawtypes") - private ConcurrentMap typeToCaseNodes = new ConcurrentHashMap<>(); + private ConcurrentMap typeToCaseCodecs = new ConcurrentHashMap<>(); private CaseClassMapFacade classToCaseRawCodec = new CaseClassMapFacade(); @@ -136,15 +136,14 @@ public class LazyGeneratedCodecRegistry implements // } return weakRef.get(); } - + @Override - public void putPathToClass(List names,Class cls) { + public void putPathToClass(List names, Class cls) { Type reference = Types.typeForClass(cls); - pathToInstantiatedType.put(names, reference ); + pathToInstantiatedType.put(names, reference); bindingClassEncountered(cls); } - @Override public IdentifierCodec getKeyCodecForPath(List names) { @SuppressWarnings("unchecked") @@ -297,10 +296,12 @@ public class LazyGeneratedCodecRegistry implements // return potential; } ConcreteType typeref = Types.typeForClass(caseClass); - ChoiceCaseCodecImpl caseCodec = typeToCaseNodes.get(typeref); + ChoiceCaseCodecImpl caseCodec = typeToCaseCodecs.get(typeref); + checkState(caseCodec != null, "Case Codec was not created proactivelly for %s", caseClass.getName()); + checkState(caseCodec.getSchema() != null, "Case schema is not available for %s", caseClass.getName()); @SuppressWarnings("unchecked") - Class newCodec = generator.caseCodecFor(caseClass, caseCodec.schema); + Class newCodec = generator.caseCodecFor(caseClass, caseCodec.getSchema()); BindingCodec newInstance = newInstanceOf(newCodec); caseCodec.setDelegate(newInstance); caseCodecs.put(caseClass, caseCodec); @@ -322,17 +323,23 @@ public class LazyGeneratedCodecRegistry implements // for (Entry caseNode : cases.entrySet()) { ReferencedTypeImpl typeref = new ReferencedTypeImpl(caseNode.getValue().getPackageName(), caseNode .getValue().getName()); + + LOG.info("Case path: {} Type : {}", caseNode.getKey(), caseNode.getValue().getFullyQualifiedName()); + pathToType.put(caseNode.getKey(), caseNode.getValue()); + ChoiceCaseNode node = (ChoiceCaseNode) SchemaContextUtil.findDataSchemaNode(module, caseNode.getKey()); + if (node == null) { LOG.error("YANGTools Bug: SchemaNode for {}, with path {} was not found in context.", typeref.getFullyQualifiedName(), caseNode.getKey()); + @SuppressWarnings("rawtypes") + ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl(); + typeToCaseCodecs.putIfAbsent(typeref, value); continue; } - - pathToType.put(caseNode.getKey(), caseNode.getValue()); @SuppressWarnings("rawtypes") ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl(node); - typeToCaseNodes.putIfAbsent(typeref, value); + typeToCaseCodecs.putIfAbsent(typeref, value); } } @@ -352,18 +359,24 @@ public class LazyGeneratedCodecRegistry implements // choiceCodecs.put(choiceClass, newCodec); CodecMapping.setClassToCaseMap(choiceCodec, (Map, BindingCodec>) classToCaseRawCodec); CodecMapping.setCompositeNodeToCaseMap(choiceCodec, newCodec.getCompositeToCase()); - + tryToCreateCasesCodecs(schema); } private void tryToCreateCasesCodecs(ChoiceNode schema) { - for(ChoiceCaseNode caseNode : schema.getCases()) { + for (ChoiceCaseNode caseNode : schema.getCases()) { SchemaPath path = caseNode.getPath(); GeneratedTypeBuilder type; - if(path != null && (type = pathToType.get(path)) != null) { + if (path != null && (type = pathToType.get(path)) != null) { + ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName()); + ChoiceCaseCodecImpl partialCodec = typeToCaseCodecs.get(typeref); + if(partialCodec.getSchema() == null ) { + partialCodec.setSchema(caseNode); + } + Class caseClass = ClassLoaderUtils.tryToLoadClassWithTCCL(type.getFullyQualifiedName()); - if(caseClass != null) { + if (caseClass != null) { getCaseCodecFor(caseClass); } } @@ -381,8 +394,7 @@ public class LazyGeneratedCodecRegistry implements // } @Override - public void onDataContainerCodecCreated(Class dataClass, - Class> dataCodec) { + public void onDataContainerCodecCreated(Class dataClass, Class> dataCodec) { if (Augmentable.class.isAssignableFrom(dataClass)) { AugmentableCompositeCodec augmentableCodec = getAugmentableCodec(dataClass); CodecMapping.setAugmentationCodec(dataCodec, augmentableCodec); @@ -471,15 +483,15 @@ public class LazyGeneratedCodecRegistry implements // @SuppressWarnings("rawtypes") private static class ChoiceCaseCodecImpl implements ChoiceCaseCodec, // Delegator { - private final boolean augmenting; + private boolean augmenting; private BindingCodec delegate; - private final Set validNames; - private final Set validQNames; + private Set validNames; + private Set validQNames; private ChoiceCaseNode schema; - public ChoiceCaseCodecImpl(ChoiceCaseNode caseNode) { - this.delegate = NOT_READY_CODEC; + public void setSchema(ChoiceCaseNode caseNode) { + this.schema = schema; this.schema = caseNode; validNames = new HashSet<>(); validQNames = new HashSet<>(); @@ -491,6 +503,15 @@ public class LazyGeneratedCodecRegistry implements // augmenting = caseNode.isAugmenting(); } + public ChoiceCaseCodecImpl() { + this.delegate = NOT_READY_CODEC; + } + + public ChoiceCaseCodecImpl(ChoiceCaseNode caseNode) { + this.delegate = NOT_READY_CODEC; + setSchema(caseNode); + } + @Override public ValueWithQName deserialize(Node input) { throw new UnsupportedOperationException("Direct invocation of this codec is not allowed."); diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/RuntimeGeneratedMappingServiceImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/RuntimeGeneratedMappingServiceImpl.xtend index 7eb473ce34..cb25f4da8b 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/RuntimeGeneratedMappingServiceImpl.xtend +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/RuntimeGeneratedMappingServiceImpl.xtend @@ -78,7 +78,7 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer for (entry : newBinding.moduleContexts.entrySet) { registry.onModuleContextAdded(schemaContext, entry.key, entry.value); - + binding.pathToType.putAll(entry.value.childNodes) //val module = entry.key; val context = entry.value; updateBindingFor(context.childNodes, schemaContext); @@ -174,16 +174,18 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer } private def void updateBindingFor(Map map, SchemaContext module) { + for (entry : map.entrySet) { val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key); //LOG.info("{} : {}",entry.key,entry.value.fullyQualifiedName) + val typeRef = new ReferencedTypeImpl(entry.value.packageName,entry.value.name) + typeToDefinition.put(typeRef, entry.value); if (schemaNode != null) { - val typeRef = new ReferencedTypeImpl(entry.value.packageName,entry.value.name) typeToSchemaNode.put(typeRef, schemaNode); - typeToDefinition.put(typeRef, entry.value); updatePromisedSchemas(typeRef, schemaNode); } + } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/TransformerGenerator.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/TransformerGenerator.xtend index a732f152b2..0316614aa1 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/TransformerGenerator.xtend +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/TransformerGenerator.xtend @@ -49,6 +49,8 @@ import static extension org.opendaylight.controller.sal.binding.impl.util.YangSc import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl import org.opendaylight.yangtools.yang.model.util.ExtendedType import org.opendaylight.yangtools.yang.model.util.EnumerationType +import static com.google.common.base.Preconditions.* +import org.opendaylight.yangtools.yang.model.api.SchemaPath class TransformerGenerator { @@ -78,6 +80,9 @@ class TransformerGenerator { @Property var Map typeToDefinition = new ConcurrentHashMap(); + @Property + var Map pathToType = new ConcurrentHashMap(); + @Property var Map typeToSchemaNode = new ConcurrentHashMap(); @@ -105,6 +110,27 @@ class TransformerGenerator { val ref = Types.typeForClass(inputType) val node = typeToSchemaNode.get(ref) val typeSpecBuilder = typeToDefinition.get(ref) + checkState(typeSpecBuilder !== null, "Could not find typedefinition for %s", inputType.name); + val typeSpec = typeSpecBuilder.toInstance(); + val newret = generateTransformerFor(inputType, typeSpec, node); + listener.onClassProcessed(inputType); + return newret as Class, Object>>; + ] + } + + def Class, Object>> transformerFor(Class inputType, DataSchemaNode node) { + return withClassLoaderAndLock(inputType.classLoader, lock) [ | + val ret = getGeneratedClass(inputType) + if (ret !== null) { + listener.onClassProcessed(inputType); + return ret as Class, Object>>; + } + val ref = Types.typeForClass(inputType) + var typeSpecBuilder = typeToDefinition.get(ref) + if (typeSpecBuilder == null) { + typeSpecBuilder = pathToType.get(node.path); + } + checkState(typeSpecBuilder !== null, "Could not find TypeDefinition for %s, $s", inputType.name, node); val typeSpec = typeSpecBuilder.toInstance(); val newret = generateTransformerFor(inputType, typeSpec, node); listener.onClassProcessed(inputType); @@ -205,11 +231,9 @@ class TransformerGenerator { keyTransformerFor(cls, type, node); } - private def serializer(Type type) { + private def serializer(Type type, DataSchemaNode node) { val cls = loadClassWithTCCL(type.resolvedName); - - transformerFor(cls); - + transformerFor(cls, node); } private def Class getValueSerializer(GeneratedTransferObject type) { @@ -367,7 +391,7 @@ class TransformerGenerator { ] val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class> - listener?.onDataContainerCodecCreated(inputType,ret); + listener?.onDataContainerCodecCreated(inputType, ret); log.info("DOM Codec for {} was generated {}", inputType, ret) return ret; } catch (Exception e) { @@ -710,7 +734,7 @@ class TransformerGenerator { Object _listItem = _iterator.next(); _is_empty = false; //System.out.println(" item" + _listItem); - Object _value = «type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem); + Object _value = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».fromDomStatic(_localQName,_listItem); //System.out.println(" value" + _value); «propertyName».add(_value); _hasNext = _iterator.hasNext(); @@ -762,12 +786,12 @@ class TransformerGenerator { if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) { _is_empty = false; java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0); - «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_dom_«propertyName»); + «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_dom_«propertyName»); } ''' private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) ''' - «type.resolvedName» «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_compositeNode); + «type.resolvedName» «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_compositeNode); if(«propertyName» != null) { _is_empty = false; } @@ -1140,7 +1164,7 @@ class TransformerGenerator { boolean _hasNext = _iterator.hasNext(); while(_hasNext) { Object _listItem = _iterator.next(); - Object _domValue = «type.actualTypeArguments.get(0).serializer.resolvedName».toDomStatic(_resultName,_listItem); + Object _domValue = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».toDomStatic(_resultName,_listItem); _childNodes.add(_domValue); _hasNext = _iterator.hasNext(); } @@ -1193,7 +1217,7 @@ class TransformerGenerator { String propertyName) ''' «type.resolvedName» «propertyName» = value.«propertyName»(); if(«propertyName» != null) { - java.util.List domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»); + java.util.List domValue = «type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»); _childNodes.addAll(domValue); } ''' @@ -1219,7 +1243,7 @@ class TransformerGenerator { String propertyName) ''' «type.resolvedName» «propertyName» = value.«propertyName»(); if(«propertyName» != null) { - Object domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»); + Object domValue = «type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»); _childNodes.add(domValue); } ''' diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/ClassLoaderUtils.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/ClassLoaderUtils.java index 596329e07b..d230fd17f9 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/ClassLoaderUtils.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/ClassLoaderUtils.java @@ -7,9 +7,10 @@ import static com.google.common.base.Preconditions.*; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import com.google.common.base.Joiner; import com.google.common.base.Optional; public final class ClassLoaderUtils { @@ -56,15 +57,28 @@ public final class ClassLoaderUtils { if ("byte[]".equals(name)) { return byte[].class; } - - return Thread.currentThread().getContextClassLoader().loadClass(name); + try { + return Thread.currentThread().getContextClassLoader().loadClass(name); + } catch (ClassNotFoundException e) { + String[] components = name.split("\\."); + String potentialOuter; + int length = components.length; + if (length > 2 && (potentialOuter = components[length - 2]) != null && Character.isUpperCase(potentialOuter.charAt(0))) { + + String outerName = Joiner.on(".").join(Arrays.asList(components).subList(0, length - 1)); + String innerName = outerName + "$" + components[length-1]; + return Thread.currentThread().getContextClassLoader().loadClass(innerName); + } else { + throw e; + } + } } public static Class tryToLoadClassWithTCCL(String fullyQualifiedName) { try { return loadClassWithTCCL(fullyQualifiedName); } catch (ClassNotFoundException e) { - + } return null; } diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java index c67a0176d2..a7a70c2839 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java @@ -14,6 +14,8 @@ import org.opendaylight.controller.sal.binding.api.data.DataProviderService; import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl; import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector; import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService; +import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory; +import org.opendaylight.controller.sal.binding.test.util.BindingTestContext; import org.opendaylight.controller.sal.binding.dom.serializer.impl.RuntimeGeneratedMappingServiceImpl; import org.opendaylight.controller.sal.core.api.data.DataBrokerService; import org.opendaylight.controller.sal.core.api.data.DataStore; @@ -37,117 +39,34 @@ public abstract class AbstractDataServiceTest { protected org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService; protected DataProviderService baDataService; - - /** - * Workaround for JUNIT sharing classloaders - * - */ - protected static final ClassPool POOL = new ClassPool(); - - protected RuntimeGeneratedMappingServiceImpl mappingServiceImpl; protected BindingIndependentMappingService mappingService; - protected DataBrokerImpl baDataImpl; - protected org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl; - protected ListeningExecutorService executor; - protected BindingIndependentDataServiceConnector connectorServiceImpl; - protected HashMapDataStore rawDataStore; - protected SchemaAwareDataStoreAdapter schemaAwareDataStore; private DataStoreStatsWrapper dataStoreStats; - protected DataStore dataStore; + protected BindingTestContext testContext; @Before public void setUp() { - executor = MoreExecutors.sameThreadExecutor(); - baDataImpl = new DataBrokerImpl(); - baDataService = baDataImpl; - baDataImpl.setExecutor(executor); - - biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl(); - biDataService = biDataImpl; - biDataImpl.setExecutor(executor); - - rawDataStore = new HashMapDataStore(); - schemaAwareDataStore = new SchemaAwareDataStoreAdapter(); - schemaAwareDataStore.changeDelegate(rawDataStore); - dataStoreStats = new DataStoreStatsWrapper(schemaAwareDataStore); - dataStore = dataStoreStats; - - org.opendaylight.yangtools.yang.data.api.InstanceIdentifier treeRoot = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier - .builder().toInstance(); - biDataImpl.registerConfigurationReader(treeRoot, dataStore); - biDataImpl.registerOperationalReader(treeRoot, dataStore); - biDataImpl.registerCommitHandler(treeRoot, dataStore); - - mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl(); - mappingServiceImpl.setPool(POOL); - mappingService = mappingServiceImpl; - File pathname = new File("target/gen-classes-debug"); - // System.out.println("Generated classes are captured in " + - // pathname.getAbsolutePath()); - mappingServiceImpl.start(null); - // mappingServiceImpl.getBinding().setClassFileCapturePath(pathname); - - connectorServiceImpl = new BindingIndependentDataServiceConnector(); - connectorServiceImpl.setBaDataService(baDataService); - connectorServiceImpl.setBiDataService(biDataService); - connectorServiceImpl.setMappingService(mappingServiceImpl); - connectorServiceImpl.start(); - - String[] yangFiles = getModelFilenames(); - if (yangFiles != null && yangFiles.length > 0) { - SchemaContext context = getContext(yangFiles); - mappingServiceImpl.onGlobalContextUpdated(context); - schemaAwareDataStore.onGlobalContextUpdated(context); - } + ListeningExecutorService executor = MoreExecutors.sameThreadExecutor(); + BindingBrokerTestFactory factory = new BindingBrokerTestFactory(); + factory.setExecutor(executor); + factory.setStartWithParsedSchema(getStartWithSchema()); + testContext = factory.getTestContext(); + testContext.start(); + + baDataService = testContext.getBindingDataBroker(); + biDataService = testContext.getDomDataBroker(); + dataStore = testContext.getDomDataStore(); + mappingService = testContext.getBindingToDomMappingService(); } - protected String[] getModelFilenames() { - return getAllModelFilenames(); - } - - public static String[] getAllModelFilenames() { - Predicate predicate = new Predicate() { - @Override - public boolean apply(String input) { - return input.endsWith(".yang"); - } - }; - Reflections reflection = new Reflections("META-INF.yang", new ResourcesScanner()); - Set result = reflection.getResources(predicate); - return (String[]) result.toArray(new String[result.size()]); - } - - public static SchemaContext getContext(String[] yangFiles) { - - ClassLoader loader = AbstractDataServiceTest.class.getClassLoader(); - - List streams = new ArrayList<>(); - for (String string : yangFiles) { - InputStream stream = loader.getResourceAsStream(string); - streams.add(stream); - - } - YangParserImpl parser = new YangParserImpl(); - - Set modules = parser.parseYangModelsFromStreams(streams); - return parser.resolveSchemaContext(modules); + protected boolean getStartWithSchema() { + return true; } @After public void afterTest() { - log.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms", - dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(), - dataStoreStats.getConfigurationReadAverageTime()); - - log.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms", - dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(), - dataStoreStats.getOperationalReadAverageTime()); - - log.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ms AverageTime (ns): {} ms", - dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(), - dataStoreStats.getRequestCommitAverageTime()); + testContext.logDataStoreStatistics(); } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingBrokerTestFactory.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingBrokerTestFactory.java new file mode 100644 index 0000000000..bad485e679 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingBrokerTestFactory.java @@ -0,0 +1,59 @@ +package org.opendaylight.controller.sal.binding.test.util; + +import java.util.concurrent.ExecutorService; + +import javassist.ClassPool; + +import org.opendaylight.controller.sal.core.api.data.DataStore; +import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper; +import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore; +import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter; + +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; + +public class BindingBrokerTestFactory { + + private static final ClassPool CLASS_POOL = new ClassPool(); + private boolean startWithParsedSchema = true; + private ExecutorService executor; + private ClassPool classPool; + + + public boolean isStartWithParsedSchema() { + return startWithParsedSchema; + } + + public void setStartWithParsedSchema(boolean startWithParsedSchema) { + this.startWithParsedSchema = startWithParsedSchema; + } + + public ExecutorService getExecutor() { + return executor; + } + + public void setExecutor(ExecutorService executor) { + this.executor = executor; + } + + + public BindingTestContext getTestContext() { + Preconditions.checkState(executor != null, "Executor is not set."); + ListeningExecutorService listenableExecutor = MoreExecutors.listeningDecorator(executor); + return new BindingTestContext(listenableExecutor, getClassPool(),startWithParsedSchema); + } + + public ClassPool getClassPool() { + if(classPool == null) { + return CLASS_POOL; + } + + return classPool; + } + + public void setClassPool(ClassPool classPool) { + this.classPool = classPool; + } + +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java new file mode 100644 index 0000000000..4e611c5fe2 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java @@ -0,0 +1,199 @@ +package org.opendaylight.controller.sal.binding.test.util; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javassist.ClassPool; + +import org.opendaylight.controller.sal.binding.api.data.DataProviderService; +import org.opendaylight.controller.sal.binding.dom.serializer.impl.RuntimeGeneratedMappingServiceImpl; +import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl; +import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector; +import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService; +import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; +import org.opendaylight.controller.sal.core.api.data.DataStore; +import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper; +import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore; +import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; +import org.reflections.Reflections; +import org.reflections.scanners.ResourcesScanner; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Predicate; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; + +import static com.google.common.base.Preconditions.*; + +public class BindingTestContext { + + + public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier TREE_ROOT = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier + .builder().toInstance(); + + private static final Logger LOG = LoggerFactory.getLogger(BindingTestContext.class); + + private RuntimeGeneratedMappingServiceImpl mappingServiceImpl; + private DataBrokerImpl baDataImpl; + private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl; + + private BindingIndependentDataServiceConnector connectorServiceImpl; + private HashMapDataStore rawDataStore; + private SchemaAwareDataStoreAdapter schemaAwareDataStore; + private DataStoreStatsWrapper dataStoreStats; + private DataStore dataStore; + + + private boolean dataStoreStatisticsEnabled = false; + + private final ListeningExecutorService executor; + private final ClassPool classPool; + + private final boolean startWithSchema; + + protected BindingTestContext(ListeningExecutorService executor, ClassPool classPool, boolean startWithSchema) { + this.executor = executor; + this.classPool = classPool; + this.startWithSchema = startWithSchema; + } + + public void startDomDataStore() { + checkState(dataStore == null, "DataStore already started."); + checkState(biDataImpl != null, "Dom Data Broker not present"); + rawDataStore = new HashMapDataStore(); + schemaAwareDataStore = new SchemaAwareDataStoreAdapter(); + schemaAwareDataStore.changeDelegate(rawDataStore); + if(dataStoreStatisticsEnabled) { + dataStoreStats = new DataStoreStatsWrapper(schemaAwareDataStore); + dataStore = dataStoreStats; + } else { + dataStore = schemaAwareDataStore; + } + + biDataImpl.registerConfigurationReader(TREE_ROOT, dataStore); + biDataImpl.registerOperationalReader(TREE_ROOT, dataStore); + biDataImpl.registerCommitHandler(TREE_ROOT, dataStore); + } + + public void startDomDataBroker() { + checkState(executor != null,"Executor needs to be set"); + biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl(); + biDataImpl.setExecutor(executor); + } + + public void startBindingDataBroker() { + checkState(executor != null,"Executor needs to be set"); + baDataImpl = new DataBrokerImpl(); + baDataImpl.setExecutor(executor); + } + + public void startBindingToDomDataConnector() { + checkState(baDataImpl != null,"Binding Data Broker needs to be started"); + checkState(biDataImpl != null,"DOM Data Broker needs to be started."); + checkState(mappingServiceImpl != null,"DOM Mapping Service needs to be started."); + connectorServiceImpl = new BindingIndependentDataServiceConnector(); + connectorServiceImpl.setBaDataService(baDataImpl); + connectorServiceImpl.setBiDataService(biDataImpl); + connectorServiceImpl.setMappingService(mappingServiceImpl); + connectorServiceImpl.start(); + } + + public void startBindingToDomMappingService() { + checkState(classPool != null,"ClassPool needs to be present"); + mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl(); + mappingServiceImpl.setPool(classPool); + mappingServiceImpl.start(null); + } + + + public void updateYangSchema(String[] files) { + SchemaContext context = getContext(files); + if(schemaAwareDataStore != null) { + schemaAwareDataStore.onGlobalContextUpdated(context); + } + if(mappingServiceImpl != null) { + mappingServiceImpl.onGlobalContextUpdated(context); + } + } + + + public static String[] getAllYangFilesOnClasspath() { + Predicate predicate = new Predicate() { + @Override + public boolean apply(String input) { + return input.endsWith(".yang"); + } + }; + Reflections reflection = new Reflections("META-INF.yang", new ResourcesScanner()); + Set result = reflection.getResources(predicate); + return (String[]) result.toArray(new String[result.size()]); + } + + private static SchemaContext getContext(String[] yangFiles) { + ClassLoader loader = BindingTestContext.class.getClassLoader(); + List streams = new ArrayList<>(); + for (String string : yangFiles) { + InputStream stream = loader.getResourceAsStream(string); + streams.add(stream); + } + YangParserImpl parser = new YangParserImpl(); + Set modules = parser.parseYangModelsFromStreams(streams); + return parser.resolveSchemaContext(modules); + } + + public void start() { + startBindingDataBroker(); + startDomDataBroker(); + startDomDataStore(); + startBindingToDomMappingService(); + startBindingToDomDataConnector(); + if(startWithSchema) { + loadYangSchemaFromClasspath(); + } + } + + public void loadYangSchemaFromClasspath() { + String[] files = getAllYangFilesOnClasspath(); + updateYangSchema(files); + } + + public DataProviderService getBindingDataBroker() { + return baDataImpl; + } + + public org.opendaylight.controller.sal.core.api.data.DataProviderService getDomDataBroker() { + return biDataImpl; + } + + public DataStore getDomDataStore() { + return dataStore; + } + + public BindingIndependentMappingService getBindingToDomMappingService() { + return mappingServiceImpl; + } + + public void logDataStoreStatistics() { + if(dataStoreStats == null) { + return; + } + + LOG.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms", + dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(), + dataStoreStats.getConfigurationReadAverageTime()); + + LOG.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms", + dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(), + dataStoreStats.getOperationalReadAverageTime()); + + LOG.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ms AverageTime (ns): {} ms", + dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(), + dataStoreStats.getRequestCommitAverageTime()); + } +} diff --git a/opendaylight/md-sal/sal-binding-dom-it/pom.xml b/opendaylight/md-sal/sal-binding-dom-it/pom.xml new file mode 100644 index 0000000000..9a143d3f00 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-dom-it/pom.xml @@ -0,0 +1,82 @@ + + 4.0.0 + + org.opendaylight.controller + sal-parent + 1.0-SNAPSHOT + + sal-binding-dom-it + bundle + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + + + + + + org.eclipse.xtend + xtend-maven-plugin + + + maven-clean-plugin + + + org.jacoco + jacoco-maven-plugin + + org.opendaylight.controller.* + + + + pre-test + + prepare-agent + + + + post-test + test + + report + + + + + + + + + + org.opendaylight.controller + sal-binding-broker-impl + 1.0-SNAPSHOT + test + + + org.opendaylight.controller + sal-binding-broker-impl + 1.0-SNAPSHOT + test-jar + test + + + org.opendaylight.controller.model + model-flow-service + 1.0-SNAPSHOT + test + + + org.opendaylight.controller.model + model-flow-management + 1.0-SNAPSHOT + test + + + junit + junit + + + diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java similarity index 100% rename from opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java rename to opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java similarity index 94% rename from opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java rename to opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java index 85d484a617..848fb6b190 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java @@ -53,11 +53,6 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest { .toInstance(); private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA); - @Override - protected String[] getModelFilenames() { - return null; - } - /** * * @@ -79,9 +74,7 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest { } }); - SchemaContext ctx = getContext(getAllModelFilenames()); - schemaAwareDataStore.onGlobalContextUpdated(ctx); - mappingServiceImpl.onGlobalContextUpdated(ctx); + testContext.loadYangSchemaFromClasspath(); RpcResult result = future.get().get(); assertEquals(TransactionStatus.COMMITED, result.getResult()); @@ -95,5 +88,10 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest { return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA); } + + @Override + protected boolean getStartWithSchema() { + return false; + } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java similarity index 100% rename from opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java rename to opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/RpcRegistrationNullPointer.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/RpcRegistrationNullPointer.java similarity index 100% rename from opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/RpcRegistrationNullPointer.java rename to opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/RpcRegistrationNullPointer.java diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java similarity index 100% rename from opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java rename to opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java similarity index 100% rename from opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java rename to opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java diff --git a/opendaylight/md-sal/sal-binding-it/pom.xml b/opendaylight/md-sal/sal-binding-it/pom.xml index 27d426791f..6a994dbd07 100644 --- a/opendaylight/md-sal/sal-binding-it/pom.xml +++ b/opendaylight/md-sal/sal-binding-it/pom.xml @@ -124,6 +124,7 @@ + org.opendaylight.yangtools.thirdparty diff --git a/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java b/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java index 4ef9d80b02..49781ce116 100644 --- a/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java +++ b/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java @@ -111,6 +111,8 @@ public class TestHelper { systemProperty("netconf.tcp.address").value("0.0.0.0"), // systemProperty("netconf.tcp.port").value("18383"), // + systemProperty("netconf.tcp.client.address").value("127.0.0.1"), // + systemProperty("netconf.tcp.client.port").value("18383"), // systemProperty("netconf.config.persister.active").value("1"), // systemProperty("netconf.config.persister.1.storageAdapterClass").value( "org.opendaylight.controller.config.persist.storage.file.FileStorageAdapter"), // diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend index da47438a6b..32e59b869e 100644 --- a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend @@ -345,10 +345,19 @@ public abstract class AbstractDataTransaction

, D> extends Abst } override readConfigurationData(P path) { + val local = this.updatedConfigurationData.get(path); + if(local != null) { + return local; + } + return broker.readConfigurationData(path); } override readOperationalData(P path) { + val local = this.updatedOperationalData.get(path); + if(local != null) { + return local; + } return broker.readOperationalData(path); } diff --git a/opendaylight/md-sal/sal-rest-connector/pom.xml b/opendaylight/md-sal/sal-rest-connector/pom.xml index 3e13a584d4..5e798b6720 100644 --- a/opendaylight/md-sal/sal-rest-connector/pom.xml +++ b/opendaylight/md-sal/sal-rest-connector/pom.xml @@ -41,6 +41,11 @@ org.opendaylight.yangtools yang-data-impl ${yang.version} + + + org.opendaylight.yangtools + yang-model-util + ${yang.version} com.google.code.gson diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java index a2ae1c9f7f..83e2d20d0e 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java @@ -7,6 +7,7 @@ import java.util.Map.Entry; import java.util.Set; import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper; +import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper; import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper; import com.google.common.collect.Lists; @@ -69,7 +70,7 @@ class JsonReader { } } else if (childType.isJsonArray()) { if (childType.getAsJsonArray().size() == 1 && childType.getAsJsonArray().get(0).isJsonNull()) { - parent.addValue(new SimpleNodeWrapper(getNamespaceFrom(childName), getLocalNameFrom(childName), null)); + parent.addValue(new EmptyNodeWrapper(getNamespaceFrom(childName), getLocalNameFrom(childName))); } else { for (JsonElement childOfChildType : childType.getAsJsonArray()) { diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToXmlProvider.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToXmlProvider.java index d0c0077952..fbddd05caf 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToXmlProvider.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToXmlProvider.java @@ -25,7 +25,7 @@ import org.opendaylight.controller.sal.rest.api.RestconfService; import org.opendaylight.controller.sal.restconf.impl.ResponseException; import org.opendaylight.controller.sal.restconf.impl.StructuredData; import org.opendaylight.yangtools.yang.data.api.CompositeNode; -import org.opendaylight.yangtools.yang.data.impl.NodeUtils; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -56,8 +56,9 @@ public enum StructuredDataToXmlProvider implements MessageBodyWriter data, YangNode schema) + throws UnsupportedDataTypeException { + QName dataType = data.getNodeType(); + Element itemEl = doc.createElementNS(dataType.getNamespace().toString(), dataType.getLocalName()); + + if (data instanceof SimpleNode) { + if (schema instanceof LeafListSchemaNode) { + writeValueOfNodeByType(itemEl, (SimpleNode) data, ((LeafListSchemaNode) schema).getType()); + } else if (schema instanceof LeafSchemaNode) { + writeValueOfNodeByType(itemEl, (SimpleNode) data, ((LeafSchemaNode) schema).getType()); + } else { + Object value = data.getValue(); + if (value != null) { + itemEl.setTextContent(String.valueOf(value)); + } + } + } else { // CompositeNode + for (Node child : ((CompositeNode) data).getChildren()) { + DataSchemaNode childSchema = findFirstSchemaForNode(child, ((DataNodeContainer) schema).getChildNodes()); + if (childSchema == null) { + throw new UnsupportedDataTypeException("Probably the data node \"" + + child.getNodeType().getLocalName() + "\" is not conform to schema"); + } + itemEl.appendChild(translateToXmlAndReturnRootElement(doc, child, childSchema)); + } + } + return itemEl; + } + + private void writeValueOfNodeByType(Element element, SimpleNode node, TypeDefinition type) { + + TypeDefinition baseType = resolveBaseTypeFrom(type); + + if (baseType instanceof IdentityrefTypeDefinition && node.getValue() instanceof QName) { + QName value = (QName) node.getValue(); + element.setAttribute("xmlns:x", value.getNamespace().toString()); + element.setTextContent("x:" + value.getLocalName()); + } else { + Object value = node.getValue(); + if (value != null) { + element.setTextContent(String.valueOf(value)); + } + } + } + + private DataSchemaNode findFirstSchemaForNode(Node node, Set dataSchemaNode) { + for (DataSchemaNode dsn : dataSchemaNode) { + if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) { + return dsn; + } else if (dsn instanceof ChoiceNode) { + for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) { + DataSchemaNode foundDsn = findFirstSchemaForNode(node, choiceCase.getChildNodes()); + if (foundDsn != null) { + return foundDsn; + } + } + } + } + return null; + } + + private TypeDefinition resolveBaseTypeFrom(TypeDefinition type) { + return type.getBaseType() != null ? resolveBaseTypeFrom(type.getBaseType()) : type; + } + +} diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java index bf7ff7d435..a53281492f 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java @@ -14,8 +14,10 @@ import javax.xml.stream.events.StartElement; import javax.xml.stream.events.XMLEvent; import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper; +import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper; import org.opendaylight.controller.sal.restconf.impl.NodeWrapper; import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper; +import org.opendaylight.yangtools.yang.data.api.Node; public class XmlReader { @@ -121,7 +123,7 @@ public class XmlReader { return false; } - private SimpleNodeWrapper resolveSimpleNodeFromStartElement(final StartElement startElement) + private NodeWrapper> resolveSimpleNodeFromStartElement(final StartElement startElement) throws XMLStreamException { checkArgument(startElement != null, "Start Element cannot be NULL!"); String data = null; @@ -141,7 +143,9 @@ public class XmlReader { } } } - + if(data == null) { + return new EmptyNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement)); + } return new SimpleNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement), data); } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java index fc146256e8..0ded60dae4 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java @@ -230,5 +230,4 @@ public final class CompositeNodeWrapper implements NodeWrapper, C public Set>>> entrySet() { return unwrap().entrySet(); } - } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend index 470b4735a4..602e8b9242 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend @@ -32,6 +32,7 @@ import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil import static com.google.common.base.Preconditions.* +import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec class ControllerContext implements SchemaServiceListener { @@ -288,9 +289,10 @@ class ControllerContext implements SchemaServiceListener { private def void addKeyValue(HashMap map, DataSchemaNode node, String uriValue) { checkNotNull(uriValue); checkArgument(node instanceof LeafSchemaNode); - val decoded = URLDecoder.decode(uriValue); + val urlDecoded = URLDecoder.decode(uriValue); + val typedef = (node as LeafSchemaNode).type; + val decoded = TypeDefinitionAwareCodec.from(typedef)?.deserialize(urlDecoded) map.put(node.QName, decoded); - } private def String toModuleName(String str) { diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/EmptyNodeWrapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/EmptyNodeWrapper.java new file mode 100644 index 0000000000..c146954dce --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/EmptyNodeWrapper.java @@ -0,0 +1,111 @@ +package org.opendaylight.controller.sal.restconf.impl; + +import java.net.URI; +import java.util.Collections; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.ModifyAction; +import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode; +import org.opendaylight.yangtools.yang.data.api.Node; +import org.opendaylight.yangtools.yang.data.api.SimpleNode; +import org.opendaylight.yangtools.yang.data.impl.NodeFactory; + +import com.google.common.base.Preconditions; + +public final class EmptyNodeWrapper implements NodeWrapper>, Node { + + private Node unwrapped; + + private String localName; + private URI namespace; + private QName name; + + private boolean composite; + + public boolean isComposite() { + return composite; + } + + public void setComposite(boolean composite) { + this.composite = composite; + } + + public EmptyNodeWrapper(URI namespace, String localName) { + this.localName = Preconditions.checkNotNull(localName); + this.namespace = namespace; + } + + @Override + public void setQname(QName name) { + Preconditions.checkState(unwrapped == null, "Cannot change the object, due to data inconsistencies."); + this.name = name; + } + + @Override + public String getLocalName() { + if (unwrapped != null) { + return unwrapped.getNodeType().getLocalName(); + } + return localName; + } + + @Override + public URI getNamespace() { + if (unwrapped != null) { + return unwrapped.getNodeType().getNamespace(); + } + return namespace; + } + + @Override + public void setNamespace(URI namespace) { + Preconditions.checkState(unwrapped == null, "Cannot change the object, due to data inconsistencies."); + this.namespace = namespace; + } + + @Override + public Node unwrap() { + if (unwrapped == null) { + if (name == null) { + Preconditions.checkNotNull(namespace); + name = new QName(namespace, localName); + } + if(composite) { + unwrapped = NodeFactory.createImmutableCompositeNode(name, null, Collections.>emptyList(),null); + } else { + unwrapped = NodeFactory.createImmutableSimpleNode(name, null, null); + } + namespace = null; + localName = null; + name = null; + } + return unwrapped; + } + + @Override + public QName getNodeType() { + return unwrap().getNodeType(); + } + + @Override + public CompositeNode getParent() { + return unwrap().getParent(); + } + + @Override + public Void getValue() { + return null; + } + + @Override + public QName getKey() { + return unwrap().getKey(); + } + + @Override + public Void setValue(Void value) { + return null; + } + +} diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend index a6a71fef55..35352e0819 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend @@ -12,6 +12,12 @@ import org.opendaylight.yangtools.yang.data.impl.NodeFactory import org.opendaylight.yangtools.yang.model.api.ChoiceNode import org.opendaylight.yangtools.yang.model.api.DataNodeContainer import org.opendaylight.yangtools.yang.model.api.DataSchemaNode +import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec +import org.opendaylight.yangtools.yang.model.api.TypeDefinition +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode +import org.opendaylight.yangtools.yang.common.QName +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode class RestconfImpl implements RestconfService { @@ -54,7 +60,7 @@ class RestconfImpl implements RestconfService { override createConfigurationData(String identifier, CompositeNode payload) { val identifierWithSchemaNode = identifier.resolveInstanceIdentifier - val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode) + val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode) val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get(); switch status.result { case TransactionStatus.COMMITED: Response.status(Response.Status.OK).build @@ -64,7 +70,7 @@ class RestconfImpl implements RestconfService { override updateConfigurationData(String identifier, CompositeNode payload) { val identifierWithSchemaNode = identifier.resolveInstanceIdentifier - val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode) + val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode) val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get(); switch status.result { case TransactionStatus.COMMITED: Response.status(Response.Status.NO_CONTENT).build @@ -77,7 +83,7 @@ class RestconfImpl implements RestconfService { if (rpc === null) { throw new ResponseException(Response.Status.NOT_FOUND, "RPC does not exist."); } - val value = resolveNodeNamespaceBySchema(payload, rpc.input) + val value = normalizeNode(payload, rpc.input) val List> input = new ArrayList input.add(value) val rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, input, null, null) @@ -113,38 +119,69 @@ class RestconfImpl implements RestconfService { return identifierWithSchemaNode } - private def CompositeNode resolveNodeNamespaceBySchema(CompositeNode node, DataSchemaNode schema) { + private def CompositeNode normalizeNode(CompositeNode node, DataSchemaNode schema) { if (node instanceof CompositeNodeWrapper) { - addNamespaceToNodeFromSchemaRecursively(node as CompositeNodeWrapper, schema) + normalizeNode(node as CompositeNodeWrapper, schema,null) return (node as CompositeNodeWrapper).unwrap() } return node } - private def void addNamespaceToNodeFromSchemaRecursively(NodeWrapper nodeBuilder, DataSchemaNode schema) { + private def void normalizeNode(NodeWrapper nodeBuilder, DataSchemaNode schema,QName previousAugment) { if (schema === null) { throw new ResponseException(Response.Status.BAD_REQUEST, "Data has bad format\n" + nodeBuilder.localName + " does not exist in yang schema."); } - val moduleName = controllerContext.findModuleByNamespace(schema.QName.namespace); - if (nodeBuilder.namespace === null || nodeBuilder.namespace == schema.QName.namespace || + var validQName = schema.QName + var currentAugment = previousAugment; + if(schema.augmenting) { + currentAugment = schema.QName + } else if(previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) { + validQName = QName.create(currentAugment,schema.QName.localName); + } + val moduleName = controllerContext.findModuleByNamespace(validQName.namespace); + if (nodeBuilder.namespace === null || nodeBuilder.namespace == validQName.namespace || nodeBuilder.namespace.path == moduleName) { - nodeBuilder.qname = schema.QName + nodeBuilder.qname = validQName } else { throw new ResponseException(Response.Status.BAD_REQUEST, "Data has bad format\nIf data is in XML format then namespace for " + nodeBuilder.localName + " should be " + schema.QName.namespace + ".\n If data is in Json format then module name for " + nodeBuilder.localName + " should be " + moduleName + "."); } + if (nodeBuilder instanceof CompositeNodeWrapper) { val List> children = (nodeBuilder as CompositeNodeWrapper).getValues for (child : children) { - addNamespaceToNodeFromSchemaRecursively(child, - findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes)) + normalizeNode(child, + findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes),currentAugment) + } + } else if (nodeBuilder instanceof SimpleNodeWrapper) { + val simpleNode = (nodeBuilder as SimpleNodeWrapper) + val stringValue = simpleNode.value as String; + + val objectValue = TypeDefinitionAwareCodec.from(schema.typeDefinition)?.deserialize(stringValue); + simpleNode.setValue(objectValue) + } else if (nodeBuilder instanceof EmptyNodeWrapper) { + val emptyNodeBuilder = nodeBuilder as EmptyNodeWrapper + if(schema instanceof LeafSchemaNode) { + emptyNodeBuilder.setComposite(false); + } else if(schema instanceof ContainerSchemaNode) { + // FIXME: Add presence check + emptyNodeBuilder.setComposite(true); } } } + private def dispatch TypeDefinition typeDefinition(LeafSchemaNode node) { + node.type + } + + private def dispatch TypeDefinition typeDefinition(LeafListSchemaNode node) { + node.type + } + + private def DataSchemaNode findFirstSchemaByLocalName(String localName, Set schemas) { for (schema : schemas) { if (schema instanceof ChoiceNode) { @@ -155,7 +192,11 @@ class RestconfImpl implements RestconfService { } } } else { - return schemas.findFirst[n|n.QName.localName.equals(localName)] + val result = schemas.findFirst[n|n.QName.localName.equals(localName)] + if(result !== null) { + return result; + + } } } return null diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/SimpleNodeWrapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/SimpleNodeWrapper.java index c1576895fd..9f3c6e51e9 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/SimpleNodeWrapper.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/SimpleNodeWrapper.java @@ -11,16 +11,16 @@ import org.opendaylight.yangtools.yang.data.impl.NodeFactory; import com.google.common.base.Preconditions; -public final class SimpleNodeWrapper implements NodeWrapper>, SimpleNode { +public final class SimpleNodeWrapper implements NodeWrapper>, SimpleNode { - private SimpleNode simpleNode; + private SimpleNode simpleNode; private String localName; - private String value; + private Object value; private URI namespace; private QName name; - public SimpleNodeWrapper(String localName, String value) { + public SimpleNodeWrapper(String localName, Object value) { this.localName = Preconditions.checkNotNull(localName); this.value = value; } @@ -59,7 +59,7 @@ public final class SimpleNodeWrapper implements NodeWrapper>, Simp } @Override - public SimpleNode unwrap() { + public SimpleNode unwrap() { if (simpleNode == null) { if (name == null) { Preconditions.checkNotNull(namespace); @@ -72,7 +72,7 @@ public final class SimpleNodeWrapper implements NodeWrapper>, Simp localName = null; name = null; } - return simpleNode; + return (SimpleNode) simpleNode; } @Override @@ -86,7 +86,7 @@ public final class SimpleNodeWrapper implements NodeWrapper>, Simp } @Override - public String getValue() { + public Object getValue() { return unwrap().getValue(); } @@ -96,7 +96,7 @@ public final class SimpleNodeWrapper implements NodeWrapper>, Simp } @Override - public MutableSimpleNode asMutable() { + public MutableSimpleNode asMutable() { return unwrap().asMutable(); } @@ -106,9 +106,10 @@ public final class SimpleNodeWrapper implements NodeWrapper>, Simp } @Override - public String setValue(String value) { + public Object setValue(Object value) { return unwrap().setValue(value); } + } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/FromXmlToCompositeNodeTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/FromXmlToCompositeNodeTest.java index 5aa6d0339d..a72bd60d30 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/FromXmlToCompositeNodeTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/FromXmlToCompositeNodeTest.java @@ -138,7 +138,7 @@ public class FromXmlToCompositeNodeTest { SimpleNode cont11_lf111 = (SimpleNode) cont11.getChildren().get(0); assertEquals(nameSpaceCont, cont11_lf111.getNodeType().getNamespace().toString()); assertEquals("lf111", cont11_lf111.getNodeType().getLocalName()); - assertEquals("100", cont11_lf111.getValue()); + assertEquals((short) 100, cont11_lf111.getValue()); // :lst1_2 } @@ -251,7 +251,7 @@ public class FromXmlToCompositeNodeTest { SimpleNode cont1_lf11 = (SimpleNode) cont1suf.getChildren().get(0); assertEquals(nameSpace, cont1_lf11.getNodeType().getNamespace().toString()); assertEquals("lf11" + suf, cont1_lf11.getNodeType().getLocalName()); - assertEquals("100", cont1_lf11.getValue()); + assertEquals((short) 100, cont1_lf11.getValue()); } private CompositeNode compositeContainerFromXml(String xmlPath, boolean dummyNamespaces) { diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java new file mode 100644 index 0000000000..104e52f6a9 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java @@ -0,0 +1,123 @@ +package org.opendaylight.controller.sal.restconf.impl.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.net.*; +import java.util.*; + +import org.junit.*; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.opendaylight.controller.sal.restconf.impl.*; +import org.opendaylight.yangtools.yang.common.*; +import org.opendaylight.yangtools.yang.data.api.*; +import org.opendaylight.yangtools.yang.data.impl.NodeFactory; +import org.opendaylight.yangtools.yang.model.api.Module; + +public class InvokeRpcMethodTest { + + private static Set modules; + + private class RpcResultImpl implements RpcResult { + + final T result; + + public RpcResultImpl(T compNode) { + this.result = compNode; + } + + @Override + public boolean isSuccessful() { + // TODO Auto-generated method stub + return false; + } + + @Override + public T getResult() { + return result; + } + + @Override + public Collection getErrors() { + // TODO Auto-generated method stub + return null; + } + + } + + private class AnswerImpl implements Answer> { + @Override + public RpcResult answer(InvocationOnMock invocation) throws Throwable { + CompositeNode compNode = (CompositeNode) invocation.getArguments()[1]; + return new RpcResultImpl(compNode); + } + } + + @BeforeClass + public static void initialization() { + modules = TestUtils.resolveModules("/invoke-rpc"); + assertEquals(1, modules.size()); + Module module = TestUtils.resolveModule("invoke-rpc-module", modules); + assertNotNull(module); + } + + /** + * Test method invokeRpc in RestconfImpl class tests if composite node as + * input parameter of method invokeRpc (second argument) is wrapped to + * parent composite node which has QName equals to QName of rpc (resolved + * from string - first argument). + */ + @Test + public void invokeRpcMethodTest() { + ControllerContext contContext = ControllerContext.getInstance(); + contContext.onGlobalContextUpdated(TestUtils.loadSchemaContext(modules)); + try { + contContext.findModuleByNamespace(new URI("invoke:rpc:module")); + } catch (URISyntaxException e) { + assertTrue("Uri wasn't created sucessfuly", false); + } + + BrokerFacade mockedBrokerFacade = mock(BrokerFacade.class); + + RestconfImpl restconf = RestconfImpl.getInstance(); + restconf.setBroker(mockedBrokerFacade); + restconf.setControllerContext(contContext); + + when(mockedBrokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class))).thenAnswer(new AnswerImpl()); + + StructuredData structData = restconf.invokeRpc("invoke-rpc-module:rpc-test", preparePayload()); + + CompositeNode rpcCompNode = structData.getData(); + CompositeNode cont = null; + assertEquals("invoke:rpc:module", rpcCompNode.getNodeType().getNamespace().toString()); + assertEquals("rpc-test", rpcCompNode.getNodeType().getLocalName()); + + for (Node node : rpcCompNode.getChildren()) { + if (node.getNodeType().getLocalName().equals("cont") + && node.getNodeType().getNamespace().toString().equals("nmspc")) { + if (node instanceof CompositeNode) { + cont = (CompositeNode) node; + } + } + } + assertNotNull(cont); + + } + + private CompositeNode preparePayload() { + MutableCompositeNode cont = NodeFactory.createMutableCompositeNode( + TestUtils.buildQName("cont", "nmspc", "2013-12-04"), null, null, ModifyAction.CREATE, null); + MutableSimpleNode lf = NodeFactory.createMutableSimpleNode( + TestUtils.buildQName("lf", "nmspc", "2013-12-04"), cont, "any value", ModifyAction.CREATE, null); + cont.getChildren().add(lf); + cont.init(); + + return cont; + } + +} diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/invoke-rpc/invoke-rpc-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/invoke-rpc/invoke-rpc-module.yang new file mode 100644 index 0000000000..ba06645354 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/invoke-rpc/invoke-rpc-module.yang @@ -0,0 +1,20 @@ +module invoke-rpc-module { + namespace "invoke:rpc:module"; + + prefix "inrpcmod"; + + revision 2013-12-3 { + + } + + rpc rpc-test { + input { + container cont { + leaf lf { + type string; + } + } + } + } + +} \ No newline at end of file diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java index 7dda447e6a..af56a84db5 100644 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java @@ -130,11 +130,12 @@ public class StatisticsProvider implements AutoCloseable { return; for (Node targetNode : targetNodes){ - spLogger.info("Send request for stats collection to node : {})",targetNode.getId()); + //We need to add check, so see if groups/meters are supported //by the target node. Below check doesn't look good. if(targetNode.getId().getValue().contains("openflow:")){ + spLogger.info("Send request for stats collection to node : {})",targetNode.getId()); InstanceIdentifier targetInstanceId = InstanceIdentifier.builder(Nodes.class).child(Node.class,targetNode.getKey()).toInstance(); NodeRef targetNodeRef = new NodeRef(targetInstanceId); diff --git a/opendaylight/md-sal/test/sal-rest-connector-it/src/test/java/org/opendaylight/controller/test/restconf/it/ServiceProviderController.java b/opendaylight/md-sal/test/sal-rest-connector-it/src/test/java/org/opendaylight/controller/test/restconf/it/ServiceProviderController.java index 41ae52b3bf..fda1e264e6 100644 --- a/opendaylight/md-sal/test/sal-rest-connector-it/src/test/java/org/opendaylight/controller/test/restconf/it/ServiceProviderController.java +++ b/opendaylight/md-sal/test/sal-rest-connector-it/src/test/java/org/opendaylight/controller/test/restconf/it/ServiceProviderController.java @@ -151,6 +151,9 @@ public class ServiceProviderController { systemProperty("netconf.tcp.address").value("127.0.0.1"), systemProperty("netconf.tcp.port").value("8383"), + systemProperty("netconf.tcp.client.address").value("127.0.0.1"), + systemProperty("netconf.tcp.client.port").value("8383"), + // Set the systemPackages (used by clustering) systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"), diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java index 5fa0b49d7b..e7916c2d5f 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java @@ -53,7 +53,7 @@ public class ConfigPersisterActivator implements BundleActivator { PersisterAggregator persister = PersisterAggregator.createFromProperties(propertiesProvider); InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context, - "Netconf is not configured, persister is not operational"); + "Netconf is not configured, persister is not operational",true); configPersisterNotificationHandler = new ConfigPersisterNotificationHandler(persister, address, platformMBeanServer, ignoredMissingCapabilityRegex); diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java index 1d18f063bc..b30c80b43d 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java @@ -34,7 +34,8 @@ public class NetconfImplActivator implements BundleActivator { @Override public void start(final BundleContext context) throws Exception { - InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context, "TCP is not configured, netconf not available."); + InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context, + "TCP is not configured, netconf not available.", false); NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl(); factoriesTracker = new NetconfOperationServiceFactoryTracker(context, factoriesListener); diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/osgi/NetconfSSHActivator.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/osgi/NetconfSSHActivator.java index 6f164f93d9..b91824866a 100644 --- a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/osgi/NetconfSSHActivator.java +++ b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/osgi/NetconfSSHActivator.java @@ -38,7 +38,8 @@ public class NetconfSSHActivator implements BundleActivator{ logger.trace("Starting netconf SSH bridge."); Optional sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context,EXCEPTION_MESSAGE); - InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,EXCEPTION_MESSAGE); + InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context, + EXCEPTION_MESSAGE, true); if (sshSocketAddressOptional.isPresent()){ server = NetconfSSHServer.start(sshSocketAddressOptional.get().getPort(),tcpSocketAddress); diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/IOThread.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/IOThread.java index 33ed88edf8..b9c9c174dc 100644 --- a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/IOThread.java +++ b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/IOThread.java @@ -26,6 +26,7 @@ public class IOThread extends Thread { private String id; private ServerSession servSession; private ServerConnection servconnection; + private String customHeader; public IOThread (InputStream is, OutputStream os, String id,ServerSession ss, ServerConnection conn){ @@ -36,11 +37,24 @@ public class IOThread extends Thread { super.setName(id); logger.trace("IOThread {} created", super.getName()); } + public IOThread (InputStream is, OutputStream os, String id,ServerSession ss, ServerConnection conn,String header){ + this.inputStream = is; + this.outputStream = os; + this.servSession = ss; + this.servconnection = conn; + this.customHeader = header; + super.setName(id); + logger.trace("IOThread {} created", super.getName()); + } @Override public void run() { logger.trace("thread {} started", super.getName()); try { + if (this.customHeader!=null && !this.customHeader.equals("")){ + this.outputStream.write(this.customHeader.getBytes()); + logger.trace("adding {} header", this.customHeader); + } IOUtils.copy(this.inputStream, this.outputStream); } catch (Exception e) { logger.error("inputstream -> outputstream copy error ",e); diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/SocketThread.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/SocketThread.java index 95fdd48bfe..15d99a44ee 100644 --- a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/SocketThread.java +++ b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/threads/SocketThread.java @@ -28,6 +28,8 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser private static final Logger logger = LoggerFactory.getLogger(SocketThread.class); private ServerConnection conn = null; private long sessionId; + private String currentUser; + private final String remoteAddressWithPort; public static void start(Socket socket, InetSocketAddress clientAddress, long sessionId) throws IOException{ @@ -40,6 +42,7 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser this.socket = socket; this.clientAddress = clientAddress; this.sessionId = sessionId; + this.remoteAddressWithPort = socket.getRemoteSocketAddress().toString().replaceFirst("/",""); } @@ -81,7 +84,8 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser netconf_ssh_input.start(); logger.trace("starting netconf_ssh_output thread"); - netconf_ssh_output = new IOThread(ss.getStdout(),echoSocket.getOutputStream(),"output_thread_"+sessionId,ss,conn); + final String customHeader = "["+currentUser+";"+remoteAddressWithPort+";ssh;;;;;;]\n"; + netconf_ssh_output = new IOThread(ss.getStdout(),echoSocket.getOutputStream(),"output_thread_"+sessionId,ss,conn,customHeader); netconf_ssh_output.setDaemon(false); netconf_ssh_output.start(); @@ -146,7 +150,8 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser public String initAuthentication(ServerConnection sc) { - return ""; + logger.trace("Established connection with host {}",remoteAddressWithPort); + return "Established connection with host "+remoteAddressWithPort+"\r\n"; } public String[] getRemainingAuthMethods(ServerConnection sc) @@ -161,8 +166,12 @@ public class SocketThread implements Runnable, ServerAuthenticationCallback, Ser public AuthenticationResult authenticateWithPassword(ServerConnection sc, String username, String password) { - if (USER.equals(username) && PASSWORD.equals(password)) + if (USER.equals(username) && PASSWORD.equals(password)){ + currentUser = username; + logger.trace("user {}@{} authenticated",currentUser,remoteAddressWithPort); return AuthenticationResult.SUCCESS; + } + return AuthenticationResult.FAILURE; } diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java index b1d902d634..987708d67e 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java @@ -8,12 +8,12 @@ package org.opendaylight.controller.netconf.util.osgi; -import com.google.common.base.Optional; -import java.net.InetSocketAddress; -import org.osgi.framework.BundleContext; -import static com.google.common.base.Preconditions.checkNotNull; + import com.google.common.base.Optional; + import java.net.InetSocketAddress; + import org.osgi.framework.BundleContext; + import static com.google.common.base.Preconditions.checkNotNull; - public class NetconfConfigUtil { +public class NetconfConfigUtil { private static final String PREFIX_PROP = "netconf."; private enum InfixProp { @@ -22,10 +22,11 @@ import static com.google.common.base.Preconditions.checkNotNull; private static final String PORT_SUFFIX_PROP = ".port"; private static final String ADDRESS_SUFFIX_PROP = ".address"; + private static final String CLIENT_PROP = ".client"; - public static InetSocketAddress extractTCPNetconfAddress(BundleContext context, String exceptionMessageIfNotFound) { + public static InetSocketAddress extractTCPNetconfAddress(BundleContext context, String exceptionMessageIfNotFound, boolean forClient) { - Optional inetSocketAddressOptional = extractSomeNetconfAddress(context, InfixProp.tcp, exceptionMessageIfNotFound); + Optional inetSocketAddressOptional = extractSomeNetconfAddress(context, InfixProp.tcp, exceptionMessageIfNotFound, forClient); if (inetSocketAddressOptional.isPresent() == false) { throw new IllegalStateException("Netconf tcp address not found." + exceptionMessageIfNotFound); @@ -34,7 +35,7 @@ import static com.google.common.base.Preconditions.checkNotNull; } public static Optional extractSSHNetconfAddress(BundleContext context, String exceptionMessage) { - return extractSomeNetconfAddress(context, InfixProp.ssh, exceptionMessage); + return extractSomeNetconfAddress(context, InfixProp.ssh, exceptionMessage, false); } /** @@ -47,14 +48,28 @@ import static com.google.common.base.Preconditions.checkNotNull; * if address or port are invalid, or configuration is missing */ private static Optional extractSomeNetconfAddress(BundleContext context, - InfixProp infixProp, String exceptionMessage) { - String address = context.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP); - if (address == null) { + InfixProp infixProp, + String exceptionMessage, + boolean client) { + String address = ""; + if (client) { + address = context.getProperty(PREFIX_PROP + infixProp + CLIENT_PROP + ADDRESS_SUFFIX_PROP); + } + if (address == null || address.equals("")){ + address = context.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP); + } + if (address == null || address.equals("")) { throw new IllegalStateException("Cannot find initial netconf configuration for parameter " +PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP +" in config.ini. "+exceptionMessage); } - String portKey = PREFIX_PROP + infixProp + PORT_SUFFIX_PROP; + String portKey = ""; + if (client) { + portKey = PREFIX_PROP + infixProp + CLIENT_PROP + PORT_SUFFIX_PROP; + } + if (portKey == null || portKey.equals("")){ + portKey = PREFIX_PROP + infixProp + PORT_SUFFIX_PROP; + } String portString = context.getProperty(portKey); checkNotNull(portString, "Netconf port must be specified in properties file with " + portKey); try { diff --git a/opendaylight/northbound/flowprogrammer/pom.xml b/opendaylight/northbound/flowprogrammer/pom.xml index af2c18a217..1b81ccb450 100644 --- a/opendaylight/northbound/flowprogrammer/pom.xml +++ b/opendaylight/northbound/flowprogrammer/pom.xml @@ -88,7 +88,7 @@ org.opendaylight.controller sal - 0.5.1-SNAPSHOT + 0.7.0-SNAPSHOT org.codehaus.enunciate diff --git a/opendaylight/northbound/integrationtest/pom.xml b/opendaylight/northbound/integrationtest/pom.xml index b4e0b34d09..793af2f5d7 100644 --- a/opendaylight/northbound/integrationtest/pom.xml +++ b/opendaylight/northbound/integrationtest/pom.xml @@ -49,7 +49,7 @@ org.opendaylight.controller sal - 0.5.1-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller @@ -74,7 +74,7 @@ org.opendaylight.controller clustering.services - 0.4.1-SNAPSHOT + 0.5.0-SNAPSHOT org.opendaylight.controller @@ -134,7 +134,7 @@ org.opendaylight.controller switchmanager - 0.6.1-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller diff --git a/opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthbound.java b/opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthbound.java index 05cb500273..5338849a62 100644 --- a/opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthbound.java +++ b/opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthbound.java @@ -844,7 +844,8 @@ public class StatisticsNorthbound { * }, * "activeCount": "11", * "lookupCount": "816", - * "matchedCount": "220" + * "matchedCount": "220", + * "maximumEntries": "1000" * }, * { * ...another table @@ -876,6 +877,7 @@ public class StatisticsNorthbound { * <activeCount>12</activeCount> * <lookupCount>10935</lookupCount> * <matchedCount>10084</matchedCount> + * <maximumEntries>1000</maximumEntries> * </tableStatistic> * <tableStatistic> * <nodeTable> @@ -888,6 +890,7 @@ public class StatisticsNorthbound { * <activeCount>0</activeCount> * <lookupCount>0</lookupCount> * <matchedCount>0</matchedCount> + * <maximumEntries>0</maximumEntries> * </tableStatistic> * <tableStatistic> * <nodeTable> @@ -900,6 +903,7 @@ public class StatisticsNorthbound { * <activeCount>0</activeCount> * <lookupCount>0</lookupCount> * <matchedCount>0</matchedCount> + * <maximumEntries>0</maximumEntries> * </tableStatistic> * </tableStatistics> * <tableStatistics> @@ -987,7 +991,8 @@ public class StatisticsNorthbound { * }, * "activeCount": "12", * "lookupCount": "11382", - * "matchedCount": "10524" + * "matchedCount": "10524", + * "maximumEntries": "1000" * }, * { * "nodeTable": { @@ -999,7 +1004,8 @@ public class StatisticsNorthbound { * }, * "activeCount": "0", * "lookupCount": "0", - * "matchedCount": "0" + * "matchedCount": "0", + * "maximumEntries": "0" * } * ] * } @@ -1022,6 +1028,7 @@ public class StatisticsNorthbound { * <activeCount>12</activeCount> * <lookupCount>10935</lookupCount> * <matchedCount>10084</matchedCount> + * <maximumEntries>1000</maximumEntries> * </tableStatistic> * <tableStatistic> * <nodeTable> @@ -1034,6 +1041,7 @@ public class StatisticsNorthbound { * <activeCount>0</activeCount> * <lookupCount>0</lookupCount> * <matchedCount>0</matchedCount> + * <maximumEntries>0</maximumEntries> * </tableStatistic> * <tableStatistic> * <nodeTable> @@ -1046,6 +1054,7 @@ public class StatisticsNorthbound { * <activeCount>0</activeCount> * <lookupCount>0</lookupCount> * <matchedCount>0</matchedCount> + * <maximumEntries>0</maximumEntries> * </tableStatistic> * </nodeTableStatistics> * diff --git a/opendaylight/protocol_plugins/openflow/pom.xml b/opendaylight/protocol_plugins/openflow/pom.xml index ca0ff45d61..ceeb29a1fc 100644 --- a/opendaylight/protocol_plugins/openflow/pom.xml +++ b/opendaylight/protocol_plugins/openflow/pom.xml @@ -70,7 +70,7 @@ org.opendaylight.controller sal - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java index 8fa4941b88..361f977b2c 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java @@ -57,6 +57,7 @@ import org.openflow.protocol.action.OFAction; import org.openflow.protocol.action.OFActionDataLayer; import org.openflow.protocol.action.OFActionDataLayerDestination; import org.openflow.protocol.action.OFActionDataLayerSource; +import org.openflow.protocol.action.OFActionEnqueue; import org.openflow.protocol.action.OFActionNetworkLayerAddress; import org.openflow.protocol.action.OFActionNetworkLayerDestination; import org.openflow.protocol.action.OFActionNetworkLayerSource; @@ -280,6 +281,15 @@ public class FlowConverter { actionsLength += OFActionOutput.MINIMUM_LENGTH; continue; } + if (action.getType() == ActionType.ENQUEUE) { + Enqueue a = (Enqueue) action; + OFActionEnqueue ofAction = new OFActionEnqueue(); + ofAction.setPort(PortConverter.toOFPort(a.getPort())); + ofAction.setQueueId(a.getQueue()); + actionsList.add(ofAction); + actionsLength += OFActionEnqueue.MINIMUM_LENGTH; + continue; + } if (action.getType() == ActionType.DROP) { continue; } @@ -683,6 +693,10 @@ public class FlowConverter { NodeConnectorCreator.createOFNodeConnector( ofPort, node)); } + } else if (ofAction instanceof OFActionEnqueue) { + salAction = new Enqueue(NodeConnectorCreator.createOFNodeConnector( + ((OFActionEnqueue) ofAction).getPort(), node), + ((OFActionEnqueue) ofAction).getQueueId()); } else if (ofAction instanceof OFActionVirtualLanIdentifier) { salAction = new SetVlanId( ((OFActionVirtualLanIdentifier) ofAction) diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryService.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryService.java index f983e1244d..39bbecf021 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryService.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryService.java @@ -8,6 +8,7 @@ package org.opendaylight.controller.protocol_plugin.openflow.internal; +import java.util.Collections; import java.util.Dictionary; import java.util.HashMap; import java.util.HashSet; @@ -138,6 +139,12 @@ public class InventoryService implements IInventoryShimInternalListener, return nodeProps; } + // nothing to return + @Override + public Set getConfiguredNotConnectedNodes() { + return Collections.emptySet(); + } + @Override public ConcurrentMap> getNodeConnectorProps( Boolean refresh) { diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TableStatisticsConverter.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TableStatisticsConverter.java index bcc2445808..35a763869b 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TableStatisticsConverter.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TableStatisticsConverter.java @@ -54,6 +54,7 @@ public class TableStatisticsConverter { ntStat.setActiveCount(ofTableStat.getActiveCount()); ntStat.setLookupCount(ofTableStat.getLookupCount()); ntStat.setMatchedCount(ofTableStat.getMatchedCount()); + ntStat.setMaximumEntries(ofTableStat.getMaximumEntries()); this.ntStatsList.add(ntStat); } } diff --git a/opendaylight/sal/api/pom.xml b/opendaylight/sal/api/pom.xml index 60e17e264e..405f924554 100644 --- a/opendaylight/sal/api/pom.xml +++ b/opendaylight/sal/api/pom.xml @@ -16,7 +16,7 @@ sal - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT bundle diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Enqueue.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Enqueue.java index b3891c8337..c711e67f9e 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Enqueue.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Enqueue.java @@ -21,6 +21,8 @@ public class Enqueue extends Action { private static final long serialVersionUID = 1L; @XmlElement private NodeConnector port; + @XmlElement + private int queue; /* Dummy constructor for JAXB */ @SuppressWarnings("unused") @@ -30,9 +32,25 @@ public class Enqueue extends Action { public Enqueue(NodeConnector port) { type = ActionType.ENQUEUE; this.port = port; + this.queue = 0; + } + + public Enqueue(NodeConnector port, int queue) { + type = ActionType.ENQUEUE; + this.port = port; + this.queue = queue; } public NodeConnector getPort() { return port; } + + public int getQueue() { + return queue; + } + + @Override + public String toString() { + return String.format("%s[%s:%s]", type, port, queue); + } } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IInventoryService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IInventoryService.java index 3c58ecbfcd..fa3afd8173 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IInventoryService.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IInventoryService.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.sal.inventory; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentMap; import org.opendaylight.controller.sal.core.Node; @@ -28,6 +29,13 @@ public interface IInventoryService { */ public ConcurrentMap> getNodeProps(); + /** + * The method retrieves all the configured nodes that are not connected to + * the controller + * + * @return Set of {@link org.opendaylight.controller.sal.core.Node} + */ + public Set getConfiguredNotConnectedNodes(); /** * The method retrieve all the existing nodeConnectors and their properties * diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IPluginInInventoryService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IPluginInInventoryService.java index 5822731f26..4007dc86e7 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IPluginInInventoryService.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IPluginInInventoryService.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.sal.inventory; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentMap; import org.opendaylight.controller.sal.core.Node; @@ -36,4 +37,12 @@ public interface IPluginInInventoryService { */ public ConcurrentMap> getNodeConnectorProps( Boolean refresh); + + /** + * The method retrieves all the configured nodes that are not connected to + * the controller + * + * @return Set of {@link org.opendaylight.controller.sal.core.Node} + */ + public Set getConfiguredNotConnectedNodes(); } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeTableStatistics.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeTableStatistics.java index 7c404178cf..eb33ad6799 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeTableStatistics.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeTableStatistics.java @@ -37,6 +37,8 @@ public class NodeTableStatistics implements Serializable { private long lookupCount; @XmlElement private long matchedCount; + @XmlElement + private int maximumEntries; @Override @@ -164,6 +166,20 @@ public class NodeTableStatistics implements Serializable { this.matchedCount = matchedCount; } + /** + * @return the maximumEntries + */ + public long getMaximumEntries() { + return maximumEntries; + } + + /** + * @param maximumEntries the maximumEntries to set + */ + public void setMaximumEntries(int maximumEntries) { + this.maximumEntries = maximumEntries; + } + @Override public String toString() { return "NodeTableStats[tableId = " + nodeTable diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NodeConnectorCreator.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NodeConnectorCreator.java index cbf3f95b2a..da4cd53883 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NodeConnectorCreator.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NodeConnectorCreator.java @@ -40,7 +40,7 @@ public abstract class NodeConnectorCreator { if (node.getType().equals(NodeIDType.OPENFLOW)) { try { return new NodeConnector(NodeConnectorIDType.OPENFLOW, - (Short) portId, node); + portId, node); } catch (ConstructionException e1) { logger.error("",e1); return null; @@ -49,6 +49,18 @@ public abstract class NodeConnectorCreator { return null; } + /** + * Generic NodeConnector creator + * The nodeConnector type is inferred from the node type + * + * @param portId The string representing the port id + * @param node The network node as {@link org.opendaylight.controller.sal.core.Node Node} object + * @return The corresponding {@link org.opendaylight.controller.sal.core.NodeConnector NodeConnector} object + */ + public static NodeConnector createNodeConnector(String portId, Node node) { + return NodeConnector.fromString(String.format("%s|%s@%s", node.getType(), portId, node.toString())); + } + /** * NodeConnector creator where NodeConnector type can be specified * Needed to create special internal node connectors (like software stack) diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/Status.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/Status.java index 00ac84fcc1..0387f72f38 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/Status.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/Status.java @@ -101,7 +101,7 @@ public class Status implements Serializable { * @return true if the Status code is {@code StatusCode.SUCCESS} */ public boolean isSuccess() { - return code == StatusCode.SUCCESS; + return code == StatusCode.SUCCESS || code == StatusCode.CREATED; } /** @@ -130,15 +130,19 @@ public class Status implements Serializable { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } Status other = (Status) obj; - if (code != other.code) + if (code != other.code) { return false; + } return true; } } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/StatusCode.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/StatusCode.java index 86b0d53fba..f8882bbd2f 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/StatusCode.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/StatusCode.java @@ -15,6 +15,7 @@ package org.opendaylight.controller.sal.utils; */ public enum StatusCode { SUCCESS("Success"), + CREATED("Created"), BADREQUEST("Bad Request"), UNAUTHORIZED("UnAuthorized"), diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/reader/NodeTableStatisticsTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/reader/NodeTableStatisticsTest.java index c0d6bb698a..a29d4268da 100644 --- a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/reader/NodeTableStatisticsTest.java +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/reader/NodeTableStatisticsTest.java @@ -24,12 +24,14 @@ public class NodeTableStatisticsTest { ntStats.setActiveCount(100); ntStats.setLookupCount(200); ntStats.setMatchedCount(500); + ntStats.setMaximumEntries(1000); ntStats.setName("Test"); Assert.assertTrue(ntStats.getNodeTable().equals(nt)); Assert.assertTrue(ntStats.getActiveCount() == 100); Assert.assertTrue(ntStats.getLookupCount() == 200); Assert.assertTrue(ntStats.getMatchedCount() == 500); + Assert.assertTrue(ntStats.getMaximumEntries() == 1000); Assert.assertTrue(ntStats.getName().equals("Test")); } } diff --git a/opendaylight/sal/implementation/pom.xml b/opendaylight/sal/implementation/pom.xml index f260f315e0..7c92a6b52b 100644 --- a/opendaylight/sal/implementation/pom.xml +++ b/opendaylight/sal/implementation/pom.xml @@ -59,7 +59,7 @@ org.opendaylight.controller sal - 0.5.1-SNAPSHOT + 0.7.0-SNAPSHOT equinoxSDK381 diff --git a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/Inventory.java b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/Inventory.java index 1cc57bac66..fbb9fbc518 100644 --- a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/Inventory.java +++ b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/Inventory.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.sal.implementation.internal; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -145,6 +146,18 @@ public class Inventory implements IPluginOutInventoryService, IInventoryService return nodeProps; } + @Override + public Set getConfiguredNotConnectedNodes() { + Set configuredNotConnected = new HashSet(), rv; + for (IPluginInInventoryService s : this.pluginService) { + rv = s.getConfiguredNotConnectedNodes(); + if (rv != null) { + configuredNotConnected.addAll(rv); + } + } + return configuredNotConnected; + } + @Override public ConcurrentMap> getNodeConnectorProps() { ConcurrentMap> ncProps = 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 043fdc08c1..a34cbb5db8 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 @@ -634,7 +634,7 @@ public class SimpleForwardingImpl implements IfNewHostNotify, po = e.getValue(); if (po != null) { // Populate the Policy field now - Status poStatus = this.frm.installFlowEntry(po); + Status poStatus = this.frm.modifyOrAddFlowEntry(po); if (!poStatus.isSuccess()) { log.error("Failed to install policy: " + po.getGroupName() + " (" @@ -842,8 +842,9 @@ public class SimpleForwardingImpl implements IfNewHostNotify, @Override public void notifyNode(Node node, UpdateType type, Map propMap) { - if (node == null) + if (node == null) { return; + } switch (type) { case REMOVED: @@ -858,8 +859,9 @@ public class SimpleForwardingImpl implements IfNewHostNotify, @Override public void notifyNodeConnector(NodeConnector nodeConnector, UpdateType type, Map propMap) { - if (nodeConnector == null) + if (nodeConnector == null) { return; + } boolean up = false; switch (type) { diff --git a/opendaylight/statisticsmanager/integrationtest/pom.xml b/opendaylight/statisticsmanager/integrationtest/pom.xml index 743c6784a5..d04371461f 100644 --- a/opendaylight/statisticsmanager/integrationtest/pom.xml +++ b/opendaylight/statisticsmanager/integrationtest/pom.xml @@ -25,7 +25,7 @@ org.opendaylight.controller sal - 0.5.1-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller @@ -50,7 +50,7 @@ org.opendaylight.controller clustering.services - 0.4.1-SNAPSHOT + 0.5.0-SNAPSHOT org.opendaylight.controller @@ -75,7 +75,7 @@ org.opendaylight.controller switchmanager - 0.6.1-SNAPSHOT + 0.7.0-SNAPSHOT diff --git a/opendaylight/switchmanager/api/pom.xml b/opendaylight/switchmanager/api/pom.xml index cf4c514965..b9cac8f2f8 100644 --- a/opendaylight/switchmanager/api/pom.xml +++ b/opendaylight/switchmanager/api/pom.xml @@ -16,7 +16,7 @@ switchmanager - 0.6.1-SNAPSHOT + 0.7.0-SNAPSHOT bundle 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 8815e5e8c0..072544c214 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 @@ -66,6 +66,13 @@ public interface ISwitchManager { */ public List getNetworkDevices(); + /** + * Return a Set of all configured devices that are not connected to the controller + * + * @return Set of {@link org.opendaylight.controller.switchmanager.Switch} + */ + public Set getConfiguredNotConnectedSwitches(); + /** * Return a list of subnet that were previously configured * diff --git a/opendaylight/switchmanager/implementation/pom.xml b/opendaylight/switchmanager/implementation/pom.xml index 1e78ec7a3d..76bfd56c29 100644 --- a/opendaylight/switchmanager/implementation/pom.xml +++ b/opendaylight/switchmanager/implementation/pom.xml @@ -107,12 +107,12 @@ org.opendaylight.controller sal - 0.5.1-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller switchmanager - 0.6.1-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller diff --git a/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java b/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java index 4d2aea2036..4950cae33a 100644 --- a/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java +++ b/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java @@ -2155,4 +2155,25 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa return (desc == null /* || desc.getValue().equalsIgnoreCase("none") */) ? "" : desc.getValue(); } + + @Override + public Set getConfiguredNotConnectedSwitches() { + Set configuredNotConnectedSwitches = new HashSet(); + if (this.inventoryService == null) { + log.trace("inventory service not avaiable"); + return configuredNotConnectedSwitches; + } + + Set configuredNotConnectedNodes = this.inventoryService.getConfiguredNotConnectedNodes(); + if (configuredNotConnectedNodes != null) { + for (Node node : configuredNotConnectedNodes) { + Switch sw = getSwitchByNode(node); + if (sw != null) { + configuredNotConnectedSwitches.add(sw); + } + } + } + return configuredNotConnectedSwitches; + } + } diff --git a/opendaylight/switchmanager/integrationtest/pom.xml b/opendaylight/switchmanager/integrationtest/pom.xml index 5d8ce9b303..24788771bf 100644 --- a/opendaylight/switchmanager/integrationtest/pom.xml +++ b/opendaylight/switchmanager/integrationtest/pom.xml @@ -21,7 +21,7 @@ org.opendaylight.controller switchmanager - 0.6.1-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller @@ -31,7 +31,7 @@ org.opendaylight.controller sal - 0.5.1-SNAPSHOT + 0.7.0-SNAPSHOT org.opendaylight.controller @@ -51,7 +51,7 @@ org.opendaylight.controller clustering.services - 0.4.1-SNAPSHOT + 0.5.0-SNAPSHOT org.opendaylight.controller