From: Giovanni Meo Date: Thu, 19 Sep 2013 15:36:49 +0000 (+0000) Subject: Merge "Validate user input in FlowSepc Configuration" X-Git-Tag: releasepom-0.1.0~54 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=52757c15dc010e68ef15899daf50f78291966bee;hp=ab70c9c38302ae1034bbde5d9c2964d7ec8bcebe Merge "Validate user input in FlowSepc Configuration" --- diff --git a/opendaylight/archetypes/odl-model-project/src/main/resources/archetype-resources/pom.xml b/opendaylight/archetypes/odl-model-project/src/main/resources/archetype-resources/pom.xml index b84346514f..ecc08d011d 100644 --- a/opendaylight/archetypes/odl-model-project/src/main/resources/archetype-resources/pom.xml +++ b/opendaylight/archetypes/odl-model-project/src/main/resources/archetype-resources/pom.xml @@ -9,7 +9,7 @@ UTF-8 http://nexus.opendaylight.org/content - 0.5.7-SNAPSHOT + 0.5.8-SNAPSHOT 2.4.0 @@ -56,7 +56,7 @@ org.opendaylight.yangtools yang-maven-plugin - 0.5.7-SNAPSHOT + ${yang.version} @@ -79,7 +79,7 @@ org.opendaylight.yangtools maven-sal-api-gen-plugin - 0.5.7-SNAPSHOT + ${yang.version} jar @@ -136,9 +136,9 @@ - central2 - central2 - http://repo2.maven.org/maven2 + central + maven repo1 + http://repo1.maven.org/maven2 false @@ -168,17 +168,6 @@ ebr-bundles-external ${nexusproxy}/repositories/ebr-bundles-external/ - - central2 - central2 - http://repo2.maven.org/maven2 - - false - - - true - - central central diff --git a/opendaylight/clustering/integrationtest/pom.xml b/opendaylight/clustering/integrationtest/pom.xml index 0fadb12890..63ef24d3b1 100644 --- a/opendaylight/clustering/integrationtest/pom.xml +++ b/opendaylight/clustering/integrationtest/pom.xml @@ -52,7 +52,7 @@ jacoco ../implementation/target/jacoco.exec - ../implementaiton/target/jacoco-it.exec + ../implementation/target/jacoco-it.exec java @@ -69,7 +69,7 @@ org.jacoco jacoco-maven-plugin - 0.5.3.201107060350 + ${jacoco.version} ../implementation/target/jacoco-it.exec org.opendaylight.controller.* diff --git a/opendaylight/clustering/services_implementation/pom.xml b/opendaylight/clustering/services_implementation/pom.xml index c0a8064493..d6bd287434 100644 --- a/opendaylight/clustering/services_implementation/pom.xml +++ b/opendaylight/clustering/services_implementation/pom.xml @@ -30,7 +30,7 @@ org.jacoco jacoco-maven-plugin - 0.5.3.201107060350 + ${jacoco.version} diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index cb1892ae66..31dd741cfd 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -55,13 +55,14 @@ 1.0-SNAPSHOT 2.3.2 3.1 + 0.5.3.201107060350 - central2 - central2 - http://repo2.maven.org/maven2 + central + maven repo1 + http://repo1.maven.org/maven2 @@ -206,17 +207,6 @@ ebr-bundles-external ${nexusproxy}/repositories/ebr-bundles-external/ - - central2 - central2 - http://repo2.maven.org/maven2 - - false - - - true - - central central @@ -438,9 +428,6 @@ org.apache.maven.plugins maven-surefire-plugin ${surefire.version} - - ${testvm.argLine} - diff --git a/opendaylight/connectionmanager/api/src/main/java/org/opendaylight/controller/connectionmanager/ConnectionLocality.java b/opendaylight/connectionmanager/api/src/main/java/org/opendaylight/controller/connectionmanager/ConnectionLocality.java new file mode 100644 index 0000000000..347ca07ec1 --- /dev/null +++ b/opendaylight/connectionmanager/api/src/main/java/org/opendaylight/controller/connectionmanager/ConnectionLocality.java @@ -0,0 +1,28 @@ +package org.opendaylight.controller.connectionmanager; + +public enum ConnectionLocality { + /** + * This controller is the (or one of the) master for a given node + */ + LOCAL("This controller is the (or one of the) master for a given node"), + + /** + * This controller is not the master for a given node + */ + NOT_LOCAL("This controller is not the master for a given node"), + + /** + * The given node is not connected to any of the controllers in the cluster + */ + NOT_CONNECTED("The given node is not connected to any of the controllers in the cluster"); + + private ConnectionLocality(String description) { + this.description = description; + } + + private String description; + + public String toString() { + return description; + } +} diff --git a/opendaylight/connectionmanager/api/src/main/java/org/opendaylight/controller/connectionmanager/IConnectionManager.java b/opendaylight/connectionmanager/api/src/main/java/org/opendaylight/controller/connectionmanager/IConnectionManager.java index 12b196989e..788af16248 100644 --- a/opendaylight/connectionmanager/api/src/main/java/org/opendaylight/controller/connectionmanager/IConnectionManager.java +++ b/opendaylight/connectionmanager/api/src/main/java/org/opendaylight/controller/connectionmanager/IConnectionManager.java @@ -54,12 +54,27 @@ public interface IConnectionManager { public Set getLocalNodes(); /** + * @deprecated Use getLocalityStatus(Node node) instead. + * * Method to test if a node is local to a controller. * - * @return true if node is local to this controller. false otherwise. + * @param node The node for which the locality is being tested + * @return true if node is local to this controller.
+ * false if either node is not connected to this controller or + * not connected to any other controllers in the cluster. */ public boolean isLocal(Node node); + /** + * getLocalityStatus provides the tri-state connectivity status as opposed to the + * binary status returned by isLocal. + * ConnectionLocality enum that is returned by this method also includes the case of + * a Node not connected to any of the controllers in the cluster. + * @param node The node for which the locality is being verified + * @return ConnectionLocality + */ + public ConnectionLocality getLocalityStatus(Node node); + /** * Disconnect a Node from the controller. * diff --git a/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/ConnectionManager.java b/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/ConnectionManager.java index bd377190f2..df5175083b 100644 --- a/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/ConnectionManager.java +++ b/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/ConnectionManager.java @@ -37,6 +37,7 @@ import org.eclipse.osgi.framework.console.CommandProvider; import org.opendaylight.controller.clustering.services.ICacheUpdateAware; import org.opendaylight.controller.clustering.services.IClusterGlobalServices; import org.opendaylight.controller.clustering.services.ICoordinatorChangeAware; +import org.opendaylight.controller.connectionmanager.ConnectionLocality; import org.opendaylight.controller.connectionmanager.ConnectionMgmtScheme; import org.opendaylight.controller.connectionmanager.IConnectionManager; import org.opendaylight.controller.connectionmanager.scheme.AbstractScheme; @@ -185,6 +186,13 @@ public class ConnectionManager implements IConnectionManager, IConnectionListene return scheme.isLocal(node); } + @Override + public ConnectionLocality getLocalityStatus(Node node) { + AbstractScheme scheme = schemes.get(activeScheme); + if (scheme == null) return ConnectionLocality.NOT_CONNECTED; + return scheme.getLocalityStatus(node); + } + @Override public void updateNode(Node node, UpdateType type, Set props) { logger.debug("updateNode: {} type {} props {}", node, type, props); diff --git a/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/scheme/AbstractScheme.java b/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/scheme/AbstractScheme.java index 06b72219f7..78f274c717 100644 --- a/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/scheme/AbstractScheme.java +++ b/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/scheme/AbstractScheme.java @@ -14,6 +14,7 @@ import org.opendaylight.controller.clustering.services.CacheConfigException; import org.opendaylight.controller.clustering.services.CacheExistException; import org.opendaylight.controller.clustering.services.IClusterGlobalServices; import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.connectionmanager.ConnectionLocality; import org.opendaylight.controller.connectionmanager.ConnectionMgmtScheme; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.utils.Status; @@ -146,6 +147,15 @@ public abstract class AbstractScheme { return (controllers != null && controllers.contains(myController)); } + public ConnectionLocality getLocalityStatus(Node node) { + if (nodeConnections == null) return ConnectionLocality.NOT_CONNECTED; + Set controllers = nodeConnections.get(node); + if (controllers == null || controllers.size() == 0) return ConnectionLocality.NOT_CONNECTED; + InetAddress myController = clusterServices.getMyAddress(); + return controllers.contains(myController) ? ConnectionLocality.LOCAL: + ConnectionLocality.NOT_LOCAL; + } + public Status removeNode (Node node) { return removeNodeFromController(node, clusterServices.getMyAddress()); } diff --git a/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/ContainerConfig.java b/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/ContainerConfig.java index a34746949e..89bf424e67 100644 --- a/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/ContainerConfig.java +++ b/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/ContainerConfig.java @@ -386,11 +386,38 @@ public class ContainerConfig implements Serializable { config.getName())); } } + } else { + // Check for conflicting names with existing cFlows + List conflicting = new ArrayList(existingNames); + conflicting.retainAll(proposedNames); + if (!conflicting.isEmpty()) { + return new Status(StatusCode.CONFLICT, + "Invalid Flow Spec configuration: flow spec name(s) conflict with existing flow specs: " + + conflicting.toString()); + } + + /* + * Check for conflicting flow spec match (we only check for strict + * equality). Remove this in case (*) is reintroduced + */ + if (this.containerFlows != null && !this.containerFlows.isEmpty()) { + Set existingMatches = new HashSet(); + for (ContainerFlowConfig existing : this.containerFlows) { + existingMatches.addAll(existing.getMatches()); + } + for (ContainerFlowConfig proposed : cFlowConfigs) { + if (existingMatches.removeAll(proposed.getMatches())) { + return new Status(StatusCode.CONFLICT, String.format( + "Invalid Flow Spec configuration: %s conflicts with existing flow spec", + proposed.getName())); + } + } + } } + /* * Revisit the following flow-spec confict validation later based on more testing. - */ - /* + * (*) if (!delete) { // Check for overlapping container flows in the request int size = cFlowConfigs.size(); diff --git a/opendaylight/containermanager/it.implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java b/opendaylight/containermanager/it.implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java index b5624af6af..24ef0c08ef 100644 --- a/opendaylight/containermanager/it.implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java +++ b/opendaylight/containermanager/it.implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java @@ -192,8 +192,7 @@ public class ContainerManager implements IContainerManager { @Override public boolean doesContainerExist(String ContainerId) { - // TODO Auto-generated method stub - return false; + return GlobalConstants.DEFAULT.toString().equalsIgnoreCase(ContainerId); } @Override diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index 1fb131e4af..3efd97e2aa 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -74,7 +74,7 @@ ../../statisticsmanager/api ../../statisticsmanager/implementation ../../statisticsmanager/integrationtest - ../../topologymanager + ../../topologymanager/implementation ../../usermanager/api ../../usermanager/implementation ../../connectionmanager/api diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini index 970929f794..12f18ff645 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini @@ -94,3 +94,6 @@ controllerKeyStore= controllerKeyStorePassword= controllerTrustStore= controllerTrustStorePassword= + +# User Manager configurations +enableStrongPasswordCheck = false 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 ba69c8a3d2..62d6855e10 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 @@ -655,6 +655,14 @@ public class FlowConfig implements Serializable { return ((to >= 0) && (to <= 0xffff)); } + public boolean isProtocolValid(String protocol) { + int protocol_number = IPProtocols.getProtocolNumberInt(protocol); + if (protocol_number < 1 || protocol_number > 255) { + return false; + } + return true; + } + private Status conflictWithContainerFlow(IContainer container) { // Return true if it's default container if (container.getName().equals(GlobalConstants.DEFAULT.toString())) { @@ -762,6 +770,10 @@ public class FlowConfig implements Serializable { } } + if ((protocol != null) && !isProtocolValid(protocol)) { + return new Status(StatusCode.BADREQUEST, String.format("Protocol %s is not valid", protocol)); + } + if ((tosBits != null) && !isTOSBitsValid(tosBits)) { return new Status(StatusCode.BADREQUEST, String.format("IP ToS bits %s is not in the range 0 - 63", tosBits)); diff --git a/opendaylight/forwardingrulesmanager/implementation/pom.xml b/opendaylight/forwardingrulesmanager/implementation/pom.xml index ea55ac8b08..d146eead6f 100644 --- a/opendaylight/forwardingrulesmanager/implementation/pom.xml +++ b/opendaylight/forwardingrulesmanager/implementation/pom.xml @@ -33,7 +33,7 @@ org.jacoco jacoco-maven-plugin - 0.5.3.201107060350 + ${jacoco.version}
diff --git a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java index 58d23655ca..6e3e6b6633 100644 --- a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java +++ b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java @@ -39,6 +39,7 @@ import org.opendaylight.controller.clustering.services.ICacheUpdateAware; import org.opendaylight.controller.clustering.services.IClusterContainerServices; import org.opendaylight.controller.clustering.services.IClusterServices; import org.opendaylight.controller.configuration.IConfigurationContainerAware; +import org.opendaylight.controller.connectionmanager.ConnectionLocality; import org.opendaylight.controller.connectionmanager.IConnectionManager; import org.opendaylight.controller.forwardingrulesmanager.FlowConfig; import org.opendaylight.controller.forwardingrulesmanager.FlowEntry; @@ -273,7 +274,7 @@ public class ForwardingRulesManager implements } Node n = e.getNode(); - if (!connectionManager.isLocal(n)) { + if (connectionManager.getLocalityStatus(n) == ConnectionLocality.NOT_LOCAL) { Callable> worker = new DistributeOrderCallable(e, u, t); if (worker != null) { Future> workerRes = this.executor.submit(worker); @@ -291,7 +292,7 @@ public class ForwardingRulesManager implements } } - logsync.trace("LOCAL Node {} so processing Entry:{} UpdateType:{}", n, e, t); + logsync.trace("Node {} could be local. so processing Entry:{} UpdateType:{}", n, e, t); return null; } @@ -1867,9 +1868,13 @@ public class ForwardingRulesManager implements } } if (target != null) { - // Program the network node - Status status = (target.installInHw()) ? this.uninstallFlowEntry(target.getFlowEntry()) : this - .installFlowEntry(target.getFlowEntry()); + Status status = target.validate(container); + if (!status.isSuccess()) { + log.warn(status.getDescription()); + return status; + } + status = (target.installInHw()) ? this.uninstallFlowEntry(target.getFlowEntry()) : this + .installFlowEntry(target.getFlowEntry()); if (status.isSuccess()) { // Update Configuration database target.setStatus(SUCCESS); @@ -3105,7 +3110,7 @@ public class ForwardingRulesManager implements return; } Node n = fei.getNode(); - if (connectionManager.isLocal(n)) { + if (connectionManager.getLocalityStatus(n) == ConnectionLocality.LOCAL) { logsync.trace("workOrder for fe {} processed locally", fe); // I'm the controller in charge for the request, queue it for // processing diff --git a/opendaylight/forwardingrulesmanager/integrationtest/pom.xml b/opendaylight/forwardingrulesmanager/integrationtest/pom.xml index 7779243599..32cae25dba 100644 --- a/opendaylight/forwardingrulesmanager/integrationtest/pom.xml +++ b/opendaylight/forwardingrulesmanager/integrationtest/pom.xml @@ -130,7 +130,7 @@ jacoco ../implementation/target/jacoco.exec - ../implementaiton/target/jacoco-it.exec + ../implementation/target/jacoco-it.exec java @@ -147,7 +147,7 @@ org.jacoco jacoco-maven-plugin - 0.5.3.201107060350 + ${jacoco.version} ../implementation/target/jacoco-it.exec org.opendaylight.controller.* diff --git a/opendaylight/hosttracker/implementation/pom.xml b/opendaylight/hosttracker/implementation/pom.xml index 268dd4f67f..e93559b42c 100644 --- a/opendaylight/hosttracker/implementation/pom.xml +++ b/opendaylight/hosttracker/implementation/pom.xml @@ -33,7 +33,7 @@ org.jacoco jacoco-maven-plugin - 0.5.3.201107060350 + ${jacoco.version} diff --git a/opendaylight/hosttracker/integrationtest/pom.xml b/opendaylight/hosttracker/integrationtest/pom.xml index 81551650c3..f2fefcdabc 100644 --- a/opendaylight/hosttracker/integrationtest/pom.xml +++ b/opendaylight/hosttracker/integrationtest/pom.xml @@ -117,7 +117,7 @@ org.jacoco jacoco-maven-plugin - 0.5.3.201107060350 + ${jacoco.version} ../implementation/target/jacoco-it.exec org.opendaylight.controller.* diff --git a/opendaylight/hosttracker_new/implementation/pom.xml b/opendaylight/hosttracker_new/implementation/pom.xml index af2ea7b347..dfc2955cfd 100644 --- a/opendaylight/hosttracker_new/implementation/pom.xml +++ b/opendaylight/hosttracker_new/implementation/pom.xml @@ -22,7 +22,7 @@ jacoco reuseReports - target/jacoco.exec + target/jacoco.exec target/jacoco-it.exec java @@ -33,7 +33,7 @@ org.jacoco jacoco-maven-plugin - 0.5.3.201107060350 + ${jacoco.version} diff --git a/opendaylight/md-sal/sal-compability/pom.xml b/opendaylight/md-sal/sal-compability/pom.xml new file mode 100644 index 0000000000..e3d8c589f7 --- /dev/null +++ b/opendaylight/md-sal/sal-compability/pom.xml @@ -0,0 +1,45 @@ + + 4.0.0 + + org.opendaylight.controller + sal-parent + 1.0-SNAPSHOT + ../../sal/yang-prototype/sal/pom.xml + + sal-compability + + + + org.opendaylight.controller + sal + 0.5.0-SNAPSHOT + + + org.opendaylight.controller.model + model-flow-service + 1.0-SNAPSHOT + + + org.opendaylight.controller.model + model-flow-statistics + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-binding-api + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-common-util + 1.0-SNAPSHOT + + + com.google.guava + guava + bundle + 14.0.1 + + + diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ToSalConversionsUtils.java b/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ToSalConversionsUtils.java new file mode 100644 index 0000000000..c113cd8924 --- /dev/null +++ b/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ToSalConversionsUtils.java @@ -0,0 +1,349 @@ +package org.opendaylight.controller.sal.compability; + +import static org.opendaylight.controller.sal.match.MatchType.DL_DST; +import static org.opendaylight.controller.sal.match.MatchType.DL_SRC; +import static org.opendaylight.controller.sal.match.MatchType.DL_TYPE; +import static org.opendaylight.controller.sal.match.MatchType.DL_VLAN; +import static org.opendaylight.controller.sal.match.MatchType.DL_VLAN_PR; +import static org.opendaylight.controller.sal.match.MatchType.NW_DST; +import static org.opendaylight.controller.sal.match.MatchType.NW_PROTO; +import static org.opendaylight.controller.sal.match.MatchType.NW_SRC; +import static org.opendaylight.controller.sal.match.MatchType.NW_TOS; +import static org.opendaylight.controller.sal.match.MatchType.TP_DST; +import static org.opendaylight.controller.sal.match.MatchType.TP_SRC; + +import java.net.InetAddress; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.opendaylight.controller.sal.action.Controller; +import org.opendaylight.controller.sal.action.Output; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.flowprogrammer.Flow; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.action.action.ControllerAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.action.action.OutputAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.action.action.PopMplsAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.action.action.PushMplsAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.action.action.PushPbbAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.action.action.PushVlanAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.action.action.SetMplsTtlAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.action.action.SetNwTtlAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.action.action.SetQueueAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.flow.Action; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev130819.MacAddressFilter; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev130819.ethernet.match.fields.EthernetType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev130819.match.EthernetMatch; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev130819.match.IpMatch; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev130819.match.Layer3Match; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev130819.match.Layer4Match; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev130819.match.VlanMatch; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev130819.match.layer._3.match.ArpMatch; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev130819.match.layer._3.match.Ipv4Match; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev130819.match.layer._3.match.Ipv6Match; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev130819.match.layer._4.match.SctpMatch; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev130819.match.layer._4.match.TcpMatch; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev130819.match.layer._4.match.UdpMatch; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev130819.vlan.match.fields.VlanId; + +import com.google.common.net.InetAddresses; + +public class ToSalConversionsUtils { + + private ToSalConversionsUtils() { + + } + + public static Flow flowFrom(NodeFlow source) { + final Flow target = new Flow(); + + Integer hardTimeout = source.getHardTimeout(); + if (hardTimeout != null) { + target.setHardTimeout(hardTimeout.shortValue()); + } + + Integer idleTimeout = source.getIdleTimeout(); + if (idleTimeout != null) { + target.setIdleTimeout(idleTimeout.shortValue()); + } + + Integer priority = source.getPriority(); + if (priority != null) { + target.setPriority(priority.shortValue()); + } + + target.setMatch(matchFrom(source.getMatch())); + + List actions = source.getAction(); + if (actions != null) { + for (Action sourceAction : actions) { + Set targetActions = actionFrom(sourceAction); + for (org.opendaylight.controller.sal.action.Action targetAction : targetActions) { + target.addAction(targetAction); + } + } + } + + target.setId(source.getCookie().longValue()); + return target; + } + + public static Set actionFrom(Action source) { + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.action.Action sourceAction = source + .getAction(); + Set targetAction = new HashSet<>(); + if (sourceAction instanceof ControllerAction) { + targetAction.add(new Controller()); + } else if (sourceAction instanceof OutputAction) { + + List nodeConnectors = ((OutputAction) sourceAction).getOutputNodeConnector(); + for (Uri uri : nodeConnectors) { + targetAction.add(new Output(fromNodeConnectorRef(uri))); + } + } else if (sourceAction instanceof PopMplsAction) { + // TODO: define maping + } else if (sourceAction instanceof PushMplsAction) { + // TODO: define maping + } else if (sourceAction instanceof PushPbbAction) { + // TODO: define maping + } else if (sourceAction instanceof PushVlanAction) { + // TODO: define maping + // PushVlanAction vlanAction = (PushVlanAction) sourceAction; + // targetAction.add(new PushVlan(vlanAction., pcp, cfi, vlanId); + } else if (sourceAction instanceof SetMplsTtlAction) { + // TODO: define maping + // targetAction = //no action to map + } else if (sourceAction instanceof SetNwTtlAction) { + // TODO: define maping + } else if (sourceAction instanceof SetQueueAction) { + // TODO: define maping + // targetAction = //no action to map + } + + return targetAction; + } + + private static NodeConnector fromNodeConnectorRef(Uri uri) { + // TODO: Define mapping + return null; + } + + public static Match matchFrom(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.flow.Match source) { + Match target = new Match(); + if (source != null) { + fillFrom(target, source.getVlanMatch()); + fillFrom(target, source.getEthernetMatch()); + fillFrom(target, source.getLayer3Match()); + fillFrom(target, source.getLayer4Match()); + fillFrom(target, source.getIpMatch()); + } + + return target; + } + + private static void fillFrom(Match target, VlanMatch vlanMatch) { + if (vlanMatch != null) { + VlanId vlanId = vlanMatch.getVlanId(); + if (vlanId != null) { + org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId vlanIdInner = vlanId + .getVlanId(); + if (vlanIdInner != null) { + Integer vlanValue = vlanIdInner.getValue(); + if (vlanValue != null) { + target.setField(DL_VLAN, vlanValue.shortValue()); + } + } + } + VlanPcp vlanPcp = vlanMatch.getVlanPcp(); + if (vlanPcp != null) { + Short vlanPcpValue = vlanPcp.getValue(); + if (vlanPcpValue != null) { + target.setField(DL_VLAN_PR, vlanPcpValue.byteValue()); + } + } + } + } + + private static void fillFrom(Match target, IpMatch ipMatch) { + if (ipMatch != null) { + Short ipProtocol = ipMatch.getIpProtocol(); + if (ipProtocol != null) { + target.setField(NW_PROTO, ipProtocol.byteValue()); + } + Dscp dscp = ipMatch.getIpDscp(); + if (dscp != null) { + Short dscpValue = dscp.getValue(); + if (dscpValue != null) { + target.setField(NW_TOS, dscpValue.byteValue()); + } + } + } + } + + private static void fillFrom(Match target, Layer4Match layer4Match) { + if (layer4Match == null) { + return; + } + if (layer4Match instanceof SctpMatch) { + fillTransportLayer(target, (SctpMatch) layer4Match); + } else if (layer4Match instanceof TcpMatch) { + fillTransportLayer(target, (TcpMatch) layer4Match); + } else if (layer4Match instanceof UdpMatch) { + fillTransportLayer(target, (UdpMatch) layer4Match); + } + } + + private static void fillTransportLayer(Match target, UdpMatch source) { + PortNumber udpSourcePort = source.getUdpSourcePort(); + if (udpSourcePort != null) { + Integer udpSourcePortValue = udpSourcePort.getValue(); + if (udpSourcePortValue != null) { + target.setField(TP_SRC, udpSourcePortValue.shortValue()); + } + } + + PortNumber udpDestPort = source.getUdpDestinationPort(); + if (udpDestPort != null) { + Integer udpDestPortValue = udpDestPort.getValue(); + if (udpDestPortValue != null) { + target.setField(TP_DST, udpDestPortValue.shortValue()); + } + } + } + + private static void fillTransportLayer(Match target, TcpMatch source) { + PortNumber tcpSourcePort = source.getTcpSourcePort(); + if (tcpSourcePort != null) { + Integer tcpSourcePortValue = tcpSourcePort.getValue(); + if (tcpSourcePortValue != null) { + target.setField(TP_SRC, tcpSourcePortValue.shortValue()); + } + } + + PortNumber tcpDestPort = source.getTcpDestinationPort(); + if (tcpDestPort != null) { + Integer tcpDestPortValue = tcpDestPort.getValue(); + if (tcpDestPortValue != null) { + target.setField(TP_DST, tcpDestPortValue.shortValue()); + } + } + } + + private static void fillTransportLayer(Match target, SctpMatch source) { + PortNumber sctpSourcePort = source.getSctpSourcePort(); + if (sctpSourcePort != null) { + Integer sctpSourcePortValue = sctpSourcePort.getValue(); + if (sctpSourcePortValue != null) { + target.setField(TP_SRC, sctpSourcePortValue.shortValue()); + } + } + PortNumber sctpDestPort = source.getSctpDestinationPort(); + if (sctpDestPort != null) { + Integer sctpDestPortValue = sctpDestPort.getValue(); + if (sctpDestPortValue != null) { + target.setField(TP_DST, sctpDestPortValue.shortValue()); + } + } + } + + private static void fillFrom(Match target, Layer3Match source) { + if (source == null) + return; + if (source instanceof Ipv4Match) { + fillFromIpv4(target, (Ipv4Match) source); + } else if (source instanceof Ipv6Match) { + fillFromIpv6(target, (Ipv6Match) source); + } else if (source instanceof ArpMatch) { + fillFromArp(target, (ArpMatch) source); + } + } + + private static void fillFromArp(Match target, ArpMatch source) { + Ipv4Prefix sourceAddress = source.getArpSourceTransportAddress(); + if (sourceAddress != null) { + target.setField(NW_SRC, (InetAddress) inetAddressFrom(sourceAddress), null); + } + Ipv4Prefix destAddress = source.getArpSourceTransportAddress(); + if (destAddress != null) { + target.setField(NW_DST, (InetAddress) inetAddressFrom(destAddress), null); + } + } + + private static void fillFromIpv6(Match target, Ipv6Match source) { + Ipv6Prefix sourceAddress = source.getIpv6Source(); + if (sourceAddress != null) { + target.setField(NW_SRC, (InetAddress) inetAddressFrom(sourceAddress), null); + } + Ipv6Prefix destAddress = source.getIpv6Source(); + if (destAddress != null) { + target.setField(NW_DST, (InetAddress) inetAddressFrom(destAddress), null); + } + } + + private static void fillFromIpv4(Match target, Ipv4Match source) { + Ipv4Prefix sourceAddress = source.getIpv4Source(); + if (sourceAddress != null) { + target.setField(NW_SRC, (InetAddress) inetAddressFrom(sourceAddress), null); + } + Ipv4Prefix destAddress = source.getIpv4Source(); + if (destAddress != null) { + target.setField(NW_DST, (InetAddress) inetAddressFrom(destAddress), null); + } + } + + private static InetAddress inetAddressFrom(Ipv4Prefix source) { + if (source != null) { + String[] parts = source.getValue().split("/"); + return InetAddresses.forString(parts[0]); + } + return null; + } + + private static InetAddress inetAddressFrom(Ipv6Prefix source) { + if (source != null) { + String[] parts = source.getValue().split("/"); + return InetAddresses.forString(parts[0]); + } + return null; + } + + private static void fillFrom(Match target, EthernetMatch source) { + if (source == null) + return; + EthernetType ethType = source.getEthernetType(); + if (ethType != null) { + EtherType ethInnerType = ethType.getType(); + if (ethInnerType != null) { + Long value = ethInnerType.getValue(); + target.setField(DL_TYPE, value.shortValue()); + } + } + + MacAddressFilter ethSource = source.getEthernetSource(); + if (ethSource != null) { + target.setField(DL_SRC, bytesFrom(ethSource.getAddress())); + } + + MacAddressFilter ethDest = source.getEthernetDestination(); + if (ethDest != null) { + target.setField(DL_DST, bytesFrom(ethDest.getAddress())); + } + } + + private static byte[] bytesFrom(MacAddress address) { + if (address != null) { + return address.getValue().getBytes(); + } + return null; + } +} diff --git a/opendaylight/northbound/commons/pom.xml b/opendaylight/northbound/commons/pom.xml index 692b17a9a6..972bece91f 100644 --- a/opendaylight/northbound/commons/pom.xml +++ b/opendaylight/northbound/commons/pom.xml @@ -48,7 +48,9 @@ org.osgi.service.packageadmin, org.osgi.util.tracker, javax.servlet.http, + org.codehaus.jackson, org.codehaus.jackson.jaxrs, + org.codehaus.jackson.map, org.slf4j diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/JacksonJsonProcessingExceptionMapper.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/JacksonJsonProcessingExceptionMapper.java new file mode 100644 index 0000000000..ca0d1b7cae --- /dev/null +++ b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/JacksonJsonProcessingExceptionMapper.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.northbound.commons; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import org.codehaus.jackson.JsonProcessingException; + +/** + * A custom exception mapper for handling Jackson JsonProcessingException types + */ +@Provider +@Consumes({MediaType.APPLICATION_JSON, "text/json"}) +public class JacksonJsonProcessingExceptionMapper + implements ExceptionMapper +{ + + @Override + public Response toResponse(JsonProcessingException exception) { + GenericEntity entity = + new GenericEntity(exception.getMessage()) {}; + return Response.status(Response.Status.BAD_REQUEST).entity(entity).build(); + } +} + diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/NorthboundApplication.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/NorthboundApplication.java index 1d3919f4ea..5b8219126b 100644 --- a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/NorthboundApplication.java +++ b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/NorthboundApplication.java @@ -20,6 +20,7 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.annotation.XmlRootElement; import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider; +import org.codehaus.jackson.map.DeserializationConfig; import org.opendaylight.controller.northbound.bundlescanner.IBundleScanService; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; @@ -54,7 +55,8 @@ public class NorthboundApplication extends Application { } } ); - singletons.add(new JacksonJaxbJsonProvider()); + singletons.add(getJsonProvider()); + singletons.add(new JacksonJsonProcessingExceptionMapper()); return singletons; } @@ -65,6 +67,13 @@ public class NorthboundApplication extends Application { return result; } + private static final JacksonJaxbJsonProvider getJsonProvider() { + JacksonJaxbJsonProvider jsonProvider = new JacksonJaxbJsonProvider(); + jsonProvider.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, + false); + return jsonProvider; + } + private BundleContext getBundleContext() { ClassLoader tlcl = Thread.currentThread().getContextClassLoader(); Bundle bundle = null; diff --git a/opendaylight/northbound/integrationtest/pom.xml b/opendaylight/northbound/integrationtest/pom.xml index 9f4e05dff0..3f2585e0c2 100644 --- a/opendaylight/northbound/integrationtest/pom.xml +++ b/opendaylight/northbound/integrationtest/pom.xml @@ -20,9 +20,9 @@ 0.4.0-SNAPSHOT - central2 - central2 - http://repo2.maven.org/maven2 + central + maven repo1 + http://repo1.maven.org/maven2 false diff --git a/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java b/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java index 4404951135..e457cbfd6e 100644 --- a/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java +++ b/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java @@ -208,47 +208,34 @@ public class NorthboundIT { Assert.assertEquals(nodeId, (Integer) nodeInfo.getInt("id")); Assert.assertEquals(nodeType, nodeInfo.getString("type")); - JSONArray propsArray = node.getJSONArray("properties"); - - for (int j = 0; j < propsArray.length(); j++) { - JSONObject properties = propsArray.getJSONObject(j); - String propName = properties.getString("name"); - if (propName.equals("timeStamp")) { - if (timestamp == null || timestampName == null) { - Assert.assertFalse("Timestamp exist", true); - } else { - Assert.assertEquals(timestamp, (Integer) properties.getInt("value")); - Assert.assertEquals(timestampName, properties.getString("timestampName")); - } - } - if (propName.equals("actions")) { - if (actionsValue == null) { - Assert.assertFalse("Actions exist", true); - } else { - Assert.assertEquals(actionsValue, (Integer) properties.getInt("value")); - } - } - if (propName.equals("capabilities")) { - if (capabilitiesValue == null) { - Assert.assertFalse("Capabilities exist", true); - } else { - Assert.assertEquals(capabilitiesValue, (Integer) properties.getInt("value")); - } - } - if (propName.equals("tables")) { - if (tablesValue == null) { - Assert.assertFalse("Tables exist", true); - } else { - Assert.assertEquals(tablesValue, (Integer) properties.getInt("value")); - } - } - if (propName.equals("buffers")) { - if (buffersValue == null) { - Assert.assertFalse("Buffers exist", true); - } else { - Assert.assertEquals(buffersValue, (Integer) properties.getInt("value")); - } - } + JSONObject properties = node.getJSONObject("properties"); + + if (timestamp == null || timestampName == null) { + Assert.assertFalse(properties.has("timeStamp")); + } else { + Assert.assertEquals(timestamp, (Integer) properties.getJSONObject("timeStamp").getInt("value")); + Assert.assertEquals(timestampName, properties.getJSONObject("timeStamp").getString("name")); + } + if (actionsValue == null) { + Assert.assertFalse(properties.has("actions")); + } else { + Assert.assertEquals(actionsValue, (Integer) properties.getJSONObject("actions").getInt("value")); + } + if (capabilitiesValue == null) { + Assert.assertFalse(properties.has("capabilities")); + } else { + Assert.assertEquals(capabilitiesValue, + (Integer) properties.getJSONObject("capabilities").getInt("value")); + } + if (tablesValue == null) { + Assert.assertFalse(properties.has("tables")); + } else { + Assert.assertEquals(tablesValue, (Integer) properties.getJSONObject("tables").getInt("value")); + } + if (buffersValue == null) { + Assert.assertFalse(properties.has("buffers")); + } else { + Assert.assertEquals(buffersValue, (Integer) properties.getJSONObject("buffers").getInt("value")); } } @@ -258,37 +245,27 @@ public class NorthboundIT { JSONObject nodeConnector = nodeConnectorProperties.getJSONObject("nodeconnector"); JSONObject node = nodeConnector.getJSONObject("node"); + JSONObject properties = nodeConnectorProperties.getJSONObject("properties"); Assert.assertEquals(ncId, (Integer) nodeConnector.getInt("id")); Assert.assertEquals(ncType, nodeConnector.getString("type")); Assert.assertEquals(nodeId, (Integer) node.getInt("id")); Assert.assertEquals(nodeType, node.getString("type")); - - JSONArray propsArray = nodeConnectorProperties.getJSONArray("properties"); - for (int j = 0; j < propsArray.length(); j++) { - JSONObject properties = propsArray.getJSONObject(j); - String propName = properties.getString("name"); - if (propName.equals("state")) { - if (state == null) { - Assert.assertFalse("State exist", true); - } else { - Assert.assertEquals(state, (Integer) properties.getInt("value")); - } - } - if (propName.equals("capabilities")) { - if (capabilities == null) { - Assert.assertFalse("Capabilities exist", true); - } else { - Assert.assertEquals(capabilities, (Integer) properties.getInt("value")); - } - } - if (propName.equals("bandwidth")) { - if (bandwidth == null) { - Assert.assertFalse("bandwidth exist", true); - } else { - Assert.assertEquals(bandwidth, (Integer) properties.getInt("value")); - } - } + if (state == null) { + Assert.assertFalse(properties.has("state")); + } else { + Assert.assertEquals(state, (Integer) properties.getJSONObject("state").getInt("value")); + } + if (capabilities == null) { + Assert.assertFalse(properties.has("capabilities")); + } else { + Assert.assertEquals(capabilities, + (Integer) properties.getJSONObject("capabilities").getInt("value")); + } + if (bandwidth == null) { + Assert.assertFalse(properties.has("bandwidth")); + } else { + Assert.assertEquals(bandwidth, (Integer) properties.getJSONObject("bandwidth").getInt("value")); } } @@ -428,6 +405,11 @@ public class NorthboundIT { // Test GET deleted subnet1 result = getJsonResult(baseURL + "default/subnet/" + name1); Assert.assertEquals(404, httpResponseCode.intValue()); + + // TEST PUT bad subnet, expect 400, validate JSON exception mapper + JSONObject joBad = new JSONObject().put("foo", "bar"); + result = getJsonResult(baseURL + "default/subnet/foo", "PUT", joBad.toString()); + Assert.assertEquals(400, httpResponseCode.intValue()); } @Test @@ -605,19 +587,8 @@ public class NorthboundIT { json = new JSONObject(jt); node = getJsonInstance(json, "nodeProperties", nodeId_1); Assert.assertNotNull(node); - - JSONArray propsArray = node.getJSONArray("properties"); - - for (int j = 0; j < propsArray.length(); j++) { - JSONObject properties = propsArray.getJSONObject(j); - String propName = properties.getString("name"); - if (propName.equals("tier")) { - Assert.assertEquals(1001, properties.getInt("value")); - } - if (propName.equals("description")) { - Assert.assertEquals("node1", properties.getString("value")); - } - } + Assert.assertEquals(1001, node.getJSONObject("properties").getJSONObject("tier").getInt("value")); + Assert.assertEquals("node1", node.getJSONObject("properties").getJSONObject("description").getString("value")); // Test delete nodeConnector property // Delete state property of nodeconnector1 @@ -1224,26 +1195,10 @@ public class NorthboundIT { JSONObject headNC = edge.getJSONObject("headNodeConnector"); JSONObject headNode = headNC.getJSONObject("node"); - - JSONArray propsArray = edgeProp.getJSONArray("properties"); - - JSONObject bandw = null; - JSONObject stt = null; - JSONObject ltc = null; - - for (int j = 0; j < propsArray.length(); j++) { - JSONObject props = propsArray.getJSONObject(j); - String propName = props.getString("name"); - if (propName.equals("bandwidth")) { - bandw = props; - } - if (propName.equals("state")) { - stt = props; - } - if (propName.equals("latency")) { - ltc = props; - } - } + JSONObject Props = edgeProp.getJSONObject("properties"); + JSONObject bandw = Props.getJSONObject("bandwidth"); + JSONObject stt = Props.getJSONObject("state"); + JSONObject ltc = Props.getJSONObject("latency"); if (headNC.getInt("id") == headNC1_nodeConnId) { Assert.assertEquals(headNode.getString("type"), nodeType); @@ -1275,7 +1230,6 @@ public class NorthboundIT { Integer nodeId_1 = 3366; String nodeConnectorType_1 = "STUB"; Integer nodeConnectorId_1 = 12; - String nodeType_2 = "STUB"; Integer nodeId_2 = 4477; String nodeConnectorType_2 = "STUB"; @@ -1364,7 +1318,6 @@ public class NorthboundIT { } } } - // Configure the OSGi container @Configuration public Option[] config() { diff --git a/opendaylight/northbound/switchmanager/pom.xml b/opendaylight/northbound/switchmanager/pom.xml index d46b17e4f7..401cc948b8 100644 --- a/opendaylight/northbound/switchmanager/pom.xml +++ b/opendaylight/northbound/switchmanager/pom.xml @@ -58,6 +58,7 @@ org.slf4j, org.apache.catalina.filters, org.codehaus.jackson.jaxrs, + org.codehaus.jackson.annotate, !org.codehaus.enunciate.jaxrs /controller/nb/v2/switchmanager diff --git a/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/NodeConnectorProperties.java b/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/NodeConnectorProperties.java index 4e67fc4058..43d3aae57c 100644 --- a/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/NodeConnectorProperties.java +++ b/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/NodeConnectorProperties.java @@ -9,6 +9,9 @@ package org.opendaylight.controller.switchmanager.northbound; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import java.util.Set; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlElementRef; @@ -17,6 +20,8 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonProperty; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.core.Property; @@ -31,6 +36,7 @@ public class NodeConnectorProperties { private NodeConnector nodeconnector; @XmlElementRef @XmlElementWrapper + @JsonIgnore private Set properties; // JAXB required constructor @@ -44,6 +50,19 @@ public class NodeConnectorProperties { this.properties = properties; } + @JsonProperty(value="properties") + public Map getMapProperties() { + Map map = new HashMap(); + for (Property p : properties) { + map.put(p.getName(), p); + } + return map; + } + + public void setMapProperties(Map propertiesMap) { + this.properties = new HashSet(propertiesMap.values()); + } + public Set getProperties() { return properties; } diff --git a/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/NodeProperties.java b/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/NodeProperties.java index 979a8e9776..58a024c928 100644 --- a/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/NodeProperties.java +++ b/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/NodeProperties.java @@ -9,6 +9,9 @@ package org.opendaylight.controller.switchmanager.northbound; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import java.util.Set; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlElementRef; @@ -17,6 +20,8 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonProperty; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.Property; @@ -31,6 +36,7 @@ public class NodeProperties { private Node node; @XmlElementRef @XmlElementWrapper + @JsonIgnore private Set properties; // JAXB required constructor @@ -44,6 +50,19 @@ public class NodeProperties { this.properties = properties; } + @JsonProperty(value="properties") + public Map getMapProperties() { + Map map = new HashMap(); + for (Property p : properties) { + map.put(p.getName(), p); + } + return map; + } + + public void setMapProperties(Map propertiesMap) { + this.properties = new HashSet(propertiesMap.values()); + } + public Set getProperties() { return properties; } diff --git a/opendaylight/northbound/topology/pom.xml b/opendaylight/northbound/topology/pom.xml index ec3489aca2..d379164a14 100644 --- a/opendaylight/northbound/topology/pom.xml +++ b/opendaylight/northbound/topology/pom.xml @@ -54,6 +54,7 @@ org.opendaylight.controller.usermanager, org.opendaylight.controller.topologymanager, com.sun.jersey.spi.container.servlet, + org.codehaus.jackson.annotate, javax.ws.rs, javax.ws.rs.core, javax.xml.bind, diff --git a/opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/EdgeProperties.java b/opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/EdgeProperties.java index b8be7c18d3..6614bbe640 100644 --- a/opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/EdgeProperties.java +++ b/opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/EdgeProperties.java @@ -9,6 +9,9 @@ package org.opendaylight.controller.topology.northbound; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import java.util.Set; import javax.xml.bind.annotation.XmlAccessType; @@ -18,6 +21,8 @@ import javax.xml.bind.annotation.XmlElementRef; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonProperty; import org.opendaylight.controller.sal.core.Edge; import org.opendaylight.controller.sal.core.Property; @@ -28,6 +33,7 @@ public class EdgeProperties { private Edge edge; @XmlElementRef @XmlElementWrapper + @JsonIgnore private Set properties; // JAXB required constructor @@ -41,10 +47,22 @@ public class EdgeProperties { this.properties = properties; } + @JsonProperty(value="properties") + public Map getMapProperties() { + Map map = new HashMap(); + for (Property p : properties) { + map.put(p.getName(), p); + } + return map; + } + + public void setMapProperties(Map propertiesMap) { + this.properties = new HashSet(propertiesMap.values()); + } + public Set getProperties() { return properties; } - public void setProperties(Set properties) { this.properties = properties; } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/ISwitch.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/ISwitch.java index af3641823c..d924b66a09 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/ISwitch.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/ISwitch.java @@ -232,4 +232,9 @@ public interface ISwitch { * until the Barrier reply arrives. */ public Object asyncSendBarrierMessage(); + + /** + * Send a FLOW_MOD message with a wildcard match and action=DELETE. + */ + public void deleteAllFlows(); } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchHandler.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchHandler.java index 91909d20f5..6e000022df 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchHandler.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchHandler.java @@ -372,12 +372,6 @@ public class SwitchHandler implements ISwitch { // send feature request OFMessage featureRequest = factory.getMessage(OFType.FEATURES_REQUEST); asyncFastSend(featureRequest); - // delete all pre-existing flows - OFMatch match = new OFMatch().setWildcards(OFMatch.OFPFW_ALL); - OFFlowMod flowMod = (OFFlowMod) factory.getMessage(OFType.FLOW_MOD); - flowMod.setMatch(match).setCommand(OFFlowMod.OFPFC_DELETE).setOutPort(OFPort.OFPP_NONE) - .setLength((short) OFFlowMod.MINIMUM_LENGTH); - asyncFastSend(flowMod); this.state = SwitchState.WAIT_FEATURES_REPLY; startSwitchTimer(); break; @@ -925,4 +919,14 @@ public class SwitchHandler implements ISwitch { return result; } } + + @Override + public void deleteAllFlows() { + logger.trace("deleteAllFlows on switch {}", HexString.toHexString(this.sid)); + OFMatch match = new OFMatch().setWildcards(OFMatch.OFPFW_ALL); + OFFlowMod flowMod = (OFFlowMod) factory.getMessage(OFType.FLOW_MOD); + flowMod.setMatch(match).setCommand(OFFlowMod.OFPFC_DELETE).setOutPort(OFPort.OFPP_NONE) + .setLength((short) OFFlowMod.MINIMUM_LENGTH); + asyncFastSend(flowMod); + } } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowStatisticsConverter.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowStatisticsConverter.java index 82dbf670a9..6873b528a2 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowStatisticsConverter.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowStatisticsConverter.java @@ -59,6 +59,7 @@ public class FlowStatisticsConverter { flow.setPriority(ofFlowStat.getPriority()); flow.setIdleTimeout(ofFlowStat.getIdleTimeout()); flow.setHardTimeout(ofFlowStat.getHardTimeout()); + flow.setId(ofFlowStat.getCookie()); flowOnNode = new FlowOnNode(flow); flowOnNode.setByteCount(ofFlowStat.getByteCount()); flowOnNode.setPacketCount(ofFlowStat.getPacketCount()); @@ -74,6 +75,7 @@ public class FlowStatisticsConverter { flow.setPriority(v6StatsReply.getPriority()); flow.setIdleTimeout(v6StatsReply.getIdleTimeout()); flow.setHardTimeout(v6StatsReply.getHardTimeout()); + flow.setId(v6StatsReply.getCookie()); flowOnNode = new FlowOnNode(flow); flowOnNode.setByteCount(v6StatsReply.getByteCount()); flowOnNode.setPacketCount(v6StatsReply.getPacketCount()); diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java index 8db83f0fc7..15bba670d2 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java @@ -239,6 +239,11 @@ public class InventoryServiceShim implements IContainerListener, if (sw == null) { return; } + Node node = NodeCreator.createOFNode(sw.getId()); + if ((nodeProps.get(node) != null) && (connectionOutService.isLocal(node))) { + logger.debug("Ignore switchAdded {}", sw); + return; + } // Add all the nodeConnectors of this switch Map> ncProps = InventoryServiceHelper @@ -437,7 +442,6 @@ public class InventoryServiceShim implements IContainerListener, for (String container : containers) { notifyInventoryShimInternalListener(container, node, type, props); } - // Notify external listener notifyInventoryShimExternalListener(node, type, props); @@ -511,6 +515,11 @@ public class InventoryServiceShim implements IContainerListener, props.add(b); } + if ((nodeProps.get(node) == null) && (connectionOutService.isLocal(node))) { + // The switch is connected for the first time, flush all flows + // that may exist on this switch + sw.deleteAllFlows(); + } nodeProps.put(node, props); // Notify all internal and external listeners notifyInventoryShimListener(node, type, props); diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/AppRoleLevel.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/AppRoleLevel.java index 7e73dd414f..124b495147 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/AppRoleLevel.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/AppRoleLevel.java @@ -45,9 +45,9 @@ public enum AppRoleLevel implements Serializable { } public static AppRoleLevel fromString(String levelString) { - for (AppRoleLevel level : AppRoleLevel.values()) { - if (level.toString().equals(levelString)) { - return level; + for (AppRoleLevel rolelevel : AppRoleLevel.values()) { + if (rolelevel.toString().equals(levelString)) { + return rolelevel; } } return null; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Actions.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Actions.java index 7b934edfa7..6cada2c041 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Actions.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Actions.java @@ -9,6 +9,8 @@ package org.opendaylight.controller.sal.core; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -21,6 +23,7 @@ import javax.xml.bind.annotation.XmlRootElement; */ @XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) public class Actions extends Property { private static final long serialVersionUID = 1L; @XmlElement(name="value") diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/AdvertisedBandwidth.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/AdvertisedBandwidth.java index ab546d7302..a0b5c0a18c 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/AdvertisedBandwidth.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/AdvertisedBandwidth.java @@ -9,6 +9,8 @@ package org.opendaylight.controller.sal.core; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; /** @@ -21,6 +23,7 @@ import javax.xml.bind.annotation.XmlRootElement; * seconds. */ @XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) @SuppressWarnings("serial") public class AdvertisedBandwidth extends Bandwidth { public static final String AdvertisedBandwidthPropName = "advertisedBandwidth"; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Bandwidth.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Bandwidth.java index 8c3a977518..5083cf57d7 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Bandwidth.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Bandwidth.java @@ -9,6 +9,8 @@ package org.opendaylight.controller.sal.core; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -22,6 +24,7 @@ import javax.xml.bind.annotation.XmlRootElement; * seconds. */ @XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) public class Bandwidth extends Property { private static final long serialVersionUID = 1L; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Buffers.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Buffers.java index 4c6e08102b..274b0f481d 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Buffers.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Buffers.java @@ -9,6 +9,8 @@ package org.opendaylight.controller.sal.core; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -20,6 +22,7 @@ import javax.xml.bind.annotation.XmlRootElement; * Describes supported buffers (#packets) */ @XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) public class Buffers extends Property { private static final long serialVersionUID = 1L; @XmlElement(name="value") diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Capabilities.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Capabilities.java index b2005913d0..147f1b13ae 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Capabilities.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Capabilities.java @@ -9,6 +9,8 @@ package org.opendaylight.controller.sal.core; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -20,6 +22,7 @@ import javax.xml.bind.annotation.XmlRootElement; * Describes supported capabilities */ @XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) public class Capabilities extends Property { private static final long serialVersionUID = 1L; @XmlElement(name="value") diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Config.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Config.java index 651c2f44e1..64562fa6ed 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Config.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Config.java @@ -8,6 +8,8 @@ package org.opendaylight.controller.sal.core; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -18,6 +20,7 @@ import javax.xml.bind.annotation.XmlRootElement; */ @XmlRootElement @SuppressWarnings("serial") +@XmlAccessorType(XmlAccessType.NONE) public class Config extends Property { @XmlElement(name="value") private short configValue; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Description.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Description.java index ebc12cdbf7..88ab11b354 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Description.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Description.java @@ -1,5 +1,7 @@ package org.opendaylight.controller.sal.core; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -8,6 +10,7 @@ import javax.xml.bind.annotation.XmlRootElement; */ @XmlRootElement @SuppressWarnings("serial") +@XmlAccessorType(XmlAccessType.NONE) public class Description extends Property { @XmlElement(name="value") private String descriptionValue; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ForwardingMode.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ForwardingMode.java index 1b19f19778..c6d7f63409 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ForwardingMode.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ForwardingMode.java @@ -1,5 +1,7 @@ package org.opendaylight.controller.sal.core; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -7,6 +9,7 @@ import javax.xml.bind.annotation.XmlRootElement; * The class represents the forwarding mode property of a node. */ @XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) @SuppressWarnings("serial") public class ForwardingMode extends Property { @XmlElement(name="value") diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Latency.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Latency.java index a64ee105cf..1320bbb693 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Latency.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Latency.java @@ -9,6 +9,8 @@ package org.opendaylight.controller.sal.core; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -20,6 +22,7 @@ import javax.xml.bind.annotation.XmlRootElement; * Describe a latency in picoseconds or multiple of its. */ @XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) public class Latency extends Property { private static final long serialVersionUID = 1L; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Name.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Name.java index 92c8454a4d..65c089956a 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Name.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Name.java @@ -9,6 +9,8 @@ package org.opendaylight.controller.sal.core; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -16,6 +18,7 @@ import javax.xml.bind.annotation.XmlRootElement; * The class represents the Name property of an element. */ @XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) @SuppressWarnings("serial") public class Name extends Property { @XmlElement(name="value") diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Node.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Node.java index d21a147506..0ea04c3206 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Node.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Node.java @@ -323,10 +323,10 @@ public class Node implements Serializable { @Override public String toString() { if (this.nodeType.equals(NodeIDType.OPENFLOW)) { - return this.nodeType.toString() + "|" + return this.nodeType + "|" + HexEncode.longToHexString((Long) this.nodeID); } else { - return this.nodeType.toString() + "|" + this.nodeID.toString(); + return this.nodeType + "|" + this.nodeID.toString(); } } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/NodeConnector.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/NodeConnector.java index 50ccf69b40..46c5a9dae9 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/NodeConnector.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/NodeConnector.java @@ -464,9 +464,9 @@ public class NodeConnector implements Serializable { .equals(NodeConnectorIDType.SWSTACK) || this.nodeConnectorType .equals(NodeConnectorIDType.HWPATH)) { - return this.nodeConnectorType.toString(); + return this.nodeConnectorType; } else { - return this.nodeConnectorType.toString() + "|" + return this.nodeConnectorType + "|" + this.nodeConnectorID.toString(); } } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/NodeTable.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/NodeTable.java index 7b7f1ccaea..9e763eb241 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/NodeTable.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/NodeTable.java @@ -292,7 +292,7 @@ public class NodeTable implements Serializable { } public String getNodeTableIdAsString() { - return this.nodeTableType.toString() + "|" + return this.nodeTableType + "|" + this.nodeTableID.toString(); } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/PeerBandwidth.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/PeerBandwidth.java index a1b436ef1a..d01e528b57 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/PeerBandwidth.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/PeerBandwidth.java @@ -9,6 +9,8 @@ package org.opendaylight.controller.sal.core; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; /** @@ -20,6 +22,7 @@ import javax.xml.bind.annotation.XmlRootElement; * bits per seconds. */ @XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) public class PeerBandwidth extends Bandwidth { private static final long serialVersionUID = 1L; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Property.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Property.java index a5deb547e3..9dc00d0dcd 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Property.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Property.java @@ -10,6 +10,8 @@ package org.opendaylight.controller.sal.core; import java.io.Serializable; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlSeeAlso; @@ -28,6 +30,7 @@ import javax.xml.bind.annotation.XmlSeeAlso; * element */ @XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) @XmlSeeAlso({ Config.class, Name.class, State.class, TimeStamp.class, Latency.class, Bandwidth.class, Tier.class, Actions.class, AdvertisedBandwidth.class, Buffers.class, Capabilities.class, diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/State.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/State.java index e47542a7be..d74f7183de 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/State.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/State.java @@ -9,6 +9,8 @@ package org.opendaylight.controller.sal.core; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -18,6 +20,7 @@ import javax.xml.bind.annotation.XmlRootElement; * */ @XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) @SuppressWarnings("serial") public class State extends Property { @XmlElement(name="value") diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/SupportedBandwidth.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/SupportedBandwidth.java index cd6589ed6d..7bcc0e01aa 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/SupportedBandwidth.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/SupportedBandwidth.java @@ -9,6 +9,8 @@ package org.opendaylight.controller.sal.core; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; /** @@ -21,6 +23,7 @@ import javax.xml.bind.annotation.XmlRootElement; * seconds. */ @XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) public class SupportedBandwidth extends Bandwidth { private static final long serialVersionUID = 1L; public static final String SupportedBandwidthPropName = "supportedBandwidth"; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Tables.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Tables.java index b92c4b693c..724c8427f6 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Tables.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Tables.java @@ -9,6 +9,8 @@ package org.opendaylight.controller.sal.core; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -20,6 +22,7 @@ import javax.xml.bind.annotation.XmlRootElement; * Describes supported # of datapath tables */ @XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) public class Tables extends Property { private static final long serialVersionUID = 1L; @XmlElement(name="value") diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Tier.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Tier.java index d1af778526..33c87db650 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Tier.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Tier.java @@ -9,6 +9,8 @@ package org.opendaylight.controller.sal.core; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -18,6 +20,7 @@ import javax.xml.bind.annotation.XmlRootElement; * */ @XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) @SuppressWarnings("serial") public class Tier extends Property { @XmlElement(name="value") diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/TimeStamp.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/TimeStamp.java index c0c8da7ae2..67f2b25bd2 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/TimeStamp.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/TimeStamp.java @@ -11,6 +11,8 @@ package org.opendaylight.controller.sal.core; import java.util.Date; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -25,11 +27,12 @@ import javax.xml.bind.annotation.XmlRootElement; * to qualify what are we talking about */ @XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) public class TimeStamp extends Property { private static final long serialVersionUID = 1L; @XmlElement(name = "value") private long timestamp; - @XmlElement(name = "timestampName") + @XmlElement(name = "name") private String timestampName; public static final String TimeStampPropName = "timeStamp"; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/IPProtocols.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/IPProtocols.java index cdb4463c02..66e6e65706 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/IPProtocols.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/IPProtocols.java @@ -168,7 +168,8 @@ public enum IPProtocols { WESP("WESP",141), ROHC("ROHC",142); */ - private static final String regexNumberString = "^[0-9]+$"; + private static final String regexDecimalString = "^[0-9]{3}$"; + private static final String regexHexString = "^(0(x|X))[0-9a-fA-F]{2}$"; private String protocolName; private int protocolNumber; @@ -215,7 +216,10 @@ public enum IPProtocols { } public static short getProtocolNumberShort(String name) { - if (name.matches(regexNumberString)) { + if (name.matches(regexHexString)) { + return Short.valueOf(Short.decode(name)); + } + if (name.matches(regexDecimalString)) { return Short.valueOf(name); } for (IPProtocols proto : IPProtocols.values()) { @@ -227,7 +231,10 @@ public enum IPProtocols { } public static int getProtocolNumberInt(String name) { - if (name.matches(regexNumberString)) { + if (name.matches(regexHexString)) { + return Integer.valueOf(Integer.decode(name)); + } + if (name.matches(regexDecimalString)) { return Integer.valueOf(name); } for (IPProtocols proto : IPProtocols.values()) { @@ -239,7 +246,10 @@ public enum IPProtocols { } public static byte getProtocolNumberByte(String name) { - if (name.matches(regexNumberString)) { + if (name.matches(regexHexString)) { + return Integer.valueOf(Integer.decode(name)).byteValue(); + } + if (name.matches(regexDecimalString)) { return Integer.valueOf(name).byteValue(); } for (IPProtocols proto : IPProtocols.values()) { diff --git a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java index a7bdb9da8b..854125b356 100644 --- a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java +++ b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java @@ -432,6 +432,7 @@ public class FlowProgrammerService implements IFlowProgrammerService, Flow flow = new Flow(match, actions); flow.setPriority((short) 100); flow.setHardTimeout((short) 360); + flow.setId(1234L); return flow; } @@ -489,6 +490,7 @@ public class FlowProgrammerService implements IFlowProgrammerService, Flow flow = new Flow(match, actions); flow.setPriority((short) 300); flow.setHardTimeout((short) 240); + flow.setId(65536L); return flow; } diff --git a/opendaylight/sal/yang-prototype/pom.xml b/opendaylight/sal/yang-prototype/pom.xml index b1107594f5..3f84ff09a4 100644 --- a/opendaylight/sal/yang-prototype/pom.xml +++ b/opendaylight/sal/yang-prototype/pom.xml @@ -43,9 +43,9 @@ - central2 - central2 - http://repo2.maven.org/maven2 + central + maven repo1 + http://repo1.maven.org/maven2 false @@ -76,17 +76,6 @@ ebr-bundles-external ${nexusproxy}/repositories/ebr-bundles-external/ - - central2 - central2 - http://repo2.maven.org/maven2 - - false - - - true - - central central diff --git a/opendaylight/sal/yang-prototype/sal/model/model-flow-base/src/main/yang/group-types.yang b/opendaylight/sal/yang-prototype/sal/model/model-flow-base/src/main/yang/group-types.yang new file mode 100644 index 0000000000..e0f60e4054 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/model/model-flow-base/src/main/yang/group-types.yang @@ -0,0 +1,175 @@ +module opendaylight-group-types { + namespace "urn:opendaylight:group:types"; + prefix group; + + import ietf-inet-types {prefix inet;} + import ietf-yang-types {prefix yang;} + import opendaylight-flow-types {prefix flow-types;} + + revision "2013-09-18" { + description "Initial revision of group service"; + } + + typedef group-ref { + type instance-identifier; + } + + grouping group-types { + leaf group-type { + type enumeration { + enum group-all; + enum group_select; + enum group_indirect; + enum group_ff; + } + } + } + + grouping group { + + uses group-types; + + leaf group-id { + type group-ref; + } + + container buckets { + list bucket { + key "order"; + leaf order { + type int32; + } + + leaf weight { + type uint16; + } + + leaf watch_port { + type uint32; + } + + leaf watch_group { + type uint32; + } + + container actions { + list action { + key "action-order"; + leaf action-order { + type int32; + } + + uses flow-types:action; + } + } + } + } + } + + grouping group-statistics-request { + list group-stats { + key "group-id"; + + leaf group-id { + type int32; + } + } + } + + grouping group-statistics { + + leaf group-id { + type int32; + } + + leaf ref-count { + type yang:counter32; + } + + leaf packet-count { + type yang:counter64; + } + + leaf byte-count { + type yang:counter64; + } + + container duration { + leaf second { + type yang:counter32; + } + leaf nanosecond { + type yang:counter32; + } + } + + container buckets { + list bucket-counter { + key "order"; + leaf order { + type int32; + } + + leaf packet-count { + type yang:counter64; + } + + leaf byte-count { + type yang:counter64; + } + } + } + } + + grouping group-statistics-reply { + list group-stats { + key "group-stats-order"; + leaf group-stats-order { + type int32; + } + + uses group-statistics; + } + } + + grouping group-desc-stats { + list group-desc-stats { + key "order-id"; + + leaf order-id { + type int32; + } + + uses group; + } + } + + grouping group-features { + list group-features { + key "order"; + leaf order { + type int32; + } + + uses group-types; + type capabilities { + enum select-weight; + enum select-liveness; + enum chaining; + enum chaining-checks; + } + + leaf-list max-groups { + type uint32; + description "Maximum number of groups for each type"; + max-elements 4; + } + + leaf-list actions { + type uint32; + description "Bitmap number OFPAT_* that are supported"; + max-elements 4; + } + } + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/model/model-flow-base/src/main/yang/match-types.yang b/opendaylight/sal/yang-prototype/sal/model/model-flow-base/src/main/yang/match-types.yang index 54b46d5587..757686c662 100644 --- a/opendaylight/sal/yang-prototype/sal/model/model-flow-base/src/main/yang/match-types.yang +++ b/opendaylight/sal/yang-prototype/sal/model/model-flow-base/src/main/yang/match-types.yang @@ -68,16 +68,16 @@ module opendaylight-match-types { grouping "ip-match-fields" { leaf ip-protocol { description "IP protocol."; - type uint8; // TODO define IP protocol number + type uint8; } leaf ip-dscp { description "IP DSCP (6 bits in ToS field)."; - type inet:dscp; // TODO: Define DSCP type + type inet:dscp; } leaf ip-ecn { description "IP ECN (2 bits in ToS field)."; - type uint8; // TODO define ECN + type uint8; } } @@ -130,7 +130,7 @@ module opendaylight-match-types { description "SCTP source port."; type inet:port-number; } - leaf sctp-destination-dst { + leaf sctp-destination-port { description "SCTP destination port."; type inet:port-number; } diff --git a/opendaylight/sal/yang-prototype/sal/model/model-flow-base/src/main/yang/meter-types.yang b/opendaylight/sal/yang-prototype/sal/model/model-flow-base/src/main/yang/meter-types.yang new file mode 100644 index 0000000000..cf309f1226 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/model/model-flow-base/src/main/yang/meter-types.yang @@ -0,0 +1,213 @@ +module opendaylight-meter-types { + namespace "urn:opendaylight:meter:types"; + prefix meter; + + import ietf-inet-types {prefix inet;} + import ietf-yang-types {prefix yang;} + + + revision "2013-09-18" { + description "Initial revision of meter service"; + } + + typedef meter-ref { + type instance-identifier; + } + + grouping meter-flags { + leaf flags { + type enumeration { + enum meter-kbps; + enum meter_pktps; + enum meter_burst; + enum meter_stats; + } + } + } + + grouping meter-band-type { + leaf flags { + type enumeration { + enum ofpmbt-drop; + enum ofpmbt-dscp-remark; + enum ofpmbt-experimenter; + } + } + } + + grouping band-type { + choice band-type { + case drop { + leaf rate { + type uint32; + } + + leaf burst-size { + type uint32; + } + } + + case dscp-remark { + leaf rate { + type uint32; + } + + leaf burst-size { + type uint32; + } + + leaf perc_level { + type uint8; + } + } + + case experimenter { + leaf rate { + type uint32; + } + + leaf burst-size { + type uint32; + } + + leaf experimenter { + type uint32; + } + } + } + } + + grouping meter { + + uses meter-flags; + + leaf meter-id { + type meter-ref; + } + + container meter-band-headers { + list meter-band-header { + key "order"; + leaf order { + type int32; + } + + container meter-band-types { + uses meter-band-type; + } + + leaf burst-size { + type uint32; + } + uses band-type; + } + } + } + + grouping meter-stats-config-request { + list meter-stats { + key "meter-id"; + + leaf meter-id { + type int32; + } + } + } + + grouping meter-statistics { + + leaf meter-id { + type int32; + } + + leaf flow-count { + type yang:counter32; + } + + leaf packet-in-count { + type yang:counter64; + } + + leaf byte-in-count { + type yang:counter64; + } + + container duration { + leaf second { + type yang:counter32; + } + leaf nanosecond { + type yang:counter32; + } + } + + container meter-band-stats { + list band-stat { + key "order"; + leaf order { + type int32; + } + + leaf packet-band-count { + type yang:counter64; + } + + leaf byte-band-count { + type yang:counter64; + } + } + } + } + + grouping meter-statistics-reply { + list meter-stats { + key "meter-stats-order"; + leaf meter-stats-order { + type int32; + } + uses meter-statistics; + } + } + + grouping meter-config-stats { + list meter-config-stats { + key "meter-config-order"; + + leaf meter-config-order { + type int32; + } + + uses meter; + } + } + + grouping meter-features { + list meter-features { + key "meter-feature-order"; + + leaf meter-feature-order { + type yang:counter32; + } + + leaf max_meter { + type yang:counter32; + } + + leaf band_types { + type yang:counter32; + } + + leaf capabilities { + type yang:counter32; + } + + leaf max_bands { + type uint8; + } + + leaf max_color { + type uint8; + } + } + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/model/model-flow-service/src/main/yang/group-service.yang b/opendaylight/sal/yang-prototype/sal/model/model-flow-service/src/main/yang/group-service.yang new file mode 100644 index 0000000000..866b359c29 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/model/model-flow-service/src/main/yang/group-service.yang @@ -0,0 +1,49 @@ +module sal-group { + namespace "urn:opendaylight:group:service"; + prefix group; + + import yang-ext {prefix ext;} + import opendaylight-inventory {prefix inv;} + import ietf-inet-types {prefix inet;} + import opendaylight-group-types {prefix group-type;} + + revision "2013-09-18" { + description "Initial revision of group service"; + } + + grouping node-group { + leaf node { + type inv:node-ref; + } + + uses group-type:group; + } + + /** Base configuration structure **/ + grouping group-update { + container original-group { + uses group-type:group; + } + container updated-group { + uses group-type:group; + } + } + + rpc add-group { + input { + uses node-group; + } + } + + rpc remove-group { + input { + uses node-group; + } + } + + rpc update-group { + input { + uses node-group; + } + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/model/model-flow-service/src/main/yang/meter-service.yang b/opendaylight/sal/yang-prototype/sal/model/model-flow-service/src/main/yang/meter-service.yang new file mode 100644 index 0000000000..f9cbd640e0 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/model/model-flow-service/src/main/yang/meter-service.yang @@ -0,0 +1,49 @@ +module sal-meter { + namespace "urn:opendaylight:meter:service"; + prefix meter; + + import yang-ext {prefix ext;} + import opendaylight-inventory {prefix inv;} + import ietf-inet-types {prefix inet;} + import opendaylight-meter-types {prefix meter-type;} + + revision "2013-09-18" { + description "Initial revision of meter service"; + } + + metering node-meter { + leaf node { + type inv:node-ref; + } + + uses meter-type:meter; + } + + /** Base configuration structure **/ + metering meter-update { + container original-meter { + uses meter-type:meter; + } + container updated-meter { + uses meter-type:meter; + } + } + + rpc add-meter { + input { + uses node-meter; + } + } + + rpc remove-meter { + input { + uses node-meter; + } + } + + rpc update-meter { + input { + uses node-meter; + } + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/pom.xml b/opendaylight/sal/yang-prototype/sal/pom.xml index 0442e8f9b2..d70338e4e0 100644 --- a/opendaylight/sal/yang-prototype/sal/pom.xml +++ b/opendaylight/sal/yang-prototype/sal/pom.xml @@ -25,7 +25,7 @@ UTF-8 1.7.2 http://nexus.opendaylight.org/content - 0.5.7-SNAPSHOT + 0.5.8-SNAPSHOT 2.4.0 2.3.2 14.0.1 @@ -33,9 +33,9 @@ - central2 - central2 - http://repo2.maven.org/maven2 + central + maven repo1 + http://repo1.maven.org/maven2 false @@ -52,17 +52,6 @@ - - central2 - central2 - http://repo2.maven.org/maven2 - - false - - - true - - central central diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/pom.xml b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/pom.xml index 549e427d82..96a16dcd57 100644 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/pom.xml +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/pom.xml @@ -1,113 +1,121 @@ - 4.0.0 - - org.opendaylight.controller - sal-parent - 1.0-SNAPSHOT - - sal-binding-broker-impl - bundle + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + + org.opendaylight.controller + sal-parent + 1.0-SNAPSHOT + + sal-binding-broker-impl + 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 + 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.apache.felix - maven-bundle-plugin - ${maven.bundle.version} - true - - - ${project.groupId}.${project.artifactId} - org.opendaylight.controller.sal.binding.impl.BrokerActivator - - org.opendaylight.controller.sal.binding.impl, - org.opendaylight.controller.sal.binding.impl.utils, - org.eclipse.xtend2.lib, - org.eclipse.xtext.xbase.* - - - - + + + + org.apache.felix + maven-bundle-plugin + ${maven.bundle.version} + true + + + ${project.groupId}.${project.artifactId} + org.opendaylight.controller.sal.binding.impl.BrokerActivator + + org.opendaylight.controller.sal.binding.impl, + org.opendaylight.controller.sal.binding.impl.*, + org.opendaylight.controller.sal.binding.codegen.*, + org.eclipse.xtend2.lib, + org.eclipse.xtend.lib, + org.eclipse.xtext.xbase.* + + + + - - org.eclipse.xtend - xtend-maven-plugin - 2.4.2 - - - - compile - - - ${basedir}/src/main/xtend-gen - - - - - - maven-clean-plugin - 2.4.1 - - - - ${basedir}/src/main/xtend-gen - - ** - - - - - - - + + org.eclipse.xtend + xtend-maven-plugin + 2.4.2 + + + + compile + + + ${basedir}/src/main/xtend-gen + + + + + + maven-clean-plugin + 2.4.1 + + + + ${basedir}/src/main/xtend-gen + + ** + + + + + + + - - - org.opendaylight.controller - sal-common-util - 1.0-SNAPSHOT - - - org.opendaylight.controller - sal-binding-api - 1.0-SNAPSHOT - - + + + org.opendaylight.controller + sal-common-util + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-binding-api + 1.0-SNAPSHOT + + - - org.slf4j - slf4j-api - - - org.osgi - org.osgi.core - 5.0.0 - - - com.google.guava - guava - - - org.reflections - reflections - 0.9.9-RC1 - - - org.javassist - javassist - 3.17.1-GA - - - org.eclipse.xtend - org.eclipse.xtend.lib - 2.4.2 - - + + org.slf4j + slf4j-api + + + org.osgi + org.osgi.core + 5.0.0 + + + com.google.guava + guava + + + org.reflections + reflections + 0.9.9-RC1 + + + org.javassist + javassist + 3.17.1-GA + + + org.eclipse.xtend + org.eclipse.xtend.lib + 2.4.2 + + + org.mockito + mockito-all + 1.9.5 + test + + diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend new file mode 100644 index 0000000000..6bdb3c8fbe --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.binding.codegen + +import java.util.Map + +import org.opendaylight.yangtools.yang.binding.BaseIdentity +import org.opendaylight.yangtools.yang.binding.RpcService +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier + +import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.* + +class RuntimeCodeHelper { + /** + * Helper method to return delegate from ManagedDirectedProxy with use of reflection. + * + * Note: This method uses reflection, but access to delegate field should be + * avoided and called only if neccessary. + * + */ + public static def getDelegate(RpcService proxy) { + val field = proxy.class.getField(DELEGATE_FIELD) + if (field == null) throw new UnsupportedOperationException("Unable to get delegate from proxy"); + return field.get(proxy) as T + } + + /** + * Helper method to set delegate to ManagedDirectedProxy with use of reflection. + * + * Note: This method uses reflection, but setting delegate field should not occur too much + * to introduce any significant performance hits. + * + */ + public static def void setDelegate(RpcService proxy, RpcService delegate) { + val field = proxy.class.getField(DELEGATE_FIELD) + if (field == null) throw new UnsupportedOperationException("Unable to set delegate to proxy"); + if (field.type.isAssignableFrom(delegate.class)) { + field.set(proxy, delegate) + } else + throw new IllegalArgumentException("delegate class is not assignable to proxy"); + } + + public static def Map getRoutingTable(RpcService target, + Class tableClass) { + val field = target.class.getField(tableClass.routingTableField) + if (field == null) throw new UnsupportedOperationException( + "Unable to get routing table. Table field does not exists"); + return field.get(target) as Map; + } + + public static def void setRoutingTable(RpcService target, Class tableClass, + Map routingTable) { + val field = target.class.getField(tableClass.routingTableField) + if (field == null) throw new UnsupportedOperationException( + "Unable to set routing table. Table field does not exists"); + field.set(target,routingTable); + + } + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.xtend new file mode 100644 index 0000000000..c6e76c2907 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.xtend @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.binding.codegen + +import org.opendaylight.yangtools.yang.binding.RpcService +import org.opendaylight.yangtools.yang.binding.BaseIdentity +import org.opendaylight.yangtools.yang.binding.NotificationListener + +/** + * + * + */ +class RuntimeCodeSpecification { + + public static val PACKAGE_PREFIX = "_gen."; + + public static val DIRECT_PROXY_SUFFIX = "DirectProxy"; + public static val ROUTER_SUFFIX = "Router"; + public static val INVOKER_SUFFIX = "Invoker"; + + public static val DELEGATE_FIELD = "_delegate" + public static val ROUTING_TABLE_FIELD_PREFIX = "_routes_" + + public static def getInvokerName(Class listener) { + getGeneratedName(listener, INVOKER_SUFFIX); + } + + /** + * Returns a name for DirectProxy implementation + * + * + */ + public static def getDirectProxyName(Class base) { + getGeneratedName(base, DIRECT_PROXY_SUFFIX); + } + + /** + * Returns a name for Router implementation + * + */ + public static def getRouterName(Class base) { + getGeneratedName(base, ROUTER_SUFFIX); + } + + /** + * Returns a name for generated interface + * + */ + public static def getGeneratedName(Class cls, String suffix) { + '''«PACKAGE_PREFIX»«cls.package.name».«cls.simpleName»$«suffix»'''.toString() + } + + /** + * Returns a field name for specified routing context + * + */ + public static def getRoutingTableField(Class routingContext) { + return '''_routes_«routingContext.simpleName»'''.toString; + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.xtend new file mode 100644 index 0000000000..18d3e26346 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.xtend @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.binding.codegen + +import java.lang.reflect.Method +import org.opendaylight.yangtools.yang.binding.Notification + +public static class YangtoolsMappingHelper { + + public static def boolean isNotificationCallback(Method it) { + return name.startsWith("on") && parameterTypes.size === 1 && + Notification.isAssignableFrom(parameterTypes.get(0)) + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/JavassistUtils.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/JavassistUtils.java new file mode 100644 index 0000000000..c6be284f4c --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/JavassistUtils.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.binding.codegen.impl; + +import javassist.CtClass; +import javassist.CtField; +import javassist.CtMethod; + +public class JavassistUtils { + + public static interface ClassGenerator { + void process(CtClass cls); + } + + public static interface MethodGenerator { + void process(CtMethod method); + } + + public static interface FieldGenerator { + void process(CtField field); + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RoutingPair.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RoutingPair.xtend new file mode 100644 index 0000000000..4324b4eb9a --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RoutingPair.xtend @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.binding.codegen.impl + +import org.opendaylight.yangtools.yang.binding.BaseIdentity +import javassist.CtMethod +import java.lang.reflect.Method + +@Data +class RoutingPair { + + @Property + val Class context; + @Property + val CtMethod getter; +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend new file mode 100644 index 0000000000..3b3f4190cf --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.binding.codegen.impl + +import javassist.ClassPool +import org.opendaylight.yangtools.yang.binding.RpcService + +import javassist.CtClass +import static com.google.common.base.Preconditions.* + +import javassist.CtField +import javassist.Modifier +import javassist.CtMethod +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext +import org.opendaylight.yangtools.yang.binding.BaseIdentity + +import java.util.Map +import java.util.HashMap +import javassist.NotFoundException +import javassist.LoaderClassPath +import org.opendaylight.controller.sal.binding.codegen.impl.JavassistUtils.MethodGenerator +import org.opendaylight.controller.sal.binding.codegen.impl.JavassistUtils.ClassGenerator +import org.opendaylight.yangtools.yang.binding.NotificationListener +import org.opendaylight.yangtools.yang.binding.Notification +import java.util.Arrays + +import static extension org.opendaylight.controller.sal.binding.codegen.YangtoolsMappingHelper.* +import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.* + +class RuntimeCodeGenerator { + + val ClassPool classPool; + + public new(ClassPool pool) { + classPool = pool; + } + + def Class generateDirectProxy(Class iface) { + val supertype = iface.asCtClass + val targetCls = createClass(iface.directProxyName, supertype) [ + field(DELEGATE_FIELD, iface); + implementMethodsFrom(supertype) [ + body = '''return ($r) «DELEGATE_FIELD».«it.name»($$);''' + ] + ] + return targetCls.toClass(iface.classLoader) + } + + def Class generateRouter(Class iface) { + val supertype = iface.asCtClass + val targetCls = createClass(iface.routerName, supertype) [ + //field(ROUTING_TABLE_FIELD,Map) + field(DELEGATE_FIELD, iface) + val contexts = new HashMap>(); + // We search for routing pairs and add fields + supertype.methods.filter[declaringClass == supertype && parameterTypes.size === 1].forEach [ method | + val routingPair = method.routingContextInput; + if (routingPair !== null) + contexts.put(routingPair.context.routingTableField, routingPair.context); + ] + for (ctx : contexts.entrySet) { + field(ctx.key, Map) + } + implementMethodsFrom(supertype) [ + if (parameterTypes.size === 1) { + val routingPair = routingContextInput; + val bodyTmp = ''' + { + final «InstanceIdentifier.name» identifier = $1.«routingPair.getter.name»(); + «supertype.name» instance = («supertype.name») «routingPair.context.routingTableField».get(identifier); + if(instance == null) { + instance = «DELEGATE_FIELD»; + } + return ($r) instance.«it.name»($$); + }''' + body = bodyTmp + } else if (parameterTypes.size === 0) { + body = '''return ($r) «DELEGATE_FIELD».«it.name»($$);''' + } + ] + ] + return targetCls.toClass(iface.classLoader) + } + + def Class generateListenerInvoker(Class iface) { + val targetCls = createClass(iface.invokerName) [ + field(DELEGATE_FIELD, iface) + it.method(Void, "invoke", Notification) [ + val callbacks = iface.methods.filter[notificationCallback] + body = ''' + { + «FOR callback : callbacks SEPARATOR " else "» + if($1 instanceof «val cls = callback.parameterTypes.get(0).name») { + «DELEGATE_FIELD».«callback.name»((«cls») $1); + return; + } + «ENDFOR» + } + ''' + ] + ] + return targetCls.toClass(iface.classLoader); + } + + def void method(CtClass it, Class returnType, String name, Class parameter, MethodGenerator function1) { + val method = new CtMethod(returnType.asCtClass, name, Arrays.asList(parameter.asCtClass), it); + function1.process(method); + it.addMethod(method); + } + + private def routingContextInput(CtMethod method) { + val inputClass = method.parameterTypes.get(0); + return inputClass.contextInstance; + } + + private def RoutingPair getContextInstance(CtClass dataClass) { + for (method : dataClass.methods) { + if (method.parameterTypes.size === 0 && method.name.startsWith("get")) { + for (annotation : method.availableAnnotations) { + if (annotation instanceof RoutingContext) { + return new RoutingPair((annotation as RoutingContext).value, method) + } + } + } + } + for (iface : dataClass.interfaces) { + val ret = getContextInstance(iface); + if (ret != null) return ret; + } + return null; + } + + private def void implementMethodsFrom(CtClass target, CtClass source, MethodGenerator function1) { + for (method : source.methods) { + if (method.declaringClass == source) { + val redeclaredMethod = new CtMethod(method, target, null); + function1.process(redeclaredMethod); + target.addMethod(redeclaredMethod); + } + } + } + + private def CtClass createClass(String fqn, ClassGenerator cls) { + val target = classPool.makeClass(fqn); + cls.process(target); + return target; + } + + private def CtClass createClass(String fqn, CtClass superInterface, ClassGenerator cls) { + val target = classPool.makeClass(fqn); + target.implementsType(superInterface); + cls.process(target); + return target; + } + + private def void implementsType(CtClass it, CtClass supertype) { + checkArgument(supertype.interface, "Supertype must be interface"); + addInterface(supertype); + } + + private def asCtClass(Class class1) { + classPool.get(class1); + } + + private def CtField field(CtClass it, String name, Class returnValue) { + val field = new CtField(returnValue.asCtClass, name, it); + field.modifiers = Modifier.PUBLIC + addField(field); + return field; + } + + def get(ClassPool pool, Class cls) { + try { + return pool.get(cls.name) + } catch (NotFoundException e) { + pool.appendClassPath(new LoaderClassPath(cls.classLoader)); + return pool.get(cls.name) + } + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend index 2953466b29..298a74ece5 100644 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend @@ -11,30 +11,29 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer import org.opendaylight.controller.sal.binding.api.BindingAwareProvider import org.opendaylight.yangtools.yang.binding.RpcService import javassist.ClassPool -import javassist.CtMethod -import javassist.CtField import org.osgi.framework.BundleContext import java.util.Map import java.util.HashMap import javassist.LoaderClassPath import org.opendaylight.controller.sal.binding.api.BindingAwareBroker import java.util.Hashtable +import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper.* -import static extension org.opendaylight.controller.sal.binding.impl.utils.PropertiesUtils.* -import static extension org.opendaylight.controller.sal.binding.impl.utils.GeneratorUtils.* import org.opendaylight.controller.sal.binding.api.NotificationProviderService import org.osgi.framework.ServiceRegistration -import org.opendaylight.controller.sal.binding.impl.utils.PropertiesUtils +import static org.opendaylight.controller.sal.binding.impl.osgi.Constants.* +import static extension org.opendaylight.controller.sal.binding.impl.osgi.PropertiesUtils.* import org.opendaylight.controller.sal.binding.api.NotificationService import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext -import javassist.Modifier + import org.slf4j.LoggerFactory +import org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator class BindingAwareBrokerImpl implements BindingAwareBroker { - private static val DELEGATE_FIELD = "_delegate" private static val log = LoggerFactory.getLogger(BindingAwareBrokerImpl) private val clsPool = ClassPool.getDefault() + private var RuntimeCodeGenerator generator; private Map, RpcProxyContext> managedProxies = new HashMap(); private var NotificationBrokerImpl notifyBroker private var ServiceRegistration notifyBrokerRegistration @@ -47,7 +46,7 @@ class BindingAwareBrokerImpl implements BindingAwareBroker { // Initialization of notificationBroker notifyBroker = new NotificationBrokerImpl(null); - val brokerProperties = PropertiesUtils.newProperties(); + val brokerProperties = newProperties(); notifyBrokerRegistration = brokerBundleContext.registerService(NotificationProviderService, notifyBroker, brokerProperties) brokerBundleContext.registerService(NotificationService, notifyBroker, brokerProperties) @@ -56,7 +55,8 @@ class BindingAwareBrokerImpl implements BindingAwareBroker { def initGenerator() { // YANG Binding Class Loader - clsPool.appendClassPath(new LoaderClassPath(RpcService.classLoader)) + clsPool.appendClassPath(new LoaderClassPath(RpcService.classLoader)); + generator = new RuntimeCodeGenerator(clsPool); } override registerConsumer(BindingAwareConsumer consumer, BundleContext bundleCtx) { @@ -97,35 +97,16 @@ class BindingAwareBrokerImpl implements BindingAwareBroker { if ((existing = managedProxies.get(service)) != null) { return existing.proxy } - val proxyClass = service.generateDirectProxy() + val proxyClass = generator.generateDirectProxy(service) val rpcProxyCtx = new RpcProxyContext(proxyClass) val properties = new Hashtable() rpcProxyCtx.proxy = proxyClass.newInstance as RpcService - properties.salServiceType = Constants.SAL_SERVICE_TYPE_CONSUMER_PROXY + properties.salServiceType = SAL_SERVICE_TYPE_CONSUMER_PROXY rpcProxyCtx.registration = brokerBundleContext.registerService(service, rpcProxyCtx.proxy as T, properties) managedProxies.put(service, rpcProxyCtx) return rpcProxyCtx.proxy } - - protected def generateDirectProxy(Class delegate) { - val targetFqn = delegate.generatedName(Constants.PROXY_DIRECT_SUFFIX) - log.debug("Generating DirectProxy for {} Proxy name: {}",delegate,targetFqn); - val objCls = clsPool.get(Object) - val delegateCls = clsPool.get(delegate) - val proxyCls = clsPool.makeClass(targetFqn) - proxyCls.addInterface(delegateCls) - val delField = new CtField(delegateCls, DELEGATE_FIELD, proxyCls); - delField.modifiers = Modifier.PUBLIC - proxyCls.addField(delField) - delegateCls.methods.filter[it.declaringClass != objCls].forEach [ - val proxyMethod = new CtMethod(it, proxyCls, null); - proxyMethod.body = '''return ($r) «DELEGATE_FIELD».«it.name»($$);''' - proxyCls.addMethod(proxyMethod) - ] - return proxyCls.toClass(delegate.classLoader) - } - /** * Registers RPC Implementation * @@ -140,34 +121,4 @@ class BindingAwareBrokerImpl implements BindingAwareBroker { proxy.delegate = service; return new RpcServiceRegistrationImpl(type, service, osgiReg); } - - /** - * Helper method to return delegate from ManagedDirectedProxy with use of reflection. - * - * Note: This method uses reflection, but access to delegate field should be - * avoided and called only if neccessary. - * - */ - def getDelegate(RpcService proxy) { - val field = proxy.class.getField(DELEGATE_FIELD) - if(field == null) throw new UnsupportedOperationException("Unable to get delegate from proxy"); - return field.get(proxy) as T - } - - /** - * Helper method to set delegate to ManagedDirectedProxy with use of reflection. - * - * Note: This method uses reflection, but setting delegate field should not occur too much - * to introduce any significant performance hits. - * - */ - def void setDelegate(RpcService proxy, RpcService delegate) { - val field = proxy.class.getField(DELEGATE_FIELD) - if(field == null) throw new UnsupportedOperationException("Unable to set delegate to proxy"); - if (field.type.isAssignableFrom(delegate.class)) { - field.set(proxy,delegate) - } else throw new IllegalArgumentException("delegate class is not assignable to proxy"); - } - - } diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend new file mode 100644 index 0000000000..398a2196c6 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.binding.impl + +import org.opendaylight.controller.sal.common.DataStoreIdentifier +import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider + +class DataProviderContext { + + @Property + var DataStoreIdentifier identifier; + @Property + var RuntimeDataProvider provider; +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend index da1ba79997..22db73526e 100644 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend @@ -45,6 +45,7 @@ class NotificationBrokerImpl implements NotificationProviderService { notification.class.interfaces.filter[it != Notification && Notification.isAssignableFrom(it)] } + @SuppressWarnings("unchecked") def notifyAll(Collection> listeners, Notification notification) { listeners.forEach[(it as NotificationListener).onNotification(notification)] } diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiConsumerContext.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiConsumerContext.xtend index a87fa0642a..a9031240c7 100644 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiConsumerContext.xtend +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiConsumerContext.xtend @@ -1,3 +1,10 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ package org.opendaylight.controller.sal.binding.impl; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext; @@ -7,47 +14,45 @@ import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.slf4j.LoggerFactory +import static org.opendaylight.controller.sal.binding.impl.osgi.Constants.* class OsgiConsumerContext implements ConsumerContext { - static val log = LoggerFactory.getLogger(OsgiConsumerContext) - protected val BundleContext bundleContext; - protected val BindingAwareBrokerImpl broker; - - new(BundleContext ctx,BindingAwareBrokerImpl broker) { - this.bundleContext = ctx; - this.broker = broker; - } - - - override def getSALService(Class service) { - // SAL Services are global - var ref = bundleContext.getServiceReference(service); - return bundleContext.getService(ref) as T; - } - - - - override def T getRpcService(Class module) { - try { - - val services = bundleContext.getServiceReferences(module, getProxyFilter()); - - // Proxy service found / using first implementation - // FIXME: Add advanced logic to retrieve service with right set of models - if(false == services.empty) { - val ref = services.iterator().next() as ServiceReference; - return bundleContext.getService(ref) as T; - } - } catch (InvalidSyntaxException e) { - log.error("Created filter was invalid:", e.message,e) - } - return null; - - - } - - private def getProxyFilter() { - return '''(«Constants.SAL_SERVICE_TYPE»=«Constants.SAL_SERVICE_TYPE_CONSUMER_PROXY»)''' - } + static val log = LoggerFactory.getLogger(OsgiConsumerContext) + protected val BundleContext bundleContext; + protected val BindingAwareBrokerImpl broker; + + new(BundleContext ctx, BindingAwareBrokerImpl broker) { + this.bundleContext = ctx; + this.broker = broker; + } + + override def getSALService(Class service) { + + // SAL Services are global + var ref = bundleContext.getServiceReference(service); + return bundleContext.getService(ref) as T; + } + + override def T getRpcService(Class module) { + try { + + val services = bundleContext.getServiceReferences(module, getProxyFilter()); + + // Proxy service found / using first implementation + // FIXME: Add advanced logic to retrieve service with right set of models + if (false == services.empty) { + val ref = services.iterator().next() as ServiceReference; + return bundleContext.getService(ref) as T; + } + } catch (InvalidSyntaxException e) { + log.error("Created filter was invalid:", e.message, e) + } + return null; + + } + + private def getProxyFilter() { + return '''(«SAL_SERVICE_TYPE»=«SAL_SERVICE_TYPE_CONSUMER_PROXY»)''' + } } diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiProviderContext.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiProviderContext.xtend index 195fa8b959..c769ca1ee3 100644 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiProviderContext.xtend +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiProviderContext.xtend @@ -16,7 +16,8 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcService import org.opendaylight.yangtools.yang.binding.RpcService; import org.osgi.framework.BundleContext; -import static extension org.opendaylight.controller.sal.binding.impl.utils.PropertiesUtils.*; +import static org.opendaylight.controller.sal.binding.impl.osgi.Constants.*; +import static extension org.opendaylight.controller.sal.binding.impl.osgi.PropertiesUtils.*; class OsgiProviderContext extends OsgiConsumerContext implements ProviderContext { @@ -32,7 +33,7 @@ class OsgiProviderContext extends OsgiConsumerContext implements ProviderContext // TODO Auto-generated method stub val properties = new Hashtable(); - properties.salServiceType = Constants.SAL_SERVICE_TYPE_PROVIDER + properties.salServiceType = SAL_SERVICE_TYPE_PROVIDER // Fill requirements val salReg = broker.registerRpcImplementation(type, implementation, this, properties) diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/_DataBrokerImpl.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/_DataBrokerImpl.xtend new file mode 100644 index 0000000000..b278df56f8 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/_DataBrokerImpl.xtend @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.binding.impl + +import org.opendaylight.controller.sal.binding.api.data.DataBrokerService +import org.opendaylight.controller.sal.common.DataStoreIdentifier +import org.opendaylight.yangtools.yang.binding.DataRoot +import org.opendaylight.controller.sal.binding.api.data.DataProviderService +import org.opendaylight.controller.sal.binding.api.data.DataCommitHandler +import org.opendaylight.controller.sal.binding.api.data.DataRefresher +import org.opendaylight.controller.sal.binding.api.data.DataValidator +import org.opendaylight.yangtools.yang.common.RpcResult +import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider +import java.util.Map + +class _DataBrokerImpl implements DataProviderService { + + Map dataProviders; + var DataProviderContext defaultDataProvider; + + override getData(DataStoreIdentifier store, Class rootType) { + val dataStore = resolveProvider(store, rootType); + return dataStore.provider.getData(store, rootType); + } + + override getData(DataStoreIdentifier store, T filter) { + } + + override T getCandidateData(DataStoreIdentifier store, Class rootType) { + throw new UnsupportedOperationException("TODO: auto-generated method stub"); + } + + override T getCandidateData(DataStoreIdentifier store, T filter) { + throw new UnsupportedOperationException("TODO: auto-generated method stub"); + } + + override commit(DataStoreIdentifier store) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override editCandidateData(DataStoreIdentifier store, DataRoot changeSet) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override addCommitHandler(DataStoreIdentifier store, DataCommitHandler provider) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override addRefresher(DataStoreIdentifier store, DataRefresher refresher) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override addValidator(DataStoreIdentifier store, DataValidator validator) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override removeRefresher(DataStoreIdentifier store, DataRefresher refresher) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override removeCommitHandler(DataStoreIdentifier store, DataCommitHandler provider) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + + } + + override removeValidator(DataStoreIdentifier store, DataValidator validator) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + def DataProviderContext resolveProvider(DataStoreIdentifier store, Class root) { + } + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/Constants.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/Constants.xtend similarity index 84% rename from opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/Constants.xtend rename to opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/Constants.xtend index 668635a39e..9fb2140e83 100644 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/Constants.xtend +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/Constants.xtend @@ -5,7 +5,7 @@ * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.sal.binding.impl +package org.opendaylight.controller.sal.binding.impl.osgi class Constants { @@ -16,6 +16,4 @@ class Constants { public static val SAL_SERVICE_TYPE_CONSUMER_PROXY = "consumerProxy" public static val SAL_SERVICE_TYPE_PROVIDER = "provider" public static val SAL_SERVICE_TYPE_CONNECTOR = "connector" - - public static val PROXY_DIRECT_SUFFIX = "DirectProxy"; } diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/PropertiesUtils.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/PropertiesUtils.xtend new file mode 100644 index 0000000000..d04ca7f4ce --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/PropertiesUtils.xtend @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.binding.impl.osgi + +import java.util.Hashtable +import static org.opendaylight.controller.sal.binding.impl.osgi.Constants.* + +class PropertiesUtils { + + private new() { + } + + static def setSalServiceType(Hashtable properties, String value) { + properties.put(SAL_SERVICE_TYPE, value) + return properties + } + + static def getSalServiceType(Hashtable properties) { + return properties.get(SAL_SERVICE_TYPE) + } + + static def newProperties() { + new Hashtable() + } + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/package-info.java new file mode 100644 index 0000000000..d788ccf3a3 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/package-info.java @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.binding.impl.osgi; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/GeneratorUtils.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/GeneratorUtils.xtend deleted file mode 100644 index c888121eb9..0000000000 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/GeneratorUtils.xtend +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.sal.binding.impl.utils - -import javassist.ClassPool -import javassist.NotFoundException -import javassist.LoaderClassPath - -class GeneratorUtils { - - static val PREFIX = "_gen."; - - public static def generatedName(Class cls, String suffix) { - '''«PREFIX»«cls.package.name».«cls.simpleName»$«suffix»'''.toString() - } - - public static def get(ClassPool pool, Class cls) { - try { - return pool.get(cls.name) - } catch (NotFoundException e) { - pool.appendClassPath(new LoaderClassPath(cls.classLoader)); - return pool.get(cls.name) - } - } -} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/PropertiesUtils.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/PropertiesUtils.xtend deleted file mode 100644 index 7ba62f5ca1..0000000000 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/PropertiesUtils.xtend +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.sal.binding.impl.utils - -import java.util.Hashtable -import org.opendaylight.controller.sal.binding.impl.Constants - -class PropertiesUtils { - - private new() {} - - static def setSalServiceType(Hashtable properties, String value) { - properties.put(Constants.SAL_SERVICE_TYPE,value) - return properties - } - - static def getSalServiceType(Hashtable properties) { - return properties.get(Constants.SAL_SERVICE_TYPE) - } - - static def newProperties() { - new Hashtable() - } - -} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/package-info.java deleted file mode 100644 index 511023860e..0000000000 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.sal.binding.impl.utils; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/test/org/opendaylight/controller/sal/binding/test/GenerationTest.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/test/org/opendaylight/controller/sal/binding/test/GenerationTest.java new file mode 100644 index 0000000000..9bbb5013c0 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/test/org/opendaylight/controller/sal/binding/test/GenerationTest.java @@ -0,0 +1,31 @@ +package org.opendaylight.controller.sal.binding.test; +import static org.junit.Assert.*; + +import java.util.concurrent.Future; + +import org.junit.Test; +import org.opendaylight.controller.sal.binding.impl.ProxyFactoryGenerator; +import org.opendaylight.controller.sal.binding.impl.RpcServiceProxy; +import org.opendaylight.yangtools.yang.binding.RpcService; +import org.opendaylight.yangtools.yang.common.RpcResult; + + +public class GenerationTest { + + public interface MockService extends RpcService { + + Future> cancelToast(); + + Future> makeToast(String input); + } + + @Test + public void test() { + ProxyFactoryGenerator generator = new ProxyFactoryGenerator(); + Class> ret = generator.generate(MockService.class); + + assertTrue(RpcServiceProxy.class.isAssignableFrom(ret)); + assertTrue(MockService.class.isAssignableFrom(ret)); + } + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/RuntimeCodeGeneratorTest.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/RuntimeCodeGeneratorTest.java new file mode 100644 index 0000000000..5dddd1ab9d --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/RuntimeCodeGeneratorTest.java @@ -0,0 +1,142 @@ +package org.opendaylight.controller.sal.binding.test; +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import javassist.ClassPool; + +import org.junit.Before; +import org.junit.Test; +import static org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper.*; +import org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator; +import org.opendaylight.controller.sal.binding.test.mock.FooService; +import org.opendaylight.controller.sal.binding.test.mock.ReferencableObject; +import org.opendaylight.controller.sal.binding.test.mock.ReferencableObjectKey; +import org.opendaylight.controller.sal.binding.test.mock.SimpleInput; +import org.opendaylight.yangtools.yang.binding.Augmentation; +import org.opendaylight.yangtools.yang.binding.BaseIdentity; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; + +import static org.mockito.Mockito.*; + + +public class RuntimeCodeGeneratorTest { + + private RuntimeCodeGenerator codeGenerator; + + + @Before + public void initialize() { + this.codeGenerator = new RuntimeCodeGenerator(ClassPool.getDefault()); + } + + @Test + public void testGenerateDirectProxy() { + Class product = codeGenerator.generateDirectProxy(FooService.class); + assertNotNull(product); + } + + @Test + public void testGenerateRouter() throws Exception { + Class product = codeGenerator.generateRouter(FooService.class); + assertNotNull(product); + assertNotNull(product.getSimpleName()); + assertEquals("2 fields should be generated.",2,product.getFields().length); + + verifyRouting(product.newInstance()); + } + + private void verifyRouting(FooService product) { + Map routingTable = new HashMap<>(); + setRoutingTable(product, BaseIdentity.class, routingTable); + + assertSame("Returned routing table should be same instance",routingTable,getRoutingTable(product, BaseIdentity.class)); + + int servicesCount = 2; + int instancesPerService = 3; + + InstanceIdentifier[][] identifiers = identifiers(servicesCount,instancesPerService); + FooService service[] = new FooService[] { + mock(FooService.class, "Instance 0"), + mock(FooService.class,"Instance 1") + }; + + for(int i = 0;i pathArg = new IdentifiableItem<>(ReferencableObject.class,key); + return new InstanceIdentifier(Arrays.asList(pathArg), ReferencableObject.class); + } + + private static class SimpleInputImpl implements SimpleInput { + private final InstanceIdentifier identifier; + + public SimpleInputImpl(InstanceIdentifier _identifier) { + this.identifier = _identifier; + } + + @Override + public > E getAugmentation(Class augmentationType) { + return null; + } + + @Override + public InstanceIdentifier getIdentifier() { + return this.identifier; + } + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/BarUpdate.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/BarUpdate.java new file mode 100644 index 0000000000..b64ebdf86b --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/BarUpdate.java @@ -0,0 +1,7 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import org.opendaylight.yangtools.yang.binding.Notification; + +public interface BarUpdate extends Grouping,Notification { + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooListener.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooListener.java new file mode 100644 index 0000000000..3629689cdf --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooListener.java @@ -0,0 +1,10 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import org.opendaylight.yangtools.yang.binding.NotificationListener; + +public interface FooListener extends NotificationListener { + + void onFooUpdate(FooUpdate notification); + void onBarUpdate(BarUpdate notification); + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooService.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooService.java new file mode 100644 index 0000000000..3161e936dc --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooService.java @@ -0,0 +1,16 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import java.util.concurrent.Future; + +import org.opendaylight.yangtools.yang.binding.RpcService; +import org.opendaylight.yangtools.yang.common.RpcResult; + +public interface FooService extends RpcService { + + Future> foo(); + + Future> simple(SimpleInput obj); + + Future> inheritedContextInput(InheritedContextInput obj); + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooUpdate.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooUpdate.java new file mode 100644 index 0000000000..a5a5eb8ecb --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooUpdate.java @@ -0,0 +1,7 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import org.opendaylight.yangtools.yang.binding.Notification; + +public interface FooUpdate extends Notification { + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/Grouping.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/Grouping.java new file mode 100644 index 0000000000..86624e0732 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/Grouping.java @@ -0,0 +1,11 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import org.opendaylight.yangtools.yang.binding.BaseIdentity; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext; + +public interface Grouping { + + @RoutingContext(BaseIdentity.class) + InstanceIdentifier getInheritedIdentifier(); +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/InheritedContextInput.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/InheritedContextInput.java new file mode 100644 index 0000000000..39b20cc1f1 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/InheritedContextInput.java @@ -0,0 +1,5 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +public interface InheritedContextInput extends Grouping { + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObject.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObject.java new file mode 100644 index 0000000000..8e0d4579eb --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObject.java @@ -0,0 +1,8 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.Identifiable; + +public interface ReferencableObject extends DataObject,Identifiable { + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObjectKey.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObjectKey.java new file mode 100644 index 0000000000..d2e18175e1 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObjectKey.java @@ -0,0 +1,44 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import org.opendaylight.yangtools.yang.binding.Identifier; + +public class ReferencableObjectKey implements Identifier { + + final Integer value; + + public ReferencableObjectKey(Integer _value) { + this.value = _value; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ReferencableObjectKey other = (ReferencableObjectKey) obj; + if (value == null) { + if (other.value != null) + return false; + } else if (!value.equals(other.value)) + return false; + return true; + } + + @Override + public String toString() { + return "ReferencableObjectKey [value=" + value + "]"; + } + + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/SimpleInput.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/SimpleInput.java new file mode 100644 index 0000000000..dedbd9885e --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/SimpleInput.java @@ -0,0 +1,13 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import org.opendaylight.yangtools.yang.binding.Augmentable; +import org.opendaylight.yangtools.yang.binding.BaseIdentity; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext; + +public interface SimpleInput extends DataObject,Augmentable { + + @RoutingContext(BaseIdentity.class) + InstanceIdentifier getIdentifier(); +} diff --git a/opendaylight/statisticsmanager/implementation/pom.xml b/opendaylight/statisticsmanager/implementation/pom.xml index 8be254e6b5..d7dea84686 100644 --- a/opendaylight/statisticsmanager/implementation/pom.xml +++ b/opendaylight/statisticsmanager/implementation/pom.xml @@ -21,7 +21,7 @@ jacoco reuseReports - target/jacoco.exec + target/jacoco.exec target/jacoco-it.exec java @@ -31,7 +31,7 @@ org.jacoco jacoco-maven-plugin - 0.5.3.201107060350 + ${jacoco.version} diff --git a/opendaylight/statisticsmanager/integrationtest/pom.xml b/opendaylight/statisticsmanager/integrationtest/pom.xml index 527dd0a02b..d620d676f4 100644 --- a/opendaylight/statisticsmanager/integrationtest/pom.xml +++ b/opendaylight/statisticsmanager/integrationtest/pom.xml @@ -104,7 +104,7 @@ jacoco ../implementation/target/jacoco.exec - ../implementaiton/target/jacoco-it.exec + ../implementation/target/jacoco-it.exec java @@ -121,7 +121,7 @@ org.jacoco jacoco-maven-plugin - 0.5.3.201107060350 + ${jacoco.version} ../implementation/target/jacoco-it.exec org.opendaylight.controller.* diff --git a/opendaylight/switchmanager/api/pom.xml b/opendaylight/switchmanager/api/pom.xml index 607c42858e..14a056d5fe 100644 --- a/opendaylight/switchmanager/api/pom.xml +++ b/opendaylight/switchmanager/api/pom.xml @@ -32,7 +32,7 @@ org.jacoco jacoco-maven-plugin - 0.5.3.201107060350 + ${jacoco.version} diff --git a/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SpanConfig.java b/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SpanConfig.java index 522f45946d..4bb6438b32 100644 --- a/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SpanConfig.java +++ b/opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SpanConfig.java @@ -14,10 +14,8 @@ import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; -import org.opendaylight.controller.sal.core.ConstructionException; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; -import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType; import org.opendaylight.controller.sal.utils.GUIField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -116,32 +114,12 @@ public class SpanConfig implements Serializable { } public ArrayList getPortArrayList() { - Node node = Node.fromString(nodeId); ArrayList portList = new ArrayList(); String[] elemArray = spanPort.split(","); for (String elem : elemArray) { - if (elem.contains("-")) { - String[] limits = elem.split("-"); - for (short j = Short.valueOf(limits[0]); j <= Short - .valueOf(limits[1]); j++) { - try { - portList.add(new NodeConnector( - NodeConnectorIDType.OPENFLOW, Short.valueOf(j), - node)); - } catch (ConstructionException e) { - logger.error("",e); - } - } - } else { - try { - portList.add(new NodeConnector( - NodeConnectorIDType.OPENFLOW, Short.valueOf(elem), - node)); - } catch (NumberFormatException e) { - logger.error("",e); - } catch (ConstructionException e) { - logger.error("",e); - } + NodeConnector nodeConnector = NodeConnector.fromString(elem); + if (nodeConnector != null) { + portList.add(nodeConnector); } } return portList; diff --git a/opendaylight/switchmanager/implementation/pom.xml b/opendaylight/switchmanager/implementation/pom.xml index 1b09f3c34d..ee126f3408 100644 --- a/opendaylight/switchmanager/implementation/pom.xml +++ b/opendaylight/switchmanager/implementation/pom.xml @@ -32,7 +32,7 @@ org.jacoco jacoco-maven-plugin - 0.5.3.201107060350 + ${jacoco.version} diff --git a/opendaylight/switchmanager/integrationtest/pom.xml b/opendaylight/switchmanager/integrationtest/pom.xml index d571d9df53..3fc63001d4 100644 --- a/opendaylight/switchmanager/integrationtest/pom.xml +++ b/opendaylight/switchmanager/integrationtest/pom.xml @@ -78,25 +78,16 @@ jacoco ../implementation/target/jacoco.exec - ../implementaiton/target/jacoco-it.exec + ../implementation/target/jacoco-it.exec java - - - - org.jacoco - jacoco-maven-plugin - 0.5.3.201107060350 - - - org.jacoco jacoco-maven-plugin - 0.5.3.201107060350 + ${jacoco.version} ../implementation/target/jacoco-it.exec org.opendaylight.controller.* diff --git a/opendaylight/topologymanager/pom.xml b/opendaylight/topologymanager/implementation/pom.xml similarity index 97% rename from opendaylight/topologymanager/pom.xml rename to opendaylight/topologymanager/implementation/pom.xml index 98bc0e42c8..399f878223 100755 --- a/opendaylight/topologymanager/pom.xml +++ b/opendaylight/topologymanager/implementation/pom.xml @@ -6,7 +6,7 @@ org.opendaylight.controller commons.opendaylight 1.4.0-SNAPSHOT - ../commons/opendaylight + ../../commons/opendaylight scm:git:ssh://git.opendaylight.org:29418/controller.git diff --git a/opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManager.java b/opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManager.java similarity index 100% rename from opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManager.java rename to opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManager.java diff --git a/opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManagerAware.java b/opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManagerAware.java similarity index 100% rename from opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManagerAware.java rename to opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManagerAware.java diff --git a/opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManagerClusterWideAware.java b/opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManagerClusterWideAware.java similarity index 100% rename from opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManagerClusterWideAware.java rename to opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManagerClusterWideAware.java diff --git a/opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/TopologyUserLinkConfig.java b/opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/TopologyUserLinkConfig.java similarity index 100% rename from opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/TopologyUserLinkConfig.java rename to opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/TopologyUserLinkConfig.java diff --git a/opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/internal/Activator.java b/opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/internal/Activator.java similarity index 100% rename from opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/internal/Activator.java rename to opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/internal/Activator.java diff --git a/opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImpl.java b/opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImpl.java similarity index 100% rename from opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImpl.java rename to opendaylight/topologymanager/implementation/src/main/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImpl.java diff --git a/opendaylight/topologymanager/src/test/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImplTest.java b/opendaylight/topologymanager/implementation/src/test/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImplTest.java similarity index 100% rename from opendaylight/topologymanager/src/test/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImplTest.java rename to opendaylight/topologymanager/implementation/src/test/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImplTest.java diff --git a/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/UserConfig.java b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/UserConfig.java index cca194e953..07c814adf1 100644 --- a/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/UserConfig.java +++ b/opendaylight/usermanager/api/src/main/java/org/opendaylight/controller/usermanager/UserConfig.java @@ -34,9 +34,11 @@ public class UserConfig implements Serializable { protected String user; protected List roles; private String password; + + private static final boolean strongPasswordCheck = Boolean.getBoolean("enableStrongPasswordCheck"); + private static final String BAD_PASSWORD = "Bad Password"; private static final int USERNAME_MAXLENGTH = 32; - private static final int PASSWORD_MINLENGTH = 5; - private static final int PASSWORD_MAXLENGTH = 256; + protected static final String PASSWORD_REGEX = "(?=.*[^\\w])(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,256}$"; private static final Pattern INVALID_USERNAME_CHARACTERS = Pattern.compile("([/\\s\\.\\?#%;\\\\]+)"); private static MessageDigest oneWayFunction = null; static { @@ -63,16 +65,12 @@ public class UserConfig implements Serializable { public UserConfig(String user, String password, List roles) { this.user = user; - this.password = password; - if (this.validatePassword().isSuccess()) { - /* - * Only if the password is a valid one, hash it. So in case it is not - * valid, when UserConfig.validate() is called, the proper - * validation error will be returned to the caller. If we hashed a - * priori instead, the mis-configuration would be masked - */ - this.password = hash(this.password); - } + /* + * Password validation to be done on clear text password. If fails, mark + * the password with a well known label, so that object validation can + * report the proper error. Only if password is a valid one, hash it. + */ + this.password = (validatePassword(password).isSuccess()) ? hash(password) : BAD_PASSWORD; this.roles = (roles == null) ? new ArrayList() : new ArrayList(roles); } @@ -142,12 +140,15 @@ public class UserConfig implements Serializable { } public Status validate() { - Status validCheck = validateRoles(); + Status validCheck = validateUsername(); if (validCheck.isSuccess()) { - validCheck = validateUsername(); + validCheck = (!password.equals(BAD_PASSWORD)) ? new Status(StatusCode.SUCCESS) : new Status( + StatusCode.BADREQUEST, + "Password should be 8 to 256 characters long, contain both upper and lower case letters, " + + "at least one number and at least one non alphanumeric character"); } if (validCheck.isSuccess()) { - validCheck = validatePassword(); + validCheck = validateRoles(); } return validCheck; } @@ -168,15 +169,15 @@ public class UserConfig implements Serializable { return new Status(StatusCode.SUCCESS); } - private Status validatePassword() { + private Status validatePassword(String password) { if (password == null || password.isEmpty()) { return new Status(StatusCode.BADREQUEST, "Password cannot be empty"); } - if (password.length() < UserConfig.PASSWORD_MINLENGTH - || password.length() > UserConfig.PASSWORD_MAXLENGTH) { - return new Status(StatusCode.BADREQUEST, - "Password should have 5-256 characters"); + if (strongPasswordCheck && !password.matches(UserConfig.PASSWORD_REGEX)) { + return new Status(StatusCode.BADREQUEST, "Password should be 8 to 256 characters long, " + + "contain both upper and lower case letters, at least one number " + + "and at least one non alphanumeric character"); } return new Status(StatusCode.SUCCESS); } @@ -247,4 +248,25 @@ public class UserConfig implements Serializable { UserConfig.oneWayFunction.reset(); return HexEncode.bytesToHexString(UserConfig.oneWayFunction.digest(message.getBytes(Charset.defaultCharset()))); } + + /** + * Returns UserConfig instance populated with the passed parameters. It does + * not run any checks on the passed parameters. + * + * @param userName + * the user name + * @param password + * the plain text password + * @param roles + * the list of roles + * @return the UserConfig object populated with the passed parameters. No + * validity check is run on the input parameters. + */ + public static UserConfig getUncheckedUserConfig(String userName, String password, List roles) { + UserConfig config = new UserConfig(); + config.user = userName; + config.password = hash(password); + config.roles = roles; + return config; + } } diff --git a/opendaylight/usermanager/api/src/test/java/org/opendaylight/controller/usermanager/AuthorizationUserConfigTest.java b/opendaylight/usermanager/api/src/test/java/org/opendaylight/controller/usermanager/AuthorizationUserConfigTest.java index 4c2a19e426..8c029a7488 100644 --- a/opendaylight/usermanager/api/src/test/java/org/opendaylight/controller/usermanager/AuthorizationUserConfigTest.java +++ b/opendaylight/usermanager/api/src/test/java/org/opendaylight/controller/usermanager/AuthorizationUserConfigTest.java @@ -117,4 +117,41 @@ public class AuthorizationUserConfigTest { UserConfig userConfig2 = new UserConfig("uname", "ciscocisco", roles); assertEquals(userConfig, userConfig2); } + + @Test + public void userConfigPasswordTest() { + + String regex = UserConfig.PASSWORD_REGEX; + String password = null; + + // Good password + password = "aBc@eF#h9"; + assertTrue(password.matches(regex)); + password = "^aBc@eF#h9$88ad*o&"; + assertTrue(password.matches(regex)); + password = "_^aBc@\":eF#h;9$\\8|8ad*o&-(){}/,.> roles = new ArrayList(1); roles.add(DEFAULT_ADMIN_ROLE); - localUserConfigList.put(DEFAULT_ADMIN, new UserConfig(DEFAULT_ADMIN, DEFAULT_ADMIN_PASSWORD, roles)); + // Need to skip the strong password check for the default admin + UserConfig defaultAdmin = UserConfig.getUncheckedUserConfig(UserManager.DEFAULT_ADMIN, + UserManager.DEFAULT_ADMIN_PASSWORD, roles); + localUserConfigList.put(UserManager.DEFAULT_ADMIN, defaultAdmin); } } diff --git a/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java index 2b58bcc4cb..eafd8c54a7 100644 --- a/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java +++ b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java @@ -15,6 +15,7 @@ import java.util.List; import java.util.Set; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; import org.opendaylight.controller.clustering.services.IClusterGlobalServices; import org.opendaylight.controller.connectionmanager.IConnectionManager; @@ -212,24 +213,63 @@ public class DaylightWebAdmin { @RequestMapping(value = "/users/password/{username}", method = RequestMethod.POST) @ResponseBody - public Status changePassword(@PathVariable("username") String username, HttpServletRequest request, - @RequestParam("currentPassword") String currentPassword, @RequestParam("newPassword") String newPassword) { + public Status changePassword( + @PathVariable("username") String username, HttpServletRequest request, + @RequestParam(value = "currentPassword", required=false) String currentPassword, + @RequestParam("newPassword") String newPassword) { IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this); if (userManager == null) { - return new Status(StatusCode.GONE, "User Manager not found"); + return new Status(StatusCode.NOSERVICE, "User Manager unavailable"); } - if (!authorize(userManager, UserLevel.NETWORKADMIN, request)) { - return new Status(StatusCode.FORBIDDEN, "Operation not permitted"); - } + Status status; + String requestingUser = request.getUserPrincipal().getName(); + + //changing own password + if (requestingUser.equals(username) ) { + status = userManager.changeLocalUserPassword(username, currentPassword, newPassword); + //enforce the user to re-login with new password + if (status.isSuccess() && !newPassword.equals(currentPassword)) { + userManager.userLogout(username); + HttpSession session = request.getSession(false); + if ( session != null) { + session.invalidate(); + } + } + + //admin level user resetting other's password + } else if (authorize(userManager, UserLevel.NETWORKADMIN, request)) { + + //Since User Manager doesn't have an unprotected password change API, + //we re-create the user with the new password (and current roles). + List roles = userManager.getUserRoles(username); + UserConfig newConfig = new UserConfig(username, newPassword, roles); + + //validate before removing existing config, so we don't remove but fail to add + status = newConfig.validate(); + if (!status.isSuccess()) { + return status; + } + + userManager.userLogout(username); + status = userManager.removeLocalUser(username); + if (!status.isSuccess()) { + return status; + } + if (userManager.addLocalUser(newConfig).isSuccess()) { + status = new Status(StatusCode.SUCCESS, "Password for user " + username + " reset successfully."); + } else { + //unexpected + status = new Status(StatusCode.INTERNALERROR, "Failed resetting password for user " + username + ". User is now removed."); + } - if (newPassword.isEmpty()) { - return new Status(StatusCode.BADREQUEST, "Empty passwords not allowed"); + //unauthorized + } else { + status = new Status(StatusCode.UNAUTHORIZED, "Operation not permitted"); } - Status status = userManager.changeLocalUserPassword(username, currentPassword, newPassword); if (status.isSuccess()) { - DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "changed password for", username); + DaylightWebUtil.auditlog("User", requestingUser, "changed password for", username); } return status; } diff --git a/opendaylight/web/root/src/main/resources/WEB-INF/jsp/main.jsp b/opendaylight/web/root/src/main/resources/WEB-INF/jsp/main.jsp index c795a5d56b..4b0ce2d07d 100644 --- a/opendaylight/web/root/src/main/resources/WEB-INF/jsp/main.jsp +++ b/opendaylight/web/root/src/main/resources/WEB-INF/jsp/main.jsp @@ -67,6 +67,7 @@
+
${username}
diff --git a/opendaylight/web/root/src/main/resources/js/open.js b/opendaylight/web/root/src/main/resources/js/open.js index 43a7dfdc44..619edcaf2c 100644 --- a/opendaylight/web/root/src/main/resources/js/open.js +++ b/opendaylight/web/root/src/main/resources/js/open.js @@ -443,9 +443,12 @@ one.main.admin = { // change password binding $('#'+one.main.admin.id.modal.password.submit, $modal).click(function() { one.main.admin.password.submit(id, $modal, function(result) { - if (result.code == 'SUCCESS') { - $modal.modal('hide'); - successCallback(); + if (result.success) { + //if changed own password, enforce relogin + if (id.trim() == $('#currentuser').val().trim()) { + alert("Password changed successfully. Please re-login with your new password."); + window.location = '/'; + } } else { alert(result.code+': '+result.description); }