<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<netconf.version>0.2.3-SNAPSHOT</netconf.version>
<mdsal.version>1.0-SNAPSHOT</mdsal.version>
<containermanager.version>0.5.1-SNAPSHOT</containermanager.version>
- <switchmanager.api.version>0.6.1-SNAPSHOT</switchmanager.api.version>
+ <switchmanager.api.version>0.7.0-SNAPSHOT</switchmanager.api.version>
<connectionmanager.version>0.1.1-SNAPSHOT</connectionmanager.version>
- <sal.version>0.6.0-SNAPSHOT</sal.version>
+ <sal.version>0.7.0-SNAPSHOT</sal.version>
<sal.networkconfiguration.version>0.0.2-SNAPSHOT</sal.networkconfiguration.version>
<sal.connection.version>0.1.1-SNAPSHOT</sal.connection.version>
<networkconfig.bridgedomain.northbound.version>0.0.2-SNAPSHOT</networkconfig.bridgedomain.northbound.version>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
netconf.tcp.address=0.0.0.0
netconf.tcp.port=8383
+netconf.tcp.client.address=127.0.0.1
+netconf.tcp.client.port=8383
+
netconf.ssh.address=0.0.0.0
netconf.ssh.port=1830
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.opendaylight.controller.sal.action.ActionType;
import org.opendaylight.controller.sal.action.Controller;
import org.opendaylight.controller.sal.action.Drop;
+import org.opendaylight.controller.sal.action.Enqueue;
import org.opendaylight.controller.sal.action.Flood;
import org.opendaylight.controller.sal.action.HwPath;
import org.opendaylight.controller.sal.action.Loopback;
return true;
}
- public boolean isPortValid(Switch sw, Short port) {
- if (port < 1) {
- log.debug("port {} is not valid", port);
- return false;
- }
-
+ public boolean isPortValid(Switch sw, String port) {
if (sw == null) {
log.debug("switch info is not available. Skip checking if port is part of a switch or not.");
return true;
}
-
- Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
- for (NodeConnector nodeConnector : nodeConnectorSet) {
- if (((Short) nodeConnector.getID()).equals(port)) {
- return true;
- }
- }
- log.debug("port {} is not a valid port of node {}", port, sw.getNode());
- return false;
+ NodeConnector nc = NodeConnectorCreator.createNodeConnector(port, sw.getNode());
+ return sw.getNodeConnectors().contains(nc);
}
public boolean isVlanIdValid(String vlanId) {
}
if (ingressPort != null) {
- Short port = Short.decode(ingressPort);
- if (isPortValid(sw, port) == false) {
- String msg = String.format("Ingress port %d is not valid for the Switch", port);
+ if (!isPortValid(sw, ingressPort)) {
+ String msg = String.format("Ingress port %s is not valid for the Switch", ingressPort);
if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
msg += " in Container " + containerName;
}
if (sstr.matches()) {
for (String t : sstr.group(1).split(",")) {
Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
+ if (n.matches()) {
+ String port = n.group(1);
+ if (port != null) {
+ if (!isPortValid(sw, port)) {
+ String msg = String.format("Output port %s is not valid for this switch", port);
+ if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
+ msg += " in Container " + containerName;
+ }
+ return new Status(StatusCode.BADREQUEST, msg);
+ }
+ }
+ } else {
+ String msg = String.format("Output port %s is not valid", t);
+ return new Status(StatusCode.BADREQUEST, msg);
+ }
+ }
+ continue;
+ }
+ // check enqueue
+ sstr = Pattern.compile("ENQUEUE=(.*)").matcher(actiongrp);
+ if (sstr.matches()) {
+ for (String t : sstr.group(1).split(",")) {
+ Matcher n = Pattern.compile("(?:(\\d+:\\d+))").matcher(t);
if (n.matches()) {
if (n.group(1) != null) {
- Short port = Short.parseShort(n.group(1));
- if (isPortValid(sw, port) == false) {
+ String port = n.group(1).split(":")[0];
+ if (!isPortValid(sw, port)) {
String msg = String.format("Output port %d is not valid for this switch", port);
if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
msg += " in Container " + containerName;
}
}
} else {
- String msg = String.format("Output port %s is not valid", t);
+ String msg = String.format("Enqueue port %s is not valid", t);
return new Status(StatusCode.BADREQUEST, msg);
}
}
if (this.ingressPort != null) {
match.setField(MatchType.IN_PORT,
- NodeConnectorCreator.createOFNodeConnector(Short.parseShort(ingressPort), getNode()));
+ NodeConnector.fromString(String.format("%s|%s@%s", node.getType(), ingressPort, node.toString())));
}
if (this.dlSrc != null) {
match.setField(MatchType.DL_SRC, HexEncode.bytesFromHexString(this.dlSrc));
Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
if (n.matches()) {
if (n.group(1) != null) {
- short ofPort = Short.parseShort(n.group(1));
- actionList.add(new Output(NodeConnectorCreator.createOFNodeConnector(ofPort,
- this.getNode())));
+ String nc = String.format("%s|%s@%s", node.getType(), n.group(1), node.toString());
+ actionList.add(new Output(NodeConnector.fromString(nc)));
+ }
+ }
+ }
+ continue;
+ }
+
+ sstr = Pattern.compile(ActionType.ENQUEUE + "=(.*)").matcher(actiongrp);
+ if (sstr.matches()) {
+ for (String t : sstr.group(1).split(",")) {
+ Matcher n = Pattern.compile("(?:(\\d+:\\d+))").matcher(t);
+ if (n.matches()) {
+ if (n.group(1) != null) {
+ String parts[] = n.group(1).split(":");
+ String nc = String.format("%s|%s@%s", node.getType(), parts[0], node.toString());
+ if (parts.length == 1) {
+ actionList.add(new Enqueue(NodeConnector.fromString(nc)));
+ } else {
+ actionList
+ .add(new Enqueue(NodeConnector.fromString(nc), Integer.parseInt(parts[1])));
+ }
}
}
}
fc.setCookie("100");
Assert.assertTrue(fc.validate(null).isSuccess());
- fc.setIngressPort("-1");
- status = fc.validate(null);
- Assert.assertFalse(status.isSuccess());
- Assert.assertTrue(status.getDescription().contains("is not valid for the Switch"));
-
fc.setIngressPort("100");
Assert.assertTrue(fc.validate(null).isSuccess());
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>switchmanager</artifactId>
- <version>0.6.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>switchmanager</artifactId>
- <version>0.6.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustered-datastore.integrationtest</artifactId>
<version>0.4.0-SNAPSHOT</version>
- <dependencies>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ <version>1.4.01</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-broker-impl</artifactId>
<version>1.0-SNAPSHOT</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>xml-apis</artifactId>
+ <groupId>xml-apis</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>reflections</artifactId>
+ <groupId>org.reflections</groupId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-netconf-connector</artifactId>
<version>${netconf.version}</version>
<scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <artifactId>xml-apis</artifactId>
+ <groupId>xml-apis</groupId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<module>sal-binding-broker</module>
<module>sal-binding-util</module>
+ <module>sal-binding-dom-it</module>
<!-- Samples -->
<module>samples</module>
<dependencyManagement>
<dependencies>
-
-
-
+ <dependency>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ <version>1.4.01</version>
+ </dependency>
<!-- YANG Tools Dependencies -->
<dependency>
</execution>
</executions>
</plugin>
+
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.9-RC1</version>
+ <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<groupId>org.eclipse.xtend</groupId>
<artifactId>org.eclipse.xtend.lib</artifactId>
</dependency>
- <dependency>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>org.eclipse.xtend.standalone</artifactId>
- <version>2.4.3</version>
- <scope>runtime</scope>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-config</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-service</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-management</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>test</scope>
- </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-impl</artifactId>
<version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-statistics</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.reflections</groupId>
- <artifactId>reflections</artifactId>
- <version>0.9.9-RC1</version>
- <scope>test</scope>
- </dependency>
</dependencies>
</project>
Map<Type, WeakReference<Class>> typeToClass = new ConcurrentHashMap<>();
@SuppressWarnings("rawtypes")
- private ConcurrentMap<Type, ChoiceCaseCodecImpl> typeToCaseNodes = new ConcurrentHashMap<>();
+ private ConcurrentMap<Type, ChoiceCaseCodecImpl> typeToCaseCodecs = new ConcurrentHashMap<>();
private CaseClassMapFacade classToCaseRawCodec = new CaseClassMapFacade();
}
return weakRef.get();
}
-
+
@Override
- public void putPathToClass(List<QName> names,Class<?> cls) {
+ public void putPathToClass(List<QName> names, Class<?> cls) {
Type reference = Types.typeForClass(cls);
- pathToInstantiatedType.put(names, reference );
+ pathToInstantiatedType.put(names, reference);
bindingClassEncountered(cls);
}
-
@Override
public IdentifierCodec<?> getKeyCodecForPath(List<QName> names) {
@SuppressWarnings("unchecked")
return potential;
}
ConcreteType typeref = Types.typeForClass(caseClass);
- ChoiceCaseCodecImpl caseCodec = typeToCaseNodes.get(typeref);
+ ChoiceCaseCodecImpl caseCodec = typeToCaseCodecs.get(typeref);
+ checkState(caseCodec != null, "Case Codec was not created proactivelly for %s", caseClass.getName());
+ checkState(caseCodec.getSchema() != null, "Case schema is not available for %s", caseClass.getName());
@SuppressWarnings("unchecked")
- Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseCodec.schema);
+ Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseCodec.getSchema());
BindingCodec newInstance = newInstanceOf(newCodec);
caseCodec.setDelegate(newInstance);
caseCodecs.put(caseClass, caseCodec);
for (Entry<SchemaPath, GeneratedTypeBuilder> caseNode : cases.entrySet()) {
ReferencedTypeImpl typeref = new ReferencedTypeImpl(caseNode.getValue().getPackageName(), caseNode
.getValue().getName());
+
+ LOG.info("Case path: {} Type : {}", caseNode.getKey(), caseNode.getValue().getFullyQualifiedName());
+ pathToType.put(caseNode.getKey(), caseNode.getValue());
+
ChoiceCaseNode node = (ChoiceCaseNode) SchemaContextUtil.findDataSchemaNode(module, caseNode.getKey());
+
if (node == null) {
LOG.error("YANGTools Bug: SchemaNode for {}, with path {} was not found in context.",
typeref.getFullyQualifiedName(), caseNode.getKey());
+ @SuppressWarnings("rawtypes")
+ ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl();
+ typeToCaseCodecs.putIfAbsent(typeref, value);
continue;
}
-
- pathToType.put(caseNode.getKey(), caseNode.getValue());
@SuppressWarnings("rawtypes")
ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl(node);
- typeToCaseNodes.putIfAbsent(typeref, value);
+ typeToCaseCodecs.putIfAbsent(typeref, value);
}
}
choiceCodecs.put(choiceClass, newCodec);
CodecMapping.setClassToCaseMap(choiceCodec, (Map<Class<?>, BindingCodec<?, ?>>) classToCaseRawCodec);
CodecMapping.setCompositeNodeToCaseMap(choiceCodec, newCodec.getCompositeToCase());
-
+
tryToCreateCasesCodecs(schema);
}
private void tryToCreateCasesCodecs(ChoiceNode schema) {
- for(ChoiceCaseNode caseNode : schema.getCases()) {
+ for (ChoiceCaseNode caseNode : schema.getCases()) {
SchemaPath path = caseNode.getPath();
GeneratedTypeBuilder type;
- if(path != null && (type = pathToType.get(path)) != null) {
+ if (path != null && (type = pathToType.get(path)) != null) {
+ ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
+ ChoiceCaseCodecImpl partialCodec = typeToCaseCodecs.get(typeref);
+ if(partialCodec.getSchema() == null ) {
+ partialCodec.setSchema(caseNode);
+ }
+
Class<?> caseClass = ClassLoaderUtils.tryToLoadClassWithTCCL(type.getFullyQualifiedName());
- if(caseClass != null) {
+ if (caseClass != null) {
getCaseCodecFor(caseClass);
}
}
}
@Override
- public void onDataContainerCodecCreated(Class<?> dataClass,
- Class<? extends BindingCodec<?,?>> dataCodec) {
+ public void onDataContainerCodecCreated(Class<?> dataClass, Class<? extends BindingCodec<?, ?>> dataCodec) {
if (Augmentable.class.isAssignableFrom(dataClass)) {
AugmentableCompositeCodec augmentableCodec = getAugmentableCodec(dataClass);
CodecMapping.setAugmentationCodec(dataCodec, augmentableCodec);
@SuppressWarnings("rawtypes")
private static class ChoiceCaseCodecImpl<T extends DataContainer> implements ChoiceCaseCodec<T>, //
Delegator<BindingCodec> {
- private final boolean augmenting;
+ private boolean augmenting;
private BindingCodec delegate;
- private final Set<String> validNames;
- private final Set<QName> validQNames;
+ private Set<String> validNames;
+ private Set<QName> validQNames;
private ChoiceCaseNode schema;
- public ChoiceCaseCodecImpl(ChoiceCaseNode caseNode) {
- this.delegate = NOT_READY_CODEC;
+ public void setSchema(ChoiceCaseNode caseNode) {
+ this.schema = schema;
this.schema = caseNode;
validNames = new HashSet<>();
validQNames = new HashSet<>();
augmenting = caseNode.isAugmenting();
}
+ public ChoiceCaseCodecImpl() {
+ this.delegate = NOT_READY_CODEC;
+ }
+
+ public ChoiceCaseCodecImpl(ChoiceCaseNode caseNode) {
+ this.delegate = NOT_READY_CODEC;
+ setSchema(caseNode);
+ }
+
@Override
public ValueWithQName<T> deserialize(Node<?> input) {
throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
for (entry : newBinding.moduleContexts.entrySet) {
registry.onModuleContextAdded(schemaContext, entry.key, entry.value);
-
+ binding.pathToType.putAll(entry.value.childNodes)
//val module = entry.key;
val context = entry.value;
updateBindingFor(context.childNodes, schemaContext);
}
private def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> map, SchemaContext module) {
+
for (entry : map.entrySet) {
val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key);
//LOG.info("{} : {}",entry.key,entry.value.fullyQualifiedName)
+ val typeRef = new ReferencedTypeImpl(entry.value.packageName,entry.value.name)
+ typeToDefinition.put(typeRef, entry.value);
if (schemaNode != null) {
- val typeRef = new ReferencedTypeImpl(entry.value.packageName,entry.value.name)
typeToSchemaNode.put(typeRef, schemaNode);
- typeToDefinition.put(typeRef, entry.value);
updatePromisedSchemas(typeRef, schemaNode);
}
+
}
}
import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl
import org.opendaylight.yangtools.yang.model.util.ExtendedType
import org.opendaylight.yangtools.yang.model.util.EnumerationType
+import static com.google.common.base.Preconditions.*
+import org.opendaylight.yangtools.yang.model.api.SchemaPath
class TransformerGenerator {
@Property
var Map<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
+ @Property
+ var Map<SchemaPath, GeneratedTypeBuilder> pathToType = new ConcurrentHashMap();
+
@Property
var Map<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
val ref = Types.typeForClass(inputType)
val node = typeToSchemaNode.get(ref)
val typeSpecBuilder = typeToDefinition.get(ref)
+ checkState(typeSpecBuilder !== null, "Could not find typedefinition for %s", inputType.name);
+ val typeSpec = typeSpecBuilder.toInstance();
+ val newret = generateTransformerFor(inputType, typeSpec, node);
+ listener.onClassProcessed(inputType);
+ return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ ]
+ }
+
+ def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType, DataSchemaNode node) {
+ return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+ val ret = getGeneratedClass(inputType)
+ if (ret !== null) {
+ listener.onClassProcessed(inputType);
+ return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ }
+ val ref = Types.typeForClass(inputType)
+ var typeSpecBuilder = typeToDefinition.get(ref)
+ if (typeSpecBuilder == null) {
+ typeSpecBuilder = pathToType.get(node.path);
+ }
+ checkState(typeSpecBuilder !== null, "Could not find TypeDefinition for %s, $s", inputType.name, node);
val typeSpec = typeSpecBuilder.toInstance();
val newret = generateTransformerFor(inputType, typeSpec, node);
listener.onClassProcessed(inputType);
keyTransformerFor(cls, type, node);
}
- private def serializer(Type type) {
+ private def serializer(Type type, DataSchemaNode node) {
val cls = loadClassWithTCCL(type.resolvedName);
-
- transformerFor(cls);
-
+ transformerFor(cls, node);
}
private def Class<?> getValueSerializer(GeneratedTransferObject type) {
]
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Object, Object>>
- listener?.onDataContainerCodecCreated(inputType,ret);
+ listener?.onDataContainerCodecCreated(inputType, ret);
log.info("DOM Codec for {} was generated {}", inputType, ret)
return ret;
} catch (Exception e) {
Object _listItem = _iterator.next();
_is_empty = false;
//System.out.println(" item" + _listItem);
- Object _value = «type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem);
+ Object _value = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».fromDomStatic(_localQName,_listItem);
//System.out.println(" value" + _value);
«propertyName».add(_value);
_hasNext = _iterator.hasNext();
if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
_is_empty = false;
java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
- «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
+ «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
}
'''
private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
- «type.resolvedName» «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_compositeNode);
+ «type.resolvedName» «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_compositeNode);
if(«propertyName» != null) {
_is_empty = false;
}
boolean _hasNext = _iterator.hasNext();
while(_hasNext) {
Object _listItem = _iterator.next();
- Object _domValue = «type.actualTypeArguments.get(0).serializer.resolvedName».toDomStatic(_resultName,_listItem);
+ Object _domValue = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».toDomStatic(_resultName,_listItem);
_childNodes.add(_domValue);
_hasNext = _iterator.hasNext();
}
String propertyName) '''
«type.resolvedName» «propertyName» = value.«propertyName»();
if(«propertyName» != null) {
- java.util.List domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
+ java.util.List domValue = «type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»);
_childNodes.addAll(domValue);
}
'''
String propertyName) '''
«type.resolvedName» «propertyName» = value.«propertyName»();
if(«propertyName» != null) {
- Object domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
+ Object domValue = «type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»);
_childNodes.add(domValue);
}
'''
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import com.google.common.base.Joiner;
import com.google.common.base.Optional;
public final class ClassLoaderUtils {
if ("byte[]".equals(name)) {
return byte[].class;
}
-
- return Thread.currentThread().getContextClassLoader().loadClass(name);
+ try {
+ return Thread.currentThread().getContextClassLoader().loadClass(name);
+ } catch (ClassNotFoundException e) {
+ String[] components = name.split("\\.");
+ String potentialOuter;
+ int length = components.length;
+ if (length > 2 && (potentialOuter = components[length - 2]) != null && Character.isUpperCase(potentialOuter.charAt(0))) {
+
+ String outerName = Joiner.on(".").join(Arrays.asList(components).subList(0, length - 1));
+ String innerName = outerName + "$" + components[length-1];
+ return Thread.currentThread().getContextClassLoader().loadClass(innerName);
+ } else {
+ throw e;
+ }
+ }
}
public static Class<?> tryToLoadClassWithTCCL(String fullyQualifiedName) {
try {
return loadClassWithTCCL(fullyQualifiedName);
} catch (ClassNotFoundException e) {
-
+
}
return null;
}
import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;
import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
+import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory;
+import org.opendaylight.controller.sal.binding.test.util.BindingTestContext;
import org.opendaylight.controller.sal.binding.dom.serializer.impl.RuntimeGeneratedMappingServiceImpl;
import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
import org.opendaylight.controller.sal.core.api.data.DataStore;
protected org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
protected DataProviderService baDataService;
-
- /**
- * Workaround for JUNIT sharing classloaders
- *
- */
- protected static final ClassPool POOL = new ClassPool();
-
- protected RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
protected BindingIndependentMappingService mappingService;
- protected DataBrokerImpl baDataImpl;
- protected org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
- protected ListeningExecutorService executor;
- protected BindingIndependentDataServiceConnector connectorServiceImpl;
- protected HashMapDataStore rawDataStore;
- protected SchemaAwareDataStoreAdapter schemaAwareDataStore;
private DataStoreStatsWrapper dataStoreStats;
-
protected DataStore dataStore;
+ protected BindingTestContext testContext;
@Before
public void setUp() {
- executor = MoreExecutors.sameThreadExecutor();
- baDataImpl = new DataBrokerImpl();
- baDataService = baDataImpl;
- baDataImpl.setExecutor(executor);
-
- biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
- biDataService = biDataImpl;
- biDataImpl.setExecutor(executor);
-
- rawDataStore = new HashMapDataStore();
- schemaAwareDataStore = new SchemaAwareDataStoreAdapter();
- schemaAwareDataStore.changeDelegate(rawDataStore);
- dataStoreStats = new DataStoreStatsWrapper(schemaAwareDataStore);
- dataStore = dataStoreStats;
-
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier treeRoot = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
- .builder().toInstance();
- biDataImpl.registerConfigurationReader(treeRoot, dataStore);
- biDataImpl.registerOperationalReader(treeRoot, dataStore);
- biDataImpl.registerCommitHandler(treeRoot, dataStore);
-
- mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
- mappingServiceImpl.setPool(POOL);
- mappingService = mappingServiceImpl;
- File pathname = new File("target/gen-classes-debug");
- // System.out.println("Generated classes are captured in " +
- // pathname.getAbsolutePath());
- mappingServiceImpl.start(null);
- // mappingServiceImpl.getBinding().setClassFileCapturePath(pathname);
-
- connectorServiceImpl = new BindingIndependentDataServiceConnector();
- connectorServiceImpl.setBaDataService(baDataService);
- connectorServiceImpl.setBiDataService(biDataService);
- connectorServiceImpl.setMappingService(mappingServiceImpl);
- connectorServiceImpl.start();
-
- String[] yangFiles = getModelFilenames();
- if (yangFiles != null && yangFiles.length > 0) {
- SchemaContext context = getContext(yangFiles);
- mappingServiceImpl.onGlobalContextUpdated(context);
- schemaAwareDataStore.onGlobalContextUpdated(context);
- }
+ ListeningExecutorService executor = MoreExecutors.sameThreadExecutor();
+ BindingBrokerTestFactory factory = new BindingBrokerTestFactory();
+ factory.setExecutor(executor);
+ factory.setStartWithParsedSchema(getStartWithSchema());
+ testContext = factory.getTestContext();
+ testContext.start();
+
+ baDataService = testContext.getBindingDataBroker();
+ biDataService = testContext.getDomDataBroker();
+ dataStore = testContext.getDomDataStore();
+ mappingService = testContext.getBindingToDomMappingService();
}
- protected String[] getModelFilenames() {
- return getAllModelFilenames();
- }
-
- public static String[] getAllModelFilenames() {
- Predicate<String> predicate = new Predicate<String>() {
- @Override
- public boolean apply(String input) {
- return input.endsWith(".yang");
- }
- };
- Reflections reflection = new Reflections("META-INF.yang", new ResourcesScanner());
- Set<String> result = reflection.getResources(predicate);
- return (String[]) result.toArray(new String[result.size()]);
- }
-
- public static SchemaContext getContext(String[] yangFiles) {
-
- ClassLoader loader = AbstractDataServiceTest.class.getClassLoader();
-
- List<InputStream> streams = new ArrayList<>();
- for (String string : yangFiles) {
- InputStream stream = loader.getResourceAsStream(string);
- streams.add(stream);
-
- }
- YangParserImpl parser = new YangParserImpl();
-
- Set<Module> modules = parser.parseYangModelsFromStreams(streams);
- return parser.resolveSchemaContext(modules);
+ protected boolean getStartWithSchema() {
+ return true;
}
@After
public void afterTest() {
- log.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
- dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(),
- dataStoreStats.getConfigurationReadAverageTime());
-
- log.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
- dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(),
- dataStoreStats.getOperationalReadAverageTime());
-
- log.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
- dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(),
- dataStoreStats.getRequestCommitAverageTime());
+ testContext.logDataStoreStatistics();
}
}
--- /dev/null
+package org.opendaylight.controller.sal.binding.test.util;
+
+import java.util.concurrent.ExecutorService;
+
+import javassist.ClassPool;
+
+import org.opendaylight.controller.sal.core.api.data.DataStore;
+import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper;
+import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+public class BindingBrokerTestFactory {
+
+ private static final ClassPool CLASS_POOL = new ClassPool();
+ private boolean startWithParsedSchema = true;
+ private ExecutorService executor;
+ private ClassPool classPool;
+
+
+ public boolean isStartWithParsedSchema() {
+ return startWithParsedSchema;
+ }
+
+ public void setStartWithParsedSchema(boolean startWithParsedSchema) {
+ this.startWithParsedSchema = startWithParsedSchema;
+ }
+
+ public ExecutorService getExecutor() {
+ return executor;
+ }
+
+ public void setExecutor(ExecutorService executor) {
+ this.executor = executor;
+ }
+
+
+ public BindingTestContext getTestContext() {
+ Preconditions.checkState(executor != null, "Executor is not set.");
+ ListeningExecutorService listenableExecutor = MoreExecutors.listeningDecorator(executor);
+ return new BindingTestContext(listenableExecutor, getClassPool(),startWithParsedSchema);
+ }
+
+ public ClassPool getClassPool() {
+ if(classPool == null) {
+ return CLASS_POOL;
+ }
+
+ return classPool;
+ }
+
+ public void setClassPool(ClassPool classPool) {
+ this.classPool = classPool;
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.test.util;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javassist.ClassPool;
+
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.dom.serializer.impl.RuntimeGeneratedMappingServiceImpl;
+import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.sal.core.api.data.DataStore;
+import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper;
+import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.reflections.Reflections;
+import org.reflections.scanners.ResourcesScanner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Predicate;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import static com.google.common.base.Preconditions.*;
+
+public class BindingTestContext {
+
+
+ public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier TREE_ROOT = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+ .builder().toInstance();
+
+ private static final Logger LOG = LoggerFactory.getLogger(BindingTestContext.class);
+
+ private RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
+ private DataBrokerImpl baDataImpl;
+ private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
+
+ private BindingIndependentDataServiceConnector connectorServiceImpl;
+ private HashMapDataStore rawDataStore;
+ private SchemaAwareDataStoreAdapter schemaAwareDataStore;
+ private DataStoreStatsWrapper dataStoreStats;
+ private DataStore dataStore;
+
+
+ private boolean dataStoreStatisticsEnabled = false;
+
+ private final ListeningExecutorService executor;
+ private final ClassPool classPool;
+
+ private final boolean startWithSchema;
+
+ protected BindingTestContext(ListeningExecutorService executor, ClassPool classPool, boolean startWithSchema) {
+ this.executor = executor;
+ this.classPool = classPool;
+ this.startWithSchema = startWithSchema;
+ }
+
+ public void startDomDataStore() {
+ checkState(dataStore == null, "DataStore already started.");
+ checkState(biDataImpl != null, "Dom Data Broker not present");
+ rawDataStore = new HashMapDataStore();
+ schemaAwareDataStore = new SchemaAwareDataStoreAdapter();
+ schemaAwareDataStore.changeDelegate(rawDataStore);
+ if(dataStoreStatisticsEnabled) {
+ dataStoreStats = new DataStoreStatsWrapper(schemaAwareDataStore);
+ dataStore = dataStoreStats;
+ } else {
+ dataStore = schemaAwareDataStore;
+ }
+
+ biDataImpl.registerConfigurationReader(TREE_ROOT, dataStore);
+ biDataImpl.registerOperationalReader(TREE_ROOT, dataStore);
+ biDataImpl.registerCommitHandler(TREE_ROOT, dataStore);
+ }
+
+ public void startDomDataBroker() {
+ checkState(executor != null,"Executor needs to be set");
+ biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
+ biDataImpl.setExecutor(executor);
+ }
+
+ public void startBindingDataBroker() {
+ checkState(executor != null,"Executor needs to be set");
+ baDataImpl = new DataBrokerImpl();
+ baDataImpl.setExecutor(executor);
+ }
+
+ public void startBindingToDomDataConnector() {
+ checkState(baDataImpl != null,"Binding Data Broker needs to be started");
+ checkState(biDataImpl != null,"DOM Data Broker needs to be started.");
+ checkState(mappingServiceImpl != null,"DOM Mapping Service needs to be started.");
+ connectorServiceImpl = new BindingIndependentDataServiceConnector();
+ connectorServiceImpl.setBaDataService(baDataImpl);
+ connectorServiceImpl.setBiDataService(biDataImpl);
+ connectorServiceImpl.setMappingService(mappingServiceImpl);
+ connectorServiceImpl.start();
+ }
+
+ public void startBindingToDomMappingService() {
+ checkState(classPool != null,"ClassPool needs to be present");
+ mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
+ mappingServiceImpl.setPool(classPool);
+ mappingServiceImpl.start(null);
+ }
+
+
+ public void updateYangSchema(String[] files) {
+ SchemaContext context = getContext(files);
+ if(schemaAwareDataStore != null) {
+ schemaAwareDataStore.onGlobalContextUpdated(context);
+ }
+ if(mappingServiceImpl != null) {
+ mappingServiceImpl.onGlobalContextUpdated(context);
+ }
+ }
+
+
+ public static String[] getAllYangFilesOnClasspath() {
+ Predicate<String> predicate = new Predicate<String>() {
+ @Override
+ public boolean apply(String input) {
+ return input.endsWith(".yang");
+ }
+ };
+ Reflections reflection = new Reflections("META-INF.yang", new ResourcesScanner());
+ Set<String> result = reflection.getResources(predicate);
+ return (String[]) result.toArray(new String[result.size()]);
+ }
+
+ private static SchemaContext getContext(String[] yangFiles) {
+ ClassLoader loader = BindingTestContext.class.getClassLoader();
+ List<InputStream> streams = new ArrayList<>();
+ for (String string : yangFiles) {
+ InputStream stream = loader.getResourceAsStream(string);
+ streams.add(stream);
+ }
+ YangParserImpl parser = new YangParserImpl();
+ Set<Module> modules = parser.parseYangModelsFromStreams(streams);
+ return parser.resolveSchemaContext(modules);
+ }
+
+ public void start() {
+ startBindingDataBroker();
+ startDomDataBroker();
+ startDomDataStore();
+ startBindingToDomMappingService();
+ startBindingToDomDataConnector();
+ if(startWithSchema) {
+ loadYangSchemaFromClasspath();
+ }
+ }
+
+ public void loadYangSchemaFromClasspath() {
+ String[] files = getAllYangFilesOnClasspath();
+ updateYangSchema(files);
+ }
+
+ public DataProviderService getBindingDataBroker() {
+ return baDataImpl;
+ }
+
+ public org.opendaylight.controller.sal.core.api.data.DataProviderService getDomDataBroker() {
+ return biDataImpl;
+ }
+
+ public DataStore getDomDataStore() {
+ return dataStore;
+ }
+
+ public BindingIndependentMappingService getBindingToDomMappingService() {
+ return mappingServiceImpl;
+ }
+
+ public void logDataStoreStatistics() {
+ if(dataStoreStats == null) {
+ return;
+ }
+
+ LOG.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
+ dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(),
+ dataStoreStats.getConfigurationReadAverageTime());
+
+ LOG.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
+ dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(),
+ dataStoreStats.getOperationalReadAverageTime());
+
+ LOG.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
+ dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(),
+ dataStoreStats.getRequestCommitAverageTime());
+ }
+}
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>sal-binding-dom-it</artifactId>
+ <packaging>bundle</packaging>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+ </scm>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>xtend-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <configuration>
+ <includes>org.opendaylight.controller.*</includes>
+ </configuration>
+ <executions>
+ <execution>
+ <id>pre-test</id>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>post-test</id>
+ <phase>test</phase>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-management</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ </dependencies>
+</project>
.toInstance();
private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
- @Override
- protected String[] getModelFilenames() {
- return null;
- }
-
/**
*
*
}
});
- SchemaContext ctx = getContext(getAllModelFilenames());
- schemaAwareDataStore.onGlobalContextUpdated(ctx);
- mappingServiceImpl.onGlobalContextUpdated(ctx);
+ testContext.loadYangSchemaFromClasspath();
RpcResult<TransactionStatus> result = future.get().get();
assertEquals(TransactionStatus.COMMITED, result.getResult());
return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA);
}
+
+ @Override
+ protected boolean getStartWithSchema() {
+ return false;
+ }
}
</pluginManagement>
</build>
+
<dependencies>
<dependency>
<groupId>org.opendaylight.yangtools.thirdparty</groupId>
systemProperty("netconf.tcp.address").value("0.0.0.0"), //
systemProperty("netconf.tcp.port").value("18383"), //
+ systemProperty("netconf.tcp.client.address").value("127.0.0.1"), //
+ systemProperty("netconf.tcp.client.port").value("18383"), //
systemProperty("netconf.config.persister.active").value("1"), //
systemProperty("netconf.config.persister.1.storageAdapterClass").value(
"org.opendaylight.controller.config.persist.storage.file.FileStorageAdapter"), //
}\r
\r
override readConfigurationData(P path) {\r
+ val local = this.updatedConfigurationData.get(path);\r
+ if(local != null) {\r
+ return local;\r
+ }\r
+ \r
return broker.readConfigurationData(path);\r
}\r
\r
override readOperationalData(P path) {\r
+ val local = this.updatedOperationalData.get(path);\r
+ if(local != null) {\r
+ return local;\r
+ }\r
return broker.readOperationalData(path);\r
}\r
\r
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-impl</artifactId>
<version>${yang.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-model-util</artifactId>
+ <version>${yang.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
import java.util.Set;
import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
import com.google.common.collect.Lists;
}
} else if (childType.isJsonArray()) {
if (childType.getAsJsonArray().size() == 1 && childType.getAsJsonArray().get(0).isJsonNull()) {
- parent.addValue(new SimpleNodeWrapper(getNamespaceFrom(childName), getLocalNameFrom(childName), null));
+ parent.addValue(new EmptyNodeWrapper(getNamespaceFrom(childName), getLocalNameFrom(childName)));
} else {
for (JsonElement childOfChildType : childType.getAsJsonArray()) {
import org.opendaylight.controller.sal.restconf.impl.ResponseException;
import org.opendaylight.controller.sal.restconf.impl.StructuredData;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.impl.NodeUtils;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
if (data == null) {
throw new ResponseException(Response.Status.NOT_FOUND, "No data exists.");
}
-
- Document domTree = NodeUtils.buildShadowDomTree(data);
+
+ XmlMapper xmlMapper = new XmlMapper();
+ Document domTree = xmlMapper.write(data, (DataNodeContainer) t.getSchema());
try {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
--- /dev/null
+package org.opendaylight.controller.sal.rest.impl;
+
+import java.util.Set;
+
+import javax.activation.UnsupportedDataTypeException;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.YangNode;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+
+public class XmlMapper {
+
+ public Document write(CompositeNode data, DataNodeContainer schema) throws UnsupportedDataTypeException {
+ Preconditions.checkNotNull(data);
+ Preconditions.checkNotNull(schema);
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ Document doc = null;
+ try {
+ DocumentBuilder bob = dbf.newDocumentBuilder();
+ doc = bob.newDocument();
+ } catch (ParserConfigurationException e) {
+ return null;
+ }
+
+ if (schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode) {
+ doc.appendChild(translateToXmlAndReturnRootElement(doc, data, schema));
+ return doc;
+ } else {
+ throw new UnsupportedDataTypeException(
+ "Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
+ }
+ }
+
+ private Element translateToXmlAndReturnRootElement(Document doc, Node<?> data, YangNode schema)
+ throws UnsupportedDataTypeException {
+ QName dataType = data.getNodeType();
+ Element itemEl = doc.createElementNS(dataType.getNamespace().toString(), dataType.getLocalName());
+
+ if (data instanceof SimpleNode<?>) {
+ if (schema instanceof LeafListSchemaNode) {
+ writeValueOfNodeByType(itemEl, (SimpleNode<?>) data, ((LeafListSchemaNode) schema).getType());
+ } else if (schema instanceof LeafSchemaNode) {
+ writeValueOfNodeByType(itemEl, (SimpleNode<?>) data, ((LeafSchemaNode) schema).getType());
+ } else {
+ Object value = data.getValue();
+ if (value != null) {
+ itemEl.setTextContent(String.valueOf(value));
+ }
+ }
+ } else { // CompositeNode
+ for (Node<?> child : ((CompositeNode) data).getChildren()) {
+ DataSchemaNode childSchema = findFirstSchemaForNode(child, ((DataNodeContainer) schema).getChildNodes());
+ if (childSchema == null) {
+ throw new UnsupportedDataTypeException("Probably the data node \""
+ + child.getNodeType().getLocalName() + "\" is not conform to schema");
+ }
+ itemEl.appendChild(translateToXmlAndReturnRootElement(doc, child, childSchema));
+ }
+ }
+ return itemEl;
+ }
+
+ private void writeValueOfNodeByType(Element element, SimpleNode<?> node, TypeDefinition<?> type) {
+
+ TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
+
+ if (baseType instanceof IdentityrefTypeDefinition && node.getValue() instanceof QName) {
+ QName value = (QName) node.getValue();
+ element.setAttribute("xmlns:x", value.getNamespace().toString());
+ element.setTextContent("x:" + value.getLocalName());
+ } else {
+ Object value = node.getValue();
+ if (value != null) {
+ element.setTextContent(String.valueOf(value));
+ }
+ }
+ }
+
+ private DataSchemaNode findFirstSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
+ for (DataSchemaNode dsn : dataSchemaNode) {
+ if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
+ return dsn;
+ } else if (dsn instanceof ChoiceNode) {
+ for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) {
+ DataSchemaNode foundDsn = findFirstSchemaForNode(node, choiceCase.getChildNodes());
+ if (foundDsn != null) {
+ return foundDsn;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private TypeDefinition<?> resolveBaseTypeFrom(TypeDefinition<?> type) {
+ return type.getBaseType() != null ? resolveBaseTypeFrom(type.getBaseType()) : type;
+ }
+
+}
import javax.xml.stream.events.XMLEvent;
import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
+import org.opendaylight.yangtools.yang.data.api.Node;
public class XmlReader {
return false;
}
- private SimpleNodeWrapper resolveSimpleNodeFromStartElement(final StartElement startElement)
+ private NodeWrapper<? extends Node<?>> resolveSimpleNodeFromStartElement(final StartElement startElement)
throws XMLStreamException {
checkArgument(startElement != null, "Start Element cannot be NULL!");
String data = null;
}
}
}
-
+ if(data == null) {
+ return new EmptyNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement));
+ }
return new SimpleNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement), data);
}
public Set<java.util.Map.Entry<QName, List<Node<?>>>> entrySet() {
return unwrap().entrySet();
}
-
}
import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil
import static com.google.common.base.Preconditions.*
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec
class ControllerContext implements SchemaServiceListener {
private def void addKeyValue(HashMap<QName, Object> map, DataSchemaNode node, String uriValue) {
checkNotNull(uriValue);
checkArgument(node instanceof LeafSchemaNode);
- val decoded = URLDecoder.decode(uriValue);
+ val urlDecoded = URLDecoder.decode(uriValue);
+ val typedef = (node as LeafSchemaNode).type;
+ val decoded = TypeDefinitionAwareCodec.from(typedef)?.deserialize(urlDecoded)
map.put(node.QName, decoded);
-
}
private def String toModuleName(String str) {
--- /dev/null
+package org.opendaylight.controller.sal.restconf.impl;
+
+import java.net.URI;
+import java.util.Collections;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
+import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+
+import com.google.common.base.Preconditions;
+
+public final class EmptyNodeWrapper implements NodeWrapper<Node<?>>, Node<Void> {
+
+ private Node<?> unwrapped;
+
+ private String localName;
+ private URI namespace;
+ private QName name;
+
+ private boolean composite;
+
+ public boolean isComposite() {
+ return composite;
+ }
+
+ public void setComposite(boolean composite) {
+ this.composite = composite;
+ }
+
+ public EmptyNodeWrapper(URI namespace, String localName) {
+ this.localName = Preconditions.checkNotNull(localName);
+ this.namespace = namespace;
+ }
+
+ @Override
+ public void setQname(QName name) {
+ Preconditions.checkState(unwrapped == null, "Cannot change the object, due to data inconsistencies.");
+ this.name = name;
+ }
+
+ @Override
+ public String getLocalName() {
+ if (unwrapped != null) {
+ return unwrapped.getNodeType().getLocalName();
+ }
+ return localName;
+ }
+
+ @Override
+ public URI getNamespace() {
+ if (unwrapped != null) {
+ return unwrapped.getNodeType().getNamespace();
+ }
+ return namespace;
+ }
+
+ @Override
+ public void setNamespace(URI namespace) {
+ Preconditions.checkState(unwrapped == null, "Cannot change the object, due to data inconsistencies.");
+ this.namespace = namespace;
+ }
+
+ @Override
+ public Node<?> unwrap() {
+ if (unwrapped == null) {
+ if (name == null) {
+ Preconditions.checkNotNull(namespace);
+ name = new QName(namespace, localName);
+ }
+ if(composite) {
+ unwrapped = NodeFactory.createImmutableCompositeNode(name, null, Collections.<Node<?>>emptyList(),null);
+ } else {
+ unwrapped = NodeFactory.createImmutableSimpleNode(name, null, null);
+ }
+ namespace = null;
+ localName = null;
+ name = null;
+ }
+ return unwrapped;
+ }
+
+ @Override
+ public QName getNodeType() {
+ return unwrap().getNodeType();
+ }
+
+ @Override
+ public CompositeNode getParent() {
+ return unwrap().getParent();
+ }
+
+ @Override
+ public Void getValue() {
+ return null;
+ }
+
+ @Override
+ public QName getKey() {
+ return unwrap().getKey();
+ }
+
+ @Override
+ public Void setValue(Void value) {
+ return null;
+ }
+
+}
import org.opendaylight.yangtools.yang.model.api.ChoiceNode
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
class RestconfImpl implements RestconfService {
override createConfigurationData(String identifier, CompositeNode payload) {
val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
- val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
+ val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode)
val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
switch status.result {
case TransactionStatus.COMMITED: Response.status(Response.Status.OK).build
override updateConfigurationData(String identifier, CompositeNode payload) {
val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
- val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
+ val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode)
val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
switch status.result {
case TransactionStatus.COMMITED: Response.status(Response.Status.NO_CONTENT).build
if (rpc === null) {
throw new ResponseException(Response.Status.NOT_FOUND, "RPC does not exist.");
}
- val value = resolveNodeNamespaceBySchema(payload, rpc.input)
+ val value = normalizeNode(payload, rpc.input)
val List<Node<?>> input = new ArrayList
input.add(value)
val rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, input, null, null)
return identifierWithSchemaNode
}
- private def CompositeNode resolveNodeNamespaceBySchema(CompositeNode node, DataSchemaNode schema) {
+ private def CompositeNode normalizeNode(CompositeNode node, DataSchemaNode schema) {
if (node instanceof CompositeNodeWrapper) {
- addNamespaceToNodeFromSchemaRecursively(node as CompositeNodeWrapper, schema)
+ normalizeNode(node as CompositeNodeWrapper, schema,null)
return (node as CompositeNodeWrapper).unwrap()
}
return node
}
- private def void addNamespaceToNodeFromSchemaRecursively(NodeWrapper<?> nodeBuilder, DataSchemaNode schema) {
+ private def void normalizeNode(NodeWrapper<?> nodeBuilder, DataSchemaNode schema,QName previousAugment) {
if (schema === null) {
throw new ResponseException(Response.Status.BAD_REQUEST,
"Data has bad format\n" + nodeBuilder.localName + " does not exist in yang schema.");
}
- val moduleName = controllerContext.findModuleByNamespace(schema.QName.namespace);
- if (nodeBuilder.namespace === null || nodeBuilder.namespace == schema.QName.namespace ||
+ var validQName = schema.QName
+ var currentAugment = previousAugment;
+ if(schema.augmenting) {
+ currentAugment = schema.QName
+ } else if(previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) {
+ validQName = QName.create(currentAugment,schema.QName.localName);
+ }
+ val moduleName = controllerContext.findModuleByNamespace(validQName.namespace);
+ if (nodeBuilder.namespace === null || nodeBuilder.namespace == validQName.namespace ||
nodeBuilder.namespace.path == moduleName) {
- nodeBuilder.qname = schema.QName
+ nodeBuilder.qname = validQName
} else {
throw new ResponseException(Response.Status.BAD_REQUEST,
"Data has bad format\nIf data is in XML format then namespace for " + nodeBuilder.localName +
" should be " + schema.QName.namespace + ".\n If data is in Json format then module name for " +
nodeBuilder.localName + " should be " + moduleName + ".");
}
+
if (nodeBuilder instanceof CompositeNodeWrapper) {
val List<NodeWrapper<?>> children = (nodeBuilder as CompositeNodeWrapper).getValues
for (child : children) {
- addNamespaceToNodeFromSchemaRecursively(child,
- findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes))
+ normalizeNode(child,
+ findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes),currentAugment)
+ }
+ } else if (nodeBuilder instanceof SimpleNodeWrapper) {
+ val simpleNode = (nodeBuilder as SimpleNodeWrapper)
+ val stringValue = simpleNode.value as String;
+
+ val objectValue = TypeDefinitionAwareCodec.from(schema.typeDefinition)?.deserialize(stringValue);
+ simpleNode.setValue(objectValue)
+ } else if (nodeBuilder instanceof EmptyNodeWrapper) {
+ val emptyNodeBuilder = nodeBuilder as EmptyNodeWrapper
+ if(schema instanceof LeafSchemaNode) {
+ emptyNodeBuilder.setComposite(false);
+ } else if(schema instanceof ContainerSchemaNode) {
+ // FIXME: Add presence check
+ emptyNodeBuilder.setComposite(true);
}
}
}
+ private def dispatch TypeDefinition<?> typeDefinition(LeafSchemaNode node) {
+ node.type
+ }
+
+ private def dispatch TypeDefinition<?> typeDefinition(LeafListSchemaNode node) {
+ node.type
+ }
+
+
private def DataSchemaNode findFirstSchemaByLocalName(String localName, Set<DataSchemaNode> schemas) {
for (schema : schemas) {
if (schema instanceof ChoiceNode) {
}
}
} else {
- return schemas.findFirst[n|n.QName.localName.equals(localName)]
+ val result = schemas.findFirst[n|n.QName.localName.equals(localName)]
+ if(result !== null) {
+ return result;
+
+ }
}
}
return null
import com.google.common.base.Preconditions;
-public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, SimpleNode<String> {
+public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, SimpleNode<Object> {
- private SimpleNode<String> simpleNode;
+ private SimpleNode<?> simpleNode;
private String localName;
- private String value;
+ private Object value;
private URI namespace;
private QName name;
- public SimpleNodeWrapper(String localName, String value) {
+ public SimpleNodeWrapper(String localName, Object value) {
this.localName = Preconditions.checkNotNull(localName);
this.value = value;
}
}
@Override
- public SimpleNode<String> unwrap() {
+ public SimpleNode<Object> unwrap() {
if (simpleNode == null) {
if (name == null) {
Preconditions.checkNotNull(namespace);
localName = null;
name = null;
}
- return simpleNode;
+ return (SimpleNode<Object>) simpleNode;
}
@Override
}
@Override
- public String getValue() {
+ public Object getValue() {
return unwrap().getValue();
}
}
@Override
- public MutableSimpleNode<String> asMutable() {
+ public MutableSimpleNode<Object> asMutable() {
return unwrap().asMutable();
}
}
@Override
- public String setValue(String value) {
+ public Object setValue(Object value) {
return unwrap().setValue(value);
}
+
}
SimpleNode<?> cont11_lf111 = (SimpleNode<?>) cont11.getChildren().get(0);
assertEquals(nameSpaceCont, cont11_lf111.getNodeType().getNamespace().toString());
assertEquals("lf111", cont11_lf111.getNodeType().getLocalName());
- assertEquals("100", cont11_lf111.getValue());
+ assertEquals((short) 100, cont11_lf111.getValue());
// :lst1_2
}
SimpleNode<?> cont1_lf11 = (SimpleNode<?>) cont1suf.getChildren().get(0);
assertEquals(nameSpace, cont1_lf11.getNodeType().getNamespace().toString());
assertEquals("lf11" + suf, cont1_lf11.getNodeType().getLocalName());
- assertEquals("100", cont1_lf11.getValue());
+ assertEquals((short) 100, cont1_lf11.getValue());
}
private CompositeNode compositeContainerFromXml(String xmlPath, boolean dummyNamespaces) {
--- /dev/null
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.net.*;
+import java.util.*;
+
+import org.junit.*;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.sal.restconf.impl.*;
+import org.opendaylight.yangtools.yang.common.*;
+import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.opendaylight.yangtools.yang.model.api.Module;
+
+public class InvokeRpcMethodTest {
+
+ private static Set<Module> modules;
+
+ private class RpcResultImpl<T> implements RpcResult<T> {
+
+ final T result;
+
+ public RpcResultImpl(T compNode) {
+ this.result = compNode;
+ }
+
+ @Override
+ public boolean isSuccessful() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public T getResult() {
+ return result;
+ }
+
+ @Override
+ public Collection<RpcError> getErrors() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ }
+
+ private class AnswerImpl implements Answer<RpcResult<CompositeNode>> {
+ @Override
+ public RpcResult<CompositeNode> answer(InvocationOnMock invocation) throws Throwable {
+ CompositeNode compNode = (CompositeNode) invocation.getArguments()[1];
+ return new RpcResultImpl<CompositeNode>(compNode);
+ }
+ }
+
+ @BeforeClass
+ public static void initialization() {
+ modules = TestUtils.resolveModules("/invoke-rpc");
+ assertEquals(1, modules.size());
+ Module module = TestUtils.resolveModule("invoke-rpc-module", modules);
+ assertNotNull(module);
+ }
+
+ /**
+ * Test method invokeRpc in RestconfImpl class tests if composite node as
+ * input parameter of method invokeRpc (second argument) is wrapped to
+ * parent composite node which has QName equals to QName of rpc (resolved
+ * from string - first argument).
+ */
+ @Test
+ public void invokeRpcMethodTest() {
+ ControllerContext contContext = ControllerContext.getInstance();
+ contContext.onGlobalContextUpdated(TestUtils.loadSchemaContext(modules));
+ try {
+ contContext.findModuleByNamespace(new URI("invoke:rpc:module"));
+ } catch (URISyntaxException e) {
+ assertTrue("Uri wasn't created sucessfuly", false);
+ }
+
+ BrokerFacade mockedBrokerFacade = mock(BrokerFacade.class);
+
+ RestconfImpl restconf = RestconfImpl.getInstance();
+ restconf.setBroker(mockedBrokerFacade);
+ restconf.setControllerContext(contContext);
+
+ when(mockedBrokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class))).thenAnswer(new AnswerImpl());
+
+ StructuredData structData = restconf.invokeRpc("invoke-rpc-module:rpc-test", preparePayload());
+
+ CompositeNode rpcCompNode = structData.getData();
+ CompositeNode cont = null;
+ assertEquals("invoke:rpc:module", rpcCompNode.getNodeType().getNamespace().toString());
+ assertEquals("rpc-test", rpcCompNode.getNodeType().getLocalName());
+
+ for (Node<?> node : rpcCompNode.getChildren()) {
+ if (node.getNodeType().getLocalName().equals("cont")
+ && node.getNodeType().getNamespace().toString().equals("nmspc")) {
+ if (node instanceof CompositeNode) {
+ cont = (CompositeNode) node;
+ }
+ }
+ }
+ assertNotNull(cont);
+
+ }
+
+ private CompositeNode preparePayload() {
+ MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(
+ TestUtils.buildQName("cont", "nmspc", "2013-12-04"), null, null, ModifyAction.CREATE, null);
+ MutableSimpleNode<?> lf = NodeFactory.createMutableSimpleNode(
+ TestUtils.buildQName("lf", "nmspc", "2013-12-04"), cont, "any value", ModifyAction.CREATE, null);
+ cont.getChildren().add(lf);
+ cont.init();
+
+ return cont;
+ }
+
+}
--- /dev/null
+module invoke-rpc-module {
+ namespace "invoke:rpc:module";
+
+ prefix "inrpcmod";
+
+ revision 2013-12-3 {
+
+ }
+
+ rpc rpc-test {
+ input {
+ container cont {
+ leaf lf {
+ type string;
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
return;
for (Node targetNode : targetNodes){
- spLogger.info("Send request for stats collection to node : {})",targetNode.getId());
+
//We need to add check, so see if groups/meters are supported
//by the target node. Below check doesn't look good.
if(targetNode.getId().getValue().contains("openflow:")){
+ spLogger.info("Send request for stats collection to node : {})",targetNode.getId());
InstanceIdentifier<Node> targetInstanceId = InstanceIdentifier.builder(Nodes.class).child(Node.class,targetNode.getKey()).toInstance();
NodeRef targetNodeRef = new NodeRef(targetInstanceId);
systemProperty("netconf.tcp.address").value("127.0.0.1"),
systemProperty("netconf.tcp.port").value("8383"),
+ systemProperty("netconf.tcp.client.address").value("127.0.0.1"),
+ systemProperty("netconf.tcp.client.port").value("8383"),
+
// Set the systemPackages (used by clustering)
systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
PersisterAggregator persister = PersisterAggregator.createFromProperties(propertiesProvider);
InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context,
- "Netconf is not configured, persister is not operational");
+ "Netconf is not configured, persister is not operational",true);
configPersisterNotificationHandler = new ConfigPersisterNotificationHandler(persister, address,
platformMBeanServer, ignoredMissingCapabilityRegex);
@Override
public void start(final BundleContext context) throws Exception {
- InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context, "TCP is not configured, netconf not available.");
+ InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context,
+ "TCP is not configured, netconf not available.", false);
NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
factoriesTracker = new NetconfOperationServiceFactoryTracker(context, factoriesListener);
logger.trace("Starting netconf SSH bridge.");
Optional<InetSocketAddress> sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context,EXCEPTION_MESSAGE);
- InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,EXCEPTION_MESSAGE);
+ InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,
+ EXCEPTION_MESSAGE, true);
if (sshSocketAddressOptional.isPresent()){
server = NetconfSSHServer.start(sshSocketAddressOptional.get().getPort(),tcpSocketAddress);
private String id;
private ServerSession servSession;
private ServerConnection servconnection;
+ private String customHeader;
public IOThread (InputStream is, OutputStream os, String id,ServerSession ss, ServerConnection conn){
super.setName(id);
logger.trace("IOThread {} created", super.getName());
}
+ public IOThread (InputStream is, OutputStream os, String id,ServerSession ss, ServerConnection conn,String header){
+ this.inputStream = is;
+ this.outputStream = os;
+ this.servSession = ss;
+ this.servconnection = conn;
+ this.customHeader = header;
+ super.setName(id);
+ logger.trace("IOThread {} created", super.getName());
+ }
@Override
public void run() {
logger.trace("thread {} started", super.getName());
try {
+ if (this.customHeader!=null && !this.customHeader.equals("")){
+ this.outputStream.write(this.customHeader.getBytes());
+ logger.trace("adding {} header", this.customHeader);
+ }
IOUtils.copy(this.inputStream, this.outputStream);
} catch (Exception e) {
logger.error("inputstream -> outputstream copy error ",e);
private static final Logger logger = LoggerFactory.getLogger(SocketThread.class);
private ServerConnection conn = null;
private long sessionId;
+ private String currentUser;
+ private final String remoteAddressWithPort;
public static void start(Socket socket, InetSocketAddress clientAddress, long sessionId) throws IOException{
this.socket = socket;
this.clientAddress = clientAddress;
this.sessionId = sessionId;
+ this.remoteAddressWithPort = socket.getRemoteSocketAddress().toString().replaceFirst("/","");
}
netconf_ssh_input.start();
logger.trace("starting netconf_ssh_output thread");
- netconf_ssh_output = new IOThread(ss.getStdout(),echoSocket.getOutputStream(),"output_thread_"+sessionId,ss,conn);
+ final String customHeader = "["+currentUser+";"+remoteAddressWithPort+";ssh;;;;;;]\n";
+ netconf_ssh_output = new IOThread(ss.getStdout(),echoSocket.getOutputStream(),"output_thread_"+sessionId,ss,conn,customHeader);
netconf_ssh_output.setDaemon(false);
netconf_ssh_output.start();
public String initAuthentication(ServerConnection sc)
{
- return "";
+ logger.trace("Established connection with host {}",remoteAddressWithPort);
+ return "Established connection with host "+remoteAddressWithPort+"\r\n";
}
public String[] getRemainingAuthMethods(ServerConnection sc)
public AuthenticationResult authenticateWithPassword(ServerConnection sc, String username, String password)
{
- if (USER.equals(username) && PASSWORD.equals(password))
+ if (USER.equals(username) && PASSWORD.equals(password)){
+ currentUser = username;
+ logger.trace("user {}@{} authenticated",currentUser,remoteAddressWithPort);
return AuthenticationResult.SUCCESS;
+ }
+
return AuthenticationResult.FAILURE;
}
package org.opendaylight.controller.netconf.util.osgi;
-import com.google.common.base.Optional;
-import java.net.InetSocketAddress;
-import org.osgi.framework.BundleContext;
-import static com.google.common.base.Preconditions.checkNotNull;
+ import com.google.common.base.Optional;
+ import java.net.InetSocketAddress;
+ import org.osgi.framework.BundleContext;
+ import static com.google.common.base.Preconditions.checkNotNull;
- public class NetconfConfigUtil {
+public class NetconfConfigUtil {
private static final String PREFIX_PROP = "netconf.";
private enum InfixProp {
private static final String PORT_SUFFIX_PROP = ".port";
private static final String ADDRESS_SUFFIX_PROP = ".address";
+ private static final String CLIENT_PROP = ".client";
- public static InetSocketAddress extractTCPNetconfAddress(BundleContext context, String exceptionMessageIfNotFound) {
+ public static InetSocketAddress extractTCPNetconfAddress(BundleContext context, String exceptionMessageIfNotFound, boolean forClient) {
- Optional<InetSocketAddress> inetSocketAddressOptional = extractSomeNetconfAddress(context, InfixProp.tcp, exceptionMessageIfNotFound);
+ Optional<InetSocketAddress> inetSocketAddressOptional = extractSomeNetconfAddress(context, InfixProp.tcp, exceptionMessageIfNotFound, forClient);
if (inetSocketAddressOptional.isPresent() == false) {
throw new IllegalStateException("Netconf tcp address not found." + exceptionMessageIfNotFound);
}
public static Optional<InetSocketAddress> extractSSHNetconfAddress(BundleContext context, String exceptionMessage) {
- return extractSomeNetconfAddress(context, InfixProp.ssh, exceptionMessage);
+ return extractSomeNetconfAddress(context, InfixProp.ssh, exceptionMessage, false);
}
/**
* if address or port are invalid, or configuration is missing
*/
private static Optional<InetSocketAddress> extractSomeNetconfAddress(BundleContext context,
- InfixProp infixProp, String exceptionMessage) {
- String address = context.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
- if (address == null) {
+ InfixProp infixProp,
+ String exceptionMessage,
+ boolean client) {
+ String address = "";
+ if (client) {
+ address = context.getProperty(PREFIX_PROP + infixProp + CLIENT_PROP + ADDRESS_SUFFIX_PROP);
+ }
+ if (address == null || address.equals("")){
+ address = context.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
+ }
+ if (address == null || address.equals("")) {
throw new IllegalStateException("Cannot find initial netconf configuration for parameter "
+PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP
+" in config.ini. "+exceptionMessage);
}
- String portKey = PREFIX_PROP + infixProp + PORT_SUFFIX_PROP;
+ String portKey = "";
+ if (client) {
+ portKey = PREFIX_PROP + infixProp + CLIENT_PROP + PORT_SUFFIX_PROP;
+ }
+ if (portKey == null || portKey.equals("")){
+ portKey = PREFIX_PROP + infixProp + PORT_SUFFIX_PROP;
+ }
String portString = context.getProperty(portKey);
checkNotNull(portString, "Netconf port must be specified in properties file with " + portKey);
try {
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.codehaus.enunciate</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>switchmanager</artifactId>
- <version>0.6.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
* },
* "activeCount": "11",
* "lookupCount": "816",
- * "matchedCount": "220"
+ * "matchedCount": "220",
+ * "maximumEntries": "1000"
* },
* {
* ...another table
* <activeCount>12</activeCount>
* <lookupCount>10935</lookupCount>
* <matchedCount>10084</matchedCount>
+ * <maximumEntries>1000</maximumEntries>
* </tableStatistic>
* <tableStatistic>
* <nodeTable>
* <activeCount>0</activeCount>
* <lookupCount>0</lookupCount>
* <matchedCount>0</matchedCount>
+ * <maximumEntries>0</maximumEntries>
* </tableStatistic>
* <tableStatistic>
* <nodeTable>
* <activeCount>0</activeCount>
* <lookupCount>0</lookupCount>
* <matchedCount>0</matchedCount>
+ * <maximumEntries>0</maximumEntries>
* </tableStatistic>
* </tableStatistics>
* <tableStatistics>
* },
* "activeCount": "12",
* "lookupCount": "11382",
- * "matchedCount": "10524"
+ * "matchedCount": "10524",
+ * "maximumEntries": "1000"
* },
* {
* "nodeTable": {
* },
* "activeCount": "0",
* "lookupCount": "0",
- * "matchedCount": "0"
+ * "matchedCount": "0",
+ * "maximumEntries": "0"
* }
* ]
* }
* <activeCount>12</activeCount>
* <lookupCount>10935</lookupCount>
* <matchedCount>10084</matchedCount>
+ * <maximumEntries>1000</maximumEntries>
* </tableStatistic>
* <tableStatistic>
* <nodeTable>
* <activeCount>0</activeCount>
* <lookupCount>0</lookupCount>
* <matchedCount>0</matchedCount>
+ * <maximumEntries>0</maximumEntries>
* </tableStatistic>
* <tableStatistic>
* <nodeTable>
* <activeCount>0</activeCount>
* <lookupCount>0</lookupCount>
* <matchedCount>0</matchedCount>
+ * <maximumEntries>0</maximumEntries>
* </tableStatistic>
* </nodeTableStatistics>
*
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.6.0-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
import org.openflow.protocol.action.OFActionDataLayer;
import org.openflow.protocol.action.OFActionDataLayerDestination;
import org.openflow.protocol.action.OFActionDataLayerSource;
+import org.openflow.protocol.action.OFActionEnqueue;
import org.openflow.protocol.action.OFActionNetworkLayerAddress;
import org.openflow.protocol.action.OFActionNetworkLayerDestination;
import org.openflow.protocol.action.OFActionNetworkLayerSource;
actionsLength += OFActionOutput.MINIMUM_LENGTH;
continue;
}
+ if (action.getType() == ActionType.ENQUEUE) {
+ Enqueue a = (Enqueue) action;
+ OFActionEnqueue ofAction = new OFActionEnqueue();
+ ofAction.setPort(PortConverter.toOFPort(a.getPort()));
+ ofAction.setQueueId(a.getQueue());
+ actionsList.add(ofAction);
+ actionsLength += OFActionEnqueue.MINIMUM_LENGTH;
+ continue;
+ }
if (action.getType() == ActionType.DROP) {
continue;
}
NodeConnectorCreator.createOFNodeConnector(
ofPort, node));
}
+ } else if (ofAction instanceof OFActionEnqueue) {
+ salAction = new Enqueue(NodeConnectorCreator.createOFNodeConnector(
+ ((OFActionEnqueue) ofAction).getPort(), node),
+ ((OFActionEnqueue) ofAction).getQueueId());
} else if (ofAction instanceof OFActionVirtualLanIdentifier) {
salAction = new SetVlanId(
((OFActionVirtualLanIdentifier) ofAction)
package org.opendaylight.controller.protocol_plugin.openflow.internal;
+import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
return nodeProps;
}
+ // nothing to return
+ @Override
+ public Set<Node> getConfiguredNotConnectedNodes() {
+ return Collections.emptySet();
+ }
+
@Override
public ConcurrentMap<NodeConnector, Map<String, Property>> getNodeConnectorProps(
Boolean refresh) {
ntStat.setActiveCount(ofTableStat.getActiveCount());
ntStat.setLookupCount(ofTableStat.getLookupCount());
ntStat.setMatchedCount(ofTableStat.getMatchedCount());
+ ntStat.setMaximumEntries(ofTableStat.getMaximumEntries());
this.ntStatsList.add(ntStat);
}
}
</scm>
<artifactId>sal</artifactId>
- <version>0.6.0-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<build>
private static final long serialVersionUID = 1L;
@XmlElement
private NodeConnector port;
+ @XmlElement
+ private int queue;
/* Dummy constructor for JAXB */
@SuppressWarnings("unused")
public Enqueue(NodeConnector port) {
type = ActionType.ENQUEUE;
this.port = port;
+ this.queue = 0;
+ }
+
+ public Enqueue(NodeConnector port, int queue) {
+ type = ActionType.ENQUEUE;
+ this.port = port;
+ this.queue = queue;
}
public NodeConnector getPort() {
return port;
}
+
+ public int getQueue() {
+ return queue;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s[%s:%s]", type, port, queue);
+ }
}
package org.opendaylight.controller.sal.inventory;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import org.opendaylight.controller.sal.core.Node;
*/
public ConcurrentMap<Node, Map<String, Property>> getNodeProps();
+ /**
+ * The method retrieves all the configured nodes that are not connected to
+ * the controller
+ *
+ * @return Set of {@link org.opendaylight.controller.sal.core.Node}
+ */
+ public Set<Node> getConfiguredNotConnectedNodes();
/**
* The method retrieve all the existing nodeConnectors and their properties
*
package org.opendaylight.controller.sal.inventory;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import org.opendaylight.controller.sal.core.Node;
*/
public ConcurrentMap<NodeConnector, Map<String, Property>> getNodeConnectorProps(
Boolean refresh);
+
+ /**
+ * The method retrieves all the configured nodes that are not connected to
+ * the controller
+ *
+ * @return Set of {@link org.opendaylight.controller.sal.core.Node}
+ */
+ public Set<Node> getConfiguredNotConnectedNodes();
}
private long lookupCount;
@XmlElement
private long matchedCount;
+ @XmlElement
+ private int maximumEntries;
@Override
this.matchedCount = matchedCount;
}
+ /**
+ * @return the maximumEntries
+ */
+ public long getMaximumEntries() {
+ return maximumEntries;
+ }
+
+ /**
+ * @param maximumEntries the maximumEntries to set
+ */
+ public void setMaximumEntries(int maximumEntries) {
+ this.maximumEntries = maximumEntries;
+ }
+
@Override
public String toString() {
return "NodeTableStats[tableId = " + nodeTable
if (node.getType().equals(NodeIDType.OPENFLOW)) {
try {
return new NodeConnector(NodeConnectorIDType.OPENFLOW,
- (Short) portId, node);
+ portId, node);
} catch (ConstructionException e1) {
logger.error("",e1);
return null;
return null;
}
+ /**
+ * Generic NodeConnector creator
+ * The nodeConnector type is inferred from the node type
+ *
+ * @param portId The string representing the port id
+ * @param node The network node as {@link org.opendaylight.controller.sal.core.Node Node} object
+ * @return The corresponding {@link org.opendaylight.controller.sal.core.NodeConnector NodeConnector} object
+ */
+ public static NodeConnector createNodeConnector(String portId, Node node) {
+ return NodeConnector.fromString(String.format("%s|%s@%s", node.getType(), portId, node.toString()));
+ }
+
/**
* NodeConnector creator where NodeConnector type can be specified
* Needed to create special internal node connectors (like software stack)
* @return true if the Status code is {@code StatusCode.SUCCESS}
*/
public boolean isSuccess() {
- return code == StatusCode.SUCCESS;
+ return code == StatusCode.SUCCESS || code == StatusCode.CREATED;
}
/**
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (obj == null)
+ }
+ if (obj == null) {
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()) {
return false;
+ }
Status other = (Status) obj;
- if (code != other.code)
+ if (code != other.code) {
return false;
+ }
return true;
}
}
*/
public enum StatusCode {
SUCCESS("Success"),
+ CREATED("Created"),
BADREQUEST("Bad Request"),
UNAUTHORIZED("UnAuthorized"),
ntStats.setActiveCount(100);
ntStats.setLookupCount(200);
ntStats.setMatchedCount(500);
+ ntStats.setMaximumEntries(1000);
ntStats.setName("Test");
Assert.assertTrue(ntStats.getNodeTable().equals(nt));
Assert.assertTrue(ntStats.getActiveCount() == 100);
Assert.assertTrue(ntStats.getLookupCount() == 200);
Assert.assertTrue(ntStats.getMatchedCount() == 500);
+ Assert.assertTrue(ntStats.getMaximumEntries() == 1000);
Assert.assertTrue(ntStats.getName().equals("Test"));
}
}
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>equinoxSDK381</groupId>
package org.opendaylight.controller.sal.implementation.internal;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
return nodeProps;
}
+ @Override
+ public Set<Node> getConfiguredNotConnectedNodes() {
+ Set<Node> configuredNotConnected = new HashSet<Node>(), rv;
+ for (IPluginInInventoryService s : this.pluginService) {
+ rv = s.getConfiguredNotConnectedNodes();
+ if (rv != null) {
+ configuredNotConnected.addAll(rv);
+ }
+ }
+ return configuredNotConnected;
+ }
+
@Override
public ConcurrentMap<NodeConnector, Map<String, Property>> getNodeConnectorProps() {
ConcurrentMap<NodeConnector, Map<String, Property>> ncProps =
po = e.getValue();
if (po != null) {
// Populate the Policy field now
- Status poStatus = this.frm.installFlowEntry(po);
+ Status poStatus = this.frm.modifyOrAddFlowEntry(po);
if (!poStatus.isSuccess()) {
log.error("Failed to install policy: "
+ po.getGroupName() + " ("
@Override
public void notifyNode(Node node, UpdateType type,
Map<String, Property> propMap) {
- if (node == null)
+ if (node == null) {
return;
+ }
switch (type) {
case REMOVED:
@Override
public void notifyNodeConnector(NodeConnector nodeConnector,
UpdateType type, Map<String, Property> propMap) {
- if (nodeConnector == null)
+ if (nodeConnector == null) {
return;
+ }
boolean up = false;
switch (type) {
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>switchmanager</artifactId>
- <version>0.6.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
</scm>
<artifactId>switchmanager</artifactId>
- <version>0.6.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<properties>
*/
public List<Switch> getNetworkDevices();
+ /**
+ * Return a Set of all configured devices that are not connected to the controller
+ *
+ * @return Set of {@link org.opendaylight.controller.switchmanager.Switch}
+ */
+ public Set<Switch> getConfiguredNotConnectedSwitches();
+
/**
* Return a list of subnet that were previously configured
*
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>switchmanager</artifactId>
- <version>0.6.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
return (desc == null /* || desc.getValue().equalsIgnoreCase("none") */) ? ""
: desc.getValue();
}
+
+ @Override
+ public Set<Switch> getConfiguredNotConnectedSwitches() {
+ Set<Switch> configuredNotConnectedSwitches = new HashSet<Switch>();
+ if (this.inventoryService == null) {
+ log.trace("inventory service not avaiable");
+ return configuredNotConnectedSwitches;
+ }
+
+ Set<Node> configuredNotConnectedNodes = this.inventoryService.getConfiguredNotConnectedNodes();
+ if (configuredNotConnectedNodes != null) {
+ for (Node node : configuredNotConnectedNodes) {
+ Switch sw = getSwitchByNode(node);
+ if (sw != null) {
+ configuredNotConnectedSwitches.add(sw);
+ }
+ }
+ }
+ return configuredNotConnectedSwitches;
+ }
+
}
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>switchmanager</artifactId>
- <version>0.6.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
+ <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>