From: Giovanni Meo Date: Wed, 29 May 2013 16:32:29 +0000 (+0000) Subject: Merge "Bumped version of Maven YANG tools to 0.5.1-SNAPSHOT" X-Git-Tag: releasepom-0.1.0~410 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=63680b9ec12d28383e544cdfc3af0599419d19d4;hp=7842f0e0466414a00ab29fe35c404e315b3e3357 Merge "Bumped version of Maven YANG tools to 0.5.1-SNAPSHOT" --- diff --git a/opendaylight/commons/concepts/pom.xml b/opendaylight/commons/concepts/pom.xml new file mode 100644 index 0000000000..369a58af44 --- /dev/null +++ b/opendaylight/commons/concepts/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../commons/opendaylight + + + concepts + 0.5.0-SNAPSHOT + bundle + + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + + org.slf4j, + org.osgi.framework, + org.apache.commons.lang3.builder, + org.apache.felix.dm, + org.apache.commons.lang3.tuple, + javax.xml.bind.annotation, + javax.xml.bind.annotation.adapters + + + org.opendaylight.controller.concepts.transform + + + ${project.basedir}/META-INF + + + + + + + junit + junit + 4.8.1 + test + + + diff --git a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/Acceptor.java b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/Acceptor.java new file mode 100644 index 0000000000..1bd78d62c7 --- /dev/null +++ b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/Acceptor.java @@ -0,0 +1,20 @@ + +/* + * 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.concepts.tranform; + +public interface Acceptor { + + /** + * + * @param input + * @return true if input is accepted. + */ + boolean isAcceptable(I input); +} diff --git a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/AggregateTransformer.java b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/AggregateTransformer.java new file mode 100644 index 0000000000..390bc0302d --- /dev/null +++ b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/AggregateTransformer.java @@ -0,0 +1,22 @@ +/* + * 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.concepts.tranform; + +import java.util.Collection; +/** + * + * @author Tony Tkacik + * + * @param + * @param

+ */ +public interface AggregateTransformer extends Transformer { + + Collection

transformAll(Collection inputs); +} diff --git a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/CompositeClassBasedTransformer.java b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/CompositeClassBasedTransformer.java new file mode 100644 index 0000000000..ec62feec7a --- /dev/null +++ b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/CompositeClassBasedTransformer.java @@ -0,0 +1,121 @@ +/* + * 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.concepts.tranform; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + + +/** + * Transformer which aggregates multiple implementations of + * {@link InputClassBasedTransformer}. + * + * The transformation process is driven by {@link Class} of input. The selection + * of used {@link InputClassBasedTransformer} is done by using the {@link Class} + * of input as a key to select the transformer. + * + * This approach provides quick resolution of transformer, but does not support + * registering a super type of input to provide transformation support for all + * subclasses, one must register a new instance of transformer for each valid + * input class. + * + * If you need more flexible selection of transformation consider using + * {@link CompositeConditionalTransformer} which is slower but most flexible or + * {@link RuleBasedTransformer} which provides declarative approach for + * transformation. + * + * See {@link #transform(Object)} for more information about tranformation + * process. + * + * @author Tony Tkacik + * + * @param + * Input super-type + * @param

+ * Product + */ +public abstract class CompositeClassBasedTransformer implements + InputClassBasedTransformer, + AggregateTransformer { + + private Map, InputClassBasedTransformer> transformers = new ConcurrentHashMap, InputClassBasedTransformer>(); + + /** + * Transforms an input into instance of Product class. + * + * The final registered transformer is the one which match following + * condition: + * + * input.getClass() == transformer.getInputClass() + * + * This means that transformers are not resolved by class hierarchy, only + * selected based on final class of the input. If you need more flexible + * selection of transformation consider using + * {@link CompositeConditionalTransformer} which is slower but more + * flexible. + * + */ + @Override + public P transform(I input) { + @SuppressWarnings("unchecked") + InputClassBasedTransformer transformer = (InputClassBasedTransformer) transformers + .get(input.getClass()); + if (transformer == null) + throw new IllegalArgumentException("Transformation of: " + input + + " is not supported"); + return transformer.transform(input); + } + + /** + * Registers a new transformer. + * + * The transformer is registered for class returned by + * {@link InputClassBasedTransformer#getInputClass()}. Only one transformer + * can be registered for particular input class. + * + */ + public void addTransformer( + InputClassBasedTransformer transformer) + throws IllegalStateException { + if (transformer == null) + throw new IllegalArgumentException("Transformer should not be null"); + if (transformer.getInputClass() == null) + throw new IllegalArgumentException( + "Transformer should specify input class."); + transformers.put(transformer.getInputClass(), transformer); + } + + /** + * Removes an registered transformer. + * + * Note: Removal is currently unsupported. + * + * @param transformer + * Tranformer to be removed. + * @throws IllegalArgumentException + * If the provided transformer is null or is not registered. + */ + public void removeTransformer( + InputClassBasedTransformer transformer) + throws IllegalArgumentException { + throw new UnsupportedOperationException("Not implemented yet"); + } + + @Override + public Collection

transformAll(Collection inputs) { + Collection

ret = new ArrayList

(); + for (I i : inputs) { + ret.add(transform(i)); + } + return ret; + } + +} diff --git a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/CompositeConditionalTransformer.java b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/CompositeConditionalTransformer.java new file mode 100644 index 0000000000..a31d896372 --- /dev/null +++ b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/CompositeConditionalTransformer.java @@ -0,0 +1,157 @@ +/* + * 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.concepts.tranform; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.Set; +import java.util.TreeSet; + +/** + * Composite transformer which aggregates multiple implementation and selects + * the one which accepts the input. + * + * + * @author Tony Tkacik + * + * @param + * Input class for transformation + * @param

+ * Product of transformation + */ +public class CompositeConditionalTransformer implements + SimpleConditionalTransformer, + AggregateTransformer { + + private final Comparator> comparator = new Comparator>() { + + @Override + public int compare(TransformerWithPriority o1, + TransformerWithPriority o2) { + return Integer.compare(o1.priority, o2.priority); + } + + }; + private final Set> transformers; + + public CompositeConditionalTransformer() { + // FIXME: Add Ordering + transformers = new TreeSet>(comparator); + } + + @Override + public boolean isAcceptable(I input) { + for (SimpleConditionalTransformer trans : transformers) { + if (trans.isAcceptable(input)) { + return true; + } + } + return false; + } + + @Override + public P transform(I input) { + for (SimpleConditionalTransformer trans : transformers) { + if (trans.isAcceptable(input)) { + return trans.transform(input); + } + } + throw new IllegalStateException( + "Transformer for provided input is not available."); + } + + public void addTransformer(SimpleConditionalTransformer transformer, + int priority) throws IllegalStateException { + if (transformer == null) { + throw new IllegalArgumentException( + "transformer should not be null."); + } + TransformerWithPriority withPriority = new TransformerWithPriority( + transformer, priority); + if (false == transformers.add(withPriority)) { + throw new IllegalStateException("transformer " + transformer + + "already registered"); + } + } + + public void removeTransformer(SimpleConditionalTransformer transformer) + throws IllegalArgumentException { + if (transformer == null) { + throw new IllegalArgumentException( + "transformer should not be null."); + } + if (false == transformers.remove(transformer)) { + throw new IllegalStateException("transformer " + transformer + + "already registered"); + } + } + + @Override + public Collection

transformAll(Collection inputs) { + Collection

ret = new ArrayList

(); + for (I i : inputs) { + ret.add(transform(i)); + } + return ret; + } + + private static class TransformerWithPriority implements + SimpleConditionalTransformer { + final int priority; + final SimpleConditionalTransformer transformer; + + public TransformerWithPriority( + SimpleConditionalTransformer transformer, int priority) { + this.priority = priority; + this.transformer = transformer; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((transformer == null) ? 0 : transformer.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; + TransformerWithPriority other = (TransformerWithPriority) obj; + if (transformer == null) { + if (other.transformer != null) + return false; + } else if (!transformer.equals(other.transformer)) + return false; + return true; + } + + @Override + public boolean isAcceptable(I input) { + return transformer.isAcceptable(input); + } + + @Override + public P transform(I input) { + return transformer.transform(input); + } + + + + + + } +} diff --git a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/InputClassBasedTransformer.java b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/InputClassBasedTransformer.java new file mode 100644 index 0000000000..1b8d1f0466 --- /dev/null +++ b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/InputClassBasedTransformer.java @@ -0,0 +1,38 @@ +/* + * 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.concepts.tranform; + +/** + * Input class based transformer + * + * {@link Transformer} which accepts / transforms only specific classes of + * input, and is useful if the selection of transformer should be based on the + * class of the input and there is one-to-one mapping between input class and + * transformer. + * + * + * @author Tony Tkacik + * + * @param + * Common supertype of input + * @param + * Concrete type of input + * @param

+ * Product + */ +public interface InputClassBasedTransformer extends + Transformer { + + /** + * Returns an {@link Class} of input which is acceptable for transformation. + * + * @return {@link Class} of input which is acceptable for transformation. + */ + Class getInputClass(); +} diff --git a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/RuleBasedTransformer.java b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/RuleBasedTransformer.java new file mode 100644 index 0000000000..3f21e5aafa --- /dev/null +++ b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/RuleBasedTransformer.java @@ -0,0 +1,42 @@ +/* + * 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.concepts.tranform; + +import java.util.Set; + +/** + * Transformer with set of acceptance rules + * + * The transformer provides a set of {@link Acceptor}s, which could be used to + * verify if the input will produce result using the transformer. + * + * The transormer is able to produce result if ANY of associated + * {@link Acceptor}s accepted result. + * + * @author Tony Tkacik + * + * @param + * Input class for transformation + * @param

+ * Product of transformation + */ +public interface RuleBasedTransformer extends Transformer { + + /** + * Set of {@link Acceptor}, which could be used to verify if the input is + * usable by transformer. + * + * The transformer is able to produce result if ANY of associated + * {@link Acceptor}s accepted result. + * + * @return Set of input acceptance rules associated to this transformer. + */ + Set> getRules(); + +} diff --git a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/SimpleConditionalTransformer.java b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/SimpleConditionalTransformer.java new file mode 100644 index 0000000000..5a9b555ac6 --- /dev/null +++ b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/SimpleConditionalTransformer.java @@ -0,0 +1,38 @@ +/* + * 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.concepts.tranform; + +/** + * Simple condition-based transformer + * + * The transformer provides {@link #isAcceptable(Object)} method, + * which could be used to query transformer if the input will produce + * result. + * + * This interface is simplified version of {@link RuleBasedTransformer} - does not + * provide decoupling of Acceptance rule from transformer, and should be used only + * for simple use-cases. + * + * @author Tony Tkacik + * + * @param Input class for transformation + * @param

Product of transformation + */ +public interface SimpleConditionalTransformer extends Transformer, Acceptor { + + + /** + * Checks if the input is acceptable + * for processing by the transformer. + * + * @return true it the input is acceptable for processing by transformer. + */ + @Override + public boolean isAcceptable(I input); +} diff --git a/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/Transformer.java b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/Transformer.java new file mode 100644 index 0000000000..58fe0e1eb6 --- /dev/null +++ b/opendaylight/commons/concepts/src/main/java/org/opendaylight/controller/concepts/tranform/Transformer.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.concepts.tranform; + +/** + * Factory which produces product based on input object + * + * @author Tony Tkacik + * + * @param Input + * @param

Product + */ +public interface Transformer { + /** + * Transforms input into instance of product. + * + * @param input Input which drives transformation + * @return Instance of product which was created from supplied input. + */ + P transform(I input); +} diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index ddc24b3965..86725e9d05 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -97,6 +97,7 @@ ../../samples/simpleforwarding ../../samples/loadbalancer ../../samples/northbound/loadbalancer + ../../commons/concepts diff --git a/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIntegrationTest.java b/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIntegrationTest.java index 19c756a1cb..4997e37a25 100644 --- a/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIntegrationTest.java +++ b/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIntegrationTest.java @@ -98,58 +98,58 @@ public class NorthboundIntegrationTest { private String getJsonResult(String restUrl, String method) { // initialize response code to indicate error httpResponseCode = 400; - + try { - URL url = new URL(restUrl); - - this.users.getAuthorizationList(); - this.users.authenticate("admin", "admin"); - String authString = "admin:admin"; - byte[] authEncBytes = Base64.encodeBase64(authString.getBytes()); - String authStringEnc = new String(authEncBytes); - - HttpURLConnection connection = (HttpURLConnection)url.openConnection(); - connection.setRequestMethod(method); - connection.setRequestProperty("Authorization", "Basic " - + authStringEnc); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setRequestProperty("Accept", "application/json"); - - connection.connect(); - connection.getContentType(); - - // Response code for success should be 2xx - httpResponseCode = connection.getResponseCode(); - - InputStream is = connection.getInputStream(); - BufferedReader rd = new BufferedReader(new InputStreamReader(is, - Charset.forName("UTF-8"))); - StringBuilder sb = new StringBuilder(); - int cp; - while ((cp = rd.read()) != -1) { - sb.append((char) cp); - } - is.close(); - connection.disconnect(); - return sb.toString(); - } catch (Exception e) { - return null; - } - - } + URL url = new URL(restUrl); + + this.users.getAuthorizationList(); + this.users.authenticate("admin", "admin"); + String authString = "admin:admin"; + byte[] authEncBytes = Base64.encodeBase64(authString.getBytes()); + String authStringEnc = new String(authEncBytes); + + HttpURLConnection connection = (HttpURLConnection) url + .openConnection(); + connection.setRequestMethod(method); + connection.setRequestProperty("Authorization", "Basic " + + authStringEnc); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setRequestProperty("Accept", "application/json"); + + connection.connect(); + connection.getContentType(); + + // Response code for success should be 2xx + httpResponseCode = connection.getResponseCode(); + + InputStream is = connection.getInputStream(); + BufferedReader rd = new BufferedReader(new InputStreamReader(is, + Charset.forName("UTF-8"))); + StringBuilder sb = new StringBuilder(); + int cp; + while ((cp = rd.read()) != -1) { + sb.append((char) cp); + } + is.close(); + connection.disconnect(); + return sb.toString(); + } catch (Exception e) { + return null; + } + + } @Test public void testStatistics() { - + String actionTypes[] = { "drop", "loopback", "flood", "floodAll", + "controller", "swPath", "hwPath", "output", "setDlSrc", + "setDlDst", "setDlType", "setVlanId", "setVlanPcp", + "setVlanCfi", "popVlan", "pushVlan", "setNwSrc", "setNwDst", + "setNwTos", "setTpSrc", "setTpDst" }; System.out.println("Starting Statistics JAXB client."); String baseURL = "http://127.0.0.1:8080/controller/nb/v2/statistics/default/"; try { - String actionTypes[] = { "drop", "loopback", "flood", "floodAll", - "controller", "swPath", "hwPath", "output", "setDlSrc", - "setDlDst", "setDlType", "setVlanId", "setVlanPcp", - "setVlanCfi", "popVlan", "pushVlan", "setNwSrc", - "setNwDst", "setNwTos", "setTpSrc", "setTpDst" }; String result = getJsonResult(baseURL + "flowstats"); JSONTokener jt = new JSONTokener(result); JSONObject json = new JSONObject(jt); @@ -164,96 +164,8 @@ public class NorthboundIntegrationTest { for (int i = 0; i < flowStats.length(); i++) { JSONObject flowStat = flowStats.getJSONObject(i); - Assert.assertTrue(flowStat.getInt("tableId") == 1); - Assert.assertTrue(flowStat.getInt("durationSeconds") == 40); - Assert.assertTrue(flowStat.getInt("durationNanoseconds") == 400); - Assert.assertTrue(flowStat.getInt("packetCount") == 200); - Assert.assertTrue(flowStat.getInt("byteCount") == 100); - - // test that flow information is correct - JSONObject flow = flowStat.getJSONObject("flow"); - Assert.assertTrue(flow.getInt("priority") == 3500); - Assert.assertTrue(flow.getInt("idleTimeout") == 1000); - Assert.assertTrue(flow.getInt("hardTimeout") == 2000); - Assert.assertTrue(flow.getInt("id") == 12345); - - JSONObject match = (flow.getJSONObject("match") - .getJSONObject("matchField")); - Assert.assertTrue(match.getString("type").equals("NW_DST")); - Assert.assertTrue(match.getString("value").equals("1.1.1.1")); - - JSONObject act = flow.getJSONObject("actions"); - Assert.assertTrue(act.getString("@type").equals(actionTypes[i])); - - if (act.getString("@type").equals("output")) { - JSONObject port = act.getJSONObject("port"); - JSONObject port_node = port.getJSONObject("node"); - Assert.assertTrue(port.getInt("@id") == 51966); - Assert.assertTrue(port.getString("@type").equals("STUB")); - Assert.assertTrue(port_node.getInt("@id") == 51966); - Assert.assertTrue(port_node.getString("@type").equals( - "STUB")); - } - - if (act.getString("@type").equals("setDlSrc")) { - byte srcMatch[] = { (byte) 5, (byte) 4, (byte) 3, (byte) 2, - (byte) 1 }; - String src = act.getString("address"); - byte srcBytes[] = new byte[5]; - srcBytes[0] = Byte.parseByte(src.substring(0, 2)); - srcBytes[1] = Byte.parseByte(src.substring(2, 4)); - srcBytes[2] = Byte.parseByte(src.substring(4, 6)); - srcBytes[3] = Byte.parseByte(src.substring(6, 8)); - srcBytes[4] = Byte.parseByte(src.substring(8, 10)); - Assert.assertTrue(Arrays.equals(srcBytes, srcMatch)); - } - - if (act.getString("@type").equals("setDlDst")) { - byte dstMatch[] = { (byte) 1, (byte) 2, (byte) 3, (byte) 4, - (byte) 5 }; - String dst = act.getString("address"); - byte dstBytes[] = new byte[5]; - dstBytes[0] = Byte.parseByte(dst.substring(0, 2)); - dstBytes[1] = Byte.parseByte(dst.substring(2, 4)); - dstBytes[2] = Byte.parseByte(dst.substring(4, 6)); - dstBytes[3] = Byte.parseByte(dst.substring(6, 8)); - dstBytes[4] = Byte.parseByte(dst.substring(8, 10)); - Assert.assertTrue(Arrays.equals(dstBytes, dstMatch)); - } - if (act.getString("@type").equals("setDlType")) - Assert.assertTrue(act.getInt("dlType") == 10); - if (act.getString("@type").equals("setVlanId")) - Assert.assertTrue(act.getInt("vlanId") == 2); - if (act.getString("@type").equals("setVlanPcp")) - Assert.assertTrue(act.getInt("pcp") == 3); - if (act.getString("@type").equals("setVlanCfi")) - Assert.assertTrue(act.getInt("cfi") == 1); - - if (act.getString("@type").equals("setNwSrc")) - Assert.assertTrue(act.getString("address") - .equals("2.2.2.2")); - if (act.getString("@type").equals("setNwDst")) - Assert.assertTrue(act.getString("address") - .equals("1.1.1.1")); - - if (act.getString("@type").equals("pushVlan")) { - int head = act.getInt("VlanHeader"); - // parsing vlan header - int id = head & 0xfff; - int cfi = (head >> 12) & 0x1; - int pcp = (head >> 13) & 0x7; - int tag = (head >> 16) & 0xffff; - Assert.assertTrue(id == 1234); - Assert.assertTrue(cfi == 1); - Assert.assertTrue(pcp == 1); - Assert.assertTrue(tag == 0x8100); - } - if (act.getString("@type").equals("setNwTos")) - Assert.assertTrue(act.getInt("tos") == 16); - if (act.getString("@type").equals("setTpSrc")) - Assert.assertTrue(act.getInt("port") == 4201); - if (act.getString("@type").equals("setTpDst")) - Assert.assertTrue(act.getInt("port") == 8080); + testFlowStat(flowStat, actionTypes[i]); + } // for /controller/nb/v2/statistics/default/portstats @@ -281,8 +193,44 @@ public class NorthboundIntegrationTest { Assert.assertTrue(portStat.getInt("receiveCrcError") == 1); Assert.assertTrue(portStat.getInt("collisionCount") == 4); - // String result = getJsonResult(baseURL+"flowstats/STUB/51966"); - // System.out.println(result); + // test for getting one specific node's stats + result = getJsonResult(baseURL + "flowstats/STUB/51966"); + jt = new JSONTokener(result); + json = new JSONObject(jt); + node = json.getJSONObject("node"); + // test that node was returned properly + Assert.assertTrue(node.getInt("@id") == 0xCAFE); + Assert.assertTrue(node.getString("@type").equals("STUB")); + + // test that flow statistics results are correct + flowStats = json.getJSONArray("flowStat"); + for (int i = 0; i < flowStats.length(); i++) { + JSONObject flowStat = flowStats.getJSONObject(i); + testFlowStat(flowStat, actionTypes[i]); + } + + result = getJsonResult(baseURL + "portstats/STUB/51966"); + jt = new JSONTokener(result); + json = new JSONObject(jt); + node2 = json.getJSONObject("node"); + // test that node was returned properly + Assert.assertTrue(node2.getInt("@id") == 0xCAFE); + Assert.assertTrue(node2.getString("@type").equals("STUB")); + + // test that port statistic results are correct + portStat = json.getJSONObject("portStat"); + Assert.assertTrue(portStat.getInt("receivePackets") == 250); + Assert.assertTrue(portStat.getInt("transmitPackets") == 500); + Assert.assertTrue(portStat.getInt("receiveBytes") == 1000); + Assert.assertTrue(portStat.getInt("transmitBytes") == 5000); + Assert.assertTrue(portStat.getInt("receiveDrops") == 2); + Assert.assertTrue(portStat.getInt("transmitDrops") == 50); + Assert.assertTrue(portStat.getInt("receiveErrors") == 3); + Assert.assertTrue(portStat.getInt("transmitErrors") == 10); + Assert.assertTrue(portStat.getInt("receiveFrameError") == 5); + Assert.assertTrue(portStat.getInt("receiveOverRunError") == 6); + Assert.assertTrue(portStat.getInt("receiveCrcError") == 1); + Assert.assertTrue(portStat.getInt("collisionCount") == 4); } catch (Exception e) { // Got an unexpected exception @@ -291,6 +239,100 @@ public class NorthboundIntegrationTest { } } + private void testFlowStat(JSONObject flowStat, String actionType) { + try { + Assert.assertTrue(flowStat.getInt("tableId") == 1); + Assert.assertTrue(flowStat.getInt("durationSeconds") == 40); + Assert.assertTrue(flowStat.getInt("durationNanoseconds") == 400); + Assert.assertTrue(flowStat.getInt("packetCount") == 200); + Assert.assertTrue(flowStat.getInt("byteCount") == 100); + + // test that flow information is correct + JSONObject flow = flowStat.getJSONObject("flow"); + Assert.assertTrue(flow.getInt("priority") == 3500); + Assert.assertTrue(flow.getInt("idleTimeout") == 1000); + Assert.assertTrue(flow.getInt("hardTimeout") == 2000); + Assert.assertTrue(flow.getInt("id") == 12345); + + JSONObject match = (flow.getJSONObject("match") + .getJSONObject("matchField")); + Assert.assertTrue(match.getString("type").equals("NW_DST")); + Assert.assertTrue(match.getString("value").equals("1.1.1.1")); + + JSONObject act = flow.getJSONObject("actions"); + Assert.assertTrue(act.getString("@type").equals(actionType)); + + if (act.getString("@type").equals("output")) { + JSONObject port = act.getJSONObject("port"); + JSONObject port_node = port.getJSONObject("node"); + Assert.assertTrue(port.getInt("@id") == 51966); + Assert.assertTrue(port.getString("@type").equals("STUB")); + Assert.assertTrue(port_node.getInt("@id") == 51966); + Assert.assertTrue(port_node.getString("@type").equals("STUB")); + } + + if (act.getString("@type").equals("setDlSrc")) { + byte srcMatch[] = { (byte) 5, (byte) 4, (byte) 3, (byte) 2, + (byte) 1 }; + String src = act.getString("address"); + byte srcBytes[] = new byte[5]; + srcBytes[0] = Byte.parseByte(src.substring(0, 2)); + srcBytes[1] = Byte.parseByte(src.substring(2, 4)); + srcBytes[2] = Byte.parseByte(src.substring(4, 6)); + srcBytes[3] = Byte.parseByte(src.substring(6, 8)); + srcBytes[4] = Byte.parseByte(src.substring(8, 10)); + Assert.assertTrue(Arrays.equals(srcBytes, srcMatch)); + } + + if (act.getString("@type").equals("setDlDst")) { + byte dstMatch[] = { (byte) 1, (byte) 2, (byte) 3, (byte) 4, + (byte) 5 }; + String dst = act.getString("address"); + byte dstBytes[] = new byte[5]; + dstBytes[0] = Byte.parseByte(dst.substring(0, 2)); + dstBytes[1] = Byte.parseByte(dst.substring(2, 4)); + dstBytes[2] = Byte.parseByte(dst.substring(4, 6)); + dstBytes[3] = Byte.parseByte(dst.substring(6, 8)); + dstBytes[4] = Byte.parseByte(dst.substring(8, 10)); + Assert.assertTrue(Arrays.equals(dstBytes, dstMatch)); + } + if (act.getString("@type").equals("setDlType")) + Assert.assertTrue(act.getInt("dlType") == 10); + if (act.getString("@type").equals("setVlanId")) + Assert.assertTrue(act.getInt("vlanId") == 2); + if (act.getString("@type").equals("setVlanPcp")) + Assert.assertTrue(act.getInt("pcp") == 3); + if (act.getString("@type").equals("setVlanCfi")) + Assert.assertTrue(act.getInt("cfi") == 1); + + if (act.getString("@type").equals("setNwSrc")) + Assert.assertTrue(act.getString("address").equals("2.2.2.2")); + if (act.getString("@type").equals("setNwDst")) + Assert.assertTrue(act.getString("address").equals("1.1.1.1")); + + if (act.getString("@type").equals("pushVlan")) { + int head = act.getInt("VlanHeader"); + // parsing vlan header + int id = head & 0xfff; + int cfi = (head >> 12) & 0x1; + int pcp = (head >> 13) & 0x7; + int tag = (head >> 16) & 0xffff; + Assert.assertTrue(id == 1234); + Assert.assertTrue(cfi == 1); + Assert.assertTrue(pcp == 1); + Assert.assertTrue(tag == 0x8100); + } + if (act.getString("@type").equals("setNwTos")) + Assert.assertTrue(act.getInt("tos") == 16); + if (act.getString("@type").equals("setTpSrc")) + Assert.assertTrue(act.getInt("port") == 4201); + if (act.getString("@type").equals("setTpDst")) + Assert.assertTrue(act.getInt("port") == 8080); + } catch (Exception e) { + Assert.assertTrue(false); + } + } + // Configure the OSGi container @Configuration public Option[] config() { diff --git a/opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/Activator.java b/opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/Activator.java index ff44fd4467..9c47b3b983 100644 --- a/opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/Activator.java +++ b/opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/Activator.java @@ -7,6 +7,7 @@ import org.apache.felix.dm.Component; import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase; import org.opendaylight.controller.sal.core.IContainerListener; +import org.opendaylight.controller.sal.utils.INodeFactory; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.discovery.IDiscoveryService; @@ -103,7 +104,7 @@ public class Activator extends ComponentActivatorAbstractBase { } public Object[] getGlobalImplementations() { - Object[] res = { FlowProgrammerService.class }; + Object[] res = { FlowProgrammerService.class, StubNodeFactory.class }; return res; } @@ -116,5 +117,14 @@ public class Activator extends ComponentActivatorAbstractBase { props.put("protocolPluginType", "STUB"); c.setInterface(IPluginInFlowProgrammerService.class.getName(), props); } + if (imp.equals(StubNodeFactory.class)) { + // export the service to be used by SAL + Dictionary props = new Hashtable(); + // Set the protocolPluginType property which will be used + // by SAL + props.put("protocolPluginType", "STUB"); + props.put("protocolName", "STUB"); + c.setInterface(INodeFactory.class.getName(), props); + } } } diff --git a/opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/StubNodeFactory.java b/opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/StubNodeFactory.java new file mode 100644 index 0000000000..c2ce473303 --- /dev/null +++ b/opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/StubNodeFactory.java @@ -0,0 +1,48 @@ +package org.opendaylight.controller.protocol_plugins.stub.internal; + +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.utils.INodeFactory; +import org.opendaylight.controller.sal.core.Node; + +public class StubNodeFactory implements INodeFactory + { + void init() { + } + + /** + * Function called by the dependency manager when at least one dependency + * become unsatisfied or when the component is shutting down because for + * example bundle is being stopped. + * + */ + void destroy() { + } + + /** + * Function called by dependency manager after "init ()" is called and after + * the services provided by the class are registered in the service registry + * + */ + void start() { + } + + /** + * Function called by the dependency manager before the services exported by + * the component are unregistered, this will be followed by a "destroy ()" + * calls + * + */ + void stop() { + } + + public Node fromString(String nodeId, String nodeType){ + if(nodeType.equals("STUB")) + try{ + return new Node("STUB", Integer.parseInt(nodeId)); + } catch(ConstructionException e) + { + return null; + } + return null; + } +} 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 ea9d93bdb6..4c7f278209 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 @@ -30,6 +30,8 @@ import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; import org.opendaylight.controller.sal.utils.HexEncode; +import org.opendaylight.controller.sal.utils.INodeFactory; +import org.opendaylight.controller.sal.utils.ServiceHelper; /** * Describe a generic network element in multiple SDNs technologies. A @@ -437,9 +439,13 @@ public class Node implements Serializable { return null; } } else { - // We need to lookup via OSGi service registry for an - // handler for this + //Use INodeFactory to create a Node of registered Node type. + //The protocol plugin being used depends on typeStr. + INodeFactory f = (INodeFactory) ServiceHelper + .getGlobalInstance(INodeFactory.class, new Node(), "(protocolName="+typeStr+")"); + if(f==null) + return null; + return f.fromString(IDStr, typeStr); } - return null; } } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/INodeFactory.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/INodeFactory.java new file mode 100644 index 0000000000..29ba7d6222 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/INodeFactory.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.utils; + +import org.opendaylight.controller.sal.core.Node; + +/** + * @file INodeFactory.java + * + * @brief Define the interface to be called when looking up custom node types + * + */ + +public interface INodeFactory { + /** + * Method to get custom node types from protocol plugins + * + */ + public Node fromString(String nodeId, String nodeType); +}